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

From: Harini Katakam
Date: Fri Sep 11 2015 - 04:13:41 EST


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 linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/