[coldfire]: switch to 2.6.38
[openwrt.git] / target / linux / coldfire / patches / 020-Add-dual-FEC-1588-timer-support.patch
1 From 67d56859d24864af530506c76523f0fc3c5cb502 Mon Sep 17 00:00:00 2001
2 From: Alison Wang <b18965@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:44 +0800
4 Subject: [PATCH 20/52] Add dual FEC 1588 timer support
5
6 Add Modelo dual FEC 1588 function with IXXXAT statck.
7
8 Signed-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