Root/target/linux/coldfire/patches/020-Add-dual-FEC-1588-timer-support.patch

1From 67d56859d24864af530506c76523f0fc3c5cb502 Mon Sep 17 00:00:00 2001
2From: Alison Wang <b18965@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:44 +0800
4Subject: [PATCH 20/52] Add dual FEC 1588 timer support
5
6Add Modelo dual FEC 1588 function with IXXXAT statck.
7
8Signed-off-by: Alison Wang <b18965@freescale.com>
9---
10 drivers/net/Kconfig | 6 +
11 drivers/net/Makefile | 3 +
12 drivers/net/fec.c | 153 ++++++++++++-
13 drivers/net/fec.h | 25 ++
14 drivers/net/fec_1588.c | 626 ++++++++++++++++++++++++++++++++++++++++++++++++
15 drivers/net/fec_1588.h | 195 +++++++++++++++
16 6 files changed, 1006 insertions(+), 2 deletions(-)
17 create mode 100644 drivers/net/fec_1588.c
18 create mode 100644 drivers/net/fec_1588.h
19
20--- a/drivers/net/Kconfig
21+++ b/drivers/net/Kconfig
22@@ -1958,6 +1958,12 @@ config FEC2
23       Say Y here if you want to use the second built-in 10/100 Fast
24       ethernet controller on some Motorola ColdFire processors.
25 
26+config FEC_1588
27+ bool "Enable 1588 interface(on some ColdFire designs)"
28+ depends on M5441X && FEC
29+ help
30+ Say Y here if 1588 function is enabled.
31+
32 config FEC_548x
33     tristate "MCF547x/MCF548x Fast Ethernet Controller support"
34     depends on M547X_8X
35--- a/drivers/net/Makefile
36+++ b/drivers/net/Makefile
37@@ -123,6 +123,9 @@ obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
38 obj-$(CONFIG_HP100) += hp100.o
39 obj-$(CONFIG_SMC9194) += smc9194.o
40 obj-$(CONFIG_FEC) += fec.o
41+ifeq ($(CONFIG_FEC_1588), y)
42+obj-$(CONFIG_FEC) += fec_1588.o
43+endif
44 obj-$(CONFIG_FEC_548x) += fec_m547x.o
45 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
46 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
47--- a/drivers/net/fec.c
48+++ b/drivers/net/fec.c
49@@ -53,6 +53,7 @@
50 #endif
51 
52 #include "fec.h"
53+#include "fec_1588.h"
54 
55 #if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
56 #define FEC_ALIGNMENT 0xf
57@@ -135,8 +136,15 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet
58 #define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
59 #define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
60 #define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
61+#define FEC_ENET_TS_AVAIL ((uint)0x00010000)
62+#define FEC_ENET_TS_TIMER ((uint)0x00008000)
63 
64+#if defined(CONFIG_FEC_1588)
65+#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | \
66+ FEC_ENET_TS_AVAIL | FEC_ENET_TS_TIMER)
67+#else
68 #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
69+#endif
70 
71 /* The FEC stores dest/src/type, data, and checksum for receive packets.
72  */
73@@ -209,6 +217,10 @@ struct fec_enet_private {
74     int link;
75     int full_duplex;
76     struct completion mdio_done;
77+#ifdef CONFIG_FEC_1588
78+ struct fec_ptp_private *ptp_priv;
79+ uint ptimer_present;
80+#endif
81 };
82 
83 static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
84@@ -252,6 +264,9 @@ fec_enet_start_xmit(struct sk_buff *skb,
85     struct bufdesc *bdp;
86     void *bufaddr;
87     unsigned short status;
88+#ifdef CONFIG_FEC_1588
89+ unsigned long estatus;
90+#endif
91     unsigned long flags;
92 
93     if (!fep->link) {
94@@ -293,6 +308,17 @@ fec_enet_start_xmit(struct sk_buff *skb,
95         bufaddr = fep->tx_bounce[index];
96     }
97 
98+#ifdef CONFIG_FEC_1588
99+ if (fep->ptimer_present) {
100+ if (fec_ptp_do_txstamp(skb))
101+ estatus = BD_ENET_TX_TS;
102+ else
103+ estatus = 0;
104+
105+ bdp->cbd_esc = (estatus | BD_ENET_TX_INT);
106+ bdp->cbd_bdu = 0;
107+ }
108+#endif
109     /*
110      * Some design made an incorrect assumption on endian mode of
111      * the system that it's running on. As the result, driver has to
112@@ -357,6 +383,9 @@ fec_enet_interrupt(int irq, void * dev_i
113 {
114     struct net_device *dev = dev_id;
115     struct fec_enet_private *fep = netdev_priv(dev);
116+#ifdef CONFIG_FEC_1588
117+ struct fec_ptp_private *fpp = fep->ptp_priv;
118+#endif
119     uint int_events;
120     irqreturn_t ret = IRQ_NONE;
121 
122@@ -364,6 +393,10 @@ fec_enet_interrupt(int irq, void * dev_i
123         int_events = readl(fep->hwp + FEC_IEVENT);
124         writel(int_events, fep->hwp + FEC_IEVENT);
125 
126+#ifdef CONFIG_FEC_1588
127+ if (__raw_readb(MCF_DTIM1_DTER) & MCF_DTIM_DTER_REF)
128+ __raw_writeb(MCF_DTIM_DTER_REF, MCF_DTIM1_DTER);
129+#endif
130         if (int_events & FEC_ENET_RXF) {
131             ret = IRQ_HANDLED;
132             fec_enet_rx(dev);
133@@ -378,6 +411,19 @@ fec_enet_interrupt(int irq, void * dev_i
134             fec_enet_tx(dev);
135         }
136 
137+#ifdef CONFIG_FEC_1588
138+ if (int_events & FEC_ENET_TS_AVAIL) {
139+ ret = IRQ_HANDLED;
140+ fec_ptp_store_txstamp(fep->ptp_priv);
141+ }
142+
143+ if (int_events & FEC_ENET_TS_TIMER) {
144+ ret = IRQ_HANDLED;
145+ if (fep->ptimer_present)
146+ fpp->prtc++;
147+ }
148+#endif
149+
150         if (int_events & FEC_ENET_MII) {
151             ret = IRQ_HANDLED;
152             complete(&fep->mdio_done);
153@@ -394,6 +440,9 @@ fec_enet_tx(struct net_device *dev)
154     struct fec_enet_private *fep;
155     struct bufdesc *bdp;
156     unsigned short status;
157+#ifdef CONFIG_FEC_1588
158+ unsigned long estatus;
159+#endif
160     struct sk_buff *skb;
161 
162     fep = netdev_priv(dev);
163@@ -437,6 +486,13 @@ fec_enet_tx(struct net_device *dev)
164         if (status & BD_ENET_TX_DEF)
165             dev->stats.collisions++;
166 
167+#if defined(CONFIG_FEC_1588)
168+ if (fep->ptimer_present) {
169+ estatus = bdp->cbd_esc;
170+ if (estatus & BD_ENET_TX_TS)
171+ fec_ptp_store_txstamp(fep->ptp_priv);
172+ }
173+#endif
174         /* Free the sk buffer associated with this last transmit */
175         dev_kfree_skb_any(skb);
176         fep->tx_skbuff[fep->skb_dirty] = NULL;
177@@ -470,6 +526,9 @@ static void
178 fec_enet_rx(struct net_device *dev)
179 {
180     struct fec_enet_private *fep = netdev_priv(dev);
181+#ifdef CONFIG_FEC_1588
182+ struct fec_ptp_private *fpp = fep->ptp_priv;
183+#endif
184     const struct platform_device_id *id_entry =
185                 platform_get_device_id(fep->pdev);
186     struct bufdesc *bdp;
187@@ -554,6 +613,12 @@ fec_enet_rx(struct net_device *dev)
188             skb_put(skb, pkt_len - 4); /* Make room */
189             skb_copy_to_linear_data(skb, data, pkt_len - 4);
190             skb->protocol = eth_type_trans(skb, dev);
191+
192+#ifdef CONFIG_FEC_1588
193+ /* 1588 messeage TS handle */
194+ if (fep->ptimer_present)
195+ fec_ptp_store_rxstamp(fpp, skb, bdp);
196+#endif
197             netif_rx(skb);
198         }
199 
200@@ -567,6 +632,11 @@ rx_processing_done:
201         status |= BD_ENET_RX_EMPTY;
202         bdp->cbd_sc = status;
203 
204+#ifdef CONFIG_FEC_1588
205+ bdp->cbd_esc = BD_ENET_RX_INT;
206+ bdp->cbd_prot = 0;
207+ bdp->cbd_bdu = 0;
208+#endif
209         /* Update BD pointer to next entry */
210         if (status & BD_ENET_RX_WRAP)
211             bdp = fep->rx_bd_base;
212@@ -669,8 +739,11 @@ static void fec_enet_adjust_link(struct
213             fec_stop(dev);
214 
215         if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
216- writel(2, fep->hwp + FEC_ECNTRL);
217-
218+#ifdef CONFIG_FEC_1588
219+ writel(0x00000012, fep->hwp + FEC_ECNTRL);
220+#else
221+ writel(0x00000002, fep->hwp + FEC_ECNTRL);
222+#endif
223         status_change = 1;
224     }
225 
226@@ -983,6 +1056,10 @@ static int fec_enet_alloc_buffers(struct
227         bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
228                 FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
229         bdp->cbd_sc = BD_ENET_RX_EMPTY;
230+
231+#ifdef CONFIG_FEC_1588
232+ bdp->cbd_esc = BD_ENET_RX_INT;
233+#endif
234         bdp++;
235     }
236 
237@@ -996,6 +1073,9 @@ static int fec_enet_alloc_buffers(struct
238 
239         bdp->cbd_sc = 0;
240         bdp->cbd_bufaddr = 0;
241+#ifdef CONFIG_FEC_1588
242+ bdp->cbd_esc = BD_ENET_TX_INT;
243+#endif
244         bdp++;
245     }
246 
247@@ -1256,8 +1336,12 @@ fec_restart(struct net_device *dev, int
248         writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
249     }
250 
251+#ifdef CONFIG_FEC_1588
252+ writel(0x7fff8000, fep->hwp + FEC_IEVENT);
253+#else
254     /* Clear any outstanding interrupt. */
255     writel(0xffc00000, fep->hwp + FEC_IEVENT);
256+#endif
257 
258     /* Reset all multicast. */
259     writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
260@@ -1342,8 +1426,25 @@ fec_restart(struct net_device *dev, int
261 #endif
262     }
263 
264+#ifdef CONFIG_FEC_1588
265+ if (fep->ptimer_present) {
266+ int ret;
267+ /* Set Timer count */
268+ ret = fec_ptp_start(fep->ptp_priv);
269+ if (ret) {
270+ fep->ptimer_present = 0;
271+ writel(2, fep->hwp + FEC_ECNTRL);
272+ } else {
273+ val = readl(fep->hwp + FEC_ECNTRL);
274+ val |= 0x00000012;
275+ writel(val, fep->hwp + FEC_ECNTRL);
276+ }
277+ } else
278+ writel(2, fep->hwp + FEC_ECNTRL);
279+#else
280     /* And last, enable the transmit and receive processing */
281     writel(2, fep->hwp + FEC_ECNTRL);
282+#endif
283     writel(0, fep->hwp + FEC_R_DES_ACTIVE);
284 
285     /* Enable interrupts we wish to service */
286@@ -1367,6 +1468,10 @@ fec_stop(struct net_device *dev)
287     writel(1, fep->hwp + FEC_ECNTRL);
288     udelay(10);
289     writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
290+#ifdef CONFIG_FEC_1588
291+ if (fep->ptimer_present)
292+ fec_ptp_stop(fep->ptp_priv);
293+#endif
294     writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
295 }
296 
297@@ -1428,6 +1533,24 @@ fec_probe(struct platform_device *pdev)
298         }
299     }
300 
301+#ifdef CONFIG_FEC_1588
302+ i = (pdev->id) ? (64 + 64 + 64 + 7) : (64 + 64 + 64);
303+ if (request_irq(i + 48, fec_enet_interrupt, IRQF_DISABLED,
304+ "1588 TS AVAIL", ndev) != 0)
305+ printk(KERN_ERR "FEC: Could not alloc FEC %x 1588 TS AVAIL "
306+ "IRQ(%d)!\n", pdev->id, i + 48);
307+
308+ if (pdev->id == 0) {
309+ printk("setup TS timer interrupt through DMA timer1\n");
310+ __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM1_DTMR);
311+
312+ if (request_irq(64 + 33, fec_enet_interrupt, IRQF_DISABLED,
313+ "1588 TS TIMER", ndev) != 0)
314+ printk(KERN_ERR "FEC: Could not alloc FEC %x 1588 TS"
315+ " TIMER IRQ(%d)!\n", pdev->id, 64 + 33);
316+ }
317+#endif
318+
319     fep->clk = clk_get(&pdev->dev, "fec_clk");
320     if (IS_ERR(fep->clk)) {
321         ret = PTR_ERR(fep->clk);
322@@ -1443,6 +1566,20 @@ fec_probe(struct platform_device *pdev)
323     if (ret)
324         goto failed_mii_init;
325 
326+#ifdef CONFIG_FEC_1588
327+ fep->ptp_priv = kzalloc(sizeof(struct fec_ptp_private),
328+ GFP_KERNEL);
329+ if (fep->ptp_priv) {
330+ fep->ptp_priv->hwp = fep->hwp;
331+ ret = fec_ptp_init(fep->ptp_priv, pdev->id);
332+ if (ret)
333+ printk(KERN_ERR "IEEE1588: ptp-timer init failed\n");
334+ else
335+ fep->ptimer_present = 1;
336+ } else
337+ printk(KERN_ERR "IEEE1588: failed to malloc memory\n");
338+#endif
339+
340     /* Carrier starts down, phylib will bring it up */
341     netif_carrier_off(ndev);
342 
343@@ -1454,6 +1591,12 @@ fec_probe(struct platform_device *pdev)
344 
345 failed_register:
346     fec_enet_mii_remove(fep);
347+#ifdef CONFIG_FEC_1588
348+ if (fep->ptimer_present)
349+ fec_ptp_cleanup(fep->ptp_priv);
350+
351+ kfree(fep->ptp_priv);
352+#endif
353 failed_mii_init:
354 failed_init:
355     clk_disable(fep->clk);
356@@ -1485,6 +1628,12 @@ fec_drv_remove(struct platform_device *p
357     clk_disable(fep->clk);
358     clk_put(fep->clk);
359     iounmap((void __iomem *)ndev->base_addr);
360+#ifdef CONFIG_FEC_1588
361+ if (fep->ptimer_present)
362+ fec_ptp_cleanup(fep->ptp_priv);
363+
364+ kfree(fep->ptp_priv);
365+#endif
366     unregister_netdev(ndev);
367     free_netdev(ndev);
368     return 0;
369--- a/drivers/net/fec.h
370+++ b/drivers/net/fec.h
371@@ -50,6 +50,16 @@
372 #define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */
373 #define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */
374 
375+#if defined(CONFIG_FEC_1588)
376+#define FEC_ATIME_CTRL 0x400
377+#define FEC_ATIME 0x404
378+#define FEC_ATIME_EVT_OFFSET 0x408
379+#define FEC_ATIME_EVT_PERIOD 0x40c
380+#define FEC_ATIME_CORR 0x410
381+#define FEC_ATIME_INC 0x414
382+#define FEC_TS_TIMESTAMP 0x418
383+#endif
384+
385 #else
386 
387 #define FEC_ECNTRL 0x000 /* Ethernet control reg */
388@@ -78,6 +88,9 @@
389 
390 #endif /* CONFIG_M5272 */
391 
392+#if defined(CONFIG_FEC_1588)
393+#define FEC_ENHANCED_MODE 1
394+#endif
395 
396 /*
397  * Define the buffer descriptor structure.
398@@ -93,6 +106,14 @@ struct bufdesc {
399     unsigned short cbd_sc; /* Control and status info */
400     unsigned short cbd_datlen; /* Data length */
401     unsigned long cbd_bufaddr; /* Buffer address */
402+
403+#ifdef FEC_ENHANCED_MODE
404+ unsigned long cbd_esc;
405+ unsigned long cbd_prot;
406+ unsigned long cbd_bdu;
407+ unsigned long ts;
408+ unsigned short res0[4];
409+#endif
410 };
411 #endif
412 
413@@ -128,6 +149,7 @@ struct bufdesc {
414 #define BD_ENET_RX_OV ((ushort)0x0002)
415 #define BD_ENET_RX_CL ((ushort)0x0001)
416 #define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */
417+#define BD_ENET_RX_INT 0x00800000
418 
419 /* Buffer descriptor control/status used by Ethernet transmit.
420 */
421@@ -146,6 +168,9 @@ struct bufdesc {
422 #define BD_ENET_TX_CSL ((ushort)0x0001)
423 #define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
424 
425+#define BD_ENET_TX_TS 0x20000000
426+#define BD_ENET_TX_INT 0x40000000
427+#define BD_ENET_TX_BDU 0x80000000
428 
429 /****************************************************************************/
430 #endif /* FEC_H */
431--- /dev/null
432+++ b/drivers/net/fec_1588.c
433@@ -0,0 +1,626 @@
434+/*
435+ * drivers/net/fec_1588.c
436+ *
437+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
438+ * Copyright (C) 2009 IXXAT Automation, GmbH
439+ *
440+ * FEC Ethernet Driver -- IEEE 1588 interface functionality
441+ *
442+ * This program is free software; you can redistribute it and/or modify
443+ * it under the terms of the GNU General Public License as published by
444+ * the Free Software Foundation; either version 2 of the License, or
445+ * (at your option) any later version.
446+ *
447+ * This program is distributed in the hope that it will be useful,
448+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
449+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
450+ * GNU General Public License for more details.
451+ *
452+ * You should have received a copy of the GNU General Public License along
453+ * with this program; if not, write to the Free Software Foundation, Inc.,
454+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
455+ *
456+ */
457+
458+#include <linux/io.h>
459+#include <linux/device.h>
460+#include <linux/fs.h>
461+#include <linux/vmalloc.h>
462+#include <linux/spinlock.h>
463+#include <linux/ip.h>
464+#include <linux/udp.h>
465+#include <asm/mcf5441x_ccm.h>
466+#include <asm/mcf5441x_dtim.h>
467+#include <asm/mcfsim.h>
468+#include "fec_1588.h"
469+
470+static DECLARE_WAIT_QUEUE_HEAD(ptp_rx_ts_wait);
471+#define PTP_GET_RX_TIMEOUT (HZ/10)
472+#define COLDFIRE_DTIM1_INT (64+32+1)
473+
474+static struct fec_ptp_private *ptp_private[2];
475+
476+static void init_DTIM1_for_1588(struct fec_ptp_private *priv)
477+{
478+ printk(KERN_INFO "Initializing DTIM1 for 1588 TS timer\n");
479+
480+ __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM1_DTMR);
481+
482+ /*Enable 1588*/
483+
484+ __raw_writeb(MCF_DTIM_DTXMR_1588EN, MCF_DTIM1_DTXMR);
485+
486+ /*Compare to the 1588 timerbase*/
487+ __raw_writel(FEC_T_PERIOD_ONE_SEC - FEC_T_INC_40MHZ, MCF_DTIM1_DTRR);
488+
489+ __raw_writeb(MCF_DTIM_DTER_REF, MCF_DTIM1_DTER);
490+
491+ MCF_GPIO_PAR_TIMER = (MCF_GPIO_PAR_TIMER & MCF_GPIO_PAR_TIMER_T1IN_MASK)
492+ | MCF_GPIO_PAR_TIMER_T1IN_T1OUT;
493+}
494+
495+static void start_DTIM1(void)
496+{
497+ __raw_writew(MCF_DTIM_DTMR_RST_EN | MCF_DTIM_DTMR_ORRI |
498+ MCF_DTIM_DTMR_OM, MCF_DTIM1_DTMR);
499+}
500+
501+static void stop_DTIM1(void)
502+{
503+ __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM1_DTMR);
504+}
505+
506+/* Alloc the ring resource */
507+static int fec_ptp_init_circ(struct circ_buf *ptp_buf)
508+{
509+ ptp_buf->buf = vmalloc(DEFAULT_PTP_RX_BUF_SZ *
510+ sizeof(struct fec_ptp_data_t));
511+
512+ if (!ptp_buf->buf)
513+ return 1;
514+ ptp_buf->head = 0;
515+ ptp_buf->tail = 0;
516+
517+ return 0;
518+}
519+
520+static inline int fec_ptp_calc_index(int size, int curr_index, int offset)
521+{
522+ return (curr_index + offset) % size;
523+}
524+
525+static int fec_ptp_is_empty(struct circ_buf *buf)
526+{
527+ return (buf->head == buf->tail);
528+}
529+
530+static int fec_ptp_nelems(struct circ_buf *buf)
531+{
532+ const int front = buf->head;
533+ const int end = buf->tail;
534+ const int size = DEFAULT_PTP_RX_BUF_SZ;
535+ int n_items;
536+
537+ if (end > front)
538+ n_items = end - front;
539+ else if (end < front)
540+ n_items = size - (front - end);
541+ else
542+ n_items = 0;
543+
544+ return n_items;
545+}
546+
547+static int fec_ptp_is_full(struct circ_buf *buf)
548+{
549+ if (fec_ptp_nelems(buf) ==
550+ (DEFAULT_PTP_RX_BUF_SZ - 1))
551+ return 1;
552+ else
553+ return 0;
554+}
555+
556+static int fec_ptp_insert(struct circ_buf *ptp_buf,
557+ struct fec_ptp_data_t *data,
558+ struct fec_ptp_private *priv)
559+{
560+ struct fec_ptp_data_t *tmp;
561+
562+ if (fec_ptp_is_full(ptp_buf))
563+ return 1;
564+
565+ spin_lock(&priv->ptp_lock);
566+ tmp = (struct fec_ptp_data_t *)(ptp_buf->buf) + ptp_buf->tail;
567+
568+ tmp->key = data->key;
569+ tmp->ts_time.sec = data->ts_time.sec;
570+ tmp->ts_time.nsec = data->ts_time.nsec;
571+
572+ ptp_buf->tail = fec_ptp_calc_index(DEFAULT_PTP_RX_BUF_SZ,
573+ ptp_buf->tail, 1);
574+ spin_unlock(&priv->ptp_lock);
575+
576+ return 0;
577+}
578+
579+static int fec_ptp_find_and_remove(struct circ_buf *ptp_buf,
580+ int key,
581+ struct fec_ptp_data_t *data,
582+ struct fec_ptp_private *priv)
583+{
584+ int i;
585+ int size = DEFAULT_PTP_RX_BUF_SZ;
586+ int end = ptp_buf->tail;
587+ unsigned long flags;
588+ struct fec_ptp_data_t *tmp;
589+
590+ if (fec_ptp_is_empty(ptp_buf))
591+ return 1;
592+
593+ i = ptp_buf->head;
594+ while (i != end) {
595+ tmp = (struct fec_ptp_data_t *)(ptp_buf->buf) + i;
596+ if (tmp->key == key)
597+ break;
598+ i = fec_ptp_calc_index(size, i, 1);
599+ }
600+
601+ spin_lock_irqsave(&priv->ptp_lock, flags);
602+ if (i == end) {
603+ ptp_buf->head = end;
604+ spin_unlock_irqrestore(&priv->ptp_lock, flags);
605+ return 1;
606+ }
607+
608+ data->ts_time.sec = tmp->ts_time.sec;
609+ data->ts_time.nsec = tmp->ts_time.nsec;
610+
611+ ptp_buf->head = fec_ptp_calc_index(size, i, 1);
612+ spin_unlock_irqrestore(&priv->ptp_lock, flags);
613+
614+ return 0;
615+}
616+
617+/* 1588 Module intialization */
618+int fec_ptp_start(struct fec_ptp_private *priv)
619+{
620+ struct fec_ptp_private *fpp = priv;
621+
622+ MCF_CCM_MISCCR3 = 0x0000;
623+
624+ init_DTIM1_for_1588(priv);
625+
626+ /* Select 1588 Timer source and enable module for starting Tmr Clock */
627+ fec_writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL);
628+ fec_writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET,
629+ fpp->hwp + FEC_ATIME_INC);
630+ fec_writel(FEC_T_PERIOD_ONE_SEC, fpp->hwp + FEC_ATIME_EVT_PERIOD);
631+ /* start counter */
632+ fec_writel(FEC_T_CTRL_PERIOD_RST | FEC_T_CTRL_ENABLE |
633+ FEC_T_CTRL_PINPER, fpp->hwp + FEC_ATIME_CTRL);
634+
635+ start_DTIM1();
636+
637+ return 0;
638+}
639+
640+/* Cleanup routine for 1588 module.
641+ * When PTP is disabled this routing is called */
642+void fec_ptp_stop(struct fec_ptp_private *priv)
643+{
644+ struct fec_ptp_private *fpp = priv;
645+
646+ fec_writel(0, fpp->hwp + FEC_ATIME_CTRL);
647+ fec_writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL);
648+ stop_DTIM1();
649+}
650+
651+static void fec_get_curr_cnt(struct fec_ptp_private *priv,
652+ struct ptp_rtc_time *curr_time)
653+{
654+ u32 tempval;
655+
656+ fec_writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
657+ fec_writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
658+ curr_time->rtc_time.nsec = fec_readl(priv->hwp + FEC_ATIME);
659+ curr_time->rtc_time.sec = priv->prtc;
660+
661+ fec_writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
662+ tempval = fec_readl(priv->hwp + FEC_ATIME);
663+ if (tempval < curr_time->rtc_time.nsec) {
664+ curr_time->rtc_time.nsec = tempval;
665+ curr_time->rtc_time.sec = priv->prtc;
666+ }
667+}
668+
669+/* Set the 1588 timer counter registers */
670+static void fec_set_1588cnt(struct fec_ptp_private *priv,
671+ struct ptp_rtc_time *fec_time)
672+{
673+ u32 tempval;
674+ unsigned long flags;
675+
676+ spin_lock_irqsave(&priv->cnt_lock, flags);
677+
678+ priv->prtc = fec_time->rtc_time.sec;
679+
680+ tempval = fec_time->rtc_time.nsec;
681+ fec_writel(tempval, priv->hwp + FEC_ATIME);
682+ spin_unlock_irqrestore(&priv->cnt_lock, flags);
683+}
684+
685+/* Set the BD to ptp */
686+int fec_ptp_do_txstamp(struct sk_buff *skb)
687+{
688+ struct iphdr *iph;
689+ struct udphdr *udph;
690+
691+ if (skb->len > 44) {
692+ /* Check if port is 319 for PTP Event, and check for UDP */
693+ iph = ip_hdr(skb);
694+ if (iph == NULL || iph->protocol != FEC_PACKET_TYPE_UDP)
695+ return 0;
696+
697+ udph = udp_hdr(skb);
698+ if (udph != NULL && ntohs(udph->source) == 319)
699+ return 1;
700+ }
701+
702+ return 0;
703+}
704+
705+void fec_ptp_store_txstamp(struct fec_ptp_private *priv)
706+{
707+ struct fec_ptp_private *fpp = priv;
708+ unsigned int reg;
709+
710+ reg = fec_readl(fpp->hwp + FEC_TS_TIMESTAMP);
711+ fpp->txstamp.nsec = reg;
712+ fpp->txstamp.sec = fpp->prtc;
713+}
714+
715+void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
716+ struct sk_buff *skb,
717+ struct bufdesc *bdp)
718+{
719+ int msg_type, seq_id, control;
720+ struct fec_ptp_data_t tmp_rx_time;
721+ struct fec_ptp_private *fpp = priv;
722+ struct iphdr *iph;
723+ struct udphdr *udph;
724+
725+ /* Check for UDP, and Check if port is 319 for PTP Event */
726+ iph = (struct iphdr *)(skb->data + FEC_PTP_IP_OFFS);
727+ if (iph->protocol != FEC_PACKET_TYPE_UDP)
728+ return;
729+
730+ udph = (struct udphdr *)(skb->data + FEC_PTP_UDP_OFFS);
731+ if (ntohs(udph->source) != 319)
732+ return;
733+
734+ seq_id = *((u16 *)(skb->data + FEC_PTP_SEQ_ID_OFFS));
735+ control = *((u8 *)(skb->data + FEC_PTP_CTRL_OFFS));
736+
737+ tmp_rx_time.key = ntohs(seq_id);
738+ tmp_rx_time.ts_time.sec = fpp->prtc;
739+ tmp_rx_time.ts_time.nsec = bdp->ts;
740+
741+ switch (control) {
742+
743+ case PTP_MSG_SYNC:
744+ fec_ptp_insert(&(priv->rx_time_sync), &tmp_rx_time, priv);
745+ break;
746+
747+ case PTP_MSG_DEL_REQ:
748+ fec_ptp_insert(&(priv->rx_time_del_req), &tmp_rx_time, priv);
749+ break;
750+
751+ /* clear transportSpecific field*/
752+ case PTP_MSG_ALL_OTHER:
753+ msg_type = (*((u8 *)(skb->data +
754+ FEC_PTP_MSG_TYPE_OFFS))) & 0x0F;
755+ switch (msg_type) {
756+ case PTP_MSG_P_DEL_REQ:
757+ fec_ptp_insert(&(priv->rx_time_pdel_req),
758+ &tmp_rx_time, priv);
759+ break;
760+ case PTP_MSG_P_DEL_RESP:
761+ fec_ptp_insert(&(priv->rx_time_pdel_resp),
762+ &tmp_rx_time, priv);
763+ break;
764+ default:
765+ break;
766+ }
767+ break;
768+ default:
769+ break;
770+ }
771+
772+ wake_up_interruptible(&ptp_rx_ts_wait);
773+}
774+
775+static void fec_get_tx_timestamp(struct fec_ptp_private *priv,
776+ struct ptp_time *tx_time)
777+{
778+ tx_time->sec = priv->txstamp.sec;
779+ tx_time->nsec = priv->txstamp.nsec;
780+}
781+
782+static uint8_t fec_get_rx_time(struct fec_ptp_private *priv,
783+ struct ptp_ts_data *pts,
784+ struct ptp_time *rx_time)
785+{
786+ struct fec_ptp_data_t tmp;
787+ int key, flag;
788+ u8 mode;
789+
790+ key = pts->seq_id;
791+ mode = pts->message_type;
792+ switch (mode) {
793+ case PTP_MSG_SYNC:
794+ flag = fec_ptp_find_and_remove(&(priv->rx_time_sync),
795+ key, &tmp, priv);
796+ break;
797+ case PTP_MSG_DEL_REQ:
798+ flag = fec_ptp_find_and_remove(&(priv->rx_time_del_req),
799+ key, &tmp, priv);
800+ break;
801+
802+ case PTP_MSG_P_DEL_REQ:
803+ flag = fec_ptp_find_and_remove(&(priv->rx_time_pdel_req),
804+ key, &tmp, priv);
805+ break;
806+ case PTP_MSG_P_DEL_RESP:
807+ flag = fec_ptp_find_and_remove(&(priv->rx_time_pdel_resp),
808+ key, &tmp, priv);
809+ break;
810+
811+ default:
812+ flag = 1;
813+ printk(KERN_ERR "ERROR\n");
814+ break;
815+ }
816+
817+ if (!flag) {
818+ rx_time->sec = tmp.ts_time.sec;
819+ rx_time->nsec = tmp.ts_time.nsec;
820+ return 0;
821+ } else {
822+ wait_event_interruptible_timeout(ptp_rx_ts_wait, 0,
823+ PTP_GET_RX_TIMEOUT);
824+
825+ switch (mode) {
826+ case PTP_MSG_SYNC:
827+ flag = fec_ptp_find_and_remove(&(priv->rx_time_sync),
828+ key, &tmp, priv);
829+ break;
830+ case PTP_MSG_DEL_REQ:
831+ flag = fec_ptp_find_and_remove(
832+ &(priv->rx_time_del_req), key, &tmp, priv);
833+ break;
834+ case PTP_MSG_P_DEL_REQ:
835+ flag = fec_ptp_find_and_remove(
836+ &(priv->rx_time_pdel_req), key, &tmp, priv);
837+ break;
838+ case PTP_MSG_P_DEL_RESP:
839+ flag = fec_ptp_find_and_remove(
840+ &(priv->rx_time_pdel_resp), key, &tmp, priv);
841+ break;
842+ }
843+
844+ if (flag == 0) {
845+ rx_time->sec = tmp.ts_time.sec;
846+ rx_time->nsec = tmp.ts_time.nsec;
847+ return 0;
848+ }
849+
850+ return -1;
851+ }
852+}
853+
854+static void fec_handle_ptpdrift(
855+ struct ptp_set_comp *comp,
856+ struct ptp_time_correct *ptc)
857+{
858+ u32 ndrift;
859+ u32 i;
860+ u32 tmp, tmp_ns, tmp_prid;
861+ u32 min_ns, min_prid, miss_ns;
862+
863+ ndrift = comp->drift;
864+ if (ndrift == 0) {
865+ ptc->corr_inc = 0;
866+ ptc->corr_period = 0;
867+ return;
868+ }
869+
870+ if (ndrift >= FEC_ATIME_40MHZ) {
871+ ptc->corr_inc = (u32)(ndrift / FEC_ATIME_40MHZ);
872+ ptc->corr_period = 1;
873+ return;
874+ }
875+
876+ min_ns = 1;
877+ tmp = FEC_ATIME_40MHZ % ndrift;
878+ tmp_prid = (u32)(FEC_ATIME_40MHZ / ndrift);
879+ min_prid = tmp_prid;
880+ miss_ns = tmp / tmp_prid;
881+ for (i = 2; i <= FEC_T_INC_40MHZ; i++) {
882+ tmp = (FEC_ATIME_40MHZ * i) % ndrift;
883+ tmp_prid = (FEC_ATIME_40MHZ * i) / ndrift;
884+ tmp_ns = tmp / tmp_prid;
885+ if (tmp_ns <= 10) {
886+ min_ns = i;
887+ min_prid = tmp_prid;
888+ break;
889+ }
890+
891+ if (tmp_ns < miss_ns) {
892+ min_ns = i;
893+ min_prid = tmp_prid;
894+ miss_ns = tmp_ns;
895+ }
896+ }
897+
898+ ptc->corr_inc = min_ns;
899+ ptc->corr_period = min_prid;
900+}
901+
902+static void fec_set_drift(struct fec_ptp_private *priv,
903+ struct ptp_set_comp *comp)
904+{
905+ struct ptp_time_correct tc;
906+ struct fec_ptp_private *fpp = priv;
907+ u32 tmp, corr_ns;
908+
909+ fec_handle_ptpdrift(comp, &tc);
910+ if (tc.corr_inc == 0)
911+ return;
912+
913+ if (comp->o_ops == TRUE)
914+ corr_ns = FEC_T_INC_40MHZ + tc.corr_inc;
915+ else
916+ corr_ns = FEC_T_INC_40MHZ - tc.corr_inc;
917+
918+ tmp = fec_readl(fpp->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
919+ tmp |= corr_ns << FEC_T_INC_CORR_OFFSET;
920+ fec_writel(tmp, fpp->hwp + FEC_ATIME_INC);
921+
922+ fec_writel(tc.corr_period, fpp->hwp + FEC_ATIME_CORR);
923+}
924+
925+static int ptp_open(struct inode *inode, struct file *file)
926+{
927+ return 0;
928+}
929+
930+static int ptp_release(struct inode *inode, struct file *file)
931+{
932+ return 0;
933+}
934+
935+static long ptp_unlocked_ioctl(
936+ struct file *file,
937+ unsigned int cmd,
938+ unsigned long arg)
939+{
940+ struct ptp_rtc_time *cnt;
941+ struct ptp_rtc_time curr_time;
942+ struct ptp_time rx_time, tx_time;
943+ struct ptp_ts_data *p_ts;
944+ struct ptp_set_comp *p_comp;
945+ struct fec_ptp_private *priv;
946+ struct inode *inode = file->f_mapping->host;
947+ unsigned int minor = MINOR(inode->i_rdev);
948+ long retval = 0;
949+
950+ priv = (struct fec_ptp_private *) ptp_private[minor];
951+ switch (cmd) {
952+ case PTP_GET_RX_TIMESTAMP:
953+ p_ts = (struct ptp_ts_data *)arg;
954+ retval = fec_get_rx_time(priv, p_ts, &rx_time);
955+ if (retval == 0)
956+ copy_to_user((void __user *)(&(p_ts->ts)), &rx_time,
957+ sizeof(rx_time));
958+ break;
959+ case PTP_GET_TX_TIMESTAMP:
960+ p_ts = (struct ptp_ts_data *)arg;
961+ fec_get_tx_timestamp(priv, &tx_time);
962+ copy_to_user((void __user *)(&(p_ts->ts)), &tx_time,
963+ sizeof(tx_time));
964+ break;
965+ case PTP_GET_CURRENT_TIME:
966+ fec_get_curr_cnt(priv, &curr_time);
967+ copy_to_user((void __user *)arg, &curr_time, sizeof(curr_time));
968+ break;
969+ case PTP_SET_RTC_TIME:
970+ cnt = (struct ptp_rtc_time *)arg;
971+ fec_set_1588cnt(priv, cnt);
972+ break;
973+ case PTP_FLUSH_TIMESTAMP:
974+ /* reset sync buffer */
975+ priv->rx_time_sync.head = 0;
976+ priv->rx_time_sync.tail = 0;
977+ /* reset delay_req buffer */
978+ priv->rx_time_del_req.head = 0;
979+ priv->rx_time_del_req.tail = 0;
980+ /* reset pdelay_req buffer */
981+ priv->rx_time_pdel_req.head = 0;
982+ priv->rx_time_pdel_req.tail = 0;
983+ /* reset pdelay_resp buffer */
984+ priv->rx_time_pdel_resp.head = 0;
985+ priv->rx_time_pdel_resp.tail = 0;
986+ break;
987+ case PTP_SET_COMPENSATION:
988+ p_comp = (struct ptp_set_comp *)arg;
989+ fec_set_drift(priv, p_comp);
990+ break;
991+ case PTP_GET_ORIG_COMP:
992+ ((struct ptp_get_comp *)arg)->dw_origcomp = FEC_PTP_ORIG_COMP;
993+ break;
994+ default:
995+ return -EINVAL;
996+ }
997+ return retval;
998+}
999+
1000+static const struct file_operations ptp_fops = {
1001+ .owner = THIS_MODULE,
1002+ .llseek = NULL,
1003+ .read = NULL,
1004+ .write = NULL,
1005+ .unlocked_ioctl = ptp_unlocked_ioctl,
1006+ .open = ptp_open,
1007+ .release = ptp_release,
1008+};
1009+
1010+static int init_ptp(void)
1011+{
1012+ if (register_chrdev(PTP_MAJOR, "ptp", &ptp_fops))
1013+ printk(KERN_ERR "Unable to register PTP deivce as char\n");
1014+
1015+ return 0;
1016+}
1017+
1018+static void ptp_free(void)
1019+{
1020+ /*unregister the PTP device*/
1021+ unregister_chrdev(PTP_MAJOR, "ptp");
1022+}
1023+
1024+
1025+
1026+/*
1027+ * Resource required for accessing 1588 Timer Registers.
1028+ */
1029+int fec_ptp_init(struct fec_ptp_private *priv, int id)
1030+{
1031+ fec_ptp_init_circ(&(priv->rx_time_sync));
1032+ fec_ptp_init_circ(&(priv->rx_time_del_req));
1033+ fec_ptp_init_circ(&(priv->rx_time_pdel_req));
1034+ fec_ptp_init_circ(&(priv->rx_time_pdel_resp));
1035+
1036+ spin_lock_init(&priv->ptp_lock);
1037+ spin_lock_init(&priv->cnt_lock);
1038+ ptp_private[id] = priv;
1039+ if (id == 0)
1040+ init_ptp();
1041+ return 0;
1042+}
1043+EXPORT_SYMBOL(fec_ptp_init);
1044+
1045+void fec_ptp_cleanup(struct fec_ptp_private *priv)
1046+{
1047+
1048+ if (priv->rx_time_sync.buf)
1049+ vfree(priv->rx_time_sync.buf);
1050+ if (priv->rx_time_del_req.buf)
1051+ vfree(priv->rx_time_del_req.buf);
1052+ if (priv->rx_time_pdel_req.buf)
1053+ vfree(priv->rx_time_pdel_req.buf);
1054+ if (priv->rx_time_pdel_resp.buf)
1055+ vfree(priv->rx_time_pdel_resp.buf);
1056+
1057+ ptp_free();
1058+}
1059+EXPORT_SYMBOL(fec_ptp_cleanup);
1060--- /dev/null
1061+++ b/drivers/net/fec_1588.h
1062@@ -0,0 +1,195 @@
1063+/*
1064+ * drivers/net/fec_1588.h
1065+ *
1066+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
1067+ *
1068+ * This program is free software; you can redistribute it and/or modify
1069+ * it under the terms of the GNU General Public License as published by
1070+ * the Free Software Foundation; either version 2 of the License, or
1071+ * (at your option) any later version.
1072+ *
1073+ * This program is distributed in the hope that it will be useful,
1074+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1075+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1076+ * GNU General Public License for more details.
1077+ *
1078+ * You should have received a copy of the GNU General Public License along
1079+ * with this program; if not, write to the Free Software Foundation, Inc.,
1080+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1081+ *
1082+ */
1083+
1084+#ifndef FEC_1588_H
1085+#define FEC_1588_H
1086+
1087+#include <linux/circ_buf.h>
1088+#include "fec.h"
1089+
1090+#define fec_readl(addr) \
1091+ ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
1092+
1093+#define fec_writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
1094+
1095+#define FALSE 0
1096+#define TRUE 1
1097+
1098+/* FEC 1588 register bits */
1099+#define FEC_T_CTRL_CAPTURE 0x00000800
1100+#define FEC_T_CTRL_RESTART 0x00000200
1101+#define FEC_T_CTRL_PERIOD_RST 0x00000010
1102+#define FEC_T_CTRL_PINPER 0x00000080
1103+#define FEC_T_CTRL_ENABLE 0x00000001
1104+
1105+#define FEC_T_INC_MASK 0x0000007f
1106+#define FEC_T_INC_OFFSET 0
1107+#define FEC_T_INC_CORR_MASK 0x00007f00
1108+#define FEC_T_INC_CORR_OFFSET 8
1109+
1110+#define FEC_T_INC_40MHZ 8
1111+#define FEC_ATIME_40MHZ 125000000
1112+
1113+#define FEC_T_PERIOD_ONE_SEC 0x3B9ACA00
1114+
1115+/* IEEE 1588 definition */
1116+#define FEC_ECNTRL_TS_EN 0x10
1117+#define PTP_MAJOR 232 /*the temporary major number
1118+ *used by PTP driver, the major
1119+ *number 232~239 is unassigned*/
1120+
1121+#define DEFAULT_PTP_RX_BUF_SZ 2048
1122+#define PTP_MSG_SYNC 0x0
1123+#define PTP_MSG_DEL_REQ 0x1
1124+#define PTP_MSG_P_DEL_REQ 0x2
1125+#define PTP_MSG_P_DEL_RESP 0x3
1126+#define PTP_MSG_DEL_RESP 0x4
1127+#define PTP_MSG_ALL_OTHER 0x5
1128+
1129+#define PTP_GET_TX_TIMESTAMP 0x1
1130+#define PTP_GET_RX_TIMESTAMP 0x9
1131+#define PTP_SET_RTC_TIME 0x3
1132+#define PTP_SET_COMPENSATION 0x4
1133+#define PTP_GET_CURRENT_TIME 0x5
1134+#define PTP_FLUSH_TIMESTAMP 0x6
1135+#define PTP_ADJ_ADDEND 0x7
1136+#define PTP_GET_ORIG_COMP 0x8
1137+#define PTP_GET_ADDEND 0xB
1138+#define PTP_GET_RX_TIMESTAMP_PDELAY_REQ 0xC
1139+#define PTP_GET_RX_TIMESTAMP_PDELAY_RESP 0xD
1140+
1141+#define FEC_PTP_DOMAIN_DLFT 0xe0000181
1142+#define FEC_PTP_IP_OFFS 0x0
1143+#define FEC_PTP_UDP_OFFS 0x14
1144+#define FEC_PTP_MSG_TYPE_OFFS 0x1C
1145+#define FEC_PTP_SEQ_ID_OFFS 0x3A
1146+#define FEC_PTP_COR_NS 0x24
1147+#define FEC_PTP_CTRL_OFFS 0x3C
1148+#define FEC_PACKET_TYPE_UDP 0x11
1149+
1150+#define FEC_PTP_ORIG_COMP 0x15555
1151+
1152+/* PTP standard time representation structure */
1153+struct ptp_time {
1154+ u64 sec; /* seconds */
1155+ u32 nsec; /* nanoseconds */
1156+};
1157+
1158+/* Structure for PTP Time Stamp */
1159+struct fec_ptp_data_t {
1160+ int key;
1161+ struct ptp_time ts_time;
1162+};
1163+
1164+/* interface for PTP driver command GET_TX_TIME */
1165+struct ptp_ts_data {
1166+ /* PTP version */
1167+ u8 version;
1168+ /* PTP source port ID */
1169+ u8 spid[10];
1170+ /* PTP sequence ID */
1171+ u16 seq_id;
1172+ /* PTP message type */
1173+ u8 message_type;
1174+ /* PTP timestamp */
1175+ struct ptp_time ts;
1176+};
1177+
1178+/* interface for PTP driver command SET_RTC_TIME/GET_CURRENT_TIME */
1179+struct ptp_rtc_time {
1180+ struct ptp_time rtc_time;
1181+};
1182+
1183+/* interface for PTP driver command SET_COMPENSATION */
1184+struct ptp_set_comp {
1185+ u32 drift;
1186+ u32 o_ops;
1187+};
1188+
1189+/* interface for PTP driver command GET_ORIG_COMP */
1190+struct ptp_get_comp {
1191+ /* the initial compensation value */
1192+ u32 dw_origcomp;
1193+ /* the minimum compensation value */
1194+ u32 dw_mincomp;
1195+ /*the max compensation value*/
1196+ u32 dw_maxcomp;
1197+ /*the min drift applying min compensation value in ppm*/
1198+ u32 dw_mindrift;
1199+ /*the max drift applying max compensation value in ppm*/
1200+ u32 dw_maxdrift;
1201+};
1202+
1203+struct ptp_time_correct {
1204+ u32 corr_period;
1205+ u32 corr_inc;
1206+};
1207+
1208+/* PTP message version */
1209+#define PTP_1588_MSG_VER_1 1
1210+#define PTP_1588_MSG_VER_2 2
1211+
1212+struct fec_ptp_private {
1213+ void __iomem *hwp;
1214+
1215+ struct circ_buf rx_time_sync;
1216+ struct circ_buf rx_time_del_req;
1217+ struct circ_buf rx_time_pdel_req;
1218+ struct circ_buf rx_time_pdel_resp;
1219+ spinlock_t ptp_lock;
1220+ spinlock_t cnt_lock;
1221+
1222+ u64 prtc;
1223+ struct ptp_time txstamp;
1224+};
1225+
1226+#ifdef CONFIG_FEC_1588
1227+extern int fec_ptp_init(struct fec_ptp_private *priv, int id);
1228+extern void fec_ptp_cleanup(struct fec_ptp_private *priv);
1229+extern int fec_ptp_start(struct fec_ptp_private *priv);
1230+extern void fec_ptp_stop(struct fec_ptp_private *priv);
1231+extern int fec_ptp_do_txstamp(struct sk_buff *skb);
1232+extern void fec_ptp_store_txstamp(struct fec_ptp_private *priv);
1233+extern void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
1234+ struct sk_buff *skb,
1235+ struct bufdesc *bdp);
1236+#else
1237+static inline int fec_ptp_init(struct fec_ptp_private *priv, int id)
1238+{
1239+ return 1;
1240+}
1241+static inline void fec_ptp_cleanup(struct fec_ptp_private *priv) { }
1242+static inline int fec_ptp_start(struct fec_ptp_private *priv)
1243+{
1244+ return 1;
1245+}
1246+static inline void fec_ptp_stop(struct fec_ptp_private *priv) {}
1247+static inline int fec_ptp_do_txstamp(struct sk_buff *skb)
1248+{
1249+ return 0;
1250+}
1251+static inline void fec_ptp_store_txstamp(struct fec_ptp_private *priv) {}
1252+static inline void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
1253+ struct sk_buff *skb,
1254+ struct bufdesc *bdp) {}
1255+#endif /* 1588 */
1256+
1257+#endif
1258

Archive Download this file



interactive