--- v15
+++ v11
@@ -1,18 +1,15 @@
This patch adds a driver for the hardware time stamping unit found on the
IXP465. The basic clock operations and an external trigger are implemented.
-Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: David S. Miller <davem@davemloft.net>
-Acked-by: John Stultz <john.stultz@linaro.org>
-Acked-by: Krzysztof Halasa <khc@pm.waw.pl>
+Signed-off-by: Richard Cochran <richard.cochran-3mrvs1K0uXizZXS1Dc/lvw@public.gmane.org>
+Acked-by: John Stultz <johnstul-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h | 78 ++++++
- drivers/net/arm/ixp4xx_eth.c | 195 ++++++++++++++-
+ drivers/net/arm/ixp4xx_eth.c | 192 ++++++++++++++-
drivers/ptp/Kconfig | 13 +
drivers/ptp/Makefile | 1 +
drivers/ptp/ptp_ixp46x.c | 332 +++++++++++++++++++++++++
- 5 files changed, 616 insertions(+), 3 deletions(-)
+ 5 files changed, 613 insertions(+), 3 deletions(-)
create mode 100644 arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
create mode 100644 drivers/ptp/ptp_ixp46x.c
@@ -101,7 +98,7 @@
+
+#endif
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
-index 9eb9b98..de51e84 100644
+index 9eb9b98..fa08c17 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -30,9 +30,12 @@
@@ -137,7 +134,7 @@
};
/* NPE message structure */
-@@ -246,6 +255,172 @@ static int ports_open;
+@@ -246,6 +255,169 @@ static int ports_open;
static struct port *npe_port_tab[MAX_NPES];
static struct dma_pool *dma_pool;
@@ -145,32 +142,29 @@
+ PTP_FILTER
+};
+
-+static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
-+{
-+ u8 *data = skb->data;
-+ unsigned int offset;
++static int match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seq)
++{
++ unsigned int type;
+ u16 *hi, *id;
-+ u32 lo;
-+
-+ if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
-+ return 0;
-+
-+ offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
-+
-+ if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid))
-+ return 0;
-+
-+ hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID);
-+ id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
-+
-+ memcpy(&lo, &hi[1], sizeof(lo));
-+
-+ return (uid_hi == ntohs(*hi) &&
-+ uid_lo == ntohl(lo) &&
-+ seqid == ntohs(*id));
-+}
-+
-+static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb)
++ u8 *lo, *data = skb->data;
++
++ type = sk_run_filter(skb, ptp_filter);
++
++ if (PTP_CLASS_V1_IPV4 == type) {
++
++ id = (u16 *)(data + 42 + 30);
++ hi = (u16 *)(data + 42 + 22);
++ lo = data + 42 + 24;
++
++ return (uid_hi == *hi &&
++ 0 == memcmp(&uid_lo, lo, sizeof(uid_lo)) &&
++ seq == *id);
++ }
++
++ return 0;
++}
++
++static void do_rx_timestamp(struct port *port, struct sk_buff *skb)
+{
+ struct skb_shared_hwtstamps *shhwtstamps;
+ struct ixp46x_ts_regs *regs;
@@ -196,7 +190,7 @@
+ uid = hi & 0xffff;
+ seq = (hi >> 16) & 0xffff;
+
-+ if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq)))
++ if (!match(skb, htons(uid), htonl(lo), htons(seq)))
+ goto out;
+
+ lo = __raw_readl(®s->channel[ch].rx_snap_lo);
@@ -212,7 +206,7 @@
+ __raw_writel(RX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event);
+}
+
-+static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
++static void do_tx_timestamp(struct port *port, struct sk_buff *skb)
+{
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct ixp46x_ts_regs *regs;
@@ -310,15 +304,15 @@
static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
int write, u16 cmd)
-@@ -573,6 +748,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
+@@ -573,6 +745,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
debug_pkt(dev, "eth_poll", skb->data, skb->len);
-+ ixp_rx_timestamp(port, skb);
++ do_rx_timestamp(port, skb);
skb->protocol = eth_type_trans(skb, dev);
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
-@@ -679,14 +855,12 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -679,14 +852,12 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
@@ -334,12 +328,12 @@
kfree(mem);
#endif
dev->stats.tx_dropped++;
-@@ -728,6 +902,13 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -728,6 +899,13 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
#if DEBUG_TX
printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name);
#endif
+
-+ ixp_tx_timestamp(port, skb);
++ do_tx_timestamp(port, skb);
+ skb_tx_timestamp(skb);
+
+#ifndef __ARMEB__
@@ -348,7 +342,7 @@
return NETDEV_TX_OK;
}
-@@ -783,6 +964,9 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+@@ -783,6 +961,9 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
if (!netif_running(dev))
return -EINVAL;
@@ -358,7 +352,7 @@
return phy_mii_ioctl(port->phydev, req, cmd);
}
-@@ -1171,6 +1355,11 @@ static int __devinit eth_init_one(struct platform_device *pdev)
+@@ -1171,6 +1352,11 @@ static int __devinit eth_init_one(struct platform_device *pdev)
char phy_id[MII_BUS_ID_SIZE + 3];
int err;
@@ -403,7 +397,7 @@
+obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c
new file mode 100644
-index 0000000..803d665
+index 0000000..e28b416
--- /dev/null
+++ b/drivers/ptp/ptp_ixp46x.c
@@ -0,0 +1,332 @@
@@ -460,7 +454,7 @@
+ * Register access functions
+ */
+
-+static u64 ixp_systime_read(struct ixp46x_ts_regs *regs)
++static u64 sys_time_read(struct ixp46x_ts_regs *regs)
+{
+ u64 ns;
+ u32 lo, hi;
@@ -475,7 +469,7 @@
+ return ns;
+}
+
-+static void ixp_systime_write(struct ixp46x_ts_regs *regs, u64 ns)
++static void sys_time_write(struct ixp46x_ts_regs *regs, u64 ns)
+{
+ u32 hi, lo;
+
@@ -575,9 +569,9 @@
+
+ spin_lock_irqsave(®ister_lock, flags);
+
-+ now = ixp_systime_read(regs);
++ now = sys_time_read(regs);
+ now += delta;
-+ ixp_systime_write(regs, now);
++ sys_time_write(regs, now);
+
+ spin_unlock_irqrestore(®ister_lock, flags);
+
@@ -594,7 +588,7 @@
+
+ spin_lock_irqsave(®ister_lock, flags);
+
-+ ns = ixp_systime_read(regs);
++ ns = sys_time_read(regs);
+
+ spin_unlock_irqrestore(®ister_lock, flags);
+
@@ -616,7 +610,7 @@
+
+ spin_lock_irqsave(®ister_lock, flags);
+
-+ ixp_systime_write(regs, ns);
++ sys_time_write(regs, ns);
+
+ spin_unlock_irqrestore(®ister_lock, flags);
+
@@ -676,7 +670,7 @@
+ if (NO_IRQ == irq)
+ return NO_IRQ;
+
-+ if (irq_set_irq_type(irq, IRQF_TRIGGER_FALLING)) {
++ if (set_irq_type(irq, IRQF_TRIGGER_FALLING)) {
+ pr_err("cannot set trigger type for irq %d\n", irq);
+ return NO_IRQ;
+ }
@@ -701,7 +695,7 @@
+ if (!cpu_is_ixp46x())
+ return -ENODEV;
+
-+ ixp_clock.regs =
++ ixp_clock.regs =
+ (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
+
+ ixp_clock.caps = ptp_ixp_caps;
@@ -736,7 +730,7 @@
+module_init(ptp_ixp_init);
+module_exit(ptp_ixp_exit);
+
-+MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
++MODULE_AUTHOR("Richard Cochran <richard.cochran-3mrvs1K0uXizZXS1Dc/lvw@public.gmane.org>");
+MODULE_DESCRIPTION("PTP clock using the IXP46X timer");
+MODULE_LICENSE("GPL");
--