diff options
Diffstat (limited to 'drivers/ptp')
-rw-r--r-- | drivers/ptp/ptp_ocp.c | 51 |
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; |