[RFC PATCH 2/3] net: macb: Add support for 1588 for Zynq Ultrascale+ MPSoC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Cadence GEM in Zynq Ultrascale+ MPSoC supports 1588 and provides a
102 bit time counter with 48 bits for seconds, 30 bits for nsecs and
24 bits for sub-nsecs. The timestamp is made available to the SW through
registers as well as (more precisely) through upper two words in
an extended BD.

This patch does the following:
- Adds MACB_CAPS_TSU in zynqmp_config.
- Registers to ptp clock framework (after checking for timestamp support in
  IP and capability in config).
- TX BD and RX BD control registers are written to populate timestamp in
  extended BD words.
- Timer initialization is done by writing time of day to the timer counter.
- ns increment register is programmed as NS_PER_SEC/TSU_CLK.
  For a 24 bit subns precision, the subns increment equals
  remainder of (NS_PER_SEC/TSU_CLK) * (2^24).
  TSU (Time stamp unit) clock is obtained by the  driver from devicetree.
- HW time stamp capabilities are advertised via ethtool and macb ioctl is
  updated accordingly.
- For all PTP event frames, nanoseconds and the lower 5 bits of seconds are
  obtained from the BD. This offers a precise timestamp. The upper bits
  (which dont vary between consecutive packets) 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. In order to be as precise as possible,
  nsecs counter is read again if secs has incremented during the counter read.
- Frequency adjustment is not directly supported by this IP.
  addend is the initial value ns increment and similarly addendesub.
  The ppb (parts per billion) provided is used as
  ns_incr = addend +/- (ppb/rate).
  Similarly the remainder of the above is used to populate subns increment.
  In case the ppb requested is negative AND subns adjustment greater than
  the addendsub, ns_incr is reduced by 1 and subns_incr is adjusted in
  positive accordingly.

Signed-off-by: Harini Katakam <harinik@xxxxxxxxxx>:
---
 drivers/net/ethernet/cadence/macb.c |  372 ++++++++++++++++++++++++++++++++++-
 drivers/net/ethernet/cadence/macb.h |   64 ++++++
 2 files changed, 428 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index bb2932c..b531008 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -30,6 +30,8 @@
 #include <linux/of_device.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
 
 #include "macb.h"
 
@@ -56,6 +58,9 @@
 
 #define GEM_MTU_MIN_SIZE	68
 
+#define GEM_TX_PTPHDR_OFFSET	42
+#define GEM_RX_PTPHDR_OFFSET	28
+
 /*
  * Graceful stop timeouts in us. We should allow up to
  * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
@@ -165,6 +170,9 @@ static void macb_set_hwaddr(struct macb *bp)
 	top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
 	macb_or_gem_writel(bp, SA1T, top);
 
+	gem_writel(bp, RXPTPUNI, bottom);
+	gem_writel(bp, TXPTPUNI, bottom);
+
 	/* Clear unused address register sets */
 	macb_or_gem_writel(bp, SA2B, 0);
 	macb_or_gem_writel(bp, SA2T, 0);
@@ -653,6 +661,40 @@ static void macb_tx_error_task(struct work_struct *work)
 	spin_unlock_irqrestore(&bp->lock, flags);
 }
 
+static inline void macb_handle_txtstamp(struct macb *bp, struct sk_buff *skb,
+					struct macb_dma_desc *desc)
+{
+	u32 ts_s, ts_ns;
+	u8 msg_type;
+
+	skb_copy_from_linear_data_offset(skb, GEM_TX_PTPHDR_OFFSET,
+					 &msg_type, 1);
+
+	/* Bit[32:6] of TS secs from register
+	 * Bit[5:0] of TS secs from BD
+	 * TS nano secs is available in BD
+	 */
+	if (msg_type & 0x2) {
+		/* PTP Peer Event Frame packets */
+		ts_s = (gem_readl(bp, 1588PEERTXSEC) & GEM_SEC_MASK) |
+		       ((desc->tsl >> GEM_TSL_SEC_RS) |
+		       (desc->tsh << GEM_TSH_SEC_LS));
+		ts_ns = desc->tsl & GEM_TSL_NSEC_MASK;
+	} else {
+		/* PTP Event Frame packets */
+		ts_s = (gem_readl(bp, 1588TXSEC) & GEM_SEC_MASK) |
+		       ((desc->tsl >> GEM_TSL_SEC_RS) |
+		       (desc->tsh << GEM_TSH_SEC_LS));
+		ts_ns = desc->tsl & GEM_TSL_NSEC_MASK;
+	}
+
+	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+
+	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime((ts_s * NS_PER_SEC) + ts_ns);
+	skb_tstamp_tx(skb, skb_hwtstamps(skb));
+}
+
 static void macb_tx_interrupt(struct macb_queue *queue)
 {
 	unsigned int tail;
@@ -703,6 +745,10 @@ static void macb_tx_interrupt(struct macb_queue *queue)
 				bp->stats.tx_bytes += skb->len;
 			}
 
