Commit 6d59d4fa authored by Jonathan Lemon's avatar Jonathan Lemon Committed by David S. Miller
Browse files

ptp: ocp: Have FPGA fold in ns adjustment for adjtime.



The current implementation of adjtime uses gettime/settime to
perform nanosecond adjustments.  This introduces addtional phase
errors due to delays.

Instead, use the FPGA's ability to just apply the nanosecond
adjustment to the clock directly.

Signed-off-by: default avatarJonathan Lemon <jonathan.lemon@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a62a56d0
Loading
Loading
Loading
Loading
+25 −15
Original line number Diff line number Diff line
@@ -594,9 +594,6 @@ ptp_ocp_settime(struct ptp_clock_info *ptp_info, const struct timespec64 *ts)
	struct ptp_ocp *bp = container_of(ptp_info, struct ptp_ocp, ptp_info);
	unsigned long flags;

	if (ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC)
		return 0;

	spin_lock_irqsave(&bp->lock, flags);
	__ptp_ocp_settime_locked(bp, ts);
	spin_unlock_irqrestore(&bp->lock, flags);
@@ -604,26 +601,39 @@ ptp_ocp_settime(struct ptp_clock_info *ptp_info, const struct timespec64 *ts)
	return 0;
}

static void
__ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u64 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);

	ctrl = OCP_CTRL_ADJUST_OFFSET | OCP_CTRL_ENABLE;
	iowrite32(ctrl, &bp->reg->ctrl);

	/* restore clock selection */
	iowrite32(select >> 16, &bp->reg->select);
}

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);
	struct timespec64 ts;
	unsigned long flags;
	int err;
	u32 adj_ns, sign;

	if (ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC)
		return 0;
	sign = delta_ns < 0 ? BIT(31) : 0;
	adj_ns = sign ? -delta_ns : delta_ns;

	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);
	}
	__ptp_ocp_adjtime_locked(bp, sign | adj_ns);
	spin_unlock_irqrestore(&bp->lock, flags);

	return err;
	return 0;
}

static int
@@ -636,7 +646,7 @@ ptp_ocp_null_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
}

static int
ptp_ocp_adjphase(struct ptp_clock_info *ptp_info, s32 phase_ns)
ptp_ocp_null_adjphase(struct ptp_clock_info *ptp_info, s32 phase_ns)
{
	return -EOPNOTSUPP;
}
@@ -699,7 +709,7 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
	.settime64	= ptp_ocp_settime,
	.adjtime	= ptp_ocp_adjtime,
	.adjfine	= ptp_ocp_null_adjfine,
	.adjphase	= ptp_ocp_adjphase,
	.adjphase	= ptp_ocp_null_adjphase,
	.enable		= ptp_ocp_enable,
	.pps		= true,
	.n_ext_ts	= 4,