]> Git Repo - linux.git/commitdiff
net: fec: Reload PTP registers after link-state change
authorCsókás, Bence <[email protected]>
Tue, 24 Sep 2024 09:37:06 +0000 (11:37 +0200)
committerPaolo Abeni <[email protected]>
Tue, 1 Oct 2024 09:21:12 +0000 (11:21 +0200)
On link-state change, the controller gets reset,
which clears all PTP registers, including PHC time,
calibrated clock correction values etc. For correct
IEEE 1588 operation we need to restore these after
the reset.

Fixes: 6605b730c061 ("FEC: Add time stamping code and a PTP hardware clock")
Signed-off-by: Csókás, Bence <[email protected]>
Reviewed-by: Wei Fang <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Paolo Abeni <[email protected]>
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_ptp.c

index 0552317a2554bcdb4833234bb4ec62c9166cdc32..1cca0425d49397bbdb97f2c058bd759f9e602f17 100644 (file)
@@ -693,6 +693,9 @@ struct fec_enet_private {
 
        struct {
                int pps_enable;
+               u64 ns_sys, ns_phc;
+               u32 at_corr;
+               u8 at_inc_corr;
        } ptp_saved_state;
 
        u64 ethtool_stats[];
index df1ef023493b9f08e30878ca85a1fbd9b55546d6..a4eb6edb850adda55df0b3b5eedb26b570be06f8 100644 (file)
@@ -767,24 +767,44 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
 void fec_ptp_save_state(struct fec_enet_private *fep)
 {
        unsigned long flags;
+       u32 atime_inc_corr;
 
        spin_lock_irqsave(&fep->tmreg_lock, flags);
 
        fep->ptp_saved_state.pps_enable = fep->pps_enable;
 
+       fep->ptp_saved_state.ns_phc = timecounter_read(&fep->tc);
+       fep->ptp_saved_state.ns_sys = ktime_get_ns();
+
+       fep->ptp_saved_state.at_corr = readl(fep->hwp + FEC_ATIME_CORR);
+       atime_inc_corr = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_CORR_MASK;
+       fep->ptp_saved_state.at_inc_corr = (u8)(atime_inc_corr >> FEC_T_INC_CORR_OFFSET);
+
        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 }
 
 /* Restore PTP functionality after a reset */
 void fec_ptp_restore_state(struct fec_enet_private *fep)
 {
+       u32 atime_inc = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
        unsigned long flags;
+       u32 counter;
+       u64 ns;
 
        spin_lock_irqsave(&fep->tmreg_lock, flags);
 
        /* Reset turned it off, so adjust our status flag */
        fep->pps_enable = 0;
 
+       writel(fep->ptp_saved_state.at_corr, fep->hwp + FEC_ATIME_CORR);
+       atime_inc |= ((u32)fep->ptp_saved_state.at_inc_corr) << FEC_T_INC_CORR_OFFSET;
+       writel(atime_inc, fep->hwp + FEC_ATIME_INC);
+
+       ns = ktime_get_ns() - fep->ptp_saved_state.ns_sys + fep->ptp_saved_state.ns_phc;
+       counter = ns & fep->cc.mask;
+       writel(counter, fep->hwp + FEC_ATIME);
+       timecounter_init(&fep->tc, &fep->cc, ns);
+
        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 
        /* Restart PPS if needed */
This page took 0.062156 seconds and 4 git commands to generate.