As discussed in this email thread: https://sourceforge.net/p/linuxptp/mailman/message/37047555/ there is a desire to synchronize multiple DSA switches in a boundary_clock_jbod setup, using a PPS signal, and the ts2phc program already offers a solid base.
This patch series extends the ts2phc program to cater for that use case by introducing a new '-a' option and friends ('--transportSpecific'). This makes it quite similar to phc2sys which has the same ability, just that ts2phc can give much better performance if the hardware can assist with that. The overall board design for my use case is that there's an SoC with an embedded DSA switch, and hanging off of 3 ports of that embedded switch are 3 external switches. Every networking device (the DSA master for the embedded switch, the embedded switch, as well as each individual external switch) has a PTP clock. The topology for PPS signal distribution is fixed - that is given by hardware ability - the /dev/ptp1 clock can emit a valid PPS, and all external switches can timestamp that PPS (it is connected in a sort-of simplex "bus" design), and it cannot be any other way around. It looks like this: +---------------------------------------------------------------+ | LS1028A /dev/ptp0 (unused) | | +------------------------------+ | | | DSA master for Felix | | | |(internal ENETC port 2: eno2))| | | +------------+------------------------------+-------------+ | | | Felix embedded L2 switch /dev/ptp1 | | | | PPS source, sync target | | | | +--------------+ +--------------+ +--------------+ | | | | |DSA master for| |DSA master for| |DSA master for| | | | | | SJA1105 1 | | SJA1105 2 | | SJA1105 3 | | | | | |(Felix port 1)| |(Felix port 2)| |(Felix port 3)| | | +--+-+--------------+---+--------------+---+--------------+--+--+ /dev/ptp2 /dev/ptp3 /dev/ptp4 PPS sink, sync reference PPS sink, sync target PPS sink, sync target +-----------------------+ +-----------------------+ +-----------------------+ | SJA1105 switch 1 | | SJA1105 switch 2 | | SJA1105 switch 3 | +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ |sw1p0|sw1p1|sw1p2|sw1p3| |sw2p0|sw2p1|sw2p2|sw2p3| |sw3p0|sw3p1|sw3p2|sw3p3| +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ ^ | GM connected here In text, it would be described as this: cat ts2phc.cfg [global] first_step_threshold 0.00002 step_threshold 0.00002 ts2phc.pulsewidth 500000000 ts2phc.perout_phase 0 # Felix [/dev/ptp1] ts2phc.master 1 # SJA1105 switch 1 [/dev/ptp2] ts2phc.channel 0 ts2phc.extts_polarity both # SJA1105 switch 2 [/dev/ptp3] ts2phc.channel 0 ts2phc.extts_polarity both # SJA1105 switch 3 [/dev/ptp4] ts2phc.channel 0 ts2phc.extts_polarity both cat gPTP.cfg [global] gmCapable 1 priority1 248 priority2 248 logAnnounceInterval 0 logSyncInterval -3 syncReceiptTimeout 3 neighborPropDelayThresh 50000 min_neighbor_prop_delay -20000000 assume_two_step 1 path_trace_enabled 1 follow_up_info 1 transportSpecific 0x1 ptp_dst_mac 01:80:C2:00:00:0E network_transport L2 delay_mechanism P2P step_threshold 0.00002 tx_timestamp_timeout 20 boundary_clock_jbod 1 [sw1p0] [sw1p1] [sw1p2] [sw1p3] [sw2p0] [sw2p1] [sw2p2] [sw2p3] [sw3p0] [sw3p1] [sw3p2] [sw3p3] At a high level, what I have done is: - I moved the PMC related code from phc2sys into pmc_common.c, for ts2phc reuse - I created an extra abstraction in ts2phc as "struct clock" that would represent what's synchronizable. The "master" and "slave" concepts retain their meaning, which is: "master" == the device that emits PPS, and "slave" == the device that timestamps PPS. - I added support for telling the PHC master to start emitting periodic output using just phase information, and not an absolute time. This is required for the kernel drivers I am working with. - I added support for configuring the pulse width, not just hoping that the value specified in ts2phc.cfg is representative of what the hardware actually uses. The changes should be backwards-compatible with the non-automatic mode. I have only tested non-automatic mode with a PHC master (that's all I have) and it still appears to work as before. Changes in v5: - Renamed "master" to "PPS source" - Renamed "slave" to "PPS sink" - Renamed "source clock" to "reference clock" - Renamed "destination clock" to "target clock" - Renamed "clock" to "ts2phc_clock" - Renamed "port" to "ts2phc_port" Changes in v4: - Rebased and resolved minor conflicts - Small coding style cleanups - Added patch for perout and phase configuration - Retested Changes in v3: - Split patch "phc2sys: break out pmc code into pmc_common.c" into more trivial chunks. There is zero delta compared to previous monolithic patch, otherwise. - Replaced full license header in ts2phc.h with simple SPDX. - Added usage message and manpage for '-a' option. - Removed some useless curly braces. - Moved ts2phc_master_get_clock() from ts2phc_phc_master.c to ts2phc_master.c where it should be. - Added justification in commit message for creating struct ts2phc_private. - Reordered headers alphabetically. Changes in v2: - Added Jacob's review tags, addressed some feedback. - Dropped patch "pmc_common: fix potential memory leak in run_pmc_events()" - Reordered patches (put the tmv helpers first) - Fixed memory leaks Vladimir Oltean (13): pmc_agent: make pmc_agent_query_port_properties take an enum port_state argument ts2phc: rename source code files ("master" to "source", "slave" to "sink") ts2phc: rename "slave clocks" to "PPS sinks" ts2phc: rename "master" to "source" ts2phc: create a private data structure ts2phc: instantiate a full clock structure for every PPS sink ts2phc: instantiate a full clock structure for every PPS source of the PHC kind ts2phc: instantiate a pmc agent ts2phc_slave: print offset to the source clock ts2phc: split PPS sink poll from servo loop ts2phc: reconfigure sync direction by subscribing to ptp4l port events ts2phc: allow PHC PPS sources to be synchronized ts2phc_phc_pps_source: make use of new kernel API for perout waveform config.c | 1 + makefile | 9 +- missing.h | 52 ++ phc2sys.c | 6 +- pmc_agent.c | 2 +- pmc_agent.h | 3 +- ts2phc.8 | 32 +- ts2phc.c | 669 ++++++++++++++++-- ts2phc.h | 64 ++ ts2phc_generic_master.c | 63 -- ts2phc_generic_master.h | 14 - ts2phc_generic_pps_source.c | 63 ++ ts2phc_generic_pps_source.h | 15 + ts2phc_master.c | 38 - ts2phc_master.h | 52 -- ts2phc_master_private.h | 20 - ts2phc_nmea_master.h | 13 - ..._nmea_master.c => ts2phc_nmea_pps_source.c | 119 ++-- ts2phc_nmea_pps_source.h | 14 + ts2phc_phc_master.c | 113 --- ts2phc_phc_master.h | 14 - ts2phc_phc_pps_source.c | 157 ++++ ts2phc_phc_pps_source.h | 15 + ts2phc_pps_sink.c | 433 ++++++++++++ ts2phc_pps_sink.h | 20 + ts2phc_pps_source.c | 48 ++ ts2phc_pps_source.h | 56 ++ ts2phc_pps_source_private.h | 21 + ts2phc_slave.c | 435 ------------ ts2phc_slave.h | 20 - 30 files changed, 1683 insertions(+), 898 deletions(-) create mode 100644 ts2phc.h delete mode 100644 ts2phc_generic_master.c delete mode 100644 ts2phc_generic_master.h create mode 100644 ts2phc_generic_pps_source.c create mode 100644 ts2phc_generic_pps_source.h delete mode 100644 ts2phc_master.c delete mode 100644 ts2phc_master.h delete mode 100644 ts2phc_master_private.h delete mode 100644 ts2phc_nmea_master.h rename ts2phc_nmea_master.c => ts2phc_nmea_pps_source.c (64%) create mode 100644 ts2phc_nmea_pps_source.h delete mode 100644 ts2phc_phc_master.c delete mode 100644 ts2phc_phc_master.h create mode 100644 ts2phc_phc_pps_source.c create mode 100644 ts2phc_phc_pps_source.h create mode 100644 ts2phc_pps_sink.c create mode 100644 ts2phc_pps_sink.h create mode 100644 ts2phc_pps_source.c create mode 100644 ts2phc_pps_source.h create mode 100644 ts2phc_pps_source_private.h delete mode 100644 ts2phc_slave.c delete mode 100644 ts2phc_slave.h -- 2.25.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel