aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ptp/ptp_ocp.c
diff options
context:
space:
mode:
authorVadim Fedorenko <vadfed@fb.com>2022-03-02 13:34:58 -0800
committerDavid S. Miller <davem@davemloft.net>2022-03-03 14:42:46 +0000
commite68462a0d99dff5879ca10d4d1da978e6142c9ec (patch)
tree751d2cd7b3b4feab7ae623d14d94abbb726230b0 /drivers/ptp/ptp_ocp.c
parentptp: ocp: add tod_correction attribute (diff)
downloadlinux-dev-e68462a0d99dff5879ca10d4d1da978e6142c9ec.tar.xz
linux-dev-e68462a0d99dff5879ca10d4d1da978e6142c9ec.zip
ptp: ocp: adjust utc_tai_offset to TOD info
utc_tai_offset is used to correct IRIG, DCF and NMEA outputs and is set during initialisation but is not corrected during leap second announce event. Add watchdog code to control this correction. Signed-off-by: Vadim Fedorenko <vadfed@fb.com> Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/ptp/ptp_ocp.c')
-rw-r--r--drivers/ptp/ptp_ocp.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index bd872a616b94..50982623aafa 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -742,11 +742,30 @@ __ptp_ocp_clear_drift_locked(struct ptp_ocp *bp)
}
static void
+ptp_ocp_utc_distribute(struct ptp_ocp *bp, u32 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->lock, flags);
+
+ bp->utc_tai_offset = val;
+
+ if (bp->irig_out)
+ iowrite32(val, &bp->irig_out->adj_sec);
+ if (bp->dcf_out)
+ iowrite32(val, &bp->dcf_out->adj_sec);
+ if (bp->nmea_out)
+ iowrite32(val, &bp->nmea_out->adj_sec);
+
+ spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static void
ptp_ocp_watchdog(struct timer_list *t)
{
struct ptp_ocp *bp = from_timer(bp, t, watchdog);
unsigned long flags;
- u32 status;
+ u32 status, utc_offset;
status = ioread32(&bp->pps_to_clk->status);
@@ -763,6 +782,17 @@ ptp_ocp_watchdog(struct timer_list *t)
bp->gnss_lost = 0;
}
+ /* if GNSS provides correct data we can rely on
+ * it to get leap second information
+ */
+ if (bp->tod) {
+ status = ioread32(&bp->tod->utc_status);
+ utc_offset = status & TOD_STATUS_UTC_MASK;
+ if (status & TOD_STATUS_UTC_VALID &&
+ utc_offset != bp->utc_tai_offset)
+ ptp_ocp_utc_distribute(bp, utc_offset);
+ }
+
mod_timer(&bp->watchdog, jiffies + HZ);
}
@@ -832,25 +862,6 @@ ptp_ocp_init_clock(struct ptp_ocp *bp)
}
static void
-ptp_ocp_utc_distribute(struct ptp_ocp *bp, u32 val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&bp->lock, flags);
-
- bp->utc_tai_offset = val;
-
- if (bp->irig_out)
- iowrite32(val, &bp->irig_out->adj_sec);
- if (bp->dcf_out)
- iowrite32(val, &bp->dcf_out->adj_sec);
- if (bp->nmea_out)
- iowrite32(val, &bp->nmea_out->adj_sec);
-
- spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static void
ptp_ocp_tod_init(struct ptp_ocp *bp)
{
u32 ctrl, reg;