+#ifdef CONFIG_MACB_EXT_BD
+			if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+				macb_handle_txtstamp(bp, skb, desc);
+#endif
 			/* Now we can safely release resources */
 			macb_tx_unmap(bp, tx_skb);
 
@@ -796,6 +842,39 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
 	 */
 }
 
+static inline void macb_handle_rxtstamp(struct macb *bp, struct sk_buff *skb,
+					struct macb_dma_desc *desc)
+{
+	u8 msg_type;
+	u32 ts_ns, ts_s;
+
+	skb_copy_from_linear_data_offset(skb, GEM_RX_PTPHDR_OFFSET,
+					 &msg_type, 1);
+
+	/* Bit[32:6] of TS secs from register
+	 * Bit[5:0] of TS secs from BD
+	 * TS nano secs is available in BD
+	 */
+	if (msg_type & 0x2) {
+		/* PTP Peer Event Frame packets */
+		ts_s = (gem_readl(bp, 1588PEERRXSEC) & GEM_SEC_MASK) |
+			((desc->tsl >> GEM_TSL_SEC_RS) |
+			(desc->tsh << GEM_TSH_SEC_LS));
+		ts_ns = desc->tsl & GEM_TSL_NSEC_MASK;
+	} else {
+		/* PTP Event Frame packets */
+		ts_s = (gem_readl(bp, 1588RXSEC) & GEM_SEC_MASK) |
+			((desc->tsl >> GEM_TSL_SEC_RS) |
+			(desc->tsh << GEM_TSH_SEC_LS));
+		ts_ns = desc->tsl & GEM_TSL_NSEC_MASK;
+	}
+
+	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+
+	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime((ts_s * NS_PER_SEC) + ts_ns);
+}
+
 static int gem_rx(struct macb *bp, int budget)
 {
 	unsigned int		len;
@@ -847,6 +926,12 @@ static int gem_rx(struct macb *bp, int budget)
 				 bp->rx_buffer_size, DMA_FROM_DEVICE);
 
 		skb->protocol = eth_type_trans(skb, bp->dev);
+
+#ifdef CONFIG_MACB_EXT_BD
+		if (addr & GEM_RX_TS_MASK)
+			macb_handle_rxtstamp(bp, skb, desc);
+#endif
+
 		skb_checksum_none_assert(skb);
 		if (bp->dev->features & NETIF_F_RXCSUM &&
 		    !(bp->dev->flags & IFF_PROMISC) &&
@@ -1636,6 +1721,193 @@ static u32 macb_dbw(struct macb *bp)
 	}
 }
 
