mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-18 15:19:38 +02:00
net: fec: Reload PTP registers after link-state change
[ Upstream commitd9335d0232
] 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:6605b730c0
("FEC: Add time stamping code and a PTP hardware clock") Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu> Reviewed-by: Wei Fang <wei.fang@nxp.com> Link: https://patch.msgid.link/20240924093705.2897329-2-csokas.bence@prolan.hu Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
dc5fb26416
commit
da14324002
|
@ -693,6 +693,9 @@ struct fec_enet_private {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int pps_enable;
|
int pps_enable;
|
||||||
|
u64 ns_sys, ns_phc;
|
||||||
|
u32 at_corr;
|
||||||
|
u8 at_inc_corr;
|
||||||
} ptp_saved_state;
|
} ptp_saved_state;
|
||||||
|
|
||||||
u64 ethtool_stats[];
|
u64 ethtool_stats[];
|
||||||
|
|
|
@ -773,24 +773,44 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
|
||||||
void fec_ptp_save_state(struct fec_enet_private *fep)
|
void fec_ptp_save_state(struct fec_enet_private *fep)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
u32 atime_inc_corr;
|
||||||
|
|
||||||
spin_lock_irqsave(&fep->tmreg_lock, flags);
|
spin_lock_irqsave(&fep->tmreg_lock, flags);
|
||||||
|
|
||||||
fep->ptp_saved_state.pps_enable = fep->pps_enable;
|
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);
|
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore PTP functionality after a reset */
|
/* Restore PTP functionality after a reset */
|
||||||
void fec_ptp_restore_state(struct fec_enet_private *fep)
|
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;
|
unsigned long flags;
|
||||||
|
u32 counter;
|
||||||
|
u64 ns;
|
||||||
|
|
||||||
spin_lock_irqsave(&fep->tmreg_lock, flags);
|
spin_lock_irqsave(&fep->tmreg_lock, flags);
|
||||||
|
|
||||||
/* Reset turned it off, so adjust our status flag */
|
/* Reset turned it off, so adjust our status flag */
|
||||||
fep->pps_enable = 0;
|
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);
|
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
|
||||||
|
|
||||||
/* Restart PPS if needed */
|
/* Restart PPS if needed */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user