summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/engleder/tsnep_ptp.c
diff options
context:
space:
mode:
authorGerhard Engleder <gerhard@engleder-embedded.com>2022-05-06 23:01:42 +0300
committerPaolo Abeni <pabeni@redhat.com>2022-05-10 10:48:09 +0300
commit0abb62b68252b1beefd553dd80f5b4c0b456bcaf (patch)
tree43baba2e7a4bf6193a9f47686f3af405a3923989 /drivers/net/ethernet/engleder/tsnep_ptp.c
parentfcf308e50928a9c9eca90c56f9fc6885005dafd1 (diff)
downloadlinux-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.c28
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);