+static inline void macb_ptp_read(struct macb *bp, struct timespec *ts)
+{
+	ts->tv_sec = gem_readl(bp, 1588S);
+	ts->tv_nsec = gem_readl(bp, 1588NS);
+
+	if (ts->tv_sec < gem_readl(bp, 1588S))
+		ts->tv_nsec = gem_readl(bp, 1588NS);
+}
+
+static inline void macb_ptp_write(struct macb *bp, const struct timespec *ts)
+{
+	gem_writel(bp, 1588S, ts->tv_sec);
+	gem_writel(bp, 1588NS, ts->tv_nsec);
+}
+
+static int macb_ptp_enable(struct ptp_clock_info *ptp,
+			   struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static void macb_ptp_close(struct macb *bp)
+{
+	/* Clear the time counters */
+	gem_writel(bp, 1588NS, 0);
+	gem_writel(bp, 1588S, 0);
+	gem_writel(bp, 1588ADJ, 0);
+	gem_writel(bp, 1588INCR, 0);
+
+	ptp_clock_unregister(bp->ptp_clock);
+}
+
+static int macb_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+
+	macb_ptp_read(bp, ts);
+
+	return 0;
+}
+
+static int macb_ptp_settime(struct ptp_clock_info *ptp,
+			    const struct timespec *ts)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+
+	macb_ptp_write(bp, ts);
+
+	return 0;
+}
+
+static int macb_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+	struct timespec now, then = ns_to_timespec(delta);
+	u32 adj, sign = 0;
+
+	if (delta < 0) {
+		delta = -delta;
+		sign = 1;
+	}
+
+	if (delta > 0x3FFFFFFF) {
+		macb_ptp_read(bp, &now);
+
+		if (sign)
+			now = timespec_sub(now, then);
+		else
+			now = timespec_add(now, then);
+
+		macb_ptp_write(bp, (const struct timespec *)&now);
+	} else {
+		adj = delta;
+		if (sign)
+			adj |= GEM_BIT(ADDSUB);
+
+		gem_writel(bp, 1588ADJ, adj);
+	}
+
+	return 0;
+}
+
+static int macb_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_caps);
+	unsigned long rate = bp->tsu_clk;
+	u64 adjsub;
+	u32 addend, diff;
+	u32 diffsub, addendsub;
+	bool neg_adj = false;
+	u32 subnsreg, rem;
+
+	if (ppb < 0) {
+		neg_adj = true;
+		ppb = -ppb;
+	}
+
+	addend = bp->ns_incr;
+	addendsub = bp->subns_incr;
+
+	diff = div_u64_rem(ppb, rate, &rem);
+	addend = neg_adj ? addend - diff : addend + diff;
+
+	if (rem) {
+		adjsub = rem;
+		/* Multiple by 2^24 as subns field is 24 bits */
+		adjsub = adjsub << 24;
+
+		diffsub = div_u64(adjsub, rate);
+	} else {
+		diffsub = 0;
+	}
+
+	if (neg_adj && (diffsub > addendsub)) {
+		addend -= 1;
+		rem = (NS_PER_SEC - rem);
+		neg_adj = false;
+
+		adjsub = rem;
+		adjsub = adjsub << 24;
+		diffsub = div_u64(adjsub, rate);
+	}
+
+	addendsub = neg_adj ? addendsub - diffsub : addendsub + diffsub;
+	/* RegBit[15:0] = Subns[23:8]; RegBit[31:24] = Subns[7:0] */
+	subnsreg = ((addendsub & GEM_SUBNSINCL_MASK) << GEM_SUBNSINCL_SHFT) |
+		   ((addendsub & GEM_SUBNSINCH_MASK) >> GEM_SUBNSINCH_SHFT);
+
+	gem_writel(bp, 1588INCRSUBNS, subnsreg);
+	gem_writel(bp, 1588INCR, GEM_BF(NSINCR, addend));
+
+	return 0;
+}
+
+static void macb_ptp_init(struct macb *bp)
+{
+	struct timespec now;
+	unsigned long rate;
+	u32 subnsreg, rem = 0;
+	u64 adj;
+
+	bp->ptp_caps.owner = THIS_MODULE;
+	bp->ptp_caps.max_adj = 250000000;
+	bp->ptp_caps.n_alarm = 0;
+	bp->ptp_caps.n_ext_ts = 0;
+	bp->ptp_caps.n_per_out = 0;
+	bp->ptp_caps.pps = 0;
+	bp->ptp_caps.adjtime = macb_ptp_adjtime;
+	bp->ptp_caps.gettime = macb_ptp_gettime;
+	bp->ptp_caps.settime = macb_ptp_settime;
+	bp->ptp_caps.enable = macb_ptp_enable;
+	bp->ptp_caps.adjfreq = macb_ptp_adjfreq;
+
+	rate = bp->tsu_clk;
+
+	getnstimeofday(&now);
+	gem_writel(bp, 1588SMSB, 0);
+	macb_ptp_write(bp, (const struct timespec *)&now);
+
+	bp->ns_incr = div_u64_rem(NS_PER_SEC, rate, &rem);
+	if (rem) {
+		adj = rem;
+		/* Multiply by 2^24 as subns register is 24 bits */
+		adj = adj << 24;
+
+		bp->subns_incr = div_u64(adj, rate);
+	} else {
+		bp->subns_incr = 0;
+	}
+
+	/* RegBit[15:0] = Subns[23:8]; RegBit[31:24] = Subns[7:0] */
+	subnsreg = ((bp->subns_incr & GEM_SUBNSINCL_MASK)
+		    << GEM_SUBNSINCL_SHFT) |
+		   ((bp->subns_incr & GEM_SUBNSINCH_MASK)
+		    >> GEM_SUBNSINCH_SHFT);
+	gem_writel(bp, 1588INCRSUBNS, subnsreg);
+	gem_writel(bp, 1588INCR, bp->ns_incr);
+	gem_writel(bp, 1588ADJ, 0);
+
+	bp->ptp_clock = ptp_clock_register(&bp->ptp_caps, &bp->pdev->dev);
+	if (IS_ERR(bp->ptp_clock)) {
+		bp->ptp_clock = NULL;
+		netdev_err(bp->dev, "ptp_clock_register failed\n");
+	}
+	bp->phc_index = ptp_clock_index(bp->ptp_clock);
+}
+
 /*
  * Configure the receive DMA engine
  * - use the correct receive buffer size
@@ -1686,6 +1958,7 @@ static void macb_init_hw(struct macb *bp)
 	macb_set_hwaddr(bp);
 
 	config = macb_mdc_clk_div(bp);
+	config |= macb_readl(bp, NCFGR) & (3 << 21);
 	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data aligned */
 	config |= MACB_BIT(PAE);		/* PAuse Enable */
 	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
@@ -1709,6 +1982,18 @@ static void macb_init_hw(struct macb *bp)
 	if (bp->caps & MACB_CAPS_JUMBO)
 		bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
 
+	gem_writel(bp, TXBDCNTRL,
+		   (gem_readl(bp, TXBDCNTRL) & ~(GEM_TXBDCNTRL_MODE_ALL)) |
+		   GEM_TXBDCNTRL_MODE_PTP_EVNT);
+	gem_writel(bp, RXBDCNTRL,
+		   (gem_readl(bp, RXBDCNTRL) & ~(GEM_RXBDCNTRL_MODE_ALL)) |
+		   GEM_RXBDCNTRL_MODE_PTP_EVNT);
+
+	if ((gem_readl(bp, DCFG5) & GEM_BIT(TSU)) &&
+	    (bp->caps & MACB_CAPS_TSU)) {
+		macb_ptp_init(bp);
+	}
+
 	macb_configure_dma(bp);
 
 	/* Initialize TX and RX buffers */
@@ -1724,7 +2009,8 @@ static void macb_init_hw(struct macb *bp)
 	}
 
 	/* Enable TX and RX */
-	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
+	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE) |
+		    MACB_BIT(PTPUNI));
 }
 
 /*
@@ -1903,6 +2189,7 @@ static int macb_close(struct net_device *dev)
 
 	spin_lock_irqsave(&bp->lock, flags);
 	macb_reset_hw(bp);
+	macb_ptp_close(bp);
 	netif_carrier_off(dev);
 	spin_unlock_irqrestore(&bp->lock, flags);
 
@@ -2130,6 +2417,23 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 	}
 }
 
+static int macb_get_ts_info(struct net_device *dev,
+			    struct ethtool_ts_info *info)
+{
+	struct macb *bp = netdev_priv(dev);
+
+	info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+				SOF_TIMESTAMPING_RX_HARDWARE |
+				SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->phc_index = bp->phc_index;
+	info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+			 (1 << HWTSTAMP_TX_ON);
+	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+			   (1 << HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
 static const struct ethtool_ops macb_ethtool_ops = {
 	.get_settings		= macb_get_settings,
 	.set_settings		= macb_set_settings,
@@ -2145,24 +2449,74 @@ 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,
 };
 
+static int macb_hwtstamp_ioctl(struct net_device *dev,
+			       struct ifreq *ifr, int cmd)
+{
+	struct hwtstamp_config config;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	if ((config.tx_type != HWTSTAMP_TX_OFF) &&
+	    (config.tx_type != HWTSTAMP_TX_ON))
+		return -ERANGE;
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	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_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	config.tx_type = HWTSTAMP_TX_ON;
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct macb *bp = netdev_priv(dev);
 	struct phy_device *phydev = bp->phy_dev;
 
-	if (!netif_running(dev))
-		return -EINVAL;
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+			return macb_hwtstamp_ioctl(dev, rq, cmd);
 
-	if (!phydev)
-		return -ENODEV;
+	default:
+		if (!netif_running(dev))
+			return -EINVAL;
+
+		if (!phydev)
+			return -ENODEV;
 
-	return phy_mii_ioctl(phydev, rq, cmd);
+		return phy_mii_ioctl(phydev, rq, cmd);
+	}
 }
 
 static int macb_set_features(struct net_device *netdev,
@@ -2778,7 +3132,7 @@ static const struct macb_config emac_config = {
 
 
 static const struct macb_config zynqmp_config = {
-	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO,
+	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO | MACB_CAPS_TSU,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
@@ -2885,6 +3239,8 @@ static int macb_probe(struct platform_device *pdev)
 	if (macb_config)
 		bp->jumbo_max_len = macb_config->jumbo_max_len;
 
+	of_property_read_u32(pdev->dev.of_node, "tsu-clk", &bp->tsu_clk);
+
 	spin_lock_init(&bp->lock);
 
 	/* setup capabilities */
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 58c9870..16edad4 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -82,6 +82,8 @@
 #define GEM_SA3T		0x009C /* Specific3 Top */
 #define GEM_SA4B		0x00A0 /* Specific4 Bottom */
 #define GEM_SA4T		0x00A4 /* Specific4 Top */
