020-Add-dual-FEC-1588-timer-support.patch 32 KB

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