diff options
author | Gerhard Engleder <gerhard@engleder-embedded.com> | 2022-05-06 23:01:42 +0300 |
---|---|---|
committer | Paolo Abeni <pabeni@redhat.com> | 2022-05-10 10:48:09 +0300 |
commit | 0abb62b68252b1beefd553dd80f5b4c0b456bcaf (patch) | |
tree | 43baba2e7a4bf6193a9f47686f3af405a3923989 /drivers/net/ethernet/engleder/tsnep_ptp.c | |
parent | fcf308e50928a9c9eca90c56f9fc6885005dafd1 (diff) | |
download | linux-0abb62b68252b1beefd553dd80f5b4c0b456bcaf.tar.xz |
tsnep: Add free running cycle counter support
The TSN endpoint Ethernet MAC supports a free running counter
additionally to its clock. This free running counter can be read and
hardware timestamps are supported. As the name implies, this counter
cannot be set and its frequency cannot be adjusted.
Add free running cycle counter support based on this free running
counter to physical clock. This also requires hardware time stamps
based on that free running counter.
Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers/net/ethernet/engleder/tsnep_ptp.c')
-rw-r--r-- | drivers/net/ethernet/engleder/tsnep_ptp.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/ethernet/engleder/tsnep_ptp.c b/drivers/net/ethernet/engleder/tsnep_ptp.c index eaad453d487e..54fbf0126815 100644 --- a/drivers/net/ethernet/engleder/tsnep_ptp.c +++ b/drivers/net/ethernet/engleder/tsnep_ptp.c @@ -175,6 +175,33 @@ static int tsnep_ptp_settime64(struct ptp_clock_info *ptp, return 0; } +static int tsnep_ptp_getcyclesx64(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct tsnep_adapter *adapter = container_of(ptp, struct tsnep_adapter, + ptp_clock_info); + u32 high_before; + u32 low; + u32 high; + u64 counter; + + /* read high dword twice to detect overrun */ + high = ioread32(adapter->addr + ECM_COUNTER_HIGH); + do { + ptp_read_system_prets(sts); + low = ioread32(adapter->addr + ECM_COUNTER_LOW); + ptp_read_system_postts(sts); + high_before = high; + high = ioread32(adapter->addr + ECM_COUNTER_HIGH); + } while (high != high_before); + counter = (((u64)high) << 32) | ((u64)low); + + *ts = ns_to_timespec64(counter); + + return 0; +} + int tsnep_ptp_init(struct tsnep_adapter *adapter) { int retval = 0; @@ -192,6 +219,7 @@ int tsnep_ptp_init(struct tsnep_adapter *adapter) adapter->ptp_clock_info.adjtime = tsnep_ptp_adjtime; adapter->ptp_clock_info.gettimex64 = tsnep_ptp_gettimex64; adapter->ptp_clock_info.settime64 = tsnep_ptp_settime64; + adapter->ptp_clock_info.getcyclesx64 = tsnep_ptp_getcyclesx64; spin_lock_init(&adapter->ptp_lock); |