Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ptp: netc: add the periodic output signal loopback support

The NETC Timer supports looping back the output pulse signal of Fiper-n
into Trigger-n input, so that users can leverage this feature to validate
some other features without external hardware support. For example, users
can use it to test external trigger stamp (EXTTS). And users can combine
EXTTS with loopback mode to check whether the generation time of PPS is
aligned with an integral second of PHC, or the periodic output signal
(PTP_CLK_REQ_PEROUT) whether is generated at the specified time.

Since ptp_clock_info::perout_loopback() has been added to the ptp_clock
driver as a generic interface to enable or disable the periodic output
signal loopback, therefore, netc_timer_perout_loopback() is added as a
callback of ptp_clock_info::perout_loopback().

Test the generation time of PPS event:

$ echo 0 1 > /sys/kernel/debug/ptp0/perout_loopback
$ echo 1 > /sys/class/ptp/ptp0/pps_enable
$ testptp -d /dev/ptp0 -e 3
external time stamp request okay
event index 0 at 63.000000017
event index 0 at 64.000000017
event index 0 at 65.000000017

Test the generation time of the periodic output signal:

$ echo 0 1 > /sys/kernel/debug/ptp0/perout_loopback
$ echo 0 150 0 1 500000000 > /sys/class/ptp/ptp0/period
$ testptp -d /dev/ptp0 -e 3
external time stamp request okay
event index 0 at 150.000000014
event index 0 at 151.500000015
event index 0 at 153.000000014

Signed-off-by: Wei Fang <wei.fang@nxp.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20250905030711.1509648-3-wei.fang@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Wei Fang and committed by
Jakub Kicinski
67ac8363 e096a7cc

+25
+25
drivers/ptp/ptp_netc.c
··· 21 21 #define TMR_ETEP(i) BIT(8 + (i)) 22 22 #define TMR_COMP_MODE BIT(15) 23 23 #define TMR_CTRL_TCLK_PERIOD GENMASK(25, 16) 24 + #define TMR_CTRL_PPL(i) BIT(27 - (i)) 24 25 #define TMR_CTRL_FS BIT(28) 25 26 26 27 #define NETC_TMR_TEVENT 0x0084 ··· 610 609 } 611 610 } 612 611 612 + static int netc_timer_perout_loopback(struct ptp_clock_info *ptp, 613 + unsigned int index, int on) 614 + { 615 + struct netc_timer *priv = ptp_to_netc_timer(ptp); 616 + unsigned long flags; 617 + u32 tmr_ctrl; 618 + 619 + spin_lock_irqsave(&priv->lock, flags); 620 + 621 + tmr_ctrl = netc_timer_rd(priv, NETC_TMR_CTRL); 622 + if (on) 623 + tmr_ctrl |= TMR_CTRL_PPL(index); 624 + else 625 + tmr_ctrl &= ~TMR_CTRL_PPL(index); 626 + 627 + netc_timer_wr(priv, NETC_TMR_CTRL, tmr_ctrl); 628 + 629 + spin_unlock_irqrestore(&priv->lock, flags); 630 + 631 + return 0; 632 + } 633 + 613 634 static void netc_timer_adjust_period(struct netc_timer *priv, u64 period) 614 635 { 615 636 u32 fractional_period = lower_32_bits(period); ··· 740 717 .pps = 1, 741 718 .n_per_out = 3, 742 719 .n_ext_ts = 2, 720 + .n_per_lp = 2, 743 721 .supported_extts_flags = PTP_RISING_EDGE | PTP_FALLING_EDGE | 744 722 PTP_STRICT_FLAGS, 745 723 .adjfine = netc_timer_adjfine, ··· 748 724 .gettimex64 = netc_timer_gettimex64, 749 725 .settime64 = netc_timer_settime64, 750 726 .enable = netc_timer_enable, 727 + .perout_loopback = netc_timer_perout_loopback, 751 728 }; 752 729 753 730 static void netc_timer_init(struct netc_timer *priv)