+#define GEM_RXPTPUNI		0x00D4 /* PTP RX Unicast address */
+#define GEM_TXPTPUNI		0x00D8 /* PTP TX Unicast address */
 #define GEM_OTX			0x0100 /* Octets transmitted */
 #define GEM_OCTTXL		0x0100 /* Octets transmitted [31:0] */
 #define GEM_OCTTXH		0x0104 /* Octets transmitted [47:32] */
@@ -129,6 +131,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_1588INCRSUBNS	0x01BC /* 1588 timer sub nsec increment */
+#define GEM_1588SMSB		0x01C0 /* 1588 timer seconds register[47:32] */
+#define GEM_1588S		0x01D0 /* 1588 timer seconds register[31:0] */
+#define GEM_1588NS		0x01D4 /* 1588 timer nano seconds register */
+#define GEM_1588ADJ		0x01D8 /* 1588 timer adjust register */
+#define GEM_1588INCR		0x01DC /* 1588 timer increment register */
+#define GEM_1588TXSEC		0x01E0 /* PTP event TX timestamp secs */
+#define GEM_1588TXNSEC		0x01E4 /* PTP event TX timestamp nsecs */
+#define GEM_1588RXSEC		0x01E8 /* PTP event RX timestamp secs */
+#define GEM_1588RXNSEC		0x01EC /* PTP event RX timestamp nsecs */
+#define GEM_1588PEERTXSEC	0x01F0 /* PTP peer event TX timestamp secs */
+#define GEM_1588PEERTXNSEC	0x01F4 /* PTP peer event TX timestamp nsecs */
+#define GEM_1588PEERRXSEC	0x01F8 /* PTP peer event RX timestamp secs */
+#define GEM_1588PEERRXNSEC	0x01FC /* PTP peer event RX timestamp nsecs */
 #define GEM_DCFG1		0x0280 /* Design Config 1 */
 #define GEM_DCFG2		0x0284 /* Design Config 2 */
 #define GEM_DCFG3		0x0288 /* Design Config 3 */
@@ -136,6 +152,8 @@
 #define GEM_DCFG5		0x0290 /* Design Config 5 */
 #define GEM_DCFG6		0x0294 /* Design Config 6 */
 #define GEM_DCFG7		0x0298 /* Design Config 7 */
+#define GEM_TXBDCNTRL		0x04CC /* TX descriptor control */
+#define GEM_RXBDCNTRL		0x04D0 /* RX descriptor control */
 
 #define GEM_ISR(hw_q)		(0x0400 + ((hw_q) << 2))
 #define GEM_TBQP(hw_q)		(0x0440 + ((hw_q) << 2))
