Skip to content

Commit

Permalink
ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments
Browse files Browse the repository at this point in the history
In ("ptp: ocp: Have FPGA fold in ns adjustment for adjtime."), the
ns adjustment was written to the FPGA register, so the clock could
accurately perform adjustments.

However, the adjtime() call passes in a s64, while the clock adjustment
registers use a s32.  When trying to perform adjustments with a large
value (37 sec), things fail.

Examine the incoming delta, and if larger than 1 sec, use the original
(coarse) adjustment method.  If smaller than 1 sec, then allow the
FPGA to fold in the changes over a 1 second window.

Fixes: 6d59d4f ("ptp: ocp: Have FPGA fold in ns adjustment for adjtime.")
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Link: https://lore.kernel.org/r/20220228203957.367371-1-jonathan.lemon@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jonathan Lemon authored and Jakub Kicinski committed Mar 2, 2022
1 parent 0b0e2ff commit 90f8f4c
Showing 1 changed file with 23 additions and 2 deletions.
25 changes: 23 additions & 2 deletions drivers/ptp/ptp_ocp.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,15 +607,15 @@ ptp_ocp_settime(struct ptp_clock_info *ptp_info, const struct timespec64 *ts)
}

static void
__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u32 adj_val)
{
u32 select, ctrl;

select = ioread32(&bp->reg->select);
iowrite32(OCP_SELECT_CLK_REG, &bp->reg->select);

iowrite32(adj_val, &bp->reg->offset_ns);
iowrite32(adj_val & 0x7f, &bp->reg->offset_window_ns);
iowrite32(NSEC_PER_SEC, &bp->reg->offset_window_ns);

ctrl = OCP_CTRL_ADJUST_OFFSET | OCP_CTRL_ENABLE;
iowrite32(ctrl, &bp->reg->ctrl);
Expand All @@ -624,13 +624,34 @@ __ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
iowrite32(select >> 16, &bp->reg->select);
}

static void
ptp_ocp_adjtime_coarse(struct ptp_ocp *bp, u64 delta_ns)
{
struct timespec64 ts;
unsigned long flags;
int err;

spin_lock_irqsave(&bp->lock, flags);
err = __ptp_ocp_gettime_locked(bp, &ts, NULL);
if (likely(!err)) {
timespec64_add_ns(&ts, delta_ns);
__ptp_ocp_settime_locked(bp, &ts);
}
spin_unlock_irqrestore(&bp->lock, flags);
}

static int
ptp_ocp_adjtime(struct ptp_clock_info *ptp_info, s64 delta_ns)
{
struct ptp_ocp *bp = container_of(ptp_info, struct ptp_ocp, ptp_info);
unsigned long flags;
u32 adj_ns, sign;

if (delta_ns > NSEC_PER_SEC || -delta_ns > NSEC_PER_SEC) {
ptp_ocp_adjtime_coarse(bp, delta_ns);
return 0;
}

sign = delta_ns < 0 ? BIT(31) : 0;
adj_ns = sign ? -delta_ns : delta_ns;

Expand Down

0 comments on commit 90f8f4c

Please sign in to comment.