diff options
author | Naveen Mamindlapalli <naveenm@marvell.com> | 2022-09-10 10:54:15 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-09-17 22:13:41 +0300 |
commit | 2ef4e45d99b19fb16834616f47d21a9b76b0e5f4 (patch) | |
tree | 66fd6c82bb2345020e7b3cb989f91e5fb53f3dc2 /drivers/net/ethernet/marvell/octeontx2/nic | |
parent | 2958d17a898416c6193431676f6130b68a2cb9fc (diff) | |
download | linux-2ef4e45d99b19fb16834616f47d21a9b76b0e5f4.tar.xz |
octeontx2-af: Add PTP PPS Errata workaround on CN10K silicon
Errata:
The ptp_clock_hi rollsover to zero one clock cycle before it
reaches one second boundary. As a result, the pps threshold
comparison fails after one second and the pps output signal
won't toggle further.
This patch workarounds the issue by programming the pps_lo_incr
register to 500msec minus one clock cycle period, ensuring that
the pps threshold comparison succeeds at one second rollover
boundary and pps edge toggles. After that point, the driver will
have enough time (~500msec) to reset the pps threshold value.
After each one second boundary, hrtimer is invoked which resets
the pps threshold value.
Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: Rakesh Babu Saladi <rsaladi2@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/nic')
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c index 743c8a6d5dad..896b2f9bac34 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c @@ -73,6 +73,23 @@ static int ptp_set_thresh(struct otx2_ptp *ptp, u64 thresh) return otx2_sync_mbox_msg(&ptp->nic->mbox); } +static int ptp_extts_on(struct otx2_ptp *ptp, int on) +{ + struct ptp_req *req; + + if (!ptp->nic) + return -ENODEV; + + req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); + if (!req) + return -ENOMEM; + + req->op = PTP_OP_EXTTS_ON; + req->extts_on = on; + + return otx2_sync_mbox_msg(&ptp->nic->mbox); +} + static u64 ptp_cc_read(const struct cyclecounter *cc) { struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter); @@ -189,8 +206,6 @@ static void otx2_ptp_extts_check(struct work_struct *work) event.index = 0; event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp); ptp_clock_event(ptp->ptp_clock, &event); - ptp->last_extts = tstmp; - new_thresh = tstmp % 500000000; if (ptp->thresh != new_thresh) { mutex_lock(&ptp->nic->mbox.lock); @@ -198,6 +213,7 @@ static void otx2_ptp_extts_check(struct work_struct *work) mutex_unlock(&ptp->nic->mbox.lock); ptp->thresh = new_thresh; } + ptp->last_extts = tstmp; } schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200)); } @@ -235,10 +251,13 @@ static int otx2_ptp_enable(struct ptp_clock_info *ptp_info, rq->extts.index); if (pin < 0) return -EBUSY; - if (on) + if (on) { + ptp_extts_on(ptp, on); schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200)); - else + } else { + ptp_extts_on(ptp, on); cancel_delayed_work_sync(&ptp->extts_work); + } return 0; default: break; |