@@ -171,6 +189,8 @@
 #define MACB_NCR_TPF_SIZE	1
 #define MACB_TZQ_OFFSET		12 /* Transmit zero quantum pause frame */
 #define MACB_TZQ_SIZE		1
+#define MACB_PTPUNI_OFFSET			20
+#define MACB_PTPUNI_SIZE			1
 
 /* Bitfields in NCFGR */
 #define MACB_SPD_OFFSET		0 /* Speed */
@@ -374,6 +394,34 @@
 #define GEM_TX_PKT_BUFF_OFFSET			21
 #define GEM_TX_PKT_BUFF_SIZE			1
 
+/* Bitfields in DCFG5. */
+#define GEM_TSU_OFFSET				8
+#define GEM_TSU_SIZE				1
+
+/* Bitfields in 1588INCRSUBNS */
+#define GEM_SUBNSINCL_SHFT			24
+#define GEM_SUBNSINCL_MASK			0xFF
+#define GEM_SUBNSINCH_SHFT			8
+#define GEM_SUBNSINCH_MASK			0xFFFF00
+
+/* Bitfields in 1588INCRNS */
+#define GEM_NSINCR_OFFSET			0
+#define GEM_NSINCR_SIZE				8
+
+/* Bitfields in 1588ADJ */
+#define GEM_ADDSUB_OFFSET			31
+#define GEM_ADDSUB_SIZE				1
+
+/* Bitfields in TXBDCNTRL */
+#define GEM_TXBDCNTRL_MODE_ALL			0x00000030
+#define GEM_TXBDCNTRL_MODE_PTP_EVNT		0x00000010
+#define GEM_TXBDCNTRL_MODE_PTP_ALL		0x00000020
+
+/* Bitfields in RXBDCNTRL */
+#define GEM_RXBDCNTRL_MODE_ALL			0x00000030
+#define GEM_RXBDCNTRL_MODE_PTP_EVNT		0x00000010
+#define GEM_RXBDCNTRL_MODE_PTP_ALL		0x00000020
+
 /* Constants for CLK */
 #define MACB_CLK_DIV8				0
 #define MACB_CLK_DIV16				1
@@ -404,6 +452,8 @@
 #define MACB_CAPS_SG_DISABLED			0x40000000
 #define MACB_CAPS_MACB_IS_GEM			0x80000000
 #define MACB_CAPS_JUMBO				0x00000010
+#define MACB_CAPS_TSU				0x00000020
+#define NS_PER_SEC				1000000000ULL
 
 /* Bit manipulation macros */
 #define MACB_BIT(name)					\
@@ -550,6 +600,11 @@ struct macb_dma_desc {
 #define GEM_TX_FRMLEN_OFFSET			0
 #define GEM_TX_FRMLEN_SIZE			14
 
+#define GEM_SEC_MASK		0xFFFFFFC0
+#define GEM_TSL_SEC_RS		30
+#define GEM_TSH_SEC_LS		2
+#define GEM_TSL_NSEC_MASK	0x3FFFFFFF
+
 /* Buffer descriptor constants */
 #define GEM_RX_CSUM_NONE			0
 #define GEM_RX_CSUM_IP_ONLY			1
@@ -559,6 +614,8 @@ struct macb_dma_desc {
 /* limit RX checksum offload to TCP and UDP packets */
 #define GEM_RX_CSUM_CHECKED_MASK		2
 
+#define GEM_RX_TS_MASK				0x4
+
 /* struct macb_tx_skb - data about an skb which is being transmitted
  * @skb: skb currently being transmitted, only set for the last buffer
  *       of the frame
@@ -843,6 +900,13 @@ struct macb {
 
 	unsigned int		rx_frm_len_mask;
 	unsigned int		jumbo_max_len;
+	unsigned int		tsu_clk;
+	struct ptp_clock	*ptp_clock;
+	struct ptp_clock_info	ptp_caps;
+	int			rx_hwtstamp_filter;
+	int			phc_index;
+	unsigned int		ns_incr;
+	unsigned int		subns_incr;
 };
 
 static inline bool macb_is_gem(struct macb *bp)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux