From: Christopher Hall christopher.s.h...@intel.com
Add getsynctime() PTP device callback to cross timestamp system device
clock using ART translation depends on platform being = SPT
and having ART
getsynctime() reads ART (TSC-derived)/device cross timestamp and
converts to realtime/device time reporting cross timestamp to
PTP driver
Signed-off-by: Christopher S. Hall christopher.s.h...@intel.com
---
drivers/net/ethernet/intel/e1000e/defines.h | 5 ++
drivers/net/ethernet/intel/e1000e/ptp.c | 88 +
drivers/net/ethernet/intel/e1000e/regs.h| 4 ++
3 files changed, 97 insertions(+)
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h
b/drivers/net/ethernet/intel/e1000e/defines.h
index 133d407..13cff75 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -527,6 +527,11 @@
#define E1000_RXCW_C 0x2000/* Receive config */
#define E1000_RXCW_SYNCH 0x4000/* Receive config synch */
+/* HH Time Sync */
+#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0xF000 /* max delay */
+#define E1000_TSYNCTXCTL_SYNC_COMP 0x4000 /* sync complete */
+#define E1000_TSYNCTXCTL_START_SYNC0x8000 /* initiate sync */
+
#define E1000_TSYNCTXCTL_VALID 0x0001 /* Tx timestamp valid */
#define E1000_TSYNCTXCTL_ENABLED 0x0010 /* enable Tx timestamping */
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c
b/drivers/net/ethernet/intel/e1000e/ptp.c
index 25a0ad5..228f3f3 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -25,6 +25,8 @@
*/
#include e1000.h
+#include asm/tsc.h
+#include linux/timekeeping.h
/**
* e1000e_phc_adjfreq - adjust the frequency of the hardware clock
@@ -98,6 +100,87 @@ static int e1000e_phc_adjtime(struct ptp_clock_info *ptp,
s64 delta)
return 0;
}
+#define MAX_HW_WAIT_COUNT (3)
+
+static int e1000e_phc_get_ts(struct correlated_ts *cts)
+{
+ struct e1000_adapter *adapter = (struct e1000_adapter *)cts-private;
+ struct e1000_hw *hw = adapter-hw;
+ int i;
+ u32 tsync_ctrl;
+ int ret;
+
+ tsync_ctrl = er32(TSYNCTXCTL);
+ tsync_ctrl |= E1000_TSYNCTXCTL_START_SYNC |
+ E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK;
+ ew32(TSYNCTXCTL, tsync_ctrl);
+ for (i = 0; i MAX_HW_WAIT_COUNT; ++i) {
+ udelay(1);
+ tsync_ctrl = er32(TSYNCTXCTL);
+ if (tsync_ctrl E1000_TSYNCTXCTL_SYNC_COMP)
+ break;
+ }
+
+ if (i == MAX_HW_WAIT_COUNT) {
+ ret = -ETIMEDOUT;
+ } else {
+ ret = 0;
+ cts-system_ts = er32(PLTSTMPH);
+ cts-system_ts = 32;
+ cts-system_ts |= er32(PLTSTMPL);
+ cts-device_ts = er32(SYSSTMPH);
+ cts-device_ts = 32;
+ cts-device_ts |= er32(SYSSTMPL);
+ }
+
+ return ret;
+}
+
+/**
+ * e1000e_phc_getsynctime - Reads the current time from the hardware clock and
+ * correlated system time
+ * @ptp: ptp clock structure
+ * @devts: timespec structure to hold the current device time value
+ * @systs: timespec structure to hold the current system time value
+ *
+ * Read device and system (ART) clock simultaneously and return the correct
+ * clock values in ns after converting into a struct timespec.
+ **/
+static int e1000e_phc_getsynctime(struct ptp_clock_info *ptp,
+ struct timespec64 *devts,
+ struct timespec64 *systs)
+{
+ struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
+ptp_clock_info);
+ unsigned long flags;
+ u32 remainder;
+ struct correlated_ts art_correlated_ts;
+ u64 device_time;
+ int ret;
+
+ art_correlated_ts.get_ts = e1000e_phc_get_ts;
+ art_correlated_ts.private = adapter;
+ ret = get_correlated_timestamp(art_correlated_ts,
+ art_timestamper);
+ if (ret != 0)
+ goto bail;
+
+ systs-tv_sec =
+ div_u64_rem(art_correlated_ts.system_real.tv64,
+ NSEC_PER_SEC, remainder);
+ systs-tv_nsec = remainder;
+ spin_lock_irqsave(adapter-systim_lock, flags);
+ device_time = timecounter_cyc2time(adapter-tc,
+ art_correlated_ts.device_ts);
+ spin_unlock_irqrestore(adapter-systim_lock, flags);
+ devts-tv_sec =
+ div_u64_rem(device_time, NSEC_PER_SEC, remainder);
+ devts-tv_nsec = remainder;
+
+bail:
+ return ret;
+}
+
/**
* e1000e_phc_gettime - Reads the current time from the hardware clock
* @ptp: ptp clock structure
@@ -190,6 +273,7 @@ static const struct ptp_clock_info