Commit e68462a0 authored by Vadim Fedorenko's avatar Vadim Fedorenko Committed by David S. Miller

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: default avatarVadim Fedorenko <vadfed@fb.com>
Signed-off-by: default avatarJonathan Lemon <jonathan.lemon@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44a412d1
...@@ -741,12 +741,31 @@ __ptp_ocp_clear_drift_locked(struct ptp_ocp *bp) ...@@ -741,12 +741,31 @@ __ptp_ocp_clear_drift_locked(struct ptp_ocp *bp)
iowrite32(select >> 16, &bp->reg->select); iowrite32(select >> 16, &bp->reg->select);
} }
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 static void
ptp_ocp_watchdog(struct timer_list *t) ptp_ocp_watchdog(struct timer_list *t)
{ {
struct ptp_ocp *bp = from_timer(bp, t, watchdog); struct ptp_ocp *bp = from_timer(bp, t, watchdog);
unsigned long flags; unsigned long flags;
u32 status; u32 status, utc_offset;
status = ioread32(&bp->pps_to_clk->status); status = ioread32(&bp->pps_to_clk->status);
...@@ -763,6 +782,17 @@ ptp_ocp_watchdog(struct timer_list *t) ...@@ -763,6 +782,17 @@ ptp_ocp_watchdog(struct timer_list *t)
bp->gnss_lost = 0; 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); mod_timer(&bp->watchdog, jiffies + HZ);
} }
...@@ -831,25 +861,6 @@ ptp_ocp_init_clock(struct ptp_ocp *bp) ...@@ -831,25 +861,6 @@ ptp_ocp_init_clock(struct ptp_ocp *bp)
return 0; return 0;
} }
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 static void
ptp_ocp_tod_init(struct ptp_ocp *bp) ptp_ocp_tod_init(struct ptp_ocp *bp)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment