linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
@ 2016-12-14 12:56 Andrei Pistirica
  2016-12-14 12:56 ` [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms Andrei Pistirica
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Andrei Pistirica @ 2016-12-14 12:56 UTC (permalink / raw)
  To: netdev, linux-kernel, linux-arm-kernel, davem, nicolas.ferre,
	harinikatakamlinux, harini.katakam
  Cc: punnaia, michals, anirudh, boris.brezillon, alexandre.belloni,
	tbultel, richardcochran, rafalo, Andrei Pistirica

Cadence GEM provides a 102 bit time counter with 48 bits for seconds,
30 bits for nsecs and 24 bits for sub-nsecs to control 1588 timestamping.

This patch does the following:
- Registers to ptp clock framework
- Timer initialization is done by writing time of day to the timer counter.
- ns increment register is programmed as NSEC_PER_SEC/tsu-clock-rate.
  For a 16 bit subns precision, the subns increment equals
  remainder of (NS_PER_SEC/TSU_CLK) * (2^16).
- Timestamps are obtained from the TX/RX PTP event/PEER registers.
  The timestamp obtained thus is updated in skb for upper layers to access.
- The drivers register functions with ptp to perform time and frequency
  adjustment.
- Time adjustment is done by writing to the 1558_ADJUST register.
  The controller will read the delta in this register and update the timer
  counter register. Alternatively, for large time offset adjustments,
  the driver reads the secs and nsecs counter values, adds/subtracts the
  delta and updates the timer counter.
- Frequency is adjusted by adjusting addend (8bit nanosecond increment) and
  addendsub (16bit increment nanosecond fractions).
  The 102bit counter is incremented at nominal frequency with addend and
  addendsub values. Each period addend and addendsub values are adjusted
  based on ppm drift.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
Signed-off-by: Harini Katakam <harinik@xilinx.com>
---
Patch history:

Version 1:
This patch is based on original Harini's patch, implemented in a
separate file to ease the review/maintanance and integration with
other platforms (e.g. Zynq Ultrascale+ MPSoC).
Feature was tested on SAMA5D2 platform using ptp4l v1.6 from linuxptp
project and also with ptpd2 version 2.3.1. PTP was tested over
IPv4,IPv6 and 802.3 protocols.

In case that macb is compiled as a module, it has been renamed to
cadence-macb.ko to avoid naming confusion in Makefile.

Version 2 modifications:
- bitfields for TSU are named according to SAMA5D2 data sheet
- identify GEM-PTP support based on platform capability
- add spinlock for TSU access
- change macb_ptp_adjfreq and use fewer 64bit divisions

Version 3 modifications:
- new adjfine api with one 64 division for frequency adjustment 
  (based on Richard's input)
- add maximum adjustment frequency (ppb) based on nominal frequency
- per platform PTP configuration
- cosmetic changes
Note 1: Kbuild uses "select" instead of "imply", and the macb maintainer agreed
        to make the change when it will be available in net-next.

Version 4 modifications:
- update adjfine for a better approximation
- add maximum adjustment frequency callback to PTP platform configuraion

Note 1: This driver does not support GEM-GXL!
Note 2: Patch on net-next, on December 14th. 

 drivers/net/ethernet/cadence/Kconfig    |  10 +-
 drivers/net/ethernet/cadence/Makefile   |   8 +-
 drivers/net/ethernet/cadence/macb.h     | 118 ++++++++++
 drivers/net/ethernet/cadence/macb_ptp.c | 366 ++++++++++++++++++++++++++++++++
 4 files changed, 500 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/cadence/macb_ptp.c

diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index f0bcb15..ebbc65f 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -29,6 +29,14 @@ config MACB
 	  support for the MACB/GEM chip.
 
 	  To compile this driver as a module, choose M here: the module
-	  will be called macb.
+	  will be called cadence-macb.
+
+config MACB_USE_HWSTAMP
+	bool "Use IEEE 1588 hwstamp"
+	depends on MACB
+	default y
+	select PTP_1588_CLOCK
+	---help---
+	  Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.
 
 endif # NET_CADENCE
diff --git a/drivers/net/ethernet/cadence/Makefile b/drivers/net/ethernet/cadence/Makefile
index 91f79b1..4402d42 100644
--- a/drivers/net/ethernet/cadence/Makefile
+++ b/drivers/net/ethernet/cadence/Makefile
@@ -2,4 +2,10 @@
 # Makefile for the Atmel network device drivers.
 #
 
-obj-$(CONFIG_MACB) += macb.o
+cadence-macb-y	:= macb.o
+
+ifeq ($(CONFIG_MACB_USE_HWSTAMP),y)
+cadence-macb-y	+= macb_ptp.o
+endif
+
+obj-$(CONFIG_MACB) += cadence-macb.o
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index d67adad..e65e985 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -10,6 +10,9 @@
 #ifndef _MACB_H
 #define _MACB_H
 
+#include <linux/ptp_clock.h>
+#include <linux/ptp_clock_kernel.h>
+
 #define MACB_GREGS_NBR 16
 #define MACB_GREGS_VERSION 2
 #define MACB_MAX_QUEUES 8
@@ -131,6 +134,20 @@
 #define GEM_RXIPCCNT		0x01a8 /* IP header Checksum Error Counter */
 #define GEM_RXTCPCCNT		0x01ac /* TCP Checksum Error Counter */
 #define GEM_RXUDPCCNT		0x01b0 /* UDP Checksum Error Counter */
+#define GEM_TISUBN		0x01bc /* 1588 Timer Increment Sub-ns */
+#define GEM_TSH			0x01c0 /* 1588 Timer Seconds High */
+#define GEM_TSL			0x01d0 /* 1588 Timer Seconds Low */
+#define GEM_TN			0x01d4 /* 1588 Timer Nanoseconds */
+#define GEM_TA			0x01d8 /* 1588 Timer Adjust */
+#define GEM_TI			0x01dc /* 1588 Timer Increment */
+#define GEM_EFTSL		0x01e0 /* PTP Event Frame Tx Seconds Low */
+#define GEM_EFTN		0x01e4 /* PTP Event Frame Tx Nanoseconds */
+#define GEM_EFRSL		0x01e8 /* PTP Event Frame Rx Seconds Low */
+#define GEM_EFRN		0x01ec /* PTP Event Frame Rx Nanoseconds */
+#define GEM_PEFTSL		0x01f0 /* PTP Peer Event Frame Tx Secs Low */
+#define GEM_PEFTN		0x01f4 /* PTP Peer Event Frame Tx Ns */
+#define GEM_PEFRSL		0x01f8 /* PTP Peer Event Frame Rx Sec Low */
+#define GEM_PEFRN		0x01fc /* PTP Peer Event Frame Rx Ns */
 #define GEM_DCFG1		0x0280 /* Design Config 1 */
 #define GEM_DCFG2		0x0284 /* Design Config 2 */
 #define GEM_DCFG3		0x0288 /* Design Config 3 */
@@ -174,6 +191,7 @@
 #define MACB_NCR_TPF_SIZE	1
 #define MACB_TZQ_OFFSET		12 /* Transmit zero quantum pause frame */
 #define MACB_TZQ_SIZE		1
+#define MACB_SRTSM_OFFSET	15
 
 /* Bitfields in NCFGR */
 #define MACB_SPD_OFFSET		0 /* Speed */
@@ -319,6 +337,32 @@
 #define MACB_PTZ_SIZE		1
 #define MACB_WOL_OFFSET		14 /* Enable wake-on-lan interrupt */
 #define MACB_WOL_SIZE		1
+#define MACB_DRQFR_OFFSET	18 /* PTP Delay Request Frame Received */
+#define MACB_DRQFR_SIZE		1
+#define MACB_SFR_OFFSET		19 /* PTP Sync Frame Received */
+#define MACB_SFR_SIZE		1
+#define MACB_DRQFT_OFFSET	20 /* PTP Delay Request Frame Transmitted */
+#define MACB_DRQFT_SIZE		1
+#define MACB_SFT_OFFSET		21 /* PTP Sync Frame Transmitted */
+#define MACB_SFT_SIZE		1
+#define MACB_PDRQFR_OFFSET	22 /* PDelay Request Frame Received */
+#define MACB_PDRQFR_SIZE	1
+#define MACB_PDRSFR_OFFSET	23 /* PDelay Response Frame Received */
+#define MACB_PDRSFR_SIZE	1
+#define MACB_PDRQFT_OFFSET	24 /* PDelay Request Frame Transmitted */
+#define MACB_PDRQFT_SIZE	1
+#define MACB_PDRSFT_OFFSET	25 /* PDelay Response Frame Transmitted */
+#define MACB_PDRSFT_SIZE	1
+#define MACB_SRI_OFFSET		26 /* TSU Seconds Register Increment */
+#define MACB_SRI_SIZE		1
+
+/* Timer increment fields */
+#define MACB_TI_CNS_OFFSET	0
+#define MACB_TI_CNS_SIZE	8
+#define MACB_TI_ACNS_OFFSET	8
+#define MACB_TI_ACNS_SIZE	8
+#define MACB_TI_NIT_OFFSET	16
+#define MACB_TI_NIT_SIZE	8
 
 /* Bitfields in MAN */
 #define MACB_DATA_OFFSET	0 /* data */
@@ -386,6 +430,17 @@
 #define GEM_PBUF_LSO_OFFSET			27
 #define GEM_PBUF_LSO_SIZE			1
 
+/* Bitfields in TISUBN */
+#define GEM_SUBNSINCR_OFFSET			0
+#define GEM_SUBNSINCR_SIZE			16
+
+/* Bitfields in TI */
+#define GEM_NSINCR_OFFSET			0
+#define GEM_NSINCR_SIZE				8
+
+/* Bitfields in ADJ */
+#define GEM_ADDSUB_OFFSET			31
+#define GEM_ADDSUB_SIZE				1
 /* Constants for CLK */
 #define MACB_CLK_DIV8				0
 #define MACB_CLK_DIV16				1
@@ -417,6 +472,7 @@
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
 #define MACB_CAPS_SG_DISABLED			0x40000000
 #define MACB_CAPS_MACB_IS_GEM			0x80000000
+#define MACB_CAPS_GEM_HAS_PTP			0x00000020
 
 /* LSO settings */
 #define MACB_LSO_UFO_ENABLE			0x01
@@ -782,6 +838,20 @@ struct macb_or_gem_ops {
 	int	(*mog_rx)(struct macb *bp, int budget);
 };
 
+/* MACB-PTP interface: adapt to platform needs and GEM (e.g. GXL). */
+struct macb_ptp_info {
+	void (*ptp_init)(struct net_device *ndev);
+	void (*ptp_remove)(struct net_device *ndev);
+	s32 (*get_ptp_max_adj)(void);
+	unsigned int (*get_tsu_rate)(struct macb *bp);
+	int (*get_ts_info)(struct net_device *dev,
+			   struct ethtool_ts_info *info);
+	int (*get_hwtst)(struct net_device *netdev,
+			 struct ifreq *ifr);
+	int (*set_hwtst)(struct net_device *netdev,
+			 struct ifreq *ifr, int cmd);
+};
+
 struct macb_config {
 	u32			caps;
 	unsigned int		dma_burst_length;
@@ -874,11 +944,59 @@ struct macb {
 	unsigned int		jumbo_max_len;
 
 	u32			wol;
+
+	struct macb_ptp_info	*ptp_info;
+#ifdef CONFIG_MACB_USE_HWSTAMP
+	bool			hwts_tx_en;
+	bool			hwts_rx_en;
+	spinlock_t		tsu_clk_lock; /* gem tsu clock locking */
+	unsigned int		tsu_rate;
+
+	struct ptp_clock	*ptp_clock;
+	struct ptp_clock_info	ptp_caps;
+	u32			ns_incr;
+	u32			subns_incr;
+#endif
 };
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+void gem_ptp_init(struct net_device *ndev);
+void gem_ptp_remove(struct net_device *ndev);
+void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb);
+void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb);
+
+static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb)
+{
+	if (!bp->hwts_tx_en)
+		return;
+
+	return gem_ptp_txstamp(bp, skb);
+}
+
+static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb)
+{
+	if (!bp->hwts_rx_en)
+		return;
+
+	return gem_ptp_rxstamp(bp, skb);
+}
+
+#else
+static inline void gem_ptp_init(struct net_device *ndev) { }
+static inline void gem_ptp_remove(struct net_device *ndev) { }
+
+static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb) { }
+static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb) { }
+#endif
+
 static inline bool macb_is_gem(struct macb *bp)
 {
 	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
 }
 
+static inline bool gem_has_ptp(struct macb *bp)
+{
+	return !!(bp->caps & MACB_CAPS_GEM_HAS_PTP);
+}
+
 #endif /* _MACB_H */
diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
new file mode 100644
index 0000000..6121b2a
--- /dev/null
+++ b/drivers/net/ethernet/cadence/macb_ptp.c
@@ -0,0 +1,366 @@
+/*
+ * 1588 PTP support for GEM device.
+ *
+ * Copyright (C) 2016 Microchip Technology
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/time64.h>
+#include <linux/ptp_classify.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
+
+#include "macb.h"
+
+#define  GEM_PTP_TIMER_NAME "gem-ptp-timer"
+
+static inline void gem_tsu_get_time(struct macb *bp,
+				    struct timespec64 *ts)
+{
+	u64 sec, sech, secl;
+
+	spin_lock(&bp->tsu_clk_lock);
+
+	/* GEM's internal time */
+	sech = gem_readl(bp, TSH);
+	secl = gem_readl(bp, TSL);
+	ts->tv_nsec = gem_readl(bp, TN);
+	ts->tv_sec = (sech << 32) | secl;
+
+	/* minimize error */
+	sech = gem_readl(bp, TSH);
+	secl = gem_readl(bp, TSL);
+	sec = (sech << 32) | secl;
+	if (ts->tv_sec != sec) {
+		ts->tv_sec = sec;
+		ts->tv_nsec = gem_readl(bp, TN);
+	}
+
+	spin_unlock(&bp->tsu_clk_lock);
+}
+
+static inline void gem_tsu_set_time(struct macb *bp,
+				    const struct timespec64 *ts)
+{
+	u32 ns, sech, secl;
+	s64 word_mask = 0xffffffff;
+
+	sech = (u32)ts->tv_sec;
+	secl = (u32)ts->tv_sec;
+	ns = ts->tv_nsec;
+	if (ts->tv_sec > word_mask)
+		sech = (ts->tv_sec >> 32);
+
+	spin_lock(&bp->tsu_clk_lock);
+
+	/* TSH doesn't latch the time and no atomicity! */
+	gem_writel(bp, TN, 0); /* clear to avoid overflow */
+	gem_writel(bp, TSH, sech);
+	gem_writel(bp, TSL, secl);
+	gem_writel(bp, TN, ns);
+
+	spin_unlock(&bp->tsu_clk_lock);
+}
+
+static int gem_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+	u32 word, diff;
+	u64 adj, rate;
+	int neg_adj = 0;
+
+	if (scaled_ppm < 0) {
+		neg_adj = 1;
+		scaled_ppm = -scaled_ppm;
+	}
+	rate = scaled_ppm;
+
+	/* word: unused(8bit) | ns(8bit) | fractions(16bit) */
+	word = (bp->ns_incr << 16) + bp->subns_incr;
+
+	adj = word;
+	adj *= rate;
+	adj += 500000UL << 16;
+	adj >>= 16; /* remove fractions */
+	diff = div_u64(adj, 1000000UL);
+	word = neg_adj ? word - diff : word + diff;
+
+	spin_lock(&bp->tsu_clk_lock);
+
+	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, (word & 0xffff)));
+	gem_writel(bp, TI, GEM_BF(NSINCR, (word >> 16)));
+
+	spin_unlock(&bp->tsu_clk_lock);
+	return 0;
+}
+
+static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+	struct timespec64 now, then = ns_to_timespec64(delta);
+	u32 adj, sign = 0;
+
+	if (delta < 0) {
+		delta = -delta;
+		sign = 1;
+	}
+
+	if (delta > 0x3FFFFFFF) {
+		gem_tsu_get_time(bp, &now);
+
+		if (sign)
+			now = timespec64_sub(now, then);
+		else
+			now = timespec64_add(now, then);
+
+		gem_tsu_set_time(bp, (const struct timespec64 *)&now);
+	} else {
+		adj = delta;
+		if (sign)
+			adj |= GEM_BIT(ADDSUB);
+
+		gem_writel(bp, TA, adj);
+	}
+
+	return 0;
+}
+
+static int gem_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+
+	gem_tsu_get_time(bp, ts);
+
+	return 0;
+}
+
+static int gem_ptp_settime(struct ptp_clock_info *ptp,
+			   const struct timespec64 *ts)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+
+	gem_tsu_set_time(bp, ts);
+
+	return 0;
+}
+
+static int gem_ptp_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info gem_ptp_caps_template = {
+	.owner		= THIS_MODULE,
+	.name		= GEM_PTP_TIMER_NAME,
+	.max_adj	= 0,
+	.n_alarm	= 0,
+	.n_ext_ts	= 0,
+	.n_per_out	= 0,
+	.n_pins		= 0,
+	.pps		= 0,
+	.adjfine	= gem_ptp_adjfine,
+	.adjtime	= gem_ptp_adjtime,
+	.gettime64	= gem_ptp_gettime,
+	.settime64	= gem_ptp_settime,
+	.enable		= gem_ptp_enable,
+};
+
+static void gem_ptp_init_timer(struct macb *bp)
+{
+	struct timespec64 now;
+	u32 rem = 0;
+
+	getnstimeofday64(&now);
+	gem_tsu_set_time(bp, (const struct timespec64 *)&now);
+
+	bp->ns_incr = div_u64_rem(NSEC_PER_SEC, bp->tsu_rate, &rem);
+	if (rem) {
+		u64 adj = rem;
+
+		adj <<= 16; /* 16 bits nsec fragments */
+		bp->subns_incr = div_u64(adj, bp->tsu_rate);
+	} else {
+		bp->subns_incr = 0;
+	}
+
+	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, bp->subns_incr));
+	gem_writel(bp, TI, GEM_BF(NSINCR, bp->ns_incr));
+	gem_writel(bp, TA, 0);
+}
+
+static void gem_ptp_clear_timer(struct macb *bp)
+{
+	bp->ns_incr = 0;
+	bp->subns_incr = 0;
+
+	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, 0));
+	gem_writel(bp, TI, GEM_BF(NSINCR, 0));
+	gem_writel(bp, TA, 0);
+}
+
+/* While GEM can timestamp PTP packets, it does not mark the RX descriptor
+ * to identify them. UDP packets must be parsed to identify PTP packets.
+ *
+ * Note: Inspired from drivers/net/ethernet/ti/cpts.c
+ */
+static int gem_get_ptp_peer(struct sk_buff *skb, int ptp_class)
+{
+	unsigned int offset = 0;
+	u8 *msgtype, *data = skb->data;
+
+	/* PTP frames are rare! */
+	if (likely(ptp_class == PTP_CLASS_NONE))
+		return -1;
+
+	if (ptp_class & PTP_CLASS_VLAN)
+		offset += VLAN_HLEN;
+
+	switch (ptp_class & PTP_CLASS_PMASK) {
+	case PTP_CLASS_IPV4:
+		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+	break;
+	case PTP_CLASS_IPV6:
+		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+	break;
+	case PTP_CLASS_L2:
+		offset += ETH_HLEN;
+		break;
+
+	/* something went wrong! */
+	default:
+		return -1;
+	}
+
+	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID)
+		return -1;
+
+	if (unlikely(ptp_class & PTP_CLASS_V1))
+		msgtype = data + offset + OFF_PTP_CONTROL;
+	else
+		msgtype = data + offset;
+
+	return (*msgtype) & 0x2;
+}
+
+static void gem_ptp_tx_hwtstamp(struct macb *bp, struct sk_buff *skb,
+				int peer_ev)
+{
+	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+	struct timespec64 ts;
+	u64 ns;
+
+	/* PTP Peer Event Frame packets */
+	if (peer_ev) {
+		ts.tv_sec = gem_readl(bp, PEFTSL);
+		ts.tv_nsec = gem_readl(bp, PEFTN);
+
+	/* PTP Event Frame packets */
+	} else {
+		ts.tv_sec = gem_readl(bp, EFTSL);
+		ts.tv_nsec = gem_readl(bp, EFTN);
+	}
+	ns = timespec64_to_ns(&ts);
+
+	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime(ns);
+	skb_tstamp_tx(skb, skb_hwtstamps(skb));
+}
+
+static void gem_ptp_rx_hwtstamp(struct macb *bp, struct sk_buff *skb,
+				int peer_ev)
+{
+	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+	struct timespec64 ts;
+	u64 ns;
+
+	if (peer_ev) {
+		/* PTP Peer Event Frame packets */
+		ts.tv_sec = gem_readl(bp, PEFRSL);
+		ts.tv_nsec = gem_readl(bp, PEFRN);
+	} else {
+		/* PTP Event Frame packets */
+		ts.tv_sec = gem_readl(bp, EFRSL);
+		ts.tv_nsec = gem_readl(bp, EFRN);
+	}
+	ns = timespec64_to_ns(&ts);
+
+	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime(ns);
+}
+
+/* no static, GEM PTP interface functions */
+void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb)
+{
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+		int class = ptp_classify_raw(skb);
+		int peer;
+
+		peer = gem_get_ptp_peer(skb, class);
+		if (peer < 0)
+			return;
+
+		/* Timestamp this packet */
+		gem_ptp_tx_hwtstamp(bp, skb, peer);
+	}
+}
+
+void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb)
+{
+	int class, peer;
+
+	__skb_push(skb, ETH_HLEN);
+	class = ptp_classify_raw(skb);
+	__skb_pull(skb, ETH_HLEN);
+
+	peer = gem_get_ptp_peer(skb, class);
+	if (peer < 0)
+		return;
+
+	gem_ptp_rx_hwtstamp(bp, skb, peer);
+}
+
+void gem_ptp_init(struct net_device *ndev)
+{
+	struct macb *bp = netdev_priv(ndev);
+
+	spin_lock_init(&bp->tsu_clk_lock);
+	bp->ptp_caps = gem_ptp_caps_template;
+
+	/* nominal frequency and maximum adjustment in ppb */
+	bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
+	bp->ptp_caps.max_adj = bp->ptp_info->get_ptp_max_adj();
+
+	gem_ptp_init_timer(bp);
+
+	bp->ptp_clock = ptp_clock_register(&bp->ptp_caps, NULL);
+	if (IS_ERR(&bp->ptp_clock)) {
+		bp->ptp_clock = NULL;
+		pr_err("ptp clock register failed\n");
+		return;
+	}
+
+	dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
+		 GEM_PTP_TIMER_NAME);
+}
+
+void gem_ptp_remove(struct net_device *ndev)
+{
+	struct macb *bp = netdev_priv(ndev);
+
+	if (bp->ptp_clock)
+		ptp_clock_unregister(bp->ptp_clock);
+
+	gem_ptp_clear_timer(bp);
+
+	dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
+		 GEM_PTP_TIMER_NAME);
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms.
  2016-12-14 12:56 [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Andrei Pistirica
@ 2016-12-14 12:56 ` Andrei Pistirica
  2016-12-20 16:38   ` Rafal Ozieblo
  2016-12-28  8:15 ` [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Richard Cochran
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Andrei Pistirica @ 2016-12-14 12:56 UTC (permalink / raw)
  To: netdev, linux-kernel, linux-arm-kernel, davem, nicolas.ferre,
	harinikatakamlinux, harini.katakam
  Cc: punnaia, michals, anirudh, boris.brezillon, alexandre.belloni,
	tbultel, richardcochran, rafalo, Andrei Pistirica

This patch does the following:
- Enable HW time stamp for the following platforms: SAMA5D2, SAMA5D3 and
  SAMA5D4.
- HW time stamp capabilities are advertised via ethtool and macb ioctl is
  updated accordingly.
- HW time stamp on the PTP Ethernet packets are received using the
  SO_TIMESTAMPING API. Where timers are obtained from the PTP event/peer
  registers.

Note: Patch on net-next, on December 7th.

Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
---
Patch history:

Version 1:
Integration with SAMA5D2 only. This feature wasn't tested on any
other platform that might use cadence/gem.

Patch is not completely ported to the very latest version of net-next,
and it will be after review.

Version 2 modifications:
- add PTP caps for SAMA5D2/3/4 platforms
- and cosmetic changes

Version 3 modifications:
- add support for sama5D2/3/4 platforms using GEM-PTP interface.

Version 4 modifications:
- time stamp only PTP_V2 events
- maximum adjustment value is set based on Richard's input

Note: Patch on net-next, on December 14th. 

 drivers/net/ethernet/cadence/macb.c | 168 ++++++++++++++++++++++++++++++++++--
 1 file changed, 163 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 538544a..8d5c976 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -714,6 +714,8 @@ static void macb_tx_interrupt(struct macb_queue *queue)
 
 			/* First, update TX stats if needed */
 			if (skb) {
+				gem_ptp_do_txstamp(bp, skb);
+
 				netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
 					    macb_tx_ring_wrap(bp, tail),
 					    skb->data);
@@ -878,6 +880,8 @@ static int gem_rx(struct macb *bp, int budget)
 		    GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
+		gem_ptp_do_rxstamp(bp, skb);
+
 		bp->stats.rx_packets++;
 		bp->stats.rx_bytes += skb->len;
 
@@ -2080,6 +2084,9 @@ static int macb_open(struct net_device *dev)
 
 	netif_tx_start_all_queues(dev);
 
+	if (bp->ptp_info)
+		bp->ptp_info->ptp_init(dev);
+
 	return 0;
 }
 
@@ -2101,6 +2108,9 @@ static int macb_close(struct net_device *dev)
 
 	macb_free_consistent(bp);
 
+	if (bp->ptp_info)
+		bp->ptp_info->ptp_remove(dev);
+
 	return 0;
 }
 
@@ -2374,6 +2384,133 @@ static int macb_set_ringparam(struct net_device *netdev,
 	return 0;
 }
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+static unsigned int gem_get_tsu_rate(struct macb *bp)
+{
+	/* Note: TSU rate is hardwired to PCLK. */
+	return clk_get_rate(bp->pclk);
+}
+
+static s32 gem_get_ptp_max_adj(void)
+{
+	return 3921508;
+}
+
+static int gem_get_ts_info(struct net_device *dev,
+			   struct ethtool_ts_info *info)
+{
+	struct macb *bp = netdev_priv(dev);
+
+	ethtool_op_get_ts_info(dev, info);
+	info->so_timestamping =
+		SOF_TIMESTAMPING_TX_SOFTWARE |
+		SOF_TIMESTAMPING_RX_SOFTWARE |
+		SOF_TIMESTAMPING_SOFTWARE |
+		SOF_TIMESTAMPING_TX_HARDWARE |
+		SOF_TIMESTAMPING_RX_HARDWARE |
+		SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->phc_index = -1;
+
+	if (bp->ptp_clock)
+		info->phc_index = ptp_clock_index(bp->ptp_clock);
+
+	return 0;
+}
+
+static int gem_set_hwtst(struct net_device *netdev,
+			 struct ifreq *ifr, int cmd)
+{
+	struct hwtstamp_config config;
+	struct macb *priv = netdev_priv(netdev);
+	u32 regval;
+
+	netdev_vdbg(netdev, "macb_hwtstamp_ioctl\n");
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		priv->hwts_tx_en = false;
+		break;
+	case HWTSTAMP_TX_ON:
+		priv->hwts_tx_en = true;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		if (priv->hwts_rx_en)
+			priv->hwts_rx_en = false;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		regval = macb_readl(priv, NCR);
+		macb_writel(priv, NCR, (regval | MACB_BIT(SRTSM)));
+
+		if (!priv->hwts_rx_en)
+			priv->hwts_rx_en = true;
+		break;
+	default:
+		config.rx_filter = HWTSTAMP_FILTER_NONE;
+		return -ERANGE;
+	}
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
+static int gem_get_hwtst(struct net_device *netdev,
+			 struct ifreq *ifr)
+{
+	struct hwtstamp_config config;
+	struct macb *priv = netdev_priv(netdev);
+
+	config.flags = 0;
+	config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+	config.rx_filter = (priv->hwts_rx_en ?
+			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
+static struct macb_ptp_info gem_ptp_info = {
+	.ptp_init	 = gem_ptp_init,
+	.ptp_remove	 = gem_ptp_remove,
+	.get_ptp_max_adj = gem_get_ptp_max_adj,
+	.get_tsu_rate	 = gem_get_tsu_rate,
+	.get_ts_info	 = gem_get_ts_info,
+	.get_hwtst	 = gem_get_hwtst,
+	.set_hwtst	 = gem_set_hwtst,
+};
+#endif
+
+static int macb_get_ts_info(struct net_device *netdev,
+			    struct ethtool_ts_info *info)
+{
+	struct macb *bp = netdev_priv(netdev);
+
+	if (bp->ptp_info)
+		return bp->ptp_info->get_ts_info(netdev, info);
+
+	return ethtool_op_get_ts_info(netdev, info);
+}
+
 static const struct ethtool_ops macb_ethtool_ops = {
 	.get_regs_len		= macb_get_regs_len,
 	.get_regs		= macb_get_regs,
@@ -2391,7 +2528,7 @@ static const struct ethtool_ops gem_ethtool_ops = {
 	.get_regs_len		= macb_get_regs_len,
 	.get_regs		= macb_get_regs,
 	.get_link		= ethtool_op_get_link,
-	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_ts_info		= macb_get_ts_info,
 	.get_ethtool_stats	= gem_get_ethtool_stats,
 	.get_strings		= gem_get_ethtool_strings,
 	.get_sset_count		= gem_get_sset_count,
@@ -2404,6 +2541,7 @@ static const struct ethtool_ops gem_ethtool_ops = {
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct phy_device *phydev = dev->phydev;
+	struct macb *bp = netdev_priv(dev);
 
 	if (!netif_running(dev))
 		return -EINVAL;
@@ -2411,7 +2549,20 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!phydev)
 		return -ENODEV;
 
-	return phy_mii_ioctl(phydev, rq, cmd);
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		if (bp->ptp_info)
+			return bp->ptp_info->set_hwtst(dev, rq, cmd);
+
+		return -EOPNOTSUPP;
+	case SIOCGHWTSTAMP:
+		if (bp->ptp_info)
+			return bp->ptp_info->get_hwtst(dev, rq);
+
+		return -EOPNOTSUPP;
+	default:
+		return phy_mii_ioctl(phydev, rq, cmd);
+	}
 }
 
 static int macb_set_features(struct net_device *netdev,
@@ -2485,6 +2636,12 @@ static void macb_configure_caps(struct macb *bp,
 		dcfg = gem_readl(bp, DCFG2);
 		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
 			bp->caps |= MACB_CAPS_FIFO_MODE;
+
+		/* iff HWSTAMP is configure and gem has the capability */
+#ifdef CONFIG_MACB_USE_HWSTAMP
+		if (gem_has_ptp(bp))
+			bp->ptp_info = &gem_ptp_info;
+#endif
 	}
 
 	dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps);
@@ -3041,7 +3198,7 @@ static const struct macb_config pc302gem_config = {
 };
 
 static const struct macb_config sama5d2_config = {
-	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
+	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_GEM_HAS_PTP,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
@@ -3049,14 +3206,15 @@ static const struct macb_config sama5d2_config = {
 
 static const struct macb_config sama5d3_config = {
 	.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE
-	      | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
+	      | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII
+	      | MACB_CAPS_GEM_HAS_PTP,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
 };
 
 static const struct macb_config sama5d4_config = {
-	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
+	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_GEM_HAS_PTP,
 	.dma_burst_length = 4,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* RE: [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms.
  2016-12-14 12:56 ` [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms Andrei Pistirica
@ 2016-12-20 16:38   ` Rafal Ozieblo
  0 siblings, 0 replies; 19+ messages in thread
From: Rafal Ozieblo @ 2016-12-20 16:38 UTC (permalink / raw)
  To: Andrei Pistirica, netdev, linux-kernel, linux-arm-kernel, davem,
	nicolas.ferre, harinikatakamlinux, harini.katakam
  Cc: punnaia, michals, anirudh, boris.brezillon, alexandre.belloni,
	tbultel, richardcochran

From: Andrei Pistirica [mailto:andrei.pistirica@microchip.com] 
Sent: 14 grudnia 2016 13:56

> This patch does the following:                                                                                     
> - Enable HW time stamp for the following platforms: SAMA5D2, SAMA5D3 and                                           
>   SAMA5D4.                                                                                                         
> - HW time stamp capabilities are advertised via ethtool and macb ioctl is                                          
>   updated accordingly.                                                                                             
> - HW time stamp on the PTP Ethernet packets are received using the                                                 
>   SO_TIMESTAMPING API. Where timers are obtained from the PTP event/peer                                           
>   registers.                                                                                                       
>                                                                                                                    
> Note: Patch on net-next, on December 7th.                                                                          
>                                                                                                                    
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>                                                   
> ---                                                                                                                
> Patch history:                                                                                                     
>                                                                                                                    
> Version 1:                                                                                                         
> Integration with SAMA5D2 only. This feature wasn't tested on any other platform that might use cadence/gem.        
>                                                                                                                    
> Patch is not completely ported to the very latest version of net-next, and it will be after review.                
>                                                                                                                    
> Version 2 modifications:                                                                                           
> - add PTP caps for SAMA5D2/3/4 platforms                                                                           
> - and cosmetic changes                                                                                             
>                                                                                                                    
> Version 3 modifications:                                                                                           
> - add support for sama5D2/3/4 platforms using GEM-PTP interface.                                                   
>                                                                                                                    
> Version 4 modifications:                                                                                           
> - time stamp only PTP_V2 events                                                                                    
> - maximum adjustment value is set based on Richard's input                                                         
>                                                                                                                    
> Note: Patch on net-next, on December 14th.                                                                         
>                                                                                                                    
>  drivers/net/ethernet/cadence/macb.c | 168 ++++++++++++++++++++++++++++++++++--                                    
>  1 file changed, 163 insertions(+), 5 deletions(-)                                                                 
>                                                                                                                    
> diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c                             
> index 538544a..8d5c976 100644                                                                                      
> --- a/drivers/net/ethernet/cadence/macb.c                                                                          
> +++ b/drivers/net/ethernet/cadence/macb.c                                                                          
> @@ -714,6 +714,8 @@ static void macb_tx_interrupt(struct macb_queue *queue)                                        
>                                                                                                                    
>                       /* First, update TX stats if needed */                                                       
>                       if (skb) {                                                                                   
> +                             gem_ptp_do_txstamp(bp, skb);                                                         
> +                                                                                          
I think, you can not do it in that way. 
It will hold two locks. If you enable appropriate option in kernel (as far as I 
remember CONFIG_DEBUG_SPINLOCK) you will get a warning here.

Please look at following call-stack:

1. macb_interrupt()   // spin_lock(&bp->lock) is taken
2. macb_tx_interrupt()
3. macb_handle_txtstamp()
4. skb_tstamp_tx()
5. __skb_tstamp_tx()
6. skb_may_tx_timestamp()
7. read_lock_bh() // second lock is taken

I know that those are different locks and different types. But this could lead 
to deadlocks. This is the reason of warning I could see.
And this is the reason why I get timestamp in interrupt routine but pass it to 
skb outside interrupt (using circular buffer).

Please, refer to this:
https://lkml.org/lkml/2016/11/18/168

1. macb_tx_interrupt()
2. macb_tx_timestamp_add() and schedule_work(&queue->tx_timestamp_task)

Then, outside interrupt (without holding a lock) :
1. macb_tx_timestamp_flush()
2. macb_tstamp_tx()
3. skb_tstamp_tx()

>                               netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",                               
>                                           macb_tx_ring_wrap(bp, tail),                                             
>                                           skb->data);                                                              
> @@ -878,6 +880,8 @@ static int gem_rx(struct macb *bp, int budget)                                                 
>                   GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)                                             
>                       skb->ip_summed = CHECKSUM_UNNECESSARY;                                                       
>                                                                                                                    
> +             gem_ptp_do_rxstamp(bp, skb);                                                                         
> +                                                                                                                  
>               bp->stats.rx_packets++;                                                                              
>               bp->stats.rx_bytes += skb->len;                                                                      
>                                                                                                                    
> @@ -2080,6 +2084,9 @@ static int macb_open(struct net_device *dev)                                                 
>                                                                                                                    
>       netif_tx_start_all_queues(dev);                                                                              
>                                                                                                                    
> +     if (bp->ptp_info)                                                                                            
> +             bp->ptp_info->ptp_init(dev);                                                                         
> +                                                                                                                  
>       return 0;                                                                                                    
>  }                                                                                                                 
>                                                                                                                    
> @@ -2101,6 +2108,9 @@ static int macb_close(struct net_device *dev)                                                
>                                                                                                                    
>       macb_free_consistent(bp);                                                                                    
>                                                                                                                    
> +     if (bp->ptp_info)                                                                                            
> +             bp->ptp_info->ptp_remove(dev);                                                                       
> +                                                                                                                  
>       return 0;                                                                                                    
>  }                                                                                                                 
>                                                                                                                    
> @@ -2374,6 +2384,133 @@ static int macb_set_ringparam(struct net_device *netdev,                                   
>       return 0;                                                                                                    
>  }                                                                                                                 
>                                                                                                                    
> +#ifdef CONFIG_MACB_USE_HWSTAMP                                                                                    
> +static unsigned int gem_get_tsu_rate(struct macb *bp) {                                                           
> +     /* Note: TSU rate is hardwired to PCLK. */                                                                   
> +     return clk_get_rate(bp->pclk);                                                                               
> +}     
Not exactly. There could be separate TSU clock. 
In my solution I check tsu_clk in DT before I decide to take pclk.
But it could be change in macb_ptp_info.

> +                                                                                                                  
> +static s32 gem_get_ptp_max_adj(void)                                                                              
> +{                                                                                                                 
> +     return 3921508;                                                                                              
> +}                                                                                                                 
> +                                                                                                                  
> +static int gem_get_ts_info(struct net_device *dev,                                                                
> +                        struct ethtool_ts_info *info)                                                             
> +{                                                                                                                 
> +     struct macb *bp = netdev_priv(dev);                                                                          
> +                                                                                                                  
> +     ethtool_op_get_ts_info(dev, info);                                                                           
> +     info->so_timestamping =                                                                                      
> +             SOF_TIMESTAMPING_TX_SOFTWARE |                                                                       
> +             SOF_TIMESTAMPING_RX_SOFTWARE |                                                                       
> +             SOF_TIMESTAMPING_SOFTWARE |                                                                          
> +             SOF_TIMESTAMPING_TX_HARDWARE |                                                                       
> +             SOF_TIMESTAMPING_RX_HARDWARE |                                                                       
> +             SOF_TIMESTAMPING_RAW_HARDWARE;                                                                       
> +     info->phc_index = -1;                                                                                        
> +                                                                                                                  
> +     if (bp->ptp_clock)                                                                                           
> +             info->phc_index = ptp_clock_index(bp->ptp_clock);                                                    
> +                                                                                                                  
> +     return 0;                                                                                                    
> +}                                                                                                                 
> +                                                                                                                  
> +static int gem_set_hwtst(struct net_device *netdev,                                                               
> +                      struct ifreq *ifr, int cmd)                                                                 
> +{                                                                                                                 
> +     struct hwtstamp_config config;                                                                               
> +     struct macb *priv = netdev_priv(netdev);                                                                     
> +     u32 regval;                                                                                                  
> +                                                                                                                  
> +     netdev_vdbg(netdev, "macb_hwtstamp_ioctl\n");                                                                
> +                                                                                                                  
> +     if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))                                                  
> +             return -EFAULT;                                                                                      
> +                                                                                                                  
> +     /* reserved for future extensions */                                                                         
> +     if (config.flags)                                                                                            
> +             return -EINVAL;                                                                                      
> +                                                                                                                  
> +     switch (config.tx_type) {                                                                                    
> +     case HWTSTAMP_TX_OFF:                                                                                        
> +             priv->hwts_tx_en = false;                                                                            
> +             break;                                                                                               
> +     case HWTSTAMP_TX_ON:                                                                                         
> +             priv->hwts_tx_en = true;                                                                             
> +             break;                                                                                               
> +     default:                                                                                                     
> +             return -ERANGE;                                                                                      
> +     }                                                                                                            
> +                                                                                                                  
> +     switch (config.rx_filter) {                                                                                  
> +     case HWTSTAMP_FILTER_NONE:                                                                                   
> +             if (priv->hwts_rx_en)                                                                                
> +                     priv->hwts_rx_en = false;                                                                    
> +             break;                                                                                               
> +     case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:                                                                        
> +     case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:                                                                        
> +     case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:                                                                         
> +     case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:                                                                         
> +     case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:                                                                    
> +     case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:                                                                    
> +     case HWTSTAMP_FILTER_PTP_V2_EVENT:                                                                           
> +     case HWTSTAMP_FILTER_PTP_V2_SYNC:                                                                            
> +     case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:                                                                       
> +             config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;                                                     
> +             regval = macb_readl(priv, NCR);                                                                      
> +             macb_writel(priv, NCR, (regval | MACB_BIT(SRTSM)));                                                  
> +                                                                                                                  
> +             if (!priv->hwts_rx_en)                                                                               
> +                     priv->hwts_rx_en = true;                                                                     
> +             break;                                                                                               
> +     default:                                                                                                     
> +             config.rx_filter = HWTSTAMP_FILTER_NONE;                                                             
> +             return -ERANGE;                                                                                      
> +     }                                                                                                            
> +                                                                                                                  
> +     return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?                                                
> +             -EFAULT : 0;                                                                                         
> +}                                                                                                                 
> +                                                                                                                  
> +static int gem_get_hwtst(struct net_device *netdev,                                                               
> +                      struct ifreq *ifr)                                                                          
> +{                                                                                                                 
> +     struct hwtstamp_config config;                                                                               
> +     struct macb *priv = netdev_priv(netdev);                                                                     
> +                                                                                                                  
> +     config.flags = 0;                                                                                            
> +     config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;                                        
> +     config.rx_filter = (priv->hwts_rx_en ?                                                                       
> +                         HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);                                             
> +                                                                                                                  
> +     return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?                                                
> +             -EFAULT : 0;                                                                                         
> +}                                                                                                                 
> +                                                                                                                  
> +static struct macb_ptp_info gem_ptp_info = {                                                                      
> +     .ptp_init        = gem_ptp_init,                                                                             
> +     .ptp_remove      = gem_ptp_remove,                                                                           
> +     .get_ptp_max_adj = gem_get_ptp_max_adj,                                                                      
> +     .get_tsu_rate    = gem_get_tsu_rate,                                                                         
> +     .get_ts_info     = gem_get_ts_info,                                                                          
> +     .get_hwtst       = gem_get_hwtst,                                                                            
> +     .set_hwtst       = gem_set_hwtst,                                                                            
> +};                                                                                                                
> +#endif                                                                                                            
> +                                                                                                                  
> +static int macb_get_ts_info(struct net_device *netdev,                                                            
> +                         struct ethtool_ts_info *info)                                                            
> +{                                                                                                                 
> +     struct macb *bp = netdev_priv(netdev);                                                                       
> +                                                                                                                  
> +     if (bp->ptp_info)                                                                                            
> +             return bp->ptp_info->get_ts_info(netdev, info);                                                      
> +                                                                                                                  
> +     return ethtool_op_get_ts_info(netdev, info); }                                                               
> +                                                                                                                  
>  static const struct ethtool_ops macb_ethtool_ops = {                                                              
>       .get_regs_len           = macb_get_regs_len,                                                                 
>       .get_regs               = macb_get_regs,                                                                     
> @@ -2391,7 +2528,7 @@ static const struct ethtool_ops gem_ethtool_ops = {                                          
>       .get_regs_len           = macb_get_regs_len,                                                                 
>       .get_regs               = macb_get_regs,                                                                     
>       .get_link               = ethtool_op_get_link,                                                               
> -     .get_ts_info            = ethtool_op_get_ts_info,                                                            
> +     .get_ts_info            = macb_get_ts_info,                                                                  
>       .get_ethtool_stats      = gem_get_ethtool_stats,                                                             
>       .get_strings            = gem_get_ethtool_strings,                                                           
>       .get_sset_count         = gem_get_sset_count,                                                                
> @@ -2404,6 +2541,7 @@ static const struct ethtool_ops gem_ethtool_ops = {  static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  {                                                                                  
>       struct phy_device *phydev = dev->phydev;                                                                     
> +     struct macb *bp = netdev_priv(dev);                                                                          
>                                                                                                                    
>       if (!netif_running(dev))                                                                                     
>               return -EINVAL;                                                                                      
> @@ -2411,7 +2549,20 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)                    
>       if (!phydev)                                                                                                 
>               return -ENODEV;
>
> -     return phy_mii_ioctl(phydev, rq, cmd);
> +     switch (cmd) {
> +     case SIOCSHWTSTAMP:
> +             if (bp->ptp_info)
> +                     return bp->ptp_info->set_hwtst(dev, rq, cmd);
> +
> +             return -EOPNOTSUPP;
> +     case SIOCGHWTSTAMP:
> +             if (bp->ptp_info)
> +                     return bp->ptp_info->get_hwtst(dev, rq);
> +
> +             return -EOPNOTSUPP;
> +     default:
> +             return phy_mii_ioctl(phydev, rq, cmd);
> +     }
>  }
>
>  static int macb_set_features(struct net_device *netdev, @@ -2485,6 +2636,12 @@ static void macb_configure_caps(struct macb *bp,
>               dcfg = gem_readl(bp, DCFG2);
>               if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
>                       bp->caps |= MACB_CAPS_FIFO_MODE;
> +
> +             /* iff HWSTAMP is configure and gem has the capability */ #ifdef
> +CONFIG_MACB_USE_HWSTAMP
> +             if (gem_has_ptp(bp))
> +                     bp->ptp_info = &gem_ptp_info;
> +#endif
>       }
>
>       dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps); @@ -3041,7 +3198,7 @@ static const struct macb_config pc302gem_config = {  };
>
>  static const struct macb_config sama5d2_config = {
> -     .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
> +     .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_GEM_HAS_PTP,
There are many IP cores with many configuration. If it is possible, capabilities should be read from IP directly.
And it is possible in that case:
Design Configuration Register 5 (0x290)
bit 8: tsu
There is now PTP hardware support without that bit.

>       .dma_burst_length = 16,
>       .clk_init = macb_clk_init,
>       .init = macb_init,
> @@ -3049,14 +3206,15 @@ static const struct macb_config sama5d2_config = {
>
>  static const struct macb_config sama5d3_config = {
>       .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE
> -           | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
> +           | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII
> +           | MACB_CAPS_GEM_HAS_PTP,
>       .dma_burst_length = 16,
>       .clk_init = macb_clk_init,
>       .init = macb_init,
>  };
>
>  static const struct macb_config sama5d4_config = {
> -     .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
> +     .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_GEM_HAS_PTP,
>       .dma_burst_length = 4,
>       .clk_init = macb_clk_init,
>       .init = macb_init,
> --
> 2.7.4

In macb_start_xmit() there is also invoked skb_tx_timestamp() for software timestamping.
I think, it should be disabled if you do hardware timestamping.

Best regards, 
Rafal Ozieblo   |   Firmware System Engineer, 
www.cadence.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2016-12-14 12:56 [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Andrei Pistirica
  2016-12-14 12:56 ` [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms Andrei Pistirica
@ 2016-12-28  8:15 ` Richard Cochran
  2016-12-28 13:23 ` Rafal Ozieblo
  2017-01-02  9:36 ` Rafal Ozieblo
  3 siblings, 0 replies; 19+ messages in thread
From: Richard Cochran @ 2016-12-28  8:15 UTC (permalink / raw)
  To: Andrei Pistirica
  Cc: netdev, linux-kernel, linux-arm-kernel, davem, nicolas.ferre,
	harinikatakamlinux, harini.katakam, punnaia, michals, anirudh,
	boris.brezillon, alexandre.belloni, tbultel, rafalo

On Wed, Dec 14, 2016 at 02:56:14PM +0200, Andrei Pistirica wrote:
> Note 1: Kbuild uses "select" instead of "imply", and the macb maintainer agreed
>         to make the change when it will be available in net-next.

> +config MACB_USE_HWSTAMP
> +	bool "Use IEEE 1588 hwstamp"
> +	depends on MACB
> +	default y
> +	select PTP_1588_CLOCK

The imply key word has been merged as of:

    237e3ad Kconfig: Introduce the "imply" keyword

Please use it.

Thanks,
Richard


> +	---help---
> +	  Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2016-12-14 12:56 [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Andrei Pistirica
  2016-12-14 12:56 ` [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms Andrei Pistirica
  2016-12-28  8:15 ` [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Richard Cochran
@ 2016-12-28 13:23 ` Rafal Ozieblo
  2017-01-02  9:36 ` Rafal Ozieblo
  3 siblings, 0 replies; 19+ messages in thread
From: Rafal Ozieblo @ 2016-12-28 13:23 UTC (permalink / raw)
  To: Andrei Pistirica, netdev, linux-kernel, linux-arm-kernel, davem,
	nicolas.ferre, harinikatakamlinux, harini.katakam
  Cc: punnaia, michals, anirudh, boris.brezillon, alexandre.belloni,
	tbultel, richardcochran

> From: Andrei Pistirica [mailto:andrei.pistirica@microchip.com] 
> Sent: 14 grudnia 2016 13:56
> Subject: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
> 
> Cadence GEM provides a 102 bit time counter with 48 bits for seconds,
> 30 bits for nsecs and 24 bits for sub-nsecs to control 1588 timestamping.
> 
> This patch does the following:
> - Registers to ptp clock framework
> - Timer initialization is done by writing time of day to the timer counter.
> - ns increment register is programmed as NSEC_PER_SEC/tsu-clock-rate.
>   For a 16 bit subns precision, the subns increment equals
>   remainder of (NS_PER_SEC/TSU_CLK) * (2^16).
> - Timestamps are obtained from the TX/RX PTP event/PEER registers.
>   The timestamp obtained thus is updated in skb for upper layers to access.
> - The drivers register functions with ptp to perform time and frequency
>   adjustment.
> - Time adjustment is done by writing to the 1558_ADJUST register.
>   The controller will read the delta in this register and update the timer
>   counter register. Alternatively, for large time offset adjustments,
>   the driver reads the secs and nsecs counter values, adds/subtracts the
>   delta and updates the timer counter.
> - Frequency is adjusted by adjusting addend (8bit nanosecond increment) and
>   addendsub (16bit increment nanosecond fractions).
>   The 102bit counter is incremented at nominal frequency with addend and
>   addendsub values. Each period addend and addendsub values are adjusted
>   based on ppm drift.
> 
> Signed-off-by: Andrei Pistirica <andrei.pistirica@microchip.com>
> Signed-off-by: Harini Katakam <harinik@xilinx.com>
> ---
> Patch history:
> 
> Version 1:
> This patch is based on original Harini's patch, implemented in a separate file to ease the review/maintanance and integration with other platforms (e.g. Zynq Ultrascale+ MPSoC).
> Feature was tested on SAMA5D2 platform using ptp4l v1.6 from linuxptp project and also with ptpd2 version 2.3.1. PTP was tested over
> IPv4,IPv6 and 802.3 protocols.
> 
> In case that macb is compiled as a module, it has been renamed to cadence-macb.ko to avoid naming confusion in Makefile.
> 
> Version 2 modifications:
> - bitfields for TSU are named according to SAMA5D2 data sheet
> - identify GEM-PTP support based on platform capability
> - add spinlock for TSU access
> - change macb_ptp_adjfreq and use fewer 64bit divisions
> 
> Version 3 modifications:
> - new adjfine api with one 64 division for frequency adjustment
>   (based on Richard's input)
> - add maximum adjustment frequency (ppb) based on nominal frequency
> - per platform PTP configuration
> - cosmetic changes
> Note 1: Kbuild uses "select" instead of "imply", and the macb maintainer agreed
>         to make the change when it will be available in net-next.
> 
> Version 4 modifications:
> - update adjfine for a better approximation
> - add maximum adjustment frequency callback to PTP platform configuraion
> 
> Note 1: This driver does not support GEM-GXL!
> Note 2: Patch on net-next, on December 14th. 
> 
>  drivers/net/ethernet/cadence/Kconfig    |  10 +-
>  drivers/net/ethernet/cadence/Makefile   |   8 +-
>  drivers/net/ethernet/cadence/macb.h     | 118 ++++++++++
>  drivers/net/ethernet/cadence/macb_ptp.c | 366 ++++++++++++++++++++++++++++++++
>  4 files changed, 500 insertions(+), 2 deletions(-)  create mode 100644 drivers/net/ethernet/cadence/macb_ptp.c
> 
> diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
> index f0bcb15..ebbc65f 100644
> --- a/drivers/net/ethernet/cadence/Kconfig
> +++ b/drivers/net/ethernet/cadence/Kconfig
> @@ -29,6 +29,14 @@ config MACB
>  	  support for the MACB/GEM chip.
>  
>  	  To compile this driver as a module, choose M here: the module
> -	  will be called macb.
> +	  will be called cadence-macb.
> +
> +config MACB_USE_HWSTAMP
> +	bool "Use IEEE 1588 hwstamp"
> +	depends on MACB
> +	default y
> +	select PTP_1588_CLOCK
> +	---help---
> +	  Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.
>  
>  endif # NET_CADENCE
> diff --git a/drivers/net/ethernet/cadence/Makefile b/drivers/net/ethernet/cadence/Makefile
> index 91f79b1..4402d42 100644
> --- a/drivers/net/ethernet/cadence/Makefile
> +++ b/drivers/net/ethernet/cadence/Makefile
> @@ -2,4 +2,10 @@
>  # Makefile for the Atmel network device drivers.
>  #
>  
> -obj-$(CONFIG_MACB) += macb.o
> +cadence-macb-y	:= macb.o
> +
> +ifeq ($(CONFIG_MACB_USE_HWSTAMP),y)
> +cadence-macb-y	+= macb_ptp.o
> +endif
> +
> +obj-$(CONFIG_MACB) += cadence-macb.o
> diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
> index d67adad..e65e985 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -10,6 +10,9 @@
>  #ifndef _MACB_H
>  #define _MACB_H
>  
> +#include <linux/ptp_clock.h>
> +#include <linux/ptp_clock_kernel.h>
> +
>  #define MACB_GREGS_NBR 16
>  #define MACB_GREGS_VERSION 2
>  #define MACB_MAX_QUEUES 8
> @@ -131,6 +134,20 @@
>  #define GEM_RXIPCCNT		0x01a8 /* IP header Checksum Error Counter */
>  #define GEM_RXTCPCCNT		0x01ac /* TCP Checksum Error Counter */
>  #define GEM_RXUDPCCNT		0x01b0 /* UDP Checksum Error Counter */
> +#define GEM_TISUBN		0x01bc /* 1588 Timer Increment Sub-ns */
> +#define GEM_TSH			0x01c0 /* 1588 Timer Seconds High */
> +#define GEM_TSL			0x01d0 /* 1588 Timer Seconds Low */
> +#define GEM_TN			0x01d4 /* 1588 Timer Nanoseconds */
> +#define GEM_TA			0x01d8 /* 1588 Timer Adjust */
> +#define GEM_TI			0x01dc /* 1588 Timer Increment */
> +#define GEM_EFTSL		0x01e0 /* PTP Event Frame Tx Seconds Low */
> +#define GEM_EFTN		0x01e4 /* PTP Event Frame Tx Nanoseconds */
> +#define GEM_EFRSL		0x01e8 /* PTP Event Frame Rx Seconds Low */
> +#define GEM_EFRN		0x01ec /* PTP Event Frame Rx Nanoseconds */
> +#define GEM_PEFTSL		0x01f0 /* PTP Peer Event Frame Tx Secs Low */
> +#define GEM_PEFTN		0x01f4 /* PTP Peer Event Frame Tx Ns */
> +#define GEM_PEFRSL		0x01f8 /* PTP Peer Event Frame Rx Sec Low */
> +#define GEM_PEFRN		0x01fc /* PTP Peer Event Frame Rx Ns */
>  #define GEM_DCFG1		0x0280 /* Design Config 1 */
>  #define GEM_DCFG2		0x0284 /* Design Config 2 */
>  #define GEM_DCFG3		0x0288 /* Design Config 3 */
> @@ -174,6 +191,7 @@
>  #define MACB_NCR_TPF_SIZE	1
>  #define MACB_TZQ_OFFSET		12 /* Transmit zero quantum pause frame */
>  #define MACB_TZQ_SIZE		1
> +#define MACB_SRTSM_OFFSET	15
>  
>  /* Bitfields in NCFGR */
>  #define MACB_SPD_OFFSET		0 /* Speed */
> @@ -319,6 +337,32 @@
>  #define MACB_PTZ_SIZE		1
>  #define MACB_WOL_OFFSET		14 /* Enable wake-on-lan interrupt */
>  #define MACB_WOL_SIZE		1
> +#define MACB_DRQFR_OFFSET	18 /* PTP Delay Request Frame Received */
> +#define MACB_DRQFR_SIZE		1
> +#define MACB_SFR_OFFSET		19 /* PTP Sync Frame Received */
> +#define MACB_SFR_SIZE		1
> +#define MACB_DRQFT_OFFSET	20 /* PTP Delay Request Frame Transmitted */
> +#define MACB_DRQFT_SIZE		1
> +#define MACB_SFT_OFFSET		21 /* PTP Sync Frame Transmitted */
> +#define MACB_SFT_SIZE		1
> +#define MACB_PDRQFR_OFFSET	22 /* PDelay Request Frame Received */
> +#define MACB_PDRQFR_SIZE	1
> +#define MACB_PDRSFR_OFFSET	23 /* PDelay Response Frame Received */
> +#define MACB_PDRSFR_SIZE	1
> +#define MACB_PDRQFT_OFFSET	24 /* PDelay Request Frame Transmitted */
> +#define MACB_PDRQFT_SIZE	1
> +#define MACB_PDRSFT_OFFSET	25 /* PDelay Response Frame Transmitted */
> +#define MACB_PDRSFT_SIZE	1
> +#define MACB_SRI_OFFSET		26 /* TSU Seconds Register Increment */
> +#define MACB_SRI_SIZE		1
> +
> +/* Timer increment fields */
> +#define MACB_TI_CNS_OFFSET	0
> +#define MACB_TI_CNS_SIZE	8
> +#define MACB_TI_ACNS_OFFSET	8
> +#define MACB_TI_ACNS_SIZE	8
> +#define MACB_TI_NIT_OFFSET	16
> +#define MACB_TI_NIT_SIZE	8
>  
>  /* Bitfields in MAN */
>  #define MACB_DATA_OFFSET	0 /* data */
> @@ -386,6 +430,17 @@
>  #define GEM_PBUF_LSO_OFFSET			27
>  #define GEM_PBUF_LSO_SIZE			1
>  
> +/* Bitfields in TISUBN */
> +#define GEM_SUBNSINCR_OFFSET			0
> +#define GEM_SUBNSINCR_SIZE			16
> +
> +/* Bitfields in TI */
> +#define GEM_NSINCR_OFFSET			0
> +#define GEM_NSINCR_SIZE				8
> +
> +/* Bitfields in ADJ */
> +#define GEM_ADDSUB_OFFSET			31
> +#define GEM_ADDSUB_SIZE				1
>  /* Constants for CLK */
>  #define MACB_CLK_DIV8				0
>  #define MACB_CLK_DIV16				1
> @@ -417,6 +472,7 @@
>  #define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
>  #define MACB_CAPS_SG_DISABLED			0x40000000
>  #define MACB_CAPS_MACB_IS_GEM			0x80000000
> +#define MACB_CAPS_GEM_HAS_PTP			0x00000020
>  
>  /* LSO settings */
>  #define MACB_LSO_UFO_ENABLE			0x01
> @@ -782,6 +838,20 @@ struct macb_or_gem_ops {
>  	int	(*mog_rx)(struct macb *bp, int budget);
>  };
>  
> +/* MACB-PTP interface: adapt to platform needs and GEM (e.g. GXL). */ 
> +struct macb_ptp_info {
> +	void (*ptp_init)(struct net_device *ndev);
> +	void (*ptp_remove)(struct net_device *ndev);
> +	s32 (*get_ptp_max_adj)(void);
> +	unsigned int (*get_tsu_rate)(struct macb *bp);
> +	int (*get_ts_info)(struct net_device *dev,
> +			   struct ethtool_ts_info *info);
> +	int (*get_hwtst)(struct net_device *netdev,
> +			 struct ifreq *ifr);
> +	int (*set_hwtst)(struct net_device *netdev,
> +			 struct ifreq *ifr, int cmd);
> +};
> +
>  struct macb_config {
>  	u32			caps;
>  	unsigned int		dma_burst_length;
> @@ -874,11 +944,59 @@ struct macb {
>  	unsigned int		jumbo_max_len;
>  
>  	u32			wol;
> +
> +	struct macb_ptp_info	*ptp_info;
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> +	bool			hwts_tx_en;
> +	bool			hwts_rx_en;
> +	spinlock_t		tsu_clk_lock; /* gem tsu clock locking */
> +	unsigned int		tsu_rate;
> +
> +	struct ptp_clock	*ptp_clock;
> +	struct ptp_clock_info	ptp_caps;
> +	u32			ns_incr;
> +	u32			subns_incr;
> +#endif
>  };
>  
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> +void gem_ptp_init(struct net_device *ndev); void gem_ptp_remove(struct 
> +net_device *ndev); void gem_ptp_txstamp(struct macb *bp, struct sk_buff 
> +*skb); void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb);
> +
> +static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff 
> +*skb) {
> +	if (!bp->hwts_tx_en)
> +		return;
> +
> +	return gem_ptp_txstamp(bp, skb);
> +}
> +
> +static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff 
> +*skb) {
> +	if (!bp->hwts_rx_en)
> +		return;
> +
> +	return gem_ptp_rxstamp(bp, skb);
> +}
> +
> +#else
> +static inline void gem_ptp_init(struct net_device *ndev) { } static 
> +inline void gem_ptp_remove(struct net_device *ndev) { }
> +
> +static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff 
> +*skb) { } static inline void gem_ptp_do_rxstamp(struct macb *bp, struct 
> +sk_buff *skb) { } #endif
> +
>  static inline bool macb_is_gem(struct macb *bp)  {
>  	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);  }
>  
> +static inline bool gem_has_ptp(struct macb *bp) {
> +	return !!(bp->caps & MACB_CAPS_GEM_HAS_PTP); }
> +
>  #endif /* _MACB_H */
> diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
> new file mode 100644
> index 0000000..6121b2a
> --- /dev/null
> +++ b/drivers/net/ethernet/cadence/macb_ptp.c
> @@ -0,0 +1,366 @@
> +/*
> + * 1588 PTP support for GEM device.
> + *
> + * Copyright (C) 2016 Microchip Technology
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/etherdevice.h>
> +#include <linux/platform_device.h>
> +#include <linux/time64.h>
> +#include <linux/ptp_classify.h>
> +#include <linux/if_ether.h>
> +#include <linux/if_vlan.h>
> +#include <linux/net_tstamp.h>
> +
> +#include "macb.h"
> +
> +#define  GEM_PTP_TIMER_NAME "gem-ptp-timer"
> +
> +static inline void gem_tsu_get_time(struct macb *bp,
> +				    struct timespec64 *ts)
> +{
> +	u64 sec, sech, secl;
> +
> +	spin_lock(&bp->tsu_clk_lock);
> +
> +	/* GEM's internal time */
> +	sech = gem_readl(bp, TSH);
> +	secl = gem_readl(bp, TSL);
> +	ts->tv_nsec = gem_readl(bp, TN);
> +	ts->tv_sec = (sech << 32) | secl;
> +
> +	/* minimize error */
> +	sech = gem_readl(bp, TSH);
> +	secl = gem_readl(bp, TSL);
> +	sec = (sech << 32) | secl;
> +	if (ts->tv_sec != sec) {
> +		ts->tv_sec = sec;
> +		ts->tv_nsec = gem_readl(bp, TN);
> +	}
> +
> +	spin_unlock(&bp->tsu_clk_lock);
> +}
> +
> +static inline void gem_tsu_set_time(struct macb *bp,
> +				    const struct timespec64 *ts)
> +{
> +	u32 ns, sech, secl;
> +	s64 word_mask = 0xffffffff;
> +
> +	sech = (u32)ts->tv_sec;
> +	secl = (u32)ts->tv_sec;
> +	ns = ts->tv_nsec;
> +	if (ts->tv_sec > word_mask)
> +		sech = (ts->tv_sec >> 32);
> +
> +	spin_lock(&bp->tsu_clk_lock);
> +
> +	/* TSH doesn't latch the time and no atomicity! */
> +	gem_writel(bp, TN, 0); /* clear to avoid overflow */
> +	gem_writel(bp, TSH, sech);
> +	gem_writel(bp, TSL, secl);
> +	gem_writel(bp, TN, ns);
> +
> +	spin_unlock(&bp->tsu_clk_lock);
> +}
> +
> +static int gem_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 
> +{
> +	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> +	u32 word, diff;
> +	u64 adj, rate;
> +	int neg_adj = 0;
> +
> +	if (scaled_ppm < 0) {
> +		neg_adj = 1;
> +		scaled_ppm = -scaled_ppm;
> +	}
> +	rate = scaled_ppm;
> +
> +	/* word: unused(8bit) | ns(8bit) | fractions(16bit) */
> +	word = (bp->ns_incr << 16) + bp->subns_incr;
> +
> +	adj = word;
> +	adj *= rate;
> +	adj += 500000UL << 16;
> +	adj >>= 16; /* remove fractions */
> +	diff = div_u64(adj, 1000000UL);
> +	word = neg_adj ? word - diff : word + diff;
> +
> +	spin_lock(&bp->tsu_clk_lock);
> +
> +	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, (word & 0xffff)));
> +	gem_writel(bp, TI, GEM_BF(NSINCR, (word >> 16)));
> +
> +	spin_unlock(&bp->tsu_clk_lock);
> +	return 0;
> +}
> +
> +static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) {
> +	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> +	struct timespec64 now, then = ns_to_timespec64(delta);
> +	u32 adj, sign = 0;
> +
> +	if (delta < 0) {
> +		delta = -delta;
> +		sign = 1;
> +	}
> +
> +	if (delta > 0x3FFFFFFF) {
> +		gem_tsu_get_time(bp, &now);
> +
> +		if (sign)
> +			now = timespec64_sub(now, then);
> +		else
> +			now = timespec64_add(now, then);
> +
> +		gem_tsu_set_time(bp, (const struct timespec64 *)&now);
> +	} else {
> +		adj = delta;
> +		if (sign)
> +			adj |= GEM_BIT(ADDSUB);
> +
> +		gem_writel(bp, TA, adj);
> +	}
> +
> +	return 0;
> +}
> +
> +static int gem_ptp_gettime(struct ptp_clock_info *ptp, struct 
> +timespec64 *ts) {
> +	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> +
> +	gem_tsu_get_time(bp, ts);
> +
> +	return 0;
> +}
> +
> +static int gem_ptp_settime(struct ptp_clock_info *ptp,
> +			   const struct timespec64 *ts)
> +{
> +	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
> +
> +	gem_tsu_set_time(bp, ts);
> +
> +	return 0;
> +}
> +
> +static int gem_ptp_enable(struct ptp_clock_info *ptp,
> +			  struct ptp_clock_request *rq, int on) {
> +	return -EOPNOTSUPP;
> +}
I think, we can support here:
1. PTP_CLK_REQ_EXTTS (interrupt mask register 0x030, bit 29: tsu_timer_comparison_mask)
2. PTP_CLK_REQ_PPS (interrupt mask register 0x030, bit 26: tsu_seconds_register_increment_mask)

> +
> +static struct ptp_clock_info gem_ptp_caps_template = {
> +	.owner		= THIS_MODULE,
> +	.name		= GEM_PTP_TIMER_NAME,
> +	.max_adj	= 0,
> +	.n_alarm	= 0,
> +	.n_ext_ts	= 0,
> +	.n_per_out	= 0,
> +	.n_pins		= 0,
> +	.pps		= 0,
> +	.adjfine	= gem_ptp_adjfine,
> +	.adjtime	= gem_ptp_adjtime,
> +	.gettime64	= gem_ptp_gettime,
> +	.settime64	= gem_ptp_settime,
> +	.enable		= gem_ptp_enable,
> +};
> +
> +static void gem_ptp_init_timer(struct macb *bp) {
> +	struct timespec64 now;
> +	u32 rem = 0;
> +
> +	getnstimeofday64(&now);
> +	gem_tsu_set_time(bp, (const struct timespec64 *)&now);
Why do you change TSU clock here? Is it necessary? You overwrite all values
even when someone doesn't need it. ptp4l calls ioctl SIOCSHWTSTAMP on start.
IMHO, there should be set up TSU and Increments.

> +
> +	bp->ns_incr = div_u64_rem(NSEC_PER_SEC, bp->tsu_rate, &rem);
> +	if (rem) {
> +		u64 adj = rem;
> +
> +		adj <<= 16; /* 16 bits nsec fragments */
> +		bp->subns_incr = div_u64(adj, bp->tsu_rate);
> +	} else {
> +		bp->subns_incr = 0;
> +	}
> +
> +	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, bp->subns_incr));
> +	gem_writel(bp, TI, GEM_BF(NSINCR, bp->ns_incr));
The same comment like above.

> +	gem_writel(bp, TA, 0);
What is the reason for zeroing Timer Adjust Register?

> +}
> +
> +static void gem_ptp_clear_timer(struct macb *bp) {
> +	bp->ns_incr = 0;
> +	bp->subns_incr = 0;
> +
> +	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, 0));
> +	gem_writel(bp, TI, GEM_BF(NSINCR, 0));
> +	gem_writel(bp, TA, 0);
> +}
> +
> +/* While GEM can timestamp PTP packets, it does not mark the RX 
> +descriptor
> + * to identify them. UDP packets must be parsed to identify PTP packets.
> + *
> + * Note: Inspired from drivers/net/ethernet/ti/cpts.c  */ static int 
> +gem_get_ptp_peer(struct sk_buff *skb, int ptp_class) {
> +	unsigned int offset = 0;
> +	u8 *msgtype, *data = skb->data;
> +
> +	/* PTP frames are rare! */
> +	if (likely(ptp_class == PTP_CLASS_NONE))
> +		return -1;
> +
> +	if (ptp_class & PTP_CLASS_VLAN)
> +		offset += VLAN_HLEN;
> +
> +	switch (ptp_class & PTP_CLASS_PMASK) {
> +	case PTP_CLASS_IPV4:
> +		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
> +	break;
> +	case PTP_CLASS_IPV6:
> +		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
> +	break;
> +	case PTP_CLASS_L2:
> +		offset += ETH_HLEN;
> +		break;
> +
> +	/* something went wrong! */
> +	default:
> +		return -1;
> +	}
> +
> +	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID)
> +		return -1;
> +
> +	if (unlikely(ptp_class & PTP_CLASS_V1))
> +		msgtype = data + offset + OFF_PTP_CONTROL;
> +	else
> +		msgtype = data + offset;
> +
> +	return (*msgtype) & 0x2;
> +}
> +
> +static void gem_ptp_tx_hwtstamp(struct macb *bp, struct sk_buff *skb,
> +				int peer_ev)
> +{
> +	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
> +	struct timespec64 ts;
> +	u64 ns;
> +
> +	/* PTP Peer Event Frame packets */
> +	if (peer_ev) {
> +		ts.tv_sec = gem_readl(bp, PEFTSL);
> +		ts.tv_nsec = gem_readl(bp, PEFTN);
> +
> +	/* PTP Event Frame packets */
> +	} else {
> +		ts.tv_sec = gem_readl(bp, EFTSL);
> +		ts.tv_nsec = gem_readl(bp, EFTN);
> +	}
I'm wondering what is a difference between timestamp in transmit buffer descriptor (Word 2 and 3)
and PTP Event Frame Transmitted Seconds/Nanoseconds Register (0x1E0, 0x1E4).

> +	ns = timespec64_to_ns(&ts);
> +
> +	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
> +	shhwtstamps->hwtstamp = ns_to_ktime(ns);
> +	skb_tstamp_tx(skb, skb_hwtstamps(skb)); }
> +
> +static void gem_ptp_rx_hwtstamp(struct macb *bp, struct sk_buff *skb,
> +				int peer_ev)
> +{
> +	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
> +	struct timespec64 ts;
> +	u64 ns;
> +
> +	if (peer_ev) {
> +		/* PTP Peer Event Frame packets */
> +		ts.tv_sec = gem_readl(bp, PEFRSL);
> +		ts.tv_nsec = gem_readl(bp, PEFRN);
> +	} else {
> +		/* PTP Event Frame packets */
> +		ts.tv_sec = gem_readl(bp, EFRSL);
> +		ts.tv_nsec = gem_readl(bp, EFRN);
> +	}
The same concerns like above.

> +	ns = timespec64_to_ns(&ts);
> +
> +	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
> +	shhwtstamps->hwtstamp = ns_to_ktime(ns); }
> +
> +/* no static, GEM PTP interface functions */ void 
> +gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb) {
> +	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
> +		int class = ptp_classify_raw(skb);
> +		int peer;
> +
> +		peer = gem_get_ptp_peer(skb, class);
> +		if (peer < 0)
> +			return;
> +
> +		/* Timestamp this packet */
> +		gem_ptp_tx_hwtstamp(bp, skb, peer);
> +	}
> +}
> +
> +void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb) {
> +	int class, peer;
> +
> +	__skb_push(skb, ETH_HLEN);
> +	class = ptp_classify_raw(skb);
> +	__skb_pull(skb, ETH_HLEN);
> +
> +	peer = gem_get_ptp_peer(skb, class);
> +	if (peer < 0)
> +		return;
> +
> +	gem_ptp_rx_hwtstamp(bp, skb, peer);
> +}
> +
> +void gem_ptp_init(struct net_device *ndev) {
> +	struct macb *bp = netdev_priv(ndev);
> +
> +	spin_lock_init(&bp->tsu_clk_lock);
> +	bp->ptp_caps = gem_ptp_caps_template;
> +
> +	/* nominal frequency and maximum adjustment in ppb */
> +	bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
> +	bp->ptp_caps.max_adj = bp->ptp_info->get_ptp_max_adj();
> +
> +	gem_ptp_init_timer(bp);
> +
> +	bp->ptp_clock = ptp_clock_register(&bp->ptp_caps, NULL);
> +	if (IS_ERR(&bp->ptp_clock)) {
> +		bp->ptp_clock = NULL;
> +		pr_err("ptp clock register failed\n");
> +		return;
But you have already overwritten TSU and Increments.

> +	}
> +
> +	dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
> +		 GEM_PTP_TIMER_NAME);
> +}
> +
> +void gem_ptp_remove(struct net_device *ndev) {
> +	struct macb *bp = netdev_priv(ndev);
> +
> +	if (bp->ptp_clock)
> +		ptp_clock_unregister(bp->ptp_clock);
> +
> +	gem_ptp_clear_timer(bp);
> +
> +	dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
> +		 GEM_PTP_TIMER_NAME);
> +}
> --
> 2.7.4
> 

Why don't you support HWTSTAMP_TX_ONESTEP_SYNC?
(Network control register 0x000, bit 24: one_step_sync_mode)

Best regards, 
Rafal Ozieblo   |   Firmware System Engineer, 
www.cadence.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2016-12-14 12:56 [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Andrei Pistirica
                   ` (2 preceding siblings ...)
  2016-12-28 13:23 ` Rafal Ozieblo
@ 2017-01-02  9:36 ` Rafal Ozieblo
  2017-01-02 11:31   ` Richard Cochran
  3 siblings, 1 reply; 19+ messages in thread
From: Rafal Ozieblo @ 2017-01-02  9:36 UTC (permalink / raw)
  To: Andrei Pistirica, netdev, linux-kernel, linux-arm-kernel, davem,
	nicolas.ferre, harinikatakamlinux, harini.katakam
  Cc: punnaia, michals, anirudh, boris.brezillon, alexandre.belloni,
	tbultel, richardcochran

> -----Original Message-----
> From: Rafal Ozieblo 
> Sent: 28 grudnia 2016 14:23
> Subject: RE: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
> 
> > +static void gem_ptp_tx_hwtstamp(struct macb *bp, struct sk_buff *skb,
> > +				int peer_ev)
> > +{
> > +	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
> > +	struct timespec64 ts;
> > +	u64 ns;
> > +
> > +	/* PTP Peer Event Frame packets */
> > +	if (peer_ev) {
> > +		ts.tv_sec = gem_readl(bp, PEFTSL);
> > +		ts.tv_nsec = gem_readl(bp, PEFTN);
> > +
> > +	/* PTP Event Frame packets */
> > +	} else {
> > +		ts.tv_sec = gem_readl(bp, EFTSL);
> > +		ts.tv_nsec = gem_readl(bp, EFTN);
> > +	}
> I'm wondering what is a difference between timestamp in transmit buffer descriptor (Word 2 and 3) and PTP Event Frame Transmitted Seconds/Nanoseconds Register (0x1E0, 0x1E4).
> 
According Cadence Hardware team:
"It is just that some customers prefer to have the time in the descriptors as that is provided per frame.
The registers are simply overwritten when a new event frame is transmitted/received and so software could miss it."
The question is are you sure that you read timestamp for current frame? (not for the next frame).

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-02  9:36 ` Rafal Ozieblo
@ 2017-01-02 11:31   ` Richard Cochran
  2017-01-02 11:43     ` Harini Katakam
  2017-01-02 14:47     ` Nicolas Ferre
  0 siblings, 2 replies; 19+ messages in thread
From: Richard Cochran @ 2017-01-02 11:31 UTC (permalink / raw)
  To: Rafal Ozieblo
  Cc: Andrei Pistirica, netdev, linux-kernel, linux-arm-kernel, davem,
	nicolas.ferre, harinikatakamlinux, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

On Mon, Jan 02, 2017 at 09:36:10AM +0000, Rafal Ozieblo wrote:
> According Cadence Hardware team:
> "It is just that some customers prefer to have the time in the descriptors as that is provided per frame.
> The registers are simply overwritten when a new event frame is transmitted/received and so software could miss it."
> The question is are you sure that you read timestamp for current frame? (not for the next frame).

AFAICT, having the time stamp in the descriptor is not universally
supported.  Looking at the Xilinx Zynq 7000 TRM, I can't find any
mention of this.

This Cadence IP core is a complete disaster.

Unless someone can tell us how this IP works in all of its
incarnations, this series is going nowhere.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-02 11:31   ` Richard Cochran
@ 2017-01-02 11:43     ` Harini Katakam
  2017-01-02 16:03       ` Richard Cochran
  2017-01-02 14:47     ` Nicolas Ferre
  1 sibling, 1 reply; 19+ messages in thread
From: Harini Katakam @ 2017-01-02 11:43 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Rafal Ozieblo, Andrei Pistirica, netdev, linux-kernel,
	linux-arm-kernel, davem, nicolas.ferre, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

Hi Richard,

On Mon, Jan 2, 2017 at 5:01 PM, Richard Cochran
<richardcochran@gmail.com> wrote:
> On Mon, Jan 02, 2017 at 09:36:10AM +0000, Rafal Ozieblo wrote:
>> According Cadence Hardware team:
>> "It is just that some customers prefer to have the time in the descriptors as that is provided per frame.
>> The registers are simply overwritten when a new event frame is transmitted/received and so software could miss it."
>> The question is are you sure that you read timestamp for current frame? (not for the next frame).
>
> AFAICT, having the time stamp in the descriptor is not universally
> supported.  Looking at the Xilinx Zynq 7000 TRM, I can't find any
> mention of this.
>
> This Cadence IP core is a complete disaster.
>
> Unless someone can tell us how this IP works in all of its
> incarnations, this series is going nowhere.

>From the revision history of Cadence spec, all versions starting
r1p02 have ability to include timestamp in descriptors.
For previous versions the event register is the only option.
But yes, there have been multiple enhancements and
bug fixes in this IP w.r.t PTP making each implementation
different.

Regards,
Harini

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-02 11:31   ` Richard Cochran
  2017-01-02 11:43     ` Harini Katakam
@ 2017-01-02 14:47     ` Nicolas Ferre
  2017-01-02 16:13       ` Richard Cochran
  1 sibling, 1 reply; 19+ messages in thread
From: Nicolas Ferre @ 2017-01-02 14:47 UTC (permalink / raw)
  To: Richard Cochran, Rafal Ozieblo
  Cc: Andrei Pistirica, netdev, linux-kernel, linux-arm-kernel, davem,
	harinikatakamlinux, harini.katakam, punnaia, michals, anirudh,
	boris.brezillon, alexandre.belloni, tbultel

Le 02/01/2017 à 12:31, Richard Cochran a écrit :
> On Mon, Jan 02, 2017 at 09:36:10AM +0000, Rafal Ozieblo wrote:
>> According Cadence Hardware team:
>> "It is just that some customers prefer to have the time in the descriptors as that is provided per frame.
>> The registers are simply overwritten when a new event frame is transmitted/received and so software could miss it."
>> The question is are you sure that you read timestamp for current frame? (not for the next frame).
> 
> AFAICT, having the time stamp in the descriptor is not universally
> supported.  Looking at the Xilinx Zynq 7000 TRM, I can't find any
> mention of this.

This is why I proposed to address options incrementally: without
timestamp support in descriptor (this patch series), then adding this
feature in another patch series.

Rafal, this is why Andrei noted that the case covered by this series is
not adapted to GEM-GXL and doesn't address the "timestamp in descriptor"
case.

> This Cadence IP core is a complete disaster.

Well, it evolved and propose several options to different SoC
integrators. This is not something unusual...
I suspect as well that some other network adapters have the same
weakness concerning PTP timestamp in single register as the early
revisions of this IP.

> Unless someone can tell us how this IP works in all of its
> incarnations, this series is going nowhere.

We're already as v4 (thanks to your fruitful contributions BTW) for this
series and will try to add features for other IP options & revisions
incrementally.
I suspect that Rafal tend to jump too quickly to the latest IP revisions
and add more options to this series: let's not try to pour too much
things into this code right now.

FYI, Andrei will be back online next week.

Regards,
-- 
Nicolas Ferre

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-02 11:43     ` Harini Katakam
@ 2017-01-02 16:03       ` Richard Cochran
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Cochran @ 2017-01-02 16:03 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Rafal Ozieblo, Andrei Pistirica, netdev, linux-kernel,
	linux-arm-kernel, davem, nicolas.ferre, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

On Mon, Jan 02, 2017 at 05:13:34PM +0530, Harini Katakam wrote:
> From the revision history of Cadence spec, all versions starting
> r1p02 have ability to include timestamp in descriptors.

So why not add code to read the version, hm?

> For previous versions the event register is the only option.

And is it true that the regsiters do not latch the time stamp?

If so, then the IP core is more than useless.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-02 14:47     ` Nicolas Ferre
@ 2017-01-02 16:13       ` Richard Cochran
  2017-01-03  5:06         ` Harini Katakam
  0 siblings, 1 reply; 19+ messages in thread
From: Richard Cochran @ 2017-01-02 16:13 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Rafal Ozieblo, Andrei Pistirica, netdev, linux-kernel,
	linux-arm-kernel, davem, harinikatakamlinux, harini.katakam,
	punnaia, michals, anirudh, boris.brezillon, alexandre.belloni,
	tbultel

On Mon, Jan 02, 2017 at 03:47:07PM +0100, Nicolas Ferre wrote:
> Le 02/01/2017 à 12:31, Richard Cochran a écrit :
> > This Cadence IP core is a complete disaster.
> 
> Well, it evolved and propose several options to different SoC
> integrators. This is not something unusual...
> I suspect as well that some other network adapters have the same
> weakness concerning PTP timestamp in single register as the early
> revisions of this IP.

It appears that this core can neither latch the time on read or write,
or even latch time stamps.  I have worked with many different PTP HW
implementations, even early ones like on the ixp4xx, and it is no
exaggeration to say that this one is uniquely broken.

> I suspect that Rafal tend to jump too quickly to the latest IP revisions
> and add more options to this series: let's not try to pour too much
> things into this code right now.

Why can't you check the IP version in the driver?

And is it really true that the registers don't latch the time stamps,
as Rafal said?  If so, then we cannot accept the non-descriptor driver
version, since it cannot possibly work correctly.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-02 16:13       ` Richard Cochran
@ 2017-01-03  5:06         ` Harini Katakam
  2017-01-03 10:20           ` Richard Cochran
                             ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Harini Katakam @ 2017-01-03  5:06 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Nicolas Ferre, Rafal Ozieblo, Andrei Pistirica, netdev,
	linux-kernel, linux-arm-kernel, davem, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

Hi Richard,

On Mon, Jan 2, 2017 at 9:43 PM, Richard Cochran
<richardcochran@gmail.com> wrote:
> On Mon, Jan 02, 2017 at 03:47:07PM +0100, Nicolas Ferre wrote:
>> Le 02/01/2017 à 12:31, Richard Cochran a écrit :
>> > This Cadence IP core is a complete disaster.
>>
>> Well, it evolved and propose several options to different SoC
>> integrators. This is not something unusual...
>> I suspect as well that some other network adapters have the same
>> weakness concerning PTP timestamp in single register as the early
>> revisions of this IP.
>
> It appears that this core can neither latch the time on read or write,
> or even latch time stamps.  I have worked with many different PTP HW
> implementations, even early ones like on the ixp4xx, and it is no
> exaggeration to say that this one is uniquely broken.
>
>> I suspect that Rafal tend to jump too quickly to the latest IP revisions
>> and add more options to this series: let's not try to pour too much
>> things into this code right now.
>
> Why can't you check the IP version in the driver?

There is an IP revision register but it would be probably be better
to rely on "caps" from the compatibility strings - to cover SoC
specific implementations. Also, when this extended BD is
added (with timestamp), additional words will need to be added
statically which will be consistent with Andrei's CONFIG_
checks.

>
> And is it really true that the registers don't latch the time stamps,
> as Rafal said?  If so, then we cannot accept the non-descriptor driver
> version, since it cannot possibly work correctly.
>

AFAIK, the two sets of registers only hold the timestamp till the next
event (or peer event) packet comes in.
I understand that it is not accurate - it is an initial version.

Regards,
Harini

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03  5:06         ` Harini Katakam
@ 2017-01-03 10:20           ` Richard Cochran
  2017-01-03 10:29           ` Richard Cochran
  2017-01-03 10:47           ` Rafal Ozieblo
  2 siblings, 0 replies; 19+ messages in thread
From: Richard Cochran @ 2017-01-03 10:20 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Nicolas Ferre, Rafal Ozieblo, Andrei Pistirica, netdev,
	linux-kernel, linux-arm-kernel, davem, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

On Tue, Jan 03, 2017 at 10:36:11AM +0530, Harini Katakam wrote:
> I understand that it is not accurate - it is an initial version.

No, it is not inaccurate at all, it is WRONG.

This means that time stamps will be randomly associated with PTP
network packets.  To the application, the protocol will appear to
work, but the time stamp information (and thus the synchronization)
will be wrong.

To me, this is unacceptable, and I will push back on this driver
getting merged.

[ In contrast, the descriptor based approach would be ok, afaict. ]

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03  5:06         ` Harini Katakam
  2017-01-03 10:20           ` Richard Cochran
@ 2017-01-03 10:29           ` Richard Cochran
  2017-01-03 10:48             ` Harini Katakam
  2017-01-03 10:47           ` Rafal Ozieblo
  2 siblings, 1 reply; 19+ messages in thread
From: Richard Cochran @ 2017-01-03 10:29 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Nicolas Ferre, Rafal Ozieblo, Andrei Pistirica, netdev,
	linux-kernel, linux-arm-kernel, davem, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

On Tue, Jan 03, 2017 at 10:36:11AM +0530, Harini Katakam wrote:
> I understand that it is not accurate - it is an initial version.

Why do you say, "it is an initial version?"

The Atmel device has this IP core burned in.  The core is hopelessly
broken, and it cannot be fixed in SW either, so what is your point?

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03  5:06         ` Harini Katakam
  2017-01-03 10:20           ` Richard Cochran
  2017-01-03 10:29           ` Richard Cochran
@ 2017-01-03 10:47           ` Rafal Ozieblo
  2017-01-03 11:14             ` Richard Cochran
  2017-01-03 14:22             ` Nicolas Ferre
  2 siblings, 2 replies; 19+ messages in thread
From: Rafal Ozieblo @ 2017-01-03 10:47 UTC (permalink / raw)
  To: Harini Katakam, Richard Cochran
  Cc: Nicolas Ferre, Andrei Pistirica, netdev, linux-kernel,
	linux-arm-kernel, davem, harini.katakam, punnaia, michals,
	anirudh, boris.brezillon, alexandre.belloni, tbultel

>From: Harini Katakam [mailto:harinikatakamlinux@gmail.com] 
>Sent: 3 stycznia 2017 06:06
>Subject: Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
>
>Hi Richard,
>
>On Mon, Jan 2, 2017 at 9:43 PM, Richard Cochran <richardcochran@gmail.com> wrote:
>> On Mon, Jan 02, 2017 at 03:47:07PM +0100, Nicolas Ferre wrote:
>>> Le 02/01/2017 à 12:31, Richard Cochran a écrit :
>>> > This Cadence IP core is a complete disaster.
>>>
>>> Well, it evolved and propose several options to different SoC 
>>> integrators. This is not something unusual...
>>> I suspect as well that some other network adapters have the same 
>>> weakness concerning PTP timestamp in single register as the early 
>>> revisions of this IP.
>>
>> It appears that this core can neither latch the time on read or write, 
>> or even latch time stamps.  I have worked with many different PTP HW 
>> implementations, even early ones like on the ixp4xx, and it is no 
>> exaggeration to say that this one is uniquely broken.
>>
>>> I suspect that Rafal tend to jump too quickly to the latest IP 
>>> revisions and add more options to this series: let's not try to pour 
>>> too much things into this code right now.
>>
>> Why can't you check the IP version in the driver?
>
>There is an IP revision register but it would be probably be better to rely on "caps" from the compatibility strings - to cover SoC specific implementations. Also, when this extended BD is added (with timestamp), additional words will need to be added statically which will be consistent with Andrei's CONFIG_ checks.
We can distinguish IP cores with and without PTP support by reading Design Configuration Register. But to distinguish IP cores with timestamps in buffer descriptors and which support only event registers, we can only check IP version by reading the revision ID register and base on that.
I agree with Harini, compatibility strings could be better. But we might end up with many different configuration in the future.
We could use only descriptor approach but there are many Atmel's cores on the market which support only event registers.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03 10:29           ` Richard Cochran
@ 2017-01-03 10:48             ` Harini Katakam
  0 siblings, 0 replies; 19+ messages in thread
From: Harini Katakam @ 2017-01-03 10:48 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Nicolas Ferre, Rafal Ozieblo, Andrei Pistirica, netdev,
	linux-kernel, linux-arm-kernel, davem, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

Hi Richard,

On Tue, Jan 3, 2017 at 3:59 PM, Richard Cochran
<richardcochran@gmail.com> wrote:
> On Tue, Jan 03, 2017 at 10:36:11AM +0530, Harini Katakam wrote:
>> I understand that it is not accurate - it is an initial version.
>
> Why do you say, "it is an initial version?"
>
> The Atmel device has this IP core burned in.  The core is hopelessly
> broken, and it cannot be fixed in SW either, so what is your point?
>

I'm sorry - I just meant that this was before many necessary
enhancements and fixes.
Newer SoCs including ZynqMP (for which the original series was sent)
have the descriptor based approach which is reliable.

Regards,
Harini

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03 10:47           ` Rafal Ozieblo
@ 2017-01-03 11:14             ` Richard Cochran
  2017-01-11 14:34               ` Andrei.Pistirica
  2017-01-03 14:22             ` Nicolas Ferre
  1 sibling, 1 reply; 19+ messages in thread
From: Richard Cochran @ 2017-01-03 11:14 UTC (permalink / raw)
  To: Rafal Ozieblo
  Cc: Harini Katakam, Nicolas Ferre, Andrei Pistirica, netdev,
	linux-kernel, linux-arm-kernel, davem, harini.katakam, punnaia,
	michals, anirudh, boris.brezillon, alexandre.belloni, tbultel

On Tue, Jan 03, 2017 at 10:47:56AM +0000, Rafal Ozieblo wrote:
> We could use only descriptor approach but there are many Atmel's cores on the market which support only event registers.

As I said in my other reply in this thread, the Atmel cores cannot
possibly be made to work correctly.

Sad, but true.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03 10:47           ` Rafal Ozieblo
  2017-01-03 11:14             ` Richard Cochran
@ 2017-01-03 14:22             ` Nicolas Ferre
  1 sibling, 0 replies; 19+ messages in thread
From: Nicolas Ferre @ 2017-01-03 14:22 UTC (permalink / raw)
  To: Rafal Ozieblo, Harini Katakam, Richard Cochran
  Cc: Andrei Pistirica, netdev, linux-kernel, linux-arm-kernel, davem,
	harini.katakam, punnaia, michals, anirudh, boris.brezillon,
	alexandre.belloni, tbultel

Le 03/01/2017 à 11:47, Rafal Ozieblo a écrit :
>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com] 
>> Sent: 3 stycznia 2017 06:06
>> Subject: Re: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
>>
>> Hi Richard,
>>
>> On Mon, Jan 2, 2017 at 9:43 PM, Richard Cochran <richardcochran@gmail.com> wrote:
>>> On Mon, Jan 02, 2017 at 03:47:07PM +0100, Nicolas Ferre wrote:
>>>> Le 02/01/2017 à 12:31, Richard Cochran a écrit :
>>>>> This Cadence IP core is a complete disaster.
>>>>
>>>> Well, it evolved and propose several options to different SoC 
>>>> integrators. This is not something unusual...
>>>> I suspect as well that some other network adapters have the same 
>>>> weakness concerning PTP timestamp in single register as the early 
>>>> revisions of this IP.
>>>
>>> It appears that this core can neither latch the time on read or write, 
>>> or even latch time stamps.  I have worked with many different PTP HW 
>>> implementations, even early ones like on the ixp4xx, and it is no 
>>> exaggeration to say that this one is uniquely broken.
>>>
>>>> I suspect that Rafal tend to jump too quickly to the latest IP 
>>>> revisions and add more options to this series: let's not try to pour 
>>>> too much things into this code right now.
>>>
>>> Why can't you check the IP version in the driver?
>>
>> There is an IP revision register but it would be probably be
>> better to rely on "caps" from the compatibility strings - to cover SoC specific
>> implementations. Also, when this extended BD is added (with timestamp),
>> additional words will need to be added statically which will be
>> consistent with Andrei's CONFIG_ checks.
> We can distinguish IP cores with and without PTP support by reading
> Design Configuration Register. But to distinguish IP cores with
> timestamps in buffer descriptors and which support only event
> registers, we can only check IP version by reading the revision ID
> register and base on that.
> I agree with Harini, compatibility strings could be better. But we
> might end up with many different configuration in the future.

Compatibility strings and associated configurations are cheap. It's not
a problem to have many different configurations and clearer for this
particular "composite" feature.

> We could use only descriptor approach but there are many Atmel's
> cores on the market which support only event registers.

Yes and once in silicon, it's hard to modify ;-)

Regards,
-- 
Nicolas Ferre

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
  2017-01-03 11:14             ` Richard Cochran
@ 2017-01-11 14:34               ` Andrei.Pistirica
  0 siblings, 0 replies; 19+ messages in thread
From: Andrei.Pistirica @ 2017-01-11 14:34 UTC (permalink / raw)
  To: richardcochran, rafalo, harinikatakamlinux, nicolas.ferre,
	harini.katakam
  Cc: netdev, linux-kernel, linux-arm-kernel, davem, punnaia, michals,
	anirudh, boris.brezillon, alexandre.belloni, tbultel

 
> On Tue, Jan 03, 2017 at 10:47:56AM +0000, Rafal Ozieblo wrote:
> > We could use only descriptor approach but there are many Atmel's cores
> on the market which support only event registers.
> 
> As I said in my other reply in this thread, the Atmel cores cannot possibly be
> made to work correctly.
> 
> Sad, but true.

In conscience, I will make a patch containing only the common code (just to benefit from this effort) and then Rafal can add the driver for the GXL version on top of it.
Everybody agrees with this?

Best regards,
Andrei

> 
> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2017-01-11 14:34 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-14 12:56 [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Andrei Pistirica
2016-12-14 12:56 ` [RFC PATCH net-next v4 2/2] macb: Enable 1588 support in SAMA5Dx platforms Andrei Pistirica
2016-12-20 16:38   ` Rafal Ozieblo
2016-12-28  8:15 ` [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM Richard Cochran
2016-12-28 13:23 ` Rafal Ozieblo
2017-01-02  9:36 ` Rafal Ozieblo
2017-01-02 11:31   ` Richard Cochran
2017-01-02 11:43     ` Harini Katakam
2017-01-02 16:03       ` Richard Cochran
2017-01-02 14:47     ` Nicolas Ferre
2017-01-02 16:13       ` Richard Cochran
2017-01-03  5:06         ` Harini Katakam
2017-01-03 10:20           ` Richard Cochran
2017-01-03 10:29           ` Richard Cochran
2017-01-03 10:48             ` Harini Katakam
2017-01-03 10:47           ` Rafal Ozieblo
2017-01-03 11:14             ` Richard Cochran
2017-01-11 14:34               ` Andrei.Pistirica
2017-01-03 14:22             ` Nicolas Ferre

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).