Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755061AbbG1AqJ (ORCPT ); Mon, 27 Jul 2015 20:46:09 -0400 Received: from mga01.intel.com ([192.55.52.88]:2755 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754528AbbG1AqF (ORCPT ); Mon, 27 Jul 2015 20:46:05 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,559,1432623600"; d="scan'208";a="736785934" From: Christopher Hall To: john.stultz@linaro.org, tglx@linutronix.de, richardcochran@gmail.com, mingo@redhat.com, jeffrey.t.kirsher@intel.com, john.ronciak@intel.com, hpa@zytor.com, x86@kernel.org Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Christopher Hall Subject: [PATCH 5/5] Enables cross timestamping in the e1000e driver Date: Mon, 27 Jul 2015 17:46:56 -0700 Message-Id: <1438044416-15588-6-git-send-email-christopher.s.hall@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1438044416-15588-1-git-send-email-christopher.s.hall@intel.com> References: <1438044416-15588-1-git-send-email-christopher.s.hall@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5156 Lines: 160 Adds getsynctime64() callback which captures "raw" cross timestamp between ART and Ethernet device clock Translates captured ART to REALTIME clock Signed-off-by: Christopher Hall --- drivers/net/ethernet/intel/e1000e/defines.h | 7 +++ drivers/net/ethernet/intel/e1000e/ptp.c | 83 +++++++++++++++++++++++++++++ drivers/net/ethernet/intel/e1000e/regs.h | 4 ++ 3 files changed, 94 insertions(+) diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index 133d407..9f16269 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h @@ -527,6 +527,13 @@ #define E1000_RXCW_C 0x20000000 /* Receive config */ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ +/* HH Time Sync */ +#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ +#define E1000_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete + */ +#define E1000_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync + */ + #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c index 25a0ad5..bd8b888 100644 --- a/drivers/net/ethernet/intel/e1000e/ptp.c +++ b/drivers/net/ethernet/intel/e1000e/ptp.c @@ -25,6 +25,7 @@ */ #include "e1000.h" +#include /** * e1000e_phc_adjfreq - adjust the frequency of the hardware clock @@ -98,6 +99,87 @@ static int e1000e_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) return 0; } +#define HW_WAIT_COUNT (2) +#define HW_RETRY_COUNT (2) + +static int e1000e_phc_read_timestamp_pair(struct e1000_adapter *adapter, + u64 *systim, u64 *plttim) +{ + struct e1000_hw *hw = &adapter->hw; + int i, j; + u32 tsync_ctrl; + int ret; + + if (hw->mac.type < e1000_pch_spt) + return -ENXIO; + + for (j = 0; j < HW_RETRY_COUNT; ++j) { + tsync_ctrl = er32(TSYNCTXCTL); + tsync_ctrl |= E1000_TSYNCTXCTL_START_SYNC | + E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK; + ew32(TSYNCTXCTL, tsync_ctrl); + ret = 0; + for (i = 0; i < HW_WAIT_COUNT; ++i) { + udelay(2); + tsync_ctrl = er32(TSYNCTXCTL); + if (tsync_ctrl & E1000_TSYNCTXCTL_SYNC_COMP) + break; + } + + if (i == HW_WAIT_COUNT) { + ret = -ETIMEDOUT; + } else if (ret == 0) { + *plttim = er32(PLTSTMPH); + *plttim <<= 32; + *plttim |= er32(PLTSTMPL); + *systim = er32(SYSSTMPH); + *systim <<= 32; + *systim |= er32(SYSSTMPL); + break; + } + } + + return ret; +} + +#define SYNCTIME_RETRY_COUNT (2) + +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; + u64 plttim, systim; + + int i, ret; + + if (!has_art()) + return -ENXIO; + + for (i = 0; i < SYNCTIME_RETRY_COUNT; ++i) { + ret = e1000e_phc_read_timestamp_pair + (adapter, &systim, &plttim); + if (ret != 0) + continue; + + ret = art_to_realtime64(systs, plttim); + if (ret == 0) { + spin_lock_irqsave(&adapter->systim_lock, flags); + systim = timecounter_cyc2time(&adapter->tc, systim); + spin_unlock_irqrestore(&adapter->systim_lock, flags); + devts->tv_sec = + div_u64_rem(systim, NSEC_PER_SEC, &remainder); + devts->tv_nsec = remainder; + break; + } + } + + return ret; +} + /** * e1000e_phc_gettime - Reads the current time from the hardware clock * @ptp: ptp clock structure @@ -190,6 +272,7 @@ static const struct ptp_clock_info e1000e_ptp_clock_info = { .adjfreq = e1000e_phc_adjfreq, .adjtime = e1000e_phc_adjtime, .gettime64 = e1000e_phc_gettime, + .getsynctime64 = e1000e_phc_getsynctime, .settime64 = e1000e_phc_settime, .enable = e1000e_phc_enable, }; diff --git a/drivers/net/ethernet/intel/e1000e/regs.h b/drivers/net/ethernet/intel/e1000e/regs.h index b24e5fe..4dd5b54 100644 --- a/drivers/net/ethernet/intel/e1000e/regs.h +++ b/drivers/net/ethernet/intel/e1000e/regs.h @@ -246,6 +246,10 @@ #define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ #define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ +#define E1000_SYSSTMPL 0x0B648 /* HH Timesync system stamp low register */ +#define E1000_SYSSTMPH 0x0B64C /* HH Timesync system stamp hi register */ +#define E1000_PLTSTMPL 0x0B640 /* HH Timesync platform stamp low register */ +#define E1000_PLTSTMPH 0x0B644 /* HH Timesync platform stamp hi register */ #define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ #define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/