Re: [PATCH net-next 1/1] net: stmmac: Add hardware supported cross-timestamp

2021-03-24 Thread patchwork-bot+netdevbpf
Hello:

This patch was applied to netdev/net-next.git (refs/heads/master):

On Tue, 23 Mar 2021 19:07:34 +0800 you wrote:
> From: Tan Tee Min 
> 
> Cross timestamping is supported on Integrated Ethernet Controller in
> Intel SoC such as EHL and TGL with Always Running Timer.
> 
> The hardware cross-timestamp result is made available to
> applications through the PTP_SYS_OFFSET_PRECISE ioctl which calls
> stmmac_getcrosststamp().
> 
> [...]

Here is the summary with links:
  - [net-next,1/1] net: stmmac: Add hardware supported cross-timestamp
https://git.kernel.org/netdev/net-next/c/341f67e424e5

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




[PATCH net-next 1/1] net: stmmac: Add hardware supported cross-timestamp

2021-03-23 Thread Wong Vee Khee
From: Tan Tee Min 

Cross timestamping is supported on Integrated Ethernet Controller in
Intel SoC such as EHL and TGL with Always Running Timer.

The hardware cross-timestamp result is made available to
applications through the PTP_SYS_OFFSET_PRECISE ioctl which calls
stmmac_getcrosststamp().

Device time is stored in the MAC Auxiliary register. The 64-bit System
time (ART timestamp) is stored in registers that are only addressable
by using MDIO space.

Signed-off-by: Tan Tee Min 
Co-developed-by: Wong Vee Khee 
Signed-off-by: Wong Vee Khee 
---
 drivers/net/ethernet/stmicro/stmmac/common.h  |   2 +
 .../net/ethernet/stmicro/stmmac/dwmac-intel.c | 108 ++
 drivers/net/ethernet/stmicro/stmmac/dwmac4.h  |   8 ++
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   2 +
 drivers/net/ethernet/stmicro/stmmac/hwif.h|   3 +
 .../ethernet/stmicro/stmmac/stmmac_hwtstamp.c |  11 ++
 .../net/ethernet/stmicro/stmmac/stmmac_ptp.c  |  32 ++
 .../net/ethernet/stmicro/stmmac/stmmac_ptp.h  |  23 
 include/linux/stmmac.h|   4 +
 9 files changed, 193 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h 
b/drivers/net/ethernet/stmicro/stmmac/common.h
index 1c0c60bdf854..95469059dca1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -388,6 +388,8 @@ struct dma_features {
unsigned int estsel;
unsigned int fpesel;
unsigned int tbssel;
+   /* Numbers of Auxiliary Snapshot Inputs */
+   unsigned int aux_snapshot_n;
 };
 
 /* RX Buffer size must be multiple of 4/8/16 bytes */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 763b549e3c2d..992294d25706 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -8,6 +8,7 @@
 #include "dwmac-intel.h"
 #include "dwmac4.h"
 #include "stmmac.h"
+#include "stmmac_ptp.h"
 
 #define INTEL_MGBE_ADHOC_ADDR  0x15
 #define INTEL_MGBE_XPCS_ADDR   0x16
@@ -240,6 +241,108 @@ static void intel_mgbe_ptp_clk_freq_config(void *npriv)
writel(gpio_value, priv->ioaddr + GMAC_GPIO_STATUS);
 }
 
+static void get_arttime(struct mii_bus *mii, int intel_adhoc_addr,
+   u64 *art_time)
+{
+   u64 ns;
+
+   ns = mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE3);
+   ns <<= GMAC4_ART_TIME_SHIFT;
+   ns |= mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE2);
+   ns <<= GMAC4_ART_TIME_SHIFT;
+   ns |= mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE1);
+   ns <<= GMAC4_ART_TIME_SHIFT;
+   ns |= mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE0);
+
+   *art_time = ns;
+}
+
+static int intel_crosststamp(ktime_t *device,
+struct system_counterval_t *system,
+void *ctx)
+{
+   struct intel_priv_data *intel_priv;
+
+   struct stmmac_priv *priv = (struct stmmac_priv *)ctx;
+   void __iomem *ptpaddr = priv->ptpaddr;
+   void __iomem *ioaddr = priv->hw->pcsr;
+   unsigned long flags;
+   u64 art_time = 0;
+   u64 ptp_time = 0;
+   u32 num_snapshot;
+   u32 gpio_value;
+   u32 acr_value;
+   int ret;
+   u32 v;
+   int i;
+
+   if (!boot_cpu_has(X86_FEATURE_ART))
+   return -EOPNOTSUPP;
+
+   intel_priv = priv->plat->bsp_priv;
+
+   /* Enable Internal snapshot trigger */
+   acr_value = readl(ptpaddr + PTP_ACR);
+   acr_value &= ~PTP_ACR_MASK;
+   switch (priv->plat->int_snapshot_num) {
+   case AUX_SNAPSHOT0:
+   acr_value |= PTP_ACR_ATSEN0;
+   break;
+   case AUX_SNAPSHOT1:
+   acr_value |= PTP_ACR_ATSEN1;
+   break;
+   case AUX_SNAPSHOT2:
+   acr_value |= PTP_ACR_ATSEN2;
+   break;
+   case AUX_SNAPSHOT3:
+   acr_value |= PTP_ACR_ATSEN3;
+   break;
+   default:
+   return -EINVAL;
+   }
+   writel(acr_value, ptpaddr + PTP_ACR);
+
+   /* Clear FIFO */
+   acr_value = readl(ptpaddr + PTP_ACR);
+   acr_value |= PTP_ACR_ATSFC;
+   writel(acr_value, ptpaddr + PTP_ACR);
+
+   /* Trigger Internal snapshot signal
+* Create a rising edge by just toggle the GPO1 to low
+* and back to high.
+*/
+   gpio_value = readl(ioaddr + GMAC_GPIO_STATUS);
+   gpio_value &= ~GMAC_GPO1;
+   writel(gpio_value, ioaddr + GMAC_GPIO_STATUS);
+   gpio_value |= GMAC_GPO1;
+   writel(gpio_value, ioaddr + GMAC_GPIO_STATUS);
+
+   /* Poll for time sync operation done */
+   ret = readl_poll_timeout(priv->ioaddr + GMAC_INT_STATUS, v,
+(v & GMAC_INT_TSIE), 100, 1);
+
+   if (ret == -ETIMEDOUT) {
+   pr_err("%s: Wait for time sync operation timeout\n", __func__);
+   return ret;
+