Skip to content

Commit

Permalink
net: macb: ptp: Switch to gettimex64() interface
Browse files Browse the repository at this point in the history
The macb PTP support currently implements the `gettime64` callback to allow
to retrieve the hardware clock time. Update the implementation to provide
the `gettimex64` callback instead.

The difference between the two is that with `gettime64` a snapshot of the
system clock is taken before and after invoking the callback. Whereas
`gettimex64` expects the callback itself to take the snapshots.

To get the time from the macb Ethernet core multiple register accesses have
to be done. Only one of which will happen at the time reported by the
function. This leads to a non-symmetric delay and adds a slight offset
between the hardware and system clock time when using the `gettime64`
method. This offset can be a few 100 nanoseconds. Switching to the
`gettimex64` method allows for a more precise correlation of the hardware
and system clocks and results in a lower offset between the two.

On a Xilinx ZynqMP system `phc2sys` reports a delay of 1120 ns before and
300 ns after the patch. With the latter being mostly symmetric.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Lars-Peter Clausen authored and David S. Miller committed Sep 30, 2021
1 parent 2e861e5 commit e51bb5c
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions drivers/net/ethernet/cadence/macb_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,18 @@ static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp,
return NULL;
}

static int gem_tsu_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
static int gem_tsu_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts,
struct ptp_system_timestamp *sts)
{
struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
unsigned long flags;
long first, second;
u32 secl, sech;

spin_lock_irqsave(&bp->tsu_clk_lock, flags);
ptp_read_system_prets(sts);
first = gem_readl(bp, TN);
ptp_read_system_postts(sts);
secl = gem_readl(bp, TSL);
sech = gem_readl(bp, TSH);
second = gem_readl(bp, TN);
Expand All @@ -56,7 +59,9 @@ static int gem_tsu_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
/* if so, use later read & re-read seconds
* (assume all done within 1s)
*/
ptp_read_system_prets(sts);
ts->tv_nsec = gem_readl(bp, TN);
ptp_read_system_postts(sts);
secl = gem_readl(bp, TSL);
sech = gem_readl(bp, TSH);
} else {
Expand Down Expand Up @@ -161,7 +166,7 @@ static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
}

if (delta > TSU_NSEC_MAX_VAL) {
gem_tsu_get_time(&bp->ptp_clock_info, &now);
gem_tsu_get_time(&bp->ptp_clock_info, &now, NULL);
now = timespec64_add(now, then);

gem_tsu_set_time(&bp->ptp_clock_info,
Expand Down Expand Up @@ -192,7 +197,7 @@ static const struct ptp_clock_info gem_ptp_caps_template = {
.pps = 1,
.adjfine = gem_ptp_adjfine,
.adjtime = gem_ptp_adjtime,
.gettime64 = gem_tsu_get_time,
.gettimex64 = gem_tsu_get_time,
.settime64 = gem_tsu_set_time,
.enable = gem_ptp_enable,
};
Expand Down Expand Up @@ -251,7 +256,7 @@ static int gem_hw_timestamp(struct macb *bp, u32 dma_desc_ts_1,
* The timestamp only contains lower few bits of seconds,
* so add value from 1588 timer
*/
gem_tsu_get_time(&bp->ptp_clock_info, &tsu);
gem_tsu_get_time(&bp->ptp_clock_info, &tsu, NULL);

/* If the top bit is set in the timestamp,
* but not in 1588 timer, it has rolled over,
Expand Down

0 comments on commit e51bb5c

Please sign in to comment.