mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 23:24:11 +08:00
ptp: ocp: Add ptp_ocp_adjtime_coarse for large adjustments
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: 6d59d4fa17
("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>
This commit is contained in:
parent
0b0e2ff103
commit
90f8f4c0e3
@ -607,7 +607,7 @@ 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;
|
||||
|
||||
@ -615,7 +615,7 @@ __ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 adj_val)
|
||||
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);
|
||||
@ -624,6 +624,22 @@ __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)
|
||||
{
|
||||
@ -631,6 +647,11 @@ ptp_ocp_adjtime(struct ptp_clock_info *ptp_info, s64 delta_ns)
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user