| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 |
- From 67d56859d24864af530506c76523f0fc3c5cb502 Mon Sep 17 00:00:00 2001
- From: Alison Wang <[email protected]>
- Date: Thu, 4 Aug 2011 09:59:44 +0800
- Subject: [PATCH 20/52] Add dual FEC 1588 timer support
- Add Modelo dual FEC 1588 function with IXXXAT statck.
- Signed-off-by: Alison Wang <[email protected]>
- ---
- drivers/net/Kconfig | 6 +
- drivers/net/Makefile | 3 +
- drivers/net/fec.c | 153 ++++++++++++-
- drivers/net/fec.h | 25 ++
- drivers/net/fec_1588.c | 626 ++++++++++++++++++++++++++++++++++++++++++++++++
- drivers/net/fec_1588.h | 195 +++++++++++++++
- 6 files changed, 1006 insertions(+), 2 deletions(-)
- create mode 100644 drivers/net/fec_1588.c
- create mode 100644 drivers/net/fec_1588.h
- --- a/drivers/net/Kconfig
- +++ b/drivers/net/Kconfig
- @@ -1958,6 +1958,12 @@ config FEC2
- Say Y here if you want to use the second built-in 10/100 Fast
- ethernet controller on some Motorola ColdFire processors.
-
- +config FEC_1588
- + bool "Enable 1588 interface(on some ColdFire designs)"
- + depends on M5441X && FEC
- + help
- + Say Y here if 1588 function is enabled.
- +
- config FEC_548x
- tristate "MCF547x/MCF548x Fast Ethernet Controller support"
- depends on M547X_8X
- --- a/drivers/net/Makefile
- +++ b/drivers/net/Makefile
- @@ -123,6 +123,9 @@ obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
- obj-$(CONFIG_HP100) += hp100.o
- obj-$(CONFIG_SMC9194) += smc9194.o
- obj-$(CONFIG_FEC) += fec.o
- +ifeq ($(CONFIG_FEC_1588), y)
- +obj-$(CONFIG_FEC) += fec_1588.o
- +endif
- obj-$(CONFIG_FEC_548x) += fec_m547x.o
- obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
- ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
- --- a/drivers/net/fec.c
- +++ b/drivers/net/fec.c
- @@ -53,6 +53,7 @@
- #endif
-
- #include "fec.h"
- +#include "fec_1588.h"
-
- #if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
- #define FEC_ALIGNMENT 0xf
- @@ -135,8 +136,15 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet
- #define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
- #define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
- #define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
- +#define FEC_ENET_TS_AVAIL ((uint)0x00010000)
- +#define FEC_ENET_TS_TIMER ((uint)0x00008000)
-
- +#if defined(CONFIG_FEC_1588)
- +#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | \
- + FEC_ENET_TS_AVAIL | FEC_ENET_TS_TIMER)
- +#else
- #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
- +#endif
-
- /* The FEC stores dest/src/type, data, and checksum for receive packets.
- */
- @@ -209,6 +217,10 @@ struct fec_enet_private {
- int link;
- int full_duplex;
- struct completion mdio_done;
- +#ifdef CONFIG_FEC_1588
- + struct fec_ptp_private *ptp_priv;
- + uint ptimer_present;
- +#endif
- };
-
- static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
- @@ -252,6 +264,9 @@ fec_enet_start_xmit(struct sk_buff *skb,
- struct bufdesc *bdp;
- void *bufaddr;
- unsigned short status;
- +#ifdef CONFIG_FEC_1588
- + unsigned long estatus;
- +#endif
- unsigned long flags;
-
- if (!fep->link) {
- @@ -293,6 +308,17 @@ fec_enet_start_xmit(struct sk_buff *skb,
- bufaddr = fep->tx_bounce[index];
- }
-
- +#ifdef CONFIG_FEC_1588
- + if (fep->ptimer_present) {
- + if (fec_ptp_do_txstamp(skb))
- + estatus = BD_ENET_TX_TS;
- + else
- + estatus = 0;
- +
- + bdp->cbd_esc = (estatus | BD_ENET_TX_INT);
- + bdp->cbd_bdu = 0;
- + }
- +#endif
- /*
- * Some design made an incorrect assumption on endian mode of
- * the system that it's running on. As the result, driver has to
- @@ -357,6 +383,9 @@ fec_enet_interrupt(int irq, void * dev_i
- {
- struct net_device *dev = dev_id;
- struct fec_enet_private *fep = netdev_priv(dev);
- +#ifdef CONFIG_FEC_1588
- + struct fec_ptp_private *fpp = fep->ptp_priv;
- +#endif
- uint int_events;
- irqreturn_t ret = IRQ_NONE;
-
- @@ -364,6 +393,10 @@ fec_enet_interrupt(int irq, void * dev_i
- int_events = readl(fep->hwp + FEC_IEVENT);
- writel(int_events, fep->hwp + FEC_IEVENT);
-
- +#ifdef CONFIG_FEC_1588
- + if (__raw_readb(MCF_DTIM1_DTER) & MCF_DTIM_DTER_REF)
- + __raw_writeb(MCF_DTIM_DTER_REF, MCF_DTIM1_DTER);
- +#endif
- if (int_events & FEC_ENET_RXF) {
- ret = IRQ_HANDLED;
- fec_enet_rx(dev);
- @@ -378,6 +411,19 @@ fec_enet_interrupt(int irq, void * dev_i
- fec_enet_tx(dev);
- }
-
- +#ifdef CONFIG_FEC_1588
- + if (int_events & FEC_ENET_TS_AVAIL) {
- + ret = IRQ_HANDLED;
- + fec_ptp_store_txstamp(fep->ptp_priv);
- + }
- +
- + if (int_events & FEC_ENET_TS_TIMER) {
- + ret = IRQ_HANDLED;
- + if (fep->ptimer_present)
- + fpp->prtc++;
- + }
- +#endif
- +
- if (int_events & FEC_ENET_MII) {
- ret = IRQ_HANDLED;
- complete(&fep->mdio_done);
- @@ -394,6 +440,9 @@ fec_enet_tx(struct net_device *dev)
- struct fec_enet_private *fep;
- struct bufdesc *bdp;
- unsigned short status;
- +#ifdef CONFIG_FEC_1588
- + unsigned long estatus;
- +#endif
- struct sk_buff *skb;
-
- fep = netdev_priv(dev);
- @@ -437,6 +486,13 @@ fec_enet_tx(struct net_device *dev)
- if (status & BD_ENET_TX_DEF)
- dev->stats.collisions++;
-
- +#if defined(CONFIG_FEC_1588)
- + if (fep->ptimer_present) {
- + estatus = bdp->cbd_esc;
- + if (estatus & BD_ENET_TX_TS)
- + fec_ptp_store_txstamp(fep->ptp_priv);
- + }
- +#endif
- /* Free the sk buffer associated with this last transmit */
- dev_kfree_skb_any(skb);
- fep->tx_skbuff[fep->skb_dirty] = NULL;
- @@ -470,6 +526,9 @@ static void
- fec_enet_rx(struct net_device *dev)
- {
- struct fec_enet_private *fep = netdev_priv(dev);
- +#ifdef CONFIG_FEC_1588
- + struct fec_ptp_private *fpp = fep->ptp_priv;
- +#endif
- const struct platform_device_id *id_entry =
- platform_get_device_id(fep->pdev);
- struct bufdesc *bdp;
- @@ -554,6 +613,12 @@ fec_enet_rx(struct net_device *dev)
- skb_put(skb, pkt_len - 4); /* Make room */
- skb_copy_to_linear_data(skb, data, pkt_len - 4);
- skb->protocol = eth_type_trans(skb, dev);
- +
- +#ifdef CONFIG_FEC_1588
- + /* 1588 messeage TS handle */
- + if (fep->ptimer_present)
- + fec_ptp_store_rxstamp(fpp, skb, bdp);
- +#endif
- netif_rx(skb);
- }
-
- @@ -567,6 +632,11 @@ rx_processing_done:
- status |= BD_ENET_RX_EMPTY;
- bdp->cbd_sc = status;
-
- +#ifdef CONFIG_FEC_1588
- + bdp->cbd_esc = BD_ENET_RX_INT;
- + bdp->cbd_prot = 0;
- + bdp->cbd_bdu = 0;
- +#endif
- /* Update BD pointer to next entry */
- if (status & BD_ENET_RX_WRAP)
- bdp = fep->rx_bd_base;
- @@ -669,8 +739,11 @@ static void fec_enet_adjust_link(struct
- fec_stop(dev);
-
- if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
- - writel(2, fep->hwp + FEC_ECNTRL);
- -
- +#ifdef CONFIG_FEC_1588
- + writel(0x00000012, fep->hwp + FEC_ECNTRL);
- +#else
- + writel(0x00000002, fep->hwp + FEC_ECNTRL);
- +#endif
- status_change = 1;
- }
-
- @@ -983,6 +1056,10 @@ static int fec_enet_alloc_buffers(struct
- bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
- FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
- +
- +#ifdef CONFIG_FEC_1588
- + bdp->cbd_esc = BD_ENET_RX_INT;
- +#endif
- bdp++;
- }
-
- @@ -996,6 +1073,9 @@ static int fec_enet_alloc_buffers(struct
-
- bdp->cbd_sc = 0;
- bdp->cbd_bufaddr = 0;
- +#ifdef CONFIG_FEC_1588
- + bdp->cbd_esc = BD_ENET_TX_INT;
- +#endif
- bdp++;
- }
-
- @@ -1256,8 +1336,12 @@ fec_restart(struct net_device *dev, int
- writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
- }
-
- +#ifdef CONFIG_FEC_1588
- + writel(0x7fff8000, fep->hwp + FEC_IEVENT);
- +#else
- /* Clear any outstanding interrupt. */
- writel(0xffc00000, fep->hwp + FEC_IEVENT);
- +#endif
-
- /* Reset all multicast. */
- writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
- @@ -1342,8 +1426,25 @@ fec_restart(struct net_device *dev, int
- #endif
- }
-
- +#ifdef CONFIG_FEC_1588
- + if (fep->ptimer_present) {
- + int ret;
- + /* Set Timer count */
- + ret = fec_ptp_start(fep->ptp_priv);
- + if (ret) {
- + fep->ptimer_present = 0;
- + writel(2, fep->hwp + FEC_ECNTRL);
- + } else {
- + val = readl(fep->hwp + FEC_ECNTRL);
- + val |= 0x00000012;
- + writel(val, fep->hwp + FEC_ECNTRL);
- + }
- + } else
- + writel(2, fep->hwp + FEC_ECNTRL);
- +#else
- /* And last, enable the transmit and receive processing */
- writel(2, fep->hwp + FEC_ECNTRL);
- +#endif
- writel(0, fep->hwp + FEC_R_DES_ACTIVE);
-
- /* Enable interrupts we wish to service */
- @@ -1367,6 +1468,10 @@ fec_stop(struct net_device *dev)
- writel(1, fep->hwp + FEC_ECNTRL);
- udelay(10);
- writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
- +#ifdef CONFIG_FEC_1588
- + if (fep->ptimer_present)
- + fec_ptp_stop(fep->ptp_priv);
- +#endif
- writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
- }
-
- @@ -1428,6 +1533,24 @@ fec_probe(struct platform_device *pdev)
- }
- }
-
- +#ifdef CONFIG_FEC_1588
- + i = (pdev->id) ? (64 + 64 + 64 + 7) : (64 + 64 + 64);
- + if (request_irq(i + 48, fec_enet_interrupt, IRQF_DISABLED,
- + "1588 TS AVAIL", ndev) != 0)
- + printk(KERN_ERR "FEC: Could not alloc FEC %x 1588 TS AVAIL "
- + "IRQ(%d)!\n", pdev->id, i + 48);
- +
- + if (pdev->id == 0) {
- + printk("setup TS timer interrupt through DMA timer1\n");
- + __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM1_DTMR);
- +
- + if (request_irq(64 + 33, fec_enet_interrupt, IRQF_DISABLED,
- + "1588 TS TIMER", ndev) != 0)
- + printk(KERN_ERR "FEC: Could not alloc FEC %x 1588 TS"
- + " TIMER IRQ(%d)!\n", pdev->id, 64 + 33);
- + }
- +#endif
- +
- fep->clk = clk_get(&pdev->dev, "fec_clk");
- if (IS_ERR(fep->clk)) {
- ret = PTR_ERR(fep->clk);
- @@ -1443,6 +1566,20 @@ fec_probe(struct platform_device *pdev)
- if (ret)
- goto failed_mii_init;
-
- +#ifdef CONFIG_FEC_1588
- + fep->ptp_priv = kzalloc(sizeof(struct fec_ptp_private),
- + GFP_KERNEL);
- + if (fep->ptp_priv) {
- + fep->ptp_priv->hwp = fep->hwp;
- + ret = fec_ptp_init(fep->ptp_priv, pdev->id);
- + if (ret)
- + printk(KERN_ERR "IEEE1588: ptp-timer init failed\n");
- + else
- + fep->ptimer_present = 1;
- + } else
- + printk(KERN_ERR "IEEE1588: failed to malloc memory\n");
- +#endif
- +
- /* Carrier starts down, phylib will bring it up */
- netif_carrier_off(ndev);
-
- @@ -1454,6 +1591,12 @@ fec_probe(struct platform_device *pdev)
-
- failed_register:
- fec_enet_mii_remove(fep);
- +#ifdef CONFIG_FEC_1588
- + if (fep->ptimer_present)
- + fec_ptp_cleanup(fep->ptp_priv);
- +
- + kfree(fep->ptp_priv);
- +#endif
- failed_mii_init:
- failed_init:
- clk_disable(fep->clk);
- @@ -1485,6 +1628,12 @@ fec_drv_remove(struct platform_device *p
- clk_disable(fep->clk);
- clk_put(fep->clk);
- iounmap((void __iomem *)ndev->base_addr);
- +#ifdef CONFIG_FEC_1588
- + if (fep->ptimer_present)
- + fec_ptp_cleanup(fep->ptp_priv);
- +
- + kfree(fep->ptp_priv);
- +#endif
- unregister_netdev(ndev);
- free_netdev(ndev);
- return 0;
- --- a/drivers/net/fec.h
- +++ b/drivers/net/fec.h
- @@ -50,6 +50,16 @@
- #define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */
- #define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */
-
- +#if defined(CONFIG_FEC_1588)
- +#define FEC_ATIME_CTRL 0x400
- +#define FEC_ATIME 0x404
- +#define FEC_ATIME_EVT_OFFSET 0x408
- +#define FEC_ATIME_EVT_PERIOD 0x40c
- +#define FEC_ATIME_CORR 0x410
- +#define FEC_ATIME_INC 0x414
- +#define FEC_TS_TIMESTAMP 0x418
- +#endif
- +
- #else
-
- #define FEC_ECNTRL 0x000 /* Ethernet control reg */
- @@ -78,6 +88,9 @@
-
- #endif /* CONFIG_M5272 */
-
- +#if defined(CONFIG_FEC_1588)
- +#define FEC_ENHANCED_MODE 1
- +#endif
-
- /*
- * Define the buffer descriptor structure.
- @@ -93,6 +106,14 @@ struct bufdesc {
- unsigned short cbd_sc; /* Control and status info */
- unsigned short cbd_datlen; /* Data length */
- unsigned long cbd_bufaddr; /* Buffer address */
- +
- +#ifdef FEC_ENHANCED_MODE
- + unsigned long cbd_esc;
- + unsigned long cbd_prot;
- + unsigned long cbd_bdu;
- + unsigned long ts;
- + unsigned short res0[4];
- +#endif
- };
- #endif
-
- @@ -128,6 +149,7 @@ struct bufdesc {
- #define BD_ENET_RX_OV ((ushort)0x0002)
- #define BD_ENET_RX_CL ((ushort)0x0001)
- #define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */
- +#define BD_ENET_RX_INT 0x00800000
-
- /* Buffer descriptor control/status used by Ethernet transmit.
- */
- @@ -146,6 +168,9 @@ struct bufdesc {
- #define BD_ENET_TX_CSL ((ushort)0x0001)
- #define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
-
- +#define BD_ENET_TX_TS 0x20000000
- +#define BD_ENET_TX_INT 0x40000000
- +#define BD_ENET_TX_BDU 0x80000000
-
- /****************************************************************************/
- #endif /* FEC_H */
- --- /dev/null
- +++ b/drivers/net/fec_1588.c
- @@ -0,0 +1,626 @@
- +/*
- + * drivers/net/fec_1588.c
- + *
- + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
- + * Copyright (C) 2009 IXXAT Automation, GmbH
- + *
- + * FEC Ethernet Driver -- IEEE 1588 interface functionality
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + *
- + */
- +
- +#include <linux/io.h>
- +#include <linux/device.h>
- +#include <linux/fs.h>
- +#include <linux/vmalloc.h>
- +#include <linux/spinlock.h>
- +#include <linux/ip.h>
- +#include <linux/udp.h>
- +#include <asm/mcf5441x_ccm.h>
- +#include <asm/mcf5441x_dtim.h>
- +#include <asm/mcfsim.h>
- +#include "fec_1588.h"
- +
- +static DECLARE_WAIT_QUEUE_HEAD(ptp_rx_ts_wait);
- +#define PTP_GET_RX_TIMEOUT (HZ/10)
- +#define COLDFIRE_DTIM1_INT (64+32+1)
- +
- +static struct fec_ptp_private *ptp_private[2];
- +
- +static void init_DTIM1_for_1588(struct fec_ptp_private *priv)
- +{
- + printk(KERN_INFO "Initializing DTIM1 for 1588 TS timer\n");
- +
- + __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM1_DTMR);
- +
- + /*Enable 1588*/
- +
- + __raw_writeb(MCF_DTIM_DTXMR_1588EN, MCF_DTIM1_DTXMR);
- +
- + /*Compare to the 1588 timerbase*/
- + __raw_writel(FEC_T_PERIOD_ONE_SEC - FEC_T_INC_40MHZ, MCF_DTIM1_DTRR);
- +
- + __raw_writeb(MCF_DTIM_DTER_REF, MCF_DTIM1_DTER);
- +
- + MCF_GPIO_PAR_TIMER = (MCF_GPIO_PAR_TIMER & MCF_GPIO_PAR_TIMER_T1IN_MASK)
- + | MCF_GPIO_PAR_TIMER_T1IN_T1OUT;
- +}
- +
- +static void start_DTIM1(void)
- +{
- + __raw_writew(MCF_DTIM_DTMR_RST_EN | MCF_DTIM_DTMR_ORRI |
- + MCF_DTIM_DTMR_OM, MCF_DTIM1_DTMR);
- +}
- +
- +static void stop_DTIM1(void)
- +{
- + __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM1_DTMR);
- +}
- +
- +/* Alloc the ring resource */
- +static int fec_ptp_init_circ(struct circ_buf *ptp_buf)
- +{
- + ptp_buf->buf = vmalloc(DEFAULT_PTP_RX_BUF_SZ *
- + sizeof(struct fec_ptp_data_t));
- +
- + if (!ptp_buf->buf)
- + return 1;
- + ptp_buf->head = 0;
- + ptp_buf->tail = 0;
- +
- + return 0;
- +}
- +
- +static inline int fec_ptp_calc_index(int size, int curr_index, int offset)
- +{
- + return (curr_index + offset) % size;
- +}
- +
- +static int fec_ptp_is_empty(struct circ_buf *buf)
- +{
- + return (buf->head == buf->tail);
- +}
- +
- +static int fec_ptp_nelems(struct circ_buf *buf)
- +{
- + const int front = buf->head;
- + const int end = buf->tail;
- + const int size = DEFAULT_PTP_RX_BUF_SZ;
- + int n_items;
- +
- + if (end > front)
- + n_items = end - front;
- + else if (end < front)
- + n_items = size - (front - end);
- + else
- + n_items = 0;
- +
- + return n_items;
- +}
- +
- +static int fec_ptp_is_full(struct circ_buf *buf)
- +{
- + if (fec_ptp_nelems(buf) ==
- + (DEFAULT_PTP_RX_BUF_SZ - 1))
- + return 1;
- + else
- + return 0;
- +}
- +
- +static int fec_ptp_insert(struct circ_buf *ptp_buf,
- + struct fec_ptp_data_t *data,
- + struct fec_ptp_private *priv)
- +{
- + struct fec_ptp_data_t *tmp;
- +
- + if (fec_ptp_is_full(ptp_buf))
- + return 1;
- +
- + spin_lock(&priv->ptp_lock);
- + tmp = (struct fec_ptp_data_t *)(ptp_buf->buf) + ptp_buf->tail;
- +
- + tmp->key = data->key;
- + tmp->ts_time.sec = data->ts_time.sec;
- + tmp->ts_time.nsec = data->ts_time.nsec;
- +
- + ptp_buf->tail = fec_ptp_calc_index(DEFAULT_PTP_RX_BUF_SZ,
- + ptp_buf->tail, 1);
- + spin_unlock(&priv->ptp_lock);
- +
- + return 0;
- +}
- +
- +static int fec_ptp_find_and_remove(struct circ_buf *ptp_buf,
- + int key,
- + struct fec_ptp_data_t *data,
- + struct fec_ptp_private *priv)
- +{
- + int i;
- + int size = DEFAULT_PTP_RX_BUF_SZ;
- + int end = ptp_buf->tail;
- + unsigned long flags;
- + struct fec_ptp_data_t *tmp;
- +
- + if (fec_ptp_is_empty(ptp_buf))
- + return 1;
- +
- + i = ptp_buf->head;
- + while (i != end) {
- + tmp = (struct fec_ptp_data_t *)(ptp_buf->buf) + i;
- + if (tmp->key == key)
- + break;
- + i = fec_ptp_calc_index(size, i, 1);
- + }
- +
- + spin_lock_irqsave(&priv->ptp_lock, flags);
- + if (i == end) {
- + ptp_buf->head = end;
- + spin_unlock_irqrestore(&priv->ptp_lock, flags);
- + return 1;
- + }
- +
- + data->ts_time.sec = tmp->ts_time.sec;
- + data->ts_time.nsec = tmp->ts_time.nsec;
- +
- + ptp_buf->head = fec_ptp_calc_index(size, i, 1);
- + spin_unlock_irqrestore(&priv->ptp_lock, flags);
- +
- + return 0;
- +}
- +
- +/* 1588 Module intialization */
- +int fec_ptp_start(struct fec_ptp_private *priv)
- +{
- + struct fec_ptp_private *fpp = priv;
- +
- + MCF_CCM_MISCCR3 = 0x0000;
- +
- + init_DTIM1_for_1588(priv);
- +
- + /* Select 1588 Timer source and enable module for starting Tmr Clock */
- + fec_writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL);
- + fec_writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET,
- + fpp->hwp + FEC_ATIME_INC);
- + fec_writel(FEC_T_PERIOD_ONE_SEC, fpp->hwp + FEC_ATIME_EVT_PERIOD);
- + /* start counter */
- + fec_writel(FEC_T_CTRL_PERIOD_RST | FEC_T_CTRL_ENABLE |
- + FEC_T_CTRL_PINPER, fpp->hwp + FEC_ATIME_CTRL);
- +
- + start_DTIM1();
- +
- + return 0;
- +}
- +
- +/* Cleanup routine for 1588 module.
- + * When PTP is disabled this routing is called */
- +void fec_ptp_stop(struct fec_ptp_private *priv)
- +{
- + struct fec_ptp_private *fpp = priv;
- +
- + fec_writel(0, fpp->hwp + FEC_ATIME_CTRL);
- + fec_writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL);
- + stop_DTIM1();
- +}
- +
- +static void fec_get_curr_cnt(struct fec_ptp_private *priv,
- + struct ptp_rtc_time *curr_time)
- +{
- + u32 tempval;
- +
- + fec_writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
- + fec_writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
- + curr_time->rtc_time.nsec = fec_readl(priv->hwp + FEC_ATIME);
- + curr_time->rtc_time.sec = priv->prtc;
- +
- + fec_writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL);
- + tempval = fec_readl(priv->hwp + FEC_ATIME);
- + if (tempval < curr_time->rtc_time.nsec) {
- + curr_time->rtc_time.nsec = tempval;
- + curr_time->rtc_time.sec = priv->prtc;
- + }
- +}
- +
- +/* Set the 1588 timer counter registers */
- +static void fec_set_1588cnt(struct fec_ptp_private *priv,
- + struct ptp_rtc_time *fec_time)
- +{
- + u32 tempval;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&priv->cnt_lock, flags);
- +
- + priv->prtc = fec_time->rtc_time.sec;
- +
- + tempval = fec_time->rtc_time.nsec;
- + fec_writel(tempval, priv->hwp + FEC_ATIME);
- + spin_unlock_irqrestore(&priv->cnt_lock, flags);
- +}
- +
- +/* Set the BD to ptp */
- +int fec_ptp_do_txstamp(struct sk_buff *skb)
- +{
- + struct iphdr *iph;
- + struct udphdr *udph;
- +
- + if (skb->len > 44) {
- + /* Check if port is 319 for PTP Event, and check for UDP */
- + iph = ip_hdr(skb);
- + if (iph == NULL || iph->protocol != FEC_PACKET_TYPE_UDP)
- + return 0;
- +
- + udph = udp_hdr(skb);
- + if (udph != NULL && ntohs(udph->source) == 319)
- + return 1;
- + }
- +
- + return 0;
- +}
- +
- +void fec_ptp_store_txstamp(struct fec_ptp_private *priv)
- +{
- + struct fec_ptp_private *fpp = priv;
- + unsigned int reg;
- +
- + reg = fec_readl(fpp->hwp + FEC_TS_TIMESTAMP);
- + fpp->txstamp.nsec = reg;
- + fpp->txstamp.sec = fpp->prtc;
- +}
- +
- +void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
- + struct sk_buff *skb,
- + struct bufdesc *bdp)
- +{
- + int msg_type, seq_id, control;
- + struct fec_ptp_data_t tmp_rx_time;
- + struct fec_ptp_private *fpp = priv;
- + struct iphdr *iph;
- + struct udphdr *udph;
- +
- + /* Check for UDP, and Check if port is 319 for PTP Event */
- + iph = (struct iphdr *)(skb->data + FEC_PTP_IP_OFFS);
- + if (iph->protocol != FEC_PACKET_TYPE_UDP)
- + return;
- +
- + udph = (struct udphdr *)(skb->data + FEC_PTP_UDP_OFFS);
- + if (ntohs(udph->source) != 319)
- + return;
- +
- + seq_id = *((u16 *)(skb->data + FEC_PTP_SEQ_ID_OFFS));
- + control = *((u8 *)(skb->data + FEC_PTP_CTRL_OFFS));
- +
- + tmp_rx_time.key = ntohs(seq_id);
- + tmp_rx_time.ts_time.sec = fpp->prtc;
- + tmp_rx_time.ts_time.nsec = bdp->ts;
- +
- + switch (control) {
- +
- + case PTP_MSG_SYNC:
- + fec_ptp_insert(&(priv->rx_time_sync), &tmp_rx_time, priv);
- + break;
- +
- + case PTP_MSG_DEL_REQ:
- + fec_ptp_insert(&(priv->rx_time_del_req), &tmp_rx_time, priv);
- + break;
- +
- + /* clear transportSpecific field*/
- + case PTP_MSG_ALL_OTHER:
- + msg_type = (*((u8 *)(skb->data +
- + FEC_PTP_MSG_TYPE_OFFS))) & 0x0F;
- + switch (msg_type) {
- + case PTP_MSG_P_DEL_REQ:
- + fec_ptp_insert(&(priv->rx_time_pdel_req),
- + &tmp_rx_time, priv);
- + break;
- + case PTP_MSG_P_DEL_RESP:
- + fec_ptp_insert(&(priv->rx_time_pdel_resp),
- + &tmp_rx_time, priv);
- + break;
- + default:
- + break;
- + }
- + break;
- + default:
- + break;
- + }
- +
- + wake_up_interruptible(&ptp_rx_ts_wait);
- +}
- +
- +static void fec_get_tx_timestamp(struct fec_ptp_private *priv,
- + struct ptp_time *tx_time)
- +{
- + tx_time->sec = priv->txstamp.sec;
- + tx_time->nsec = priv->txstamp.nsec;
- +}
- +
- +static uint8_t fec_get_rx_time(struct fec_ptp_private *priv,
- + struct ptp_ts_data *pts,
- + struct ptp_time *rx_time)
- +{
- + struct fec_ptp_data_t tmp;
- + int key, flag;
- + u8 mode;
- +
- + key = pts->seq_id;
- + mode = pts->message_type;
- + switch (mode) {
- + case PTP_MSG_SYNC:
- + flag = fec_ptp_find_and_remove(&(priv->rx_time_sync),
- + key, &tmp, priv);
- + break;
- + case PTP_MSG_DEL_REQ:
- + flag = fec_ptp_find_and_remove(&(priv->rx_time_del_req),
- + key, &tmp, priv);
- + break;
- +
- + case PTP_MSG_P_DEL_REQ:
- + flag = fec_ptp_find_and_remove(&(priv->rx_time_pdel_req),
- + key, &tmp, priv);
- + break;
- + case PTP_MSG_P_DEL_RESP:
- + flag = fec_ptp_find_and_remove(&(priv->rx_time_pdel_resp),
- + key, &tmp, priv);
- + break;
- +
- + default:
- + flag = 1;
- + printk(KERN_ERR "ERROR\n");
- + break;
- + }
- +
- + if (!flag) {
- + rx_time->sec = tmp.ts_time.sec;
- + rx_time->nsec = tmp.ts_time.nsec;
- + return 0;
- + } else {
- + wait_event_interruptible_timeout(ptp_rx_ts_wait, 0,
- + PTP_GET_RX_TIMEOUT);
- +
- + switch (mode) {
- + case PTP_MSG_SYNC:
- + flag = fec_ptp_find_and_remove(&(priv->rx_time_sync),
- + key, &tmp, priv);
- + break;
- + case PTP_MSG_DEL_REQ:
- + flag = fec_ptp_find_and_remove(
- + &(priv->rx_time_del_req), key, &tmp, priv);
- + break;
- + case PTP_MSG_P_DEL_REQ:
- + flag = fec_ptp_find_and_remove(
- + &(priv->rx_time_pdel_req), key, &tmp, priv);
- + break;
- + case PTP_MSG_P_DEL_RESP:
- + flag = fec_ptp_find_and_remove(
- + &(priv->rx_time_pdel_resp), key, &tmp, priv);
- + break;
- + }
- +
- + if (flag == 0) {
- + rx_time->sec = tmp.ts_time.sec;
- + rx_time->nsec = tmp.ts_time.nsec;
- + return 0;
- + }
- +
- + return -1;
- + }
- +}
- +
- +static void fec_handle_ptpdrift(
- + struct ptp_set_comp *comp,
- + struct ptp_time_correct *ptc)
- +{
- + u32 ndrift;
- + u32 i;
- + u32 tmp, tmp_ns, tmp_prid;
- + u32 min_ns, min_prid, miss_ns;
- +
- + ndrift = comp->drift;
- + if (ndrift == 0) {
- + ptc->corr_inc = 0;
- + ptc->corr_period = 0;
- + return;
- + }
- +
- + if (ndrift >= FEC_ATIME_40MHZ) {
- + ptc->corr_inc = (u32)(ndrift / FEC_ATIME_40MHZ);
- + ptc->corr_period = 1;
- + return;
- + }
- +
- + min_ns = 1;
- + tmp = FEC_ATIME_40MHZ % ndrift;
- + tmp_prid = (u32)(FEC_ATIME_40MHZ / ndrift);
- + min_prid = tmp_prid;
- + miss_ns = tmp / tmp_prid;
- + for (i = 2; i <= FEC_T_INC_40MHZ; i++) {
- + tmp = (FEC_ATIME_40MHZ * i) % ndrift;
- + tmp_prid = (FEC_ATIME_40MHZ * i) / ndrift;
- + tmp_ns = tmp / tmp_prid;
- + if (tmp_ns <= 10) {
- + min_ns = i;
- + min_prid = tmp_prid;
- + break;
- + }
- +
- + if (tmp_ns < miss_ns) {
- + min_ns = i;
- + min_prid = tmp_prid;
- + miss_ns = tmp_ns;
- + }
- + }
- +
- + ptc->corr_inc = min_ns;
- + ptc->corr_period = min_prid;
- +}
- +
- +static void fec_set_drift(struct fec_ptp_private *priv,
- + struct ptp_set_comp *comp)
- +{
- + struct ptp_time_correct tc;
- + struct fec_ptp_private *fpp = priv;
- + u32 tmp, corr_ns;
- +
- + fec_handle_ptpdrift(comp, &tc);
- + if (tc.corr_inc == 0)
- + return;
- +
- + if (comp->o_ops == TRUE)
- + corr_ns = FEC_T_INC_40MHZ + tc.corr_inc;
- + else
- + corr_ns = FEC_T_INC_40MHZ - tc.corr_inc;
- +
- + tmp = fec_readl(fpp->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
- + tmp |= corr_ns << FEC_T_INC_CORR_OFFSET;
- + fec_writel(tmp, fpp->hwp + FEC_ATIME_INC);
- +
- + fec_writel(tc.corr_period, fpp->hwp + FEC_ATIME_CORR);
- +}
- +
- +static int ptp_open(struct inode *inode, struct file *file)
- +{
- + return 0;
- +}
- +
- +static int ptp_release(struct inode *inode, struct file *file)
- +{
- + return 0;
- +}
- +
- +static long ptp_unlocked_ioctl(
- + struct file *file,
- + unsigned int cmd,
- + unsigned long arg)
- +{
- + struct ptp_rtc_time *cnt;
- + struct ptp_rtc_time curr_time;
- + struct ptp_time rx_time, tx_time;
- + struct ptp_ts_data *p_ts;
- + struct ptp_set_comp *p_comp;
- + struct fec_ptp_private *priv;
- + struct inode *inode = file->f_mapping->host;
- + unsigned int minor = MINOR(inode->i_rdev);
- + long retval = 0;
- +
- + priv = (struct fec_ptp_private *) ptp_private[minor];
- + switch (cmd) {
- + case PTP_GET_RX_TIMESTAMP:
- + p_ts = (struct ptp_ts_data *)arg;
- + retval = fec_get_rx_time(priv, p_ts, &rx_time);
- + if (retval == 0)
- + copy_to_user((void __user *)(&(p_ts->ts)), &rx_time,
- + sizeof(rx_time));
- + break;
- + case PTP_GET_TX_TIMESTAMP:
- + p_ts = (struct ptp_ts_data *)arg;
- + fec_get_tx_timestamp(priv, &tx_time);
- + copy_to_user((void __user *)(&(p_ts->ts)), &tx_time,
- + sizeof(tx_time));
- + break;
- + case PTP_GET_CURRENT_TIME:
- + fec_get_curr_cnt(priv, &curr_time);
- + copy_to_user((void __user *)arg, &curr_time, sizeof(curr_time));
- + break;
- + case PTP_SET_RTC_TIME:
- + cnt = (struct ptp_rtc_time *)arg;
- + fec_set_1588cnt(priv, cnt);
- + break;
- + case PTP_FLUSH_TIMESTAMP:
- + /* reset sync buffer */
- + priv->rx_time_sync.head = 0;
- + priv->rx_time_sync.tail = 0;
- + /* reset delay_req buffer */
- + priv->rx_time_del_req.head = 0;
- + priv->rx_time_del_req.tail = 0;
- + /* reset pdelay_req buffer */
- + priv->rx_time_pdel_req.head = 0;
- + priv->rx_time_pdel_req.tail = 0;
- + /* reset pdelay_resp buffer */
- + priv->rx_time_pdel_resp.head = 0;
- + priv->rx_time_pdel_resp.tail = 0;
- + break;
- + case PTP_SET_COMPENSATION:
- + p_comp = (struct ptp_set_comp *)arg;
- + fec_set_drift(priv, p_comp);
- + break;
- + case PTP_GET_ORIG_COMP:
- + ((struct ptp_get_comp *)arg)->dw_origcomp = FEC_PTP_ORIG_COMP;
- + break;
- + default:
- + return -EINVAL;
- + }
- + return retval;
- +}
- +
- +static const struct file_operations ptp_fops = {
- + .owner = THIS_MODULE,
- + .llseek = NULL,
- + .read = NULL,
- + .write = NULL,
- + .unlocked_ioctl = ptp_unlocked_ioctl,
- + .open = ptp_open,
- + .release = ptp_release,
- +};
- +
- +static int init_ptp(void)
- +{
- + if (register_chrdev(PTP_MAJOR, "ptp", &ptp_fops))
- + printk(KERN_ERR "Unable to register PTP deivce as char\n");
- +
- + return 0;
- +}
- +
- +static void ptp_free(void)
- +{
- + /*unregister the PTP device*/
- + unregister_chrdev(PTP_MAJOR, "ptp");
- +}
- +
- +
- +
- +/*
- + * Resource required for accessing 1588 Timer Registers.
- + */
- +int fec_ptp_init(struct fec_ptp_private *priv, int id)
- +{
- + fec_ptp_init_circ(&(priv->rx_time_sync));
- + fec_ptp_init_circ(&(priv->rx_time_del_req));
- + fec_ptp_init_circ(&(priv->rx_time_pdel_req));
- + fec_ptp_init_circ(&(priv->rx_time_pdel_resp));
- +
- + spin_lock_init(&priv->ptp_lock);
- + spin_lock_init(&priv->cnt_lock);
- + ptp_private[id] = priv;
- + if (id == 0)
- + init_ptp();
- + return 0;
- +}
- +EXPORT_SYMBOL(fec_ptp_init);
- +
- +void fec_ptp_cleanup(struct fec_ptp_private *priv)
- +{
- +
- + if (priv->rx_time_sync.buf)
- + vfree(priv->rx_time_sync.buf);
- + if (priv->rx_time_del_req.buf)
- + vfree(priv->rx_time_del_req.buf);
- + if (priv->rx_time_pdel_req.buf)
- + vfree(priv->rx_time_pdel_req.buf);
- + if (priv->rx_time_pdel_resp.buf)
- + vfree(priv->rx_time_pdel_resp.buf);
- +
- + ptp_free();
- +}
- +EXPORT_SYMBOL(fec_ptp_cleanup);
- --- /dev/null
- +++ b/drivers/net/fec_1588.h
- @@ -0,0 +1,195 @@
- +/*
- + * drivers/net/fec_1588.h
- + *
- + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- + *
- + */
- +
- +#ifndef FEC_1588_H
- +#define FEC_1588_H
- +
- +#include <linux/circ_buf.h>
- +#include "fec.h"
- +
- +#define fec_readl(addr) \
- + ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
- +
- +#define fec_writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
- +
- +#define FALSE 0
- +#define TRUE 1
- +
- +/* FEC 1588 register bits */
- +#define FEC_T_CTRL_CAPTURE 0x00000800
- +#define FEC_T_CTRL_RESTART 0x00000200
- +#define FEC_T_CTRL_PERIOD_RST 0x00000010
- +#define FEC_T_CTRL_PINPER 0x00000080
- +#define FEC_T_CTRL_ENABLE 0x00000001
- +
- +#define FEC_T_INC_MASK 0x0000007f
- +#define FEC_T_INC_OFFSET 0
- +#define FEC_T_INC_CORR_MASK 0x00007f00
- +#define FEC_T_INC_CORR_OFFSET 8
- +
- +#define FEC_T_INC_40MHZ 8
- +#define FEC_ATIME_40MHZ 125000000
- +
- +#define FEC_T_PERIOD_ONE_SEC 0x3B9ACA00
- +
- +/* IEEE 1588 definition */
- +#define FEC_ECNTRL_TS_EN 0x10
- +#define PTP_MAJOR 232 /*the temporary major number
- + *used by PTP driver, the major
- + *number 232~239 is unassigned*/
- +
- +#define DEFAULT_PTP_RX_BUF_SZ 2048
- +#define PTP_MSG_SYNC 0x0
- +#define PTP_MSG_DEL_REQ 0x1
- +#define PTP_MSG_P_DEL_REQ 0x2
- +#define PTP_MSG_P_DEL_RESP 0x3
- +#define PTP_MSG_DEL_RESP 0x4
- +#define PTP_MSG_ALL_OTHER 0x5
- +
- +#define PTP_GET_TX_TIMESTAMP 0x1
- +#define PTP_GET_RX_TIMESTAMP 0x9
- +#define PTP_SET_RTC_TIME 0x3
- +#define PTP_SET_COMPENSATION 0x4
- +#define PTP_GET_CURRENT_TIME 0x5
- +#define PTP_FLUSH_TIMESTAMP 0x6
- +#define PTP_ADJ_ADDEND 0x7
- +#define PTP_GET_ORIG_COMP 0x8
- +#define PTP_GET_ADDEND 0xB
- +#define PTP_GET_RX_TIMESTAMP_PDELAY_REQ 0xC
- +#define PTP_GET_RX_TIMESTAMP_PDELAY_RESP 0xD
- +
- +#define FEC_PTP_DOMAIN_DLFT 0xe0000181
- +#define FEC_PTP_IP_OFFS 0x0
- +#define FEC_PTP_UDP_OFFS 0x14
- +#define FEC_PTP_MSG_TYPE_OFFS 0x1C
- +#define FEC_PTP_SEQ_ID_OFFS 0x3A
- +#define FEC_PTP_COR_NS 0x24
- +#define FEC_PTP_CTRL_OFFS 0x3C
- +#define FEC_PACKET_TYPE_UDP 0x11
- +
- +#define FEC_PTP_ORIG_COMP 0x15555
- +
- +/* PTP standard time representation structure */
- +struct ptp_time {
- + u64 sec; /* seconds */
- + u32 nsec; /* nanoseconds */
- +};
- +
- +/* Structure for PTP Time Stamp */
- +struct fec_ptp_data_t {
- + int key;
- + struct ptp_time ts_time;
- +};
- +
- +/* interface for PTP driver command GET_TX_TIME */
- +struct ptp_ts_data {
- + /* PTP version */
- + u8 version;
- + /* PTP source port ID */
- + u8 spid[10];
- + /* PTP sequence ID */
- + u16 seq_id;
- + /* PTP message type */
- + u8 message_type;
- + /* PTP timestamp */
- + struct ptp_time ts;
- +};
- +
- +/* interface for PTP driver command SET_RTC_TIME/GET_CURRENT_TIME */
- +struct ptp_rtc_time {
- + struct ptp_time rtc_time;
- +};
- +
- +/* interface for PTP driver command SET_COMPENSATION */
- +struct ptp_set_comp {
- + u32 drift;
- + u32 o_ops;
- +};
- +
- +/* interface for PTP driver command GET_ORIG_COMP */
- +struct ptp_get_comp {
- + /* the initial compensation value */
- + u32 dw_origcomp;
- + /* the minimum compensation value */
- + u32 dw_mincomp;
- + /*the max compensation value*/
- + u32 dw_maxcomp;
- + /*the min drift applying min compensation value in ppm*/
- + u32 dw_mindrift;
- + /*the max drift applying max compensation value in ppm*/
- + u32 dw_maxdrift;
- +};
- +
- +struct ptp_time_correct {
- + u32 corr_period;
- + u32 corr_inc;
- +};
- +
- +/* PTP message version */
- +#define PTP_1588_MSG_VER_1 1
- +#define PTP_1588_MSG_VER_2 2
- +
- +struct fec_ptp_private {
- + void __iomem *hwp;
- +
- + struct circ_buf rx_time_sync;
- + struct circ_buf rx_time_del_req;
- + struct circ_buf rx_time_pdel_req;
- + struct circ_buf rx_time_pdel_resp;
- + spinlock_t ptp_lock;
- + spinlock_t cnt_lock;
- +
- + u64 prtc;
- + struct ptp_time txstamp;
- +};
- +
- +#ifdef CONFIG_FEC_1588
- +extern int fec_ptp_init(struct fec_ptp_private *priv, int id);
- +extern void fec_ptp_cleanup(struct fec_ptp_private *priv);
- +extern int fec_ptp_start(struct fec_ptp_private *priv);
- +extern void fec_ptp_stop(struct fec_ptp_private *priv);
- +extern int fec_ptp_do_txstamp(struct sk_buff *skb);
- +extern void fec_ptp_store_txstamp(struct fec_ptp_private *priv);
- +extern void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
- + struct sk_buff *skb,
- + struct bufdesc *bdp);
- +#else
- +static inline int fec_ptp_init(struct fec_ptp_private *priv, int id)
- +{
- + return 1;
- +}
- +static inline void fec_ptp_cleanup(struct fec_ptp_private *priv) { }
- +static inline int fec_ptp_start(struct fec_ptp_private *priv)
- +{
- + return 1;
- +}
- +static inline void fec_ptp_stop(struct fec_ptp_private *priv) {}
- +static inline int fec_ptp_do_txstamp(struct sk_buff *skb)
- +{
- + return 0;
- +}
- +static inline void fec_ptp_store_txstamp(struct fec_ptp_private *priv) {}
- +static inline void fec_ptp_store_rxstamp(struct fec_ptp_private *priv,
- + struct sk_buff *skb,
- + struct bufdesc *bdp) {}
- +#endif /* 1588 */
- +
- +#endif
|