diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/net/ethernet/freescale | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/net/ethernet/freescale')
27 files changed, 0 insertions, 20561 deletions
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/Kconfig b/ANDROID_3.4.5/drivers/net/ethernet/freescale/Kconfig deleted file mode 100644 index 3574e149..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/Kconfig +++ /dev/null @@ -1,88 +0,0 @@ -# -# Freescale device configuration -# - -config NET_VENDOR_FREESCALE - bool "Freescale devices" - default y - depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \ - M523x || M527x || M5272 || M528x || M520x || M532x || \ - ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) - ---help--- - If you have a network (Ethernet) card belonging to this class, say Y - and read the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Freescale devices. If you say Y, you will be - asked for your specific card in the following questions. - -if NET_VENDOR_FREESCALE - -config FEC - tristate "FEC ethernet controller (of ColdFire and some i.MX CPUs)" - depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \ - ARCH_MXC || SOC_IMX28) - default ARCH_MXC || SOC_IMX28 if ARM - select PHYLIB - ---help--- - Say Y here if you want to use the built-in 10/100 Fast ethernet - controller on some Motorola ColdFire and Freescale i.MX processors. - -config FEC_MPC52xx - tristate "FEC MPC52xx driver" - depends on PPC_MPC52xx && PPC_BESTCOMM - select CRC32 - select PHYLIB - select PPC_BESTCOMM_FEC - ---help--- - This option enables support for the MPC5200's on-chip - Fast Ethernet Controller - If compiled as module, it will be called fec_mpc52xx. - -config FEC_MPC52xx_MDIO - bool "FEC MPC52xx MDIO bus driver" - depends on FEC_MPC52xx - default y - ---help--- - The MPC5200's FEC can connect to the Ethernet either with - an external MII PHY chip or 10 Mbps 7-wire interface - (Motorola? industry standard). - If your board uses an external PHY connected to FEC, enable this. - If not sure, enable. - If compiled as module, it will be called fec_mpc52xx_phy. - -source "drivers/net/ethernet/freescale/fs_enet/Kconfig" - -config FSL_PQ_MDIO - tristate "Freescale PQ MDIO" - depends on FSL_SOC - select PHYLIB - ---help--- - This driver supports the MDIO bus used by the gianfar and UCC drivers. - -config UCC_GETH - tristate "Freescale QE Gigabit Ethernet" - depends on QUICC_ENGINE - select FSL_PQ_MDIO - select PHYLIB - ---help--- - This driver supports the Gigabit Ethernet mode of the QUICC Engine, - which is available on some Freescale SOCs. - -config UGETH_TX_ON_DEMAND - bool "Transmit on Demand support" - depends on UCC_GETH - -config GIANFAR - tristate "Gianfar Ethernet" - depends on FSL_SOC - select FSL_PQ_MDIO - select PHYLIB - select CRC32 - ---help--- - This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, - and MPC86xx family of chips, and the FEC on the 8540. - -endif # NET_VENDOR_FREESCALE diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/Makefile b/ANDROID_3.4.5/drivers/net/ethernet/freescale/Makefile deleted file mode 100644 index 1752488c..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# Makefile for the Freescale network device drivers. -# - -obj-$(CONFIG_FEC) += fec.o -obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o -ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) - obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o -endif -obj-$(CONFIG_FS_ENET) += fs_enet/ -obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o -obj-$(CONFIG_GIANFAR) += gianfar_driver.o -obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o -gianfar_driver-objs := gianfar.o \ - gianfar_ethtool.o \ - gianfar_sysfs.o -obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o -ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec.c deleted file mode 100644 index a12b3f5b..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec.c +++ /dev/null @@ -1,1744 +0,0 @@ -/* - * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx. - * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) - * - * Right now, I am very wasteful with the buffers. I allocate memory - * pages and then divide them into 2K frame buffers. This way I know I - * have buffers large enough to hold one frame within one buffer descriptor. - * Once I get this working, I will use 64 or 128 byte CPM buffers, which - * will be much more memory efficient and will easily handle lots of - * small packets. - * - * Much better multiple PHY support by Magnus Damm. - * Copyright (c) 2000 Ericsson Radio Systems AB. - * - * Support for FEC controller of ColdFire processors. - * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) - * - * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) - * Copyright (c) 2004-2006 Macq Electronique SA. - * - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/workqueue.h> -#include <linux/bitops.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/phy.h> -#include <linux/fec.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_gpio.h> -#include <linux/of_net.h> - -#include <asm/cacheflush.h> - -#ifndef CONFIG_ARM -#include <asm/coldfire.h> -#include <asm/mcfsim.h> -#endif - -#include "fec.h" - -#if defined(CONFIG_ARM) -#define FEC_ALIGNMENT 0xf -#else -#define FEC_ALIGNMENT 0x3 -#endif - -#define DRIVER_NAME "fec" - -/* Controller is ENET-MAC */ -#define FEC_QUIRK_ENET_MAC (1 << 0) -/* Controller needs driver to swap frame */ -#define FEC_QUIRK_SWAP_FRAME (1 << 1) -/* Controller uses gasket */ -#define FEC_QUIRK_USE_GASKET (1 << 2) -/* Controller has GBIT support */ -#define FEC_QUIRK_HAS_GBIT (1 << 3) - -static struct platform_device_id fec_devtype[] = { - { - /* keep it for coldfire */ - .name = DRIVER_NAME, - .driver_data = 0, - }, { - .name = "imx25-fec", - .driver_data = FEC_QUIRK_USE_GASKET, - }, { - .name = "imx27-fec", - .driver_data = 0, - }, { - .name = "imx28-fec", - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME, - }, { - .name = "imx6q-fec", - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, fec_devtype); - -enum imx_fec_type { - IMX25_FEC = 1, /* runs on i.mx25/50/53 */ - IMX27_FEC, /* runs on i.mx27/35/51 */ - IMX28_FEC, - IMX6Q_FEC, -}; - -static const struct of_device_id fec_dt_ids[] = { - { .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], }, - { .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], }, - { .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], }, - { .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, fec_dt_ids); - -static unsigned char macaddr[ETH_ALEN]; -module_param_array(macaddr, byte, NULL, 0); -MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); - -#if defined(CONFIG_M5272) -/* - * Some hardware gets it MAC address out of local flash memory. - * if this is non-zero then assume it is the address to get MAC from. - */ -#if defined(CONFIG_NETtel) -#define FEC_FLASHMAC 0xf0006006 -#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES) -#define FEC_FLASHMAC 0xf0006000 -#elif defined(CONFIG_CANCam) -#define FEC_FLASHMAC 0xf0020000 -#elif defined (CONFIG_M5272C3) -#define FEC_FLASHMAC (0xffe04000 + 4) -#elif defined(CONFIG_MOD5272) -#define FEC_FLASHMAC 0xffc0406b -#else -#define FEC_FLASHMAC 0 -#endif -#endif /* CONFIG_M5272 */ - -/* The number of Tx and Rx buffers. These are allocated from the page - * pool. The code may assume these are power of two, so it it best - * to keep them that size. - * We don't need to allocate pages for the transmitter. We just use - * the skbuffer directly. - */ -#define FEC_ENET_RX_PAGES 8 -#define FEC_ENET_RX_FRSIZE 2048 -#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) -#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) -#define FEC_ENET_TX_FRSIZE 2048 -#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) -#define TX_RING_SIZE 16 /* Must be power of two */ -#define TX_RING_MOD_MASK 15 /* for this to work */ - -#if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) -#error "FEC: descriptor ring size constants too large" -#endif - -/* Interrupt events/masks. */ -#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ -#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ -#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ -#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ -#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ -#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ -#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ -#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_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII) - -/* The FEC stores dest/src/type, data, and checksum for receive packets. - */ -#define PKT_MAXBUF_SIZE 1518 -#define PKT_MINBUF_SIZE 64 -#define PKT_MAXBLR_SIZE 1520 - -/* This device has up to three irqs on some platforms */ -#define FEC_IRQ_NUM 3 - -/* - * The 5270/5271/5280/5282/532x RX control register also contains maximum frame - * size bits. Other FEC hardware does not, so we need to take that into - * account when setting it. - */ -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) -#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) -#else -#define OPT_FRAME_SIZE 0 -#endif - -/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and - * tx_bd_base always point to the base of the buffer descriptors. The - * cur_rx and cur_tx point to the currently available buffer. - * The dirty_tx tracks the current buffer that is being sent by the - * controller. The cur_tx and dirty_tx are equal under both completely - * empty and completely full conditions. The empty/ready indicator in - * the buffer descriptor determines the actual condition. - */ -struct fec_enet_private { - /* Hardware registers of the FEC device */ - void __iomem *hwp; - - struct net_device *netdev; - - struct clk *clk; - - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - unsigned char *tx_bounce[TX_RING_SIZE]; - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - struct sk_buff* rx_skbuff[RX_RING_SIZE]; - ushort skb_cur; - ushort skb_dirty; - - /* CPM dual port RAM relative addresses */ - dma_addr_t bd_dma; - /* Address of Rx and Tx buffers */ - struct bufdesc *rx_bd_base; - struct bufdesc *tx_bd_base; - /* The next free ring entry */ - struct bufdesc *cur_rx, *cur_tx; - /* The ring entries to be free()ed */ - struct bufdesc *dirty_tx; - - uint tx_full; - /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ - spinlock_t hw_lock; - - struct platform_device *pdev; - - int opened; - int dev_id; - - /* Phylib and MDIO interface */ - struct mii_bus *mii_bus; - struct phy_device *phy_dev; - int mii_timeout; - uint phy_speed; - phy_interface_t phy_interface; - int link; - int full_duplex; - struct completion mdio_done; - int irq[FEC_IRQ_NUM]; -}; - -/* FEC MII MMFR bits definition */ -#define FEC_MMFR_ST (1 << 30) -#define FEC_MMFR_OP_READ (2 << 28) -#define FEC_MMFR_OP_WRITE (1 << 28) -#define FEC_MMFR_PA(v) ((v & 0x1f) << 23) -#define FEC_MMFR_RA(v) ((v & 0x1f) << 18) -#define FEC_MMFR_TA (2 << 16) -#define FEC_MMFR_DATA(v) (v & 0xffff) - -#define FEC_MII_TIMEOUT 30000 /* us */ - -/* Transmitter timeout */ -#define TX_TIMEOUT (2 * HZ) - -static int mii_cnt; - -static void *swap_buffer(void *bufaddr, int len) -{ - int i; - unsigned int *buf = bufaddr; - - for (i = 0; i < (len + 3) / 4; i++, buf++) - *buf = cpu_to_be32(*buf); - - return bufaddr; -} - -static netdev_tx_t -fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - struct bufdesc *bdp; - void *bufaddr; - unsigned short status; - unsigned long flags; - - if (!fep->link) { - /* Link is down or autonegotiation is in progress. */ - return NETDEV_TX_BUSY; - } - - spin_lock_irqsave(&fep->hw_lock, flags); - /* Fill in a Tx ring entry */ - bdp = fep->cur_tx; - - status = bdp->cbd_sc; - - if (status & BD_ENET_TX_READY) { - /* Ooops. All transmit buffers are full. Bail out. - * This should not happen, since ndev->tbusy should be set. - */ - printk("%s: tx queue full!.\n", ndev->name); - spin_unlock_irqrestore(&fep->hw_lock, flags); - return NETDEV_TX_BUSY; - } - - /* Clear all of the status flags */ - status &= ~BD_ENET_TX_STATS; - - /* Set buffer length and buffer pointer */ - bufaddr = skb->data; - bdp->cbd_datlen = skb->len; - - /* - * On some FEC implementations data must be aligned on - * 4-byte boundaries. Use bounce buffers to copy data - * and get it aligned. Ugh. - */ - if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { - unsigned int index; - index = bdp - fep->tx_bd_base; - memcpy(fep->tx_bounce[index], skb->data, skb->len); - bufaddr = fep->tx_bounce[index]; - } - - /* - * Some design made an incorrect assumption on endian mode of - * the system that it's running on. As the result, driver has to - * swap every frame going to and coming from the controller. - */ - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) - swap_buffer(bufaddr, skb->len); - - /* Save skb pointer */ - fep->tx_skbuff[fep->skb_cur] = skb; - - ndev->stats.tx_bytes += skb->len; - fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; - - /* Push the data cache so the CPM does not get stale memory - * data. - */ - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, - FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); - - /* Send it on its way. Tell FEC it's ready, interrupt when done, - * it's the last BD of the frame, and to put the CRC on the end. - */ - status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR - | BD_ENET_TX_LAST | BD_ENET_TX_TC); - bdp->cbd_sc = status; - - /* Trigger transmission start */ - writel(0, fep->hwp + FEC_X_DES_ACTIVE); - - /* If this was the last BD in the ring, start at the beginning again. */ - if (status & BD_ENET_TX_WRAP) - bdp = fep->tx_bd_base; - else - bdp++; - - if (bdp == fep->dirty_tx) { - fep->tx_full = 1; - netif_stop_queue(ndev); - } - - fep->cur_tx = bdp; - - skb_tx_timestamp(skb); - - spin_unlock_irqrestore(&fep->hw_lock, flags); - - return NETDEV_TX_OK; -} - -/* This function is called to start or restart the FEC during a link - * change. This only happens when switching between half and full - * duplex. - */ -static void -fec_restart(struct net_device *ndev, int duplex) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - int i; - u32 temp_mac[2]; - u32 rcntl = OPT_FRAME_SIZE | 0x04; - u32 ecntl = 0x2; /* ETHEREN */ - - /* Whack a reset. We should wait for this. */ - writel(1, fep->hwp + FEC_ECNTRL); - udelay(10); - - /* - * enet-mac reset will reset mac address registers too, - * so need to reconfigure it. - */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); - writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); - writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); - } - - /* Clear any outstanding interrupt. */ - writel(0xffc00000, fep->hwp + FEC_IEVENT); - - /* Reset all multicast. */ - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); -#ifndef CONFIG_M5272 - writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -#endif - - /* Set maximum receive buffer size. */ - writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); - - /* Set receive and transmit descriptor base. */ - writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); - writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, - fep->hwp + FEC_X_DES_START); - - fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; - fep->cur_rx = fep->rx_bd_base; - - /* Reset SKB transmit buffers. */ - fep->skb_cur = fep->skb_dirty = 0; - for (i = 0; i <= TX_RING_MOD_MASK; i++) { - if (fep->tx_skbuff[i]) { - dev_kfree_skb_any(fep->tx_skbuff[i]); - fep->tx_skbuff[i] = NULL; - } - } - - /* Enable MII mode */ - if (duplex) { - /* FD enable */ - writel(0x04, fep->hwp + FEC_X_CNTRL); - } else { - /* No Rcv on Xmit */ - rcntl |= 0x02; - writel(0x0, fep->hwp + FEC_X_CNTRL); - } - - fep->full_duplex = duplex; - - /* Set MII speed */ - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - - /* - * The phy interface and speed need to get configured - * differently on enet-mac. - */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - /* Enable flow control and length check */ - rcntl |= 0x40000000 | 0x00000020; - - /* RGMII, RMII or MII */ - if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII) - rcntl |= (1 << 6); - else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) - rcntl |= (1 << 8); - else - rcntl &= ~(1 << 8); - - /* 1G, 100M or 10M */ - if (fep->phy_dev) { - if (fep->phy_dev->speed == SPEED_1000) - ecntl |= (1 << 5); - else if (fep->phy_dev->speed == SPEED_100) - rcntl &= ~(1 << 9); - else - rcntl |= (1 << 9); - } - } else { -#ifdef FEC_MIIGSK_ENR - if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) { - u32 cfgr; - /* disable the gasket and wait */ - writel(0, fep->hwp + FEC_MIIGSK_ENR); - while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) - udelay(1); - - /* - * configure the gasket: - * RMII, 50 MHz, no loopback, no echo - * MII, 25 MHz, no loopback, no echo - */ - cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII) - ? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII; - if (fep->phy_dev && fep->phy_dev->speed == SPEED_10) - cfgr |= BM_MIIGSK_CFGR_FRCONT_10M; - writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR); - - /* re-enable the gasket */ - writel(2, fep->hwp + FEC_MIIGSK_ENR); - } -#endif - } - writel(rcntl, fep->hwp + FEC_R_CNTRL); - - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - /* enable ENET endian swap */ - ecntl |= (1 << 8); - /* enable ENET store and forward mode */ - writel(1 << 8, fep->hwp + FEC_X_WMRK); - } - - /* And last, enable the transmit and receive processing */ - writel(ecntl, fep->hwp + FEC_ECNTRL); - writel(0, fep->hwp + FEC_R_DES_ACTIVE); - - /* Enable interrupts we wish to service */ - writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); -} - -static void -fec_stop(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8); - - /* We cannot expect a graceful transmit stop without link !!! */ - if (fep->link) { - writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ - udelay(10); - if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA)) - printk("fec_stop : Graceful transmit stop did not complete !\n"); - } - - /* Whack a reset. We should wait for this. */ - writel(1, fep->hwp + FEC_ECNTRL); - udelay(10); - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); - - /* We have to keep ENET enabled to have MII interrupt stay working */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { - writel(2, fep->hwp + FEC_ECNTRL); - writel(rmii_mode, fep->hwp + FEC_R_CNTRL); - } -} - - -static void -fec_timeout(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - ndev->stats.tx_errors++; - - fec_restart(ndev, fep->full_duplex); - netif_wake_queue(ndev); -} - -static void -fec_enet_tx(struct net_device *ndev) -{ - struct fec_enet_private *fep; - struct bufdesc *bdp; - unsigned short status; - struct sk_buff *skb; - - fep = netdev_priv(ndev); - spin_lock(&fep->hw_lock); - bdp = fep->dirty_tx; - - while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { - if (bdp == fep->cur_tx && fep->tx_full == 0) - break; - - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); - bdp->cbd_bufaddr = 0; - - skb = fep->tx_skbuff[fep->skb_dirty]; - /* Check for errors. */ - if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | - BD_ENET_TX_RL | BD_ENET_TX_UN | - BD_ENET_TX_CSL)) { - ndev->stats.tx_errors++; - if (status & BD_ENET_TX_HB) /* No heartbeat */ - ndev->stats.tx_heartbeat_errors++; - if (status & BD_ENET_TX_LC) /* Late collision */ - ndev->stats.tx_window_errors++; - if (status & BD_ENET_TX_RL) /* Retrans limit */ - ndev->stats.tx_aborted_errors++; - if (status & BD_ENET_TX_UN) /* Underrun */ - ndev->stats.tx_fifo_errors++; - if (status & BD_ENET_TX_CSL) /* Carrier lost */ - ndev->stats.tx_carrier_errors++; - } else { - ndev->stats.tx_packets++; - } - - if (status & BD_ENET_TX_READY) - printk("HEY! Enet xmit interrupt and TX_READY.\n"); - - /* Deferred means some collisions occurred during transmit, - * but we eventually sent the packet OK. - */ - if (status & BD_ENET_TX_DEF) - ndev->stats.collisions++; - - /* Free the sk buffer associated with this last transmit */ - dev_kfree_skb_any(skb); - fep->tx_skbuff[fep->skb_dirty] = NULL; - fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; - - /* Update pointer to next buffer descriptor to be transmitted */ - if (status & BD_ENET_TX_WRAP) - bdp = fep->tx_bd_base; - else - bdp++; - - /* Since we have freed up a buffer, the ring is no longer full - */ - if (fep->tx_full) { - fep->tx_full = 0; - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); - } - } - fep->dirty_tx = bdp; - spin_unlock(&fep->hw_lock); -} - - -/* During a receive, the cur_rx points to the current incoming buffer. - * When we update through the ring, if the next incoming buffer has - * not been given to the system, we just set the empty indicator, - * effectively tossing the packet. - */ -static void -fec_enet_rx(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - struct bufdesc *bdp; - unsigned short status; - struct sk_buff *skb; - ushort pkt_len; - __u8 *data; - -#ifdef CONFIG_M532x - flush_cache_all(); -#endif - - spin_lock(&fep->hw_lock); - - /* First, grab all of the stats for the incoming packet. - * These get messed up if we get called due to a busy condition. - */ - bdp = fep->cur_rx; - - while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { - - /* Since we have allocated space to hold a complete frame, - * the last indicator should be set. - */ - if ((status & BD_ENET_RX_LAST) == 0) - printk("FEC ENET: rcv is not +last\n"); - - if (!fep->opened) - goto rx_processing_done; - - /* Check for errors. */ - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | - BD_ENET_RX_CR | BD_ENET_RX_OV)) { - ndev->stats.rx_errors++; - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { - /* Frame too long or too short. */ - ndev->stats.rx_length_errors++; - } - if (status & BD_ENET_RX_NO) /* Frame alignment */ - ndev->stats.rx_frame_errors++; - if (status & BD_ENET_RX_CR) /* CRC Error */ - ndev->stats.rx_crc_errors++; - if (status & BD_ENET_RX_OV) /* FIFO overrun */ - ndev->stats.rx_fifo_errors++; - } - - /* Report late collisions as a frame error. - * On this error, the BD is closed, but we don't know what we - * have in the buffer. So, just drop this frame on the floor. - */ - if (status & BD_ENET_RX_CL) { - ndev->stats.rx_errors++; - ndev->stats.rx_frame_errors++; - goto rx_processing_done; - } - - /* Process the incoming frame. */ - ndev->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; - ndev->stats.rx_bytes += pkt_len; - data = (__u8*)__va(bdp->cbd_bufaddr); - - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE); - - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) - swap_buffer(data, pkt_len); - - /* This does 16 byte alignment, exactly what we need. - * The packet length includes FCS, but we don't want to - * include that when passing upstream as it messes up - * bridging applications. - */ - skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN); - - if (unlikely(!skb)) { - printk("%s: Memory squeeze, dropping packet.\n", - ndev->name); - ndev->stats.rx_dropped++; - } else { - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, pkt_len - 4); /* Make room */ - skb_copy_to_linear_data(skb, data, pkt_len - 4); - skb->protocol = eth_type_trans(skb, ndev); - if (!skb_defer_rx_timestamp(skb)) - netif_rx(skb); - } - - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data, - FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE); -rx_processing_done: - /* Clear the status flags for this buffer */ - status &= ~BD_ENET_RX_STATS; - - /* Mark the buffer empty */ - status |= BD_ENET_RX_EMPTY; - bdp->cbd_sc = status; - - /* Update BD pointer to next entry */ - if (status & BD_ENET_RX_WRAP) - bdp = fep->rx_bd_base; - else - bdp++; - /* Doing this here will keep the FEC running while we process - * incoming frames. On a heavily loaded network, we should be - * able to keep up at the expense of system resources. - */ - writel(0, fep->hwp + FEC_R_DES_ACTIVE); - } - fep->cur_rx = bdp; - - spin_unlock(&fep->hw_lock); -} - -static irqreturn_t -fec_enet_interrupt(int irq, void *dev_id) -{ - struct net_device *ndev = dev_id; - struct fec_enet_private *fep = netdev_priv(ndev); - uint int_events; - irqreturn_t ret = IRQ_NONE; - - do { - int_events = readl(fep->hwp + FEC_IEVENT); - writel(int_events, fep->hwp + FEC_IEVENT); - - if (int_events & FEC_ENET_RXF) { - ret = IRQ_HANDLED; - fec_enet_rx(ndev); - } - - /* Transmit OK, or non-fatal error. Update the buffer - * descriptors. FEC handles all errors, we just discover - * them as part of the transmit process. - */ - if (int_events & FEC_ENET_TXF) { - ret = IRQ_HANDLED; - fec_enet_tx(ndev); - } - - if (int_events & FEC_ENET_MII) { - ret = IRQ_HANDLED; - complete(&fep->mdio_done); - } - } while (int_events); - - return ret; -} - - - -/* ------------------------------------------------------------------------- */ -static void __inline__ fec_get_mac(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_platform_data *pdata = fep->pdev->dev.platform_data; - unsigned char *iap, tmpaddr[ETH_ALEN]; - - /* - * try to get mac address in following order: - * - * 1) module parameter via kernel command line in form - * fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0 - */ - iap = macaddr; - -#ifdef CONFIG_OF - /* - * 2) from device tree data - */ - if (!is_valid_ether_addr(iap)) { - struct device_node *np = fep->pdev->dev.of_node; - if (np) { - const char *mac = of_get_mac_address(np); - if (mac) - iap = (unsigned char *) mac; - } - } -#endif - - /* - * 3) from flash or fuse (via platform data) - */ - if (!is_valid_ether_addr(iap)) { -#ifdef CONFIG_M5272 - if (FEC_FLASHMAC) - iap = (unsigned char *)FEC_FLASHMAC; -#else - if (pdata) - iap = (unsigned char *)&pdata->mac; -#endif - } - - /* - * 4) FEC mac registers set by bootloader - */ - if (!is_valid_ether_addr(iap)) { - *((unsigned long *) &tmpaddr[0]) = - be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW)); - *((unsigned short *) &tmpaddr[4]) = - be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16); - iap = &tmpaddr[0]; - } - - memcpy(ndev->dev_addr, iap, ETH_ALEN); - - /* Adjust MAC if using macaddr */ - if (iap == macaddr) - ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id; -} - -/* ------------------------------------------------------------------------- */ - -/* - * Phy section - */ -static void fec_enet_adjust_link(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phy_dev = fep->phy_dev; - unsigned long flags; - - int status_change = 0; - - spin_lock_irqsave(&fep->hw_lock, flags); - - /* Prevent a state halted on mii error */ - if (fep->mii_timeout && phy_dev->state == PHY_HALTED) { - phy_dev->state = PHY_RESUMING; - goto spin_unlock; - } - - /* Duplex link change */ - if (phy_dev->link) { - if (fep->full_duplex != phy_dev->duplex) { - fec_restart(ndev, phy_dev->duplex); - /* prevent unnecessary second fec_restart() below */ - fep->link = phy_dev->link; - status_change = 1; - } - } - - /* Link on or off change */ - if (phy_dev->link != fep->link) { - fep->link = phy_dev->link; - if (phy_dev->link) - fec_restart(ndev, phy_dev->duplex); - else - fec_stop(ndev); - status_change = 1; - } - -spin_unlock: - spin_unlock_irqrestore(&fep->hw_lock, flags); - - if (status_change) - phy_print_status(phy_dev); -} - -static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct fec_enet_private *fep = bus->priv; - unsigned long time_left; - - fep->mii_timeout = 0; - init_completion(&fep->mdio_done); - - /* start a read op */ - writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | - FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); - - /* wait for end of transfer */ - time_left = wait_for_completion_timeout(&fep->mdio_done, - usecs_to_jiffies(FEC_MII_TIMEOUT)); - if (time_left == 0) { - fep->mii_timeout = 1; - printk(KERN_ERR "FEC: MDIO read timeout\n"); - return -ETIMEDOUT; - } - - /* return value */ - return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); -} - -static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, - u16 value) -{ - struct fec_enet_private *fep = bus->priv; - unsigned long time_left; - - fep->mii_timeout = 0; - init_completion(&fep->mdio_done); - - /* start a write op */ - writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | - FEC_MMFR_TA | FEC_MMFR_DATA(value), - fep->hwp + FEC_MII_DATA); - - /* wait for end of transfer */ - time_left = wait_for_completion_timeout(&fep->mdio_done, - usecs_to_jiffies(FEC_MII_TIMEOUT)); - if (time_left == 0) { - fep->mii_timeout = 1; - printk(KERN_ERR "FEC: MDIO write timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int fec_enet_mdio_reset(struct mii_bus *bus) -{ - return 0; -} - -static int fec_enet_mii_probe(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - struct phy_device *phy_dev = NULL; - char mdio_bus_id[MII_BUS_ID_SIZE]; - char phy_name[MII_BUS_ID_SIZE + 3]; - int phy_id; - int dev_id = fep->dev_id; - - fep->phy_dev = NULL; - - /* check for attached phy */ - for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { - if ((fep->mii_bus->phy_mask & (1 << phy_id))) - continue; - if (fep->mii_bus->phy_map[phy_id] == NULL) - continue; - if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) - continue; - if (dev_id--) - continue; - strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); - break; - } - - if (phy_id >= PHY_MAX_ADDR) { - printk(KERN_INFO - "%s: no PHY, assuming direct connection to switch\n", - ndev->name); - strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); - phy_id = 0; - } - - snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id); - phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0, - fep->phy_interface); - if (IS_ERR(phy_dev)) { - printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name); - return PTR_ERR(phy_dev); - } - - /* mask with MAC supported features */ - if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) - phy_dev->supported &= PHY_GBIT_FEATURES; - else - phy_dev->supported &= PHY_BASIC_FEATURES; - - phy_dev->advertising = phy_dev->supported; - - fep->phy_dev = phy_dev; - fep->link = 0; - fep->full_duplex = 0; - - printk(KERN_INFO - "%s: Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - ndev->name, - fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), - fep->phy_dev->irq); - - return 0; -} - -static int fec_enet_mii_init(struct platform_device *pdev) -{ - static struct mii_bus *fec0_mii_bus; - struct net_device *ndev = platform_get_drvdata(pdev); - struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - int err = -ENXIO, i; - - /* - * The dual fec interfaces are not equivalent with enet-mac. - * Here are the differences: - * - * - fec0 supports MII & RMII modes while fec1 only supports RMII - * - fec0 acts as the 1588 time master while fec1 is slave - * - external phys can only be configured by fec0 - * - * That is to say fec1 can not work independently. It only works - * when fec0 is working. The reason behind this design is that the - * second interface is added primarily for Switch mode. - * - * Because of the last point above, both phys are attached on fec0 - * mdio interface in board design, and need to be configured by - * fec0 mii_bus. - */ - if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { - /* fec1 uses fec0 mii_bus */ - if (mii_cnt && fec0_mii_bus) { - fep->mii_bus = fec0_mii_bus; - mii_cnt++; - return 0; - } - return -ENOENT; - } - - fep->mii_timeout = 0; - - /* - * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) - * - * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while - * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. The i.MX28 - * Reference Manual has an error on this, and gets fixed on i.MX6Q - * document. - */ - fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000); - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) - fep->phy_speed--; - fep->phy_speed <<= 1; - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - - fep->mii_bus = mdiobus_alloc(); - if (fep->mii_bus == NULL) { - err = -ENOMEM; - goto err_out; - } - - fep->mii_bus->name = "fec_enet_mii_bus"; - fep->mii_bus->read = fec_enet_mdio_read; - fep->mii_bus->write = fec_enet_mdio_write; - fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", - pdev->name, fep->dev_id + 1); - fep->mii_bus->priv = fep; - fep->mii_bus->parent = &pdev->dev; - - fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!fep->mii_bus->irq) { - err = -ENOMEM; - goto err_out_free_mdiobus; - } - - for (i = 0; i < PHY_MAX_ADDR; i++) - fep->mii_bus->irq[i] = PHY_POLL; - - if (mdiobus_register(fep->mii_bus)) - goto err_out_free_mdio_irq; - - mii_cnt++; - - /* save fec0 mii_bus */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) - fec0_mii_bus = fep->mii_bus; - - return 0; - -err_out_free_mdio_irq: - kfree(fep->mii_bus->irq); -err_out_free_mdiobus: - mdiobus_free(fep->mii_bus); -err_out: - return err; -} - -static void fec_enet_mii_remove(struct fec_enet_private *fep) -{ - if (--mii_cnt == 0) { - mdiobus_unregister(fep->mii_bus); - kfree(fep->mii_bus->irq); - mdiobus_free(fep->mii_bus); - } -} - -static int fec_enet_get_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phydev = fep->phy_dev; - - if (!phydev) - return -ENODEV; - - return phy_ethtool_gset(phydev, cmd); -} - -static int fec_enet_set_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phydev = fep->phy_dev; - - if (!phydev) - return -ENODEV; - - return phy_ethtool_sset(phydev, cmd); -} - -static void fec_enet_get_drvinfo(struct net_device *ndev, - struct ethtool_drvinfo *info) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - strcpy(info->driver, fep->pdev->dev.driver->name); - strcpy(info->version, "Revision: 1.0"); - strcpy(info->bus_info, dev_name(&ndev->dev)); -} - -static const struct ethtool_ops fec_enet_ethtool_ops = { - .get_settings = fec_enet_get_settings, - .set_settings = fec_enet_set_settings, - .get_drvinfo = fec_enet_get_drvinfo, - .get_link = ethtool_op_get_link, -}; - -static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phydev = fep->phy_dev; - - if (!netif_running(ndev)) - return -EINVAL; - - if (!phydev) - return -ENODEV; - - return phy_mii_ioctl(phydev, rq, cmd); -} - -static void fec_enet_free_buffers(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - int i; - struct sk_buff *skb; - struct bufdesc *bdp; - - bdp = fep->rx_bd_base; - for (i = 0; i < RX_RING_SIZE; i++) { - skb = fep->rx_skbuff[i]; - - if (bdp->cbd_bufaddr) - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - if (skb) - dev_kfree_skb(skb); - bdp++; - } - - bdp = fep->tx_bd_base; - for (i = 0; i < TX_RING_SIZE; i++) - kfree(fep->tx_bounce[i]); -} - -static int fec_enet_alloc_buffers(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - int i; - struct sk_buff *skb; - struct bufdesc *bdp; - - bdp = fep->rx_bd_base; - for (i = 0; i < RX_RING_SIZE; i++) { - skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); - if (!skb) { - fec_enet_free_buffers(ndev); - return -ENOMEM; - } - fep->rx_skbuff[i] = skb; - - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, - FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - bdp->cbd_sc = BD_ENET_RX_EMPTY; - bdp++; - } - - /* Set the last buffer to wrap. */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - bdp = fep->tx_bd_base; - for (i = 0; i < TX_RING_SIZE; i++) { - fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); - - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } - - /* Set the last buffer to wrap. */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - return 0; -} - -static int -fec_enet_open(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - int ret; - - /* I should reset the ring buffers here, but I don't yet know - * a simple way to do that. - */ - - ret = fec_enet_alloc_buffers(ndev); - if (ret) - return ret; - - /* Probe and connect to PHY when open the interface */ - ret = fec_enet_mii_probe(ndev); - if (ret) { - fec_enet_free_buffers(ndev); - return ret; - } - phy_start(fep->phy_dev); - netif_start_queue(ndev); - fep->opened = 1; - return 0; -} - -static int -fec_enet_close(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - /* Don't know what to do yet. */ - fep->opened = 0; - netif_stop_queue(ndev); - fec_stop(ndev); - - if (fep->phy_dev) { - phy_stop(fep->phy_dev); - phy_disconnect(fep->phy_dev); - } - - fec_enet_free_buffers(ndev); - - return 0; -} - -/* Set or clear the multicast filter for this adaptor. - * Skeleton taken from sunlance driver. - * The CPM Ethernet implementation allows Multicast as well as individual - * MAC address filtering. Some of the drivers check to make sure it is - * a group multicast address, and discard those that are not. I guess I - * will do the same for now, but just remove the test if you want - * individual filtering as well (do the upper net layers want or support - * this kind of feature?). - */ - -#define HASH_BITS 6 /* #bits in hash */ -#define CRC32_POLY 0xEDB88320 - -static void set_multicast_list(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct netdev_hw_addr *ha; - unsigned int i, bit, data, crc, tmp; - unsigned char hash; - - if (ndev->flags & IFF_PROMISC) { - tmp = readl(fep->hwp + FEC_R_CNTRL); - tmp |= 0x8; - writel(tmp, fep->hwp + FEC_R_CNTRL); - return; - } - - tmp = readl(fep->hwp + FEC_R_CNTRL); - tmp &= ~0x8; - writel(tmp, fep->hwp + FEC_R_CNTRL); - - if (ndev->flags & IFF_ALLMULTI) { - /* Catch all multicast addresses, so set the - * filter to all 1's - */ - writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - - return; - } - - /* Clear filter and add the addresses in hash register - */ - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - - netdev_for_each_mc_addr(ha, ndev) { - /* calculate crc32 value of mac address */ - crc = 0xffffffff; - - for (i = 0; i < ndev->addr_len; i++) { - data = ha->addr[i]; - for (bit = 0; bit < 8; bit++, data >>= 1) { - crc = (crc >> 1) ^ - (((crc ^ data) & 1) ? CRC32_POLY : 0); - } - } - - /* only upper 6 bits (HASH_BITS) are used - * which point to specific bit in he hash registers - */ - hash = (crc >> (32 - HASH_BITS)) & 0x3f; - - if (hash > 31) { - tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - tmp |= 1 << (hash - 32); - writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - } else { - tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); - tmp |= 1 << hash; - writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - } - } -} - -/* Set a MAC change in hardware. */ -static int -fec_set_mac_address(struct net_device *ndev, void *p) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); - - writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) | - (ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24), - fep->hwp + FEC_ADDR_LOW); - writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24), - fep->hwp + FEC_ADDR_HIGH); - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * fec_poll_controller: FEC Poll controller function - * @dev: The FEC network adapter - * - * Polled functionality used by netconsole and others in non interrupt mode - * - */ -void fec_poll_controller(struct net_device *dev) -{ - int i; - struct fec_enet_private *fep = netdev_priv(dev); - - for (i = 0; i < FEC_IRQ_NUM; i++) { - if (fep->irq[i] > 0) { - disable_irq(fep->irq[i]); - fec_enet_interrupt(fep->irq[i], dev); - enable_irq(fep->irq[i]); - } - } -} -#endif - -static const struct net_device_ops fec_netdev_ops = { - .ndo_open = fec_enet_open, - .ndo_stop = fec_enet_close, - .ndo_start_xmit = fec_enet_start_xmit, - .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_tx_timeout = fec_timeout, - .ndo_set_mac_address = fec_set_mac_address, - .ndo_do_ioctl = fec_enet_ioctl, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = fec_poll_controller, -#endif -}; - - /* - * XXX: We need to clean up on failure exits here. - * - */ -static int fec_enet_init(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct bufdesc *cbd_base; - struct bufdesc *bdp; - int i; - - /* Allocate memory for buffer descriptors. */ - cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, - GFP_KERNEL); - if (!cbd_base) { - printk("FEC: allocate descriptor memory failed?\n"); - return -ENOMEM; - } - - spin_lock_init(&fep->hw_lock); - - fep->netdev = ndev; - - /* Get the Ethernet address */ - fec_get_mac(ndev); - - /* Set receive and transmit descriptor base. */ - fep->rx_bd_base = cbd_base; - fep->tx_bd_base = cbd_base + RX_RING_SIZE; - - /* The FEC Ethernet specific entries in the device structure */ - ndev->watchdog_timeo = TX_TIMEOUT; - ndev->netdev_ops = &fec_netdev_ops; - ndev->ethtool_ops = &fec_enet_ethtool_ops; - - /* Initialize the receive buffer descriptors. */ - bdp = fep->rx_bd_base; - for (i = 0; i < RX_RING_SIZE; i++) { - - /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = 0; - bdp++; - } - - /* Set the last buffer to wrap */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - /* ...and the same for transmit */ - bdp = fep->tx_bd_base; - for (i = 0; i < TX_RING_SIZE; i++) { - - /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } - - /* Set the last buffer to wrap */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - fec_restart(ndev, 0); - - return 0; -} - -#ifdef CONFIG_OF -static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - - if (np) - return of_get_phy_mode(np); - - return -ENODEV; -} - -static void __devinit fec_reset_phy(struct platform_device *pdev) -{ - int err, phy_reset; - struct device_node *np = pdev->dev.of_node; - - if (!np) - return; - - phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); - err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset"); - if (err) { - pr_debug("FEC: failed to get gpio phy-reset: %d\n", err); - return; - } - msleep(1); - gpio_set_value(phy_reset, 1); -} -#else /* CONFIG_OF */ -static inline int fec_get_phy_mode_dt(struct platform_device *pdev) -{ - return -ENODEV; -} - -static inline void fec_reset_phy(struct platform_device *pdev) -{ - /* - * In case of platform probe, the reset has been done - * by machine code. - */ -} -#endif /* CONFIG_OF */ - -static int __devinit -fec_probe(struct platform_device *pdev) -{ - struct fec_enet_private *fep; - struct fec_platform_data *pdata; - struct net_device *ndev; - int i, irq, ret = 0; - struct resource *r; - const struct of_device_id *of_id; - static int dev_id; - - of_id = of_match_device(fec_dt_ids, &pdev->dev); - if (of_id) - pdev->id_entry = of_id->data; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - return -ENXIO; - - r = request_mem_region(r->start, resource_size(r), pdev->name); - if (!r) - return -EBUSY; - - /* Init network device */ - ndev = alloc_etherdev(sizeof(struct fec_enet_private)); - if (!ndev) { - ret = -ENOMEM; - goto failed_alloc_etherdev; - } - - SET_NETDEV_DEV(ndev, &pdev->dev); - - /* setup board info structure */ - fep = netdev_priv(ndev); - - fep->hwp = ioremap(r->start, resource_size(r)); - fep->pdev = pdev; - fep->dev_id = dev_id++; - - if (!fep->hwp) { - ret = -ENOMEM; - goto failed_ioremap; - } - - platform_set_drvdata(pdev, ndev); - - ret = fec_get_phy_mode_dt(pdev); - if (ret < 0) { - pdata = pdev->dev.platform_data; - if (pdata) - fep->phy_interface = pdata->phy; - else - fep->phy_interface = PHY_INTERFACE_MODE_MII; - } else { - fep->phy_interface = ret; - } - - fec_reset_phy(pdev); - - for (i = 0; i < FEC_IRQ_NUM; i++) { - irq = platform_get_irq(pdev, i); - if (irq < 0) { - if (i) - break; - ret = irq; - goto failed_irq; - } - ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); - if (ret) { - while (--i >= 0) { - irq = platform_get_irq(pdev, i); - free_irq(irq, ndev); - } - goto failed_irq; - } - } - - fep->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(fep->clk)) { - ret = PTR_ERR(fep->clk); - goto failed_clk; - } - clk_prepare_enable(fep->clk); - - ret = fec_enet_init(ndev); - if (ret) - goto failed_init; - - ret = fec_enet_mii_init(pdev); - if (ret) - goto failed_mii_init; - - /* Carrier starts down, phylib will bring it up */ - netif_carrier_off(ndev); - - ret = register_netdev(ndev); - if (ret) - goto failed_register; - - return 0; - -failed_register: - fec_enet_mii_remove(fep); -failed_mii_init: -failed_init: - clk_disable_unprepare(fep->clk); - clk_put(fep->clk); -failed_clk: - for (i = 0; i < FEC_IRQ_NUM; i++) { - irq = platform_get_irq(pdev, i); - if (irq > 0) - free_irq(irq, ndev); - } -failed_irq: - iounmap(fep->hwp); -failed_ioremap: - free_netdev(ndev); -failed_alloc_etherdev: - release_mem_region(r->start, resource_size(r)); - - return ret; -} - -static int __devexit -fec_drv_remove(struct platform_device *pdev) -{ - struct net_device *ndev = platform_get_drvdata(pdev); - struct fec_enet_private *fep = netdev_priv(ndev); - struct resource *r; - int i; - - unregister_netdev(ndev); - fec_enet_mii_remove(fep); - for (i = 0; i < FEC_IRQ_NUM; i++) { - int irq = platform_get_irq(pdev, i); - if (irq > 0) - free_irq(irq, ndev); - } - clk_disable_unprepare(fep->clk); - clk_put(fep->clk); - iounmap(fep->hwp); - free_netdev(ndev); - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - BUG_ON(!r); - release_mem_region(r->start, resource_size(r)); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef CONFIG_PM -static int -fec_suspend(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct fec_enet_private *fep = netdev_priv(ndev); - - if (netif_running(ndev)) { - fec_stop(ndev); - netif_device_detach(ndev); - } - clk_disable_unprepare(fep->clk); - - return 0; -} - -static int -fec_resume(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct fec_enet_private *fep = netdev_priv(ndev); - - clk_prepare_enable(fep->clk); - if (netif_running(ndev)) { - fec_restart(ndev, fep->full_duplex); - netif_device_attach(ndev); - } - - return 0; -} - -static const struct dev_pm_ops fec_pm_ops = { - .suspend = fec_suspend, - .resume = fec_resume, - .freeze = fec_suspend, - .thaw = fec_resume, - .poweroff = fec_suspend, - .restore = fec_resume, -}; -#endif - -static struct platform_driver fec_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &fec_pm_ops, -#endif - .of_match_table = fec_dt_ids, - }, - .id_table = fec_devtype, - .probe = fec_probe, - .remove = __devexit_p(fec_drv_remove), -}; - -module_platform_driver(fec_driver); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec.h deleted file mode 100644 index 8408c627..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec.h +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************/ - -/* - * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC - * processors. - * - * (C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com) - * (C) Copyright 2000-2001, Lineo (www.lineo.com) - */ - -/****************************************************************************/ -#ifndef FEC_H -#define FEC_H -/****************************************************************************/ - -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ - defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) -/* - * Just figures, Motorola would have to change the offsets for - * registers in the same peripheral device on different models - * of the ColdFire! - */ -#define FEC_IEVENT 0x004 /* Interrupt event reg */ -#define FEC_IMASK 0x008 /* Interrupt mask reg */ -#define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ -#define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ -#define FEC_ECNTRL 0x024 /* Ethernet control reg */ -#define FEC_MII_DATA 0x040 /* MII manage frame reg */ -#define FEC_MII_SPEED 0x044 /* MII speed control reg */ -#define FEC_MIB_CTRLSTAT 0x064 /* MIB control/status reg */ -#define FEC_R_CNTRL 0x084 /* Receive control reg */ -#define FEC_X_CNTRL 0x0c4 /* Transmit Control reg */ -#define FEC_ADDR_LOW 0x0e4 /* Low 32bits MAC address */ -#define FEC_ADDR_HIGH 0x0e8 /* High 16bits MAC address */ -#define FEC_OPD 0x0ec /* Opcode + Pause duration */ -#define FEC_HASH_TABLE_HIGH 0x118 /* High 32bits hash table */ -#define FEC_HASH_TABLE_LOW 0x11c /* Low 32bits hash table */ -#define FEC_GRP_HASH_TABLE_HIGH 0x120 /* High 32bits hash table */ -#define FEC_GRP_HASH_TABLE_LOW 0x124 /* Low 32bits hash table */ -#define FEC_X_WMRK 0x144 /* FIFO transmit water mark */ -#define FEC_R_BOUND 0x14c /* FIFO receive bound reg */ -#define FEC_R_FSTART 0x150 /* FIFO receive start reg */ -#define FEC_R_DES_START 0x180 /* Receive descriptor ring */ -#define FEC_X_DES_START 0x184 /* Transmit descriptor ring */ -#define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ -#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */ -#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */ - -#define BM_MIIGSK_CFGR_MII 0x00 -#define BM_MIIGSK_CFGR_RMII 0x01 -#define BM_MIIGSK_CFGR_FRCONT_10M 0x40 - -#else - -#define FEC_ECNTRL 0x000 /* Ethernet control reg */ -#define FEC_IEVENT 0x004 /* Interrupt even reg */ -#define FEC_IMASK 0x008 /* Interrupt mask reg */ -#define FEC_IVEC 0x00c /* Interrupt vec status reg */ -#define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ -#define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ -#define FEC_MII_DATA 0x040 /* MII manage frame reg */ -#define FEC_MII_SPEED 0x044 /* MII speed control reg */ -#define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ -#define FEC_R_FSTART 0x090 /* FIFO receive start reg */ -#define FEC_X_WMRK 0x0a4 /* FIFO transmit water mark */ -#define FEC_X_FSTART 0x0ac /* FIFO transmit start reg */ -#define FEC_R_CNTRL 0x104 /* Receive control reg */ -#define FEC_MAX_FRM_LEN 0x108 /* Maximum frame length reg */ -#define FEC_X_CNTRL 0x144 /* Transmit Control reg */ -#define FEC_ADDR_LOW 0x3c0 /* Low 32bits MAC address */ -#define FEC_ADDR_HIGH 0x3c4 /* High 16bits MAC address */ -#define FEC_GRP_HASH_TABLE_HIGH 0x3c8 /* High 32bits hash table */ -#define FEC_GRP_HASH_TABLE_LOW 0x3cc /* Low 32bits hash table */ -#define FEC_R_DES_START 0x3d0 /* Receive descriptor ring */ -#define FEC_X_DES_START 0x3d4 /* Transmit descriptor ring */ -#define FEC_R_BUFF_SIZE 0x3d8 /* Maximum receive buff size */ -#define FEC_FIFO_RAM 0x400 /* FIFO RAM buffer */ - -#endif /* CONFIG_M5272 */ - - -/* - * Define the buffer descriptor structure. - */ -#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) -struct bufdesc { - unsigned short cbd_datlen; /* Data length */ - unsigned short cbd_sc; /* Control and status info */ - unsigned long cbd_bufaddr; /* Buffer address */ -}; -#else -struct bufdesc { - unsigned short cbd_sc; /* Control and status info */ - unsigned short cbd_datlen; /* Data length */ - unsigned long cbd_bufaddr; /* Buffer address */ -}; -#endif - -/* - * The following definitions courtesy of commproc.h, which where - * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). - */ -#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */ -#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ -#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ -#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ -#define BD_SC_CM ((ushort)0x0200) /* Continuous mode */ -#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ -#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ -#define BD_SC_BR ((ushort)0x0020) /* Break received */ -#define BD_SC_FR ((ushort)0x0010) /* Framing error */ -#define BD_SC_PR ((ushort)0x0008) /* Parity error */ -#define BD_SC_OV ((ushort)0x0002) /* Overrun */ -#define BD_SC_CD ((ushort)0x0001) /* ?? */ - -/* Buffer descriptor control/status used by Ethernet receive. -*/ -#define BD_ENET_RX_EMPTY ((ushort)0x8000) -#define BD_ENET_RX_WRAP ((ushort)0x2000) -#define BD_ENET_RX_INTR ((ushort)0x1000) -#define BD_ENET_RX_LAST ((ushort)0x0800) -#define BD_ENET_RX_FIRST ((ushort)0x0400) -#define BD_ENET_RX_MISS ((ushort)0x0100) -#define BD_ENET_RX_LG ((ushort)0x0020) -#define BD_ENET_RX_NO ((ushort)0x0010) -#define BD_ENET_RX_SH ((ushort)0x0008) -#define BD_ENET_RX_CR ((ushort)0x0004) -#define BD_ENET_RX_OV ((ushort)0x0002) -#define BD_ENET_RX_CL ((ushort)0x0001) -#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ - -/* Buffer descriptor control/status used by Ethernet transmit. -*/ -#define BD_ENET_TX_READY ((ushort)0x8000) -#define BD_ENET_TX_PAD ((ushort)0x4000) -#define BD_ENET_TX_WRAP ((ushort)0x2000) -#define BD_ENET_TX_INTR ((ushort)0x1000) -#define BD_ENET_TX_LAST ((ushort)0x0800) -#define BD_ENET_TX_TC ((ushort)0x0400) -#define BD_ENET_TX_DEF ((ushort)0x0200) -#define BD_ENET_TX_HB ((ushort)0x0100) -#define BD_ENET_TX_LC ((ushort)0x0080) -#define BD_ENET_TX_RL ((ushort)0x0040) -#define BD_ENET_TX_RCMASK ((ushort)0x003c) -#define BD_ENET_TX_UN ((ushort)0x0002) -#define BD_ENET_TX_CSL ((ushort)0x0001) -#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ - - -/****************************************************************************/ -#endif /* FEC_H */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx.c deleted file mode 100644 index fc87e893..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - * Driver for the MPC5200 Fast Ethernet Controller - * - * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and - * now maintained by Sylvain Munaut <tnt@246tNt.com> - * - * Copyright (C) 2007 Domen Puncer, Telargo, Inc. - * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com> - * Copyright (C) 2003-2004 MontaVista, Software, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - * - */ - -#include <linux/dma-mapping.h> -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/crc32.h> -#include <linux/hardirq.h> -#include <linux/delay.h> -#include <linux/of_device.h> -#include <linux/of_mdio.h> -#include <linux/of_platform.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/skbuff.h> - -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/mpc52xx.h> - -#include <sysdev/bestcomm/bestcomm.h> -#include <sysdev/bestcomm/fec.h> - -#include "fec_mpc52xx.h" - -#define DRIVER_NAME "mpc52xx-fec" - -/* Private driver data structure */ -struct mpc52xx_fec_priv { - struct net_device *ndev; - int duplex; - int speed; - int r_irq; - int t_irq; - struct mpc52xx_fec __iomem *fec; - struct bcom_task *rx_dmatsk; - struct bcom_task *tx_dmatsk; - spinlock_t lock; - int msg_enable; - - /* MDIO link details */ - unsigned int mdio_speed; - struct device_node *phy_node; - struct phy_device *phydev; - enum phy_state link; - int seven_wire_mode; -}; - - -static irqreturn_t mpc52xx_fec_interrupt(int, void *); -static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); -static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); -static void mpc52xx_fec_stop(struct net_device *dev); -static void mpc52xx_fec_start(struct net_device *dev); -static void mpc52xx_fec_reset(struct net_device *dev); - -static u8 mpc52xx_fec_mac_addr[6]; -module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0); -MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe"); - -#define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ - NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) -static int debug = -1; /* the above default */ -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "debugging messages level"); - -static void mpc52xx_fec_tx_timeout(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - unsigned long flags; - - dev_warn(&dev->dev, "transmit timed out\n"); - - spin_lock_irqsave(&priv->lock, flags); - mpc52xx_fec_reset(dev); - dev->stats.tx_errors++; - spin_unlock_irqrestore(&priv->lock, flags); - - netif_wake_queue(dev); -} - -static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - - out_be32(&fec->paddr1, *(u32 *)(&mac[0])); - out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); -} - -static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - - *(u32 *)(&mac[0]) = in_be32(&fec->paddr1); - *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16; -} - -static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) -{ - struct sockaddr *sock = addr; - - memcpy(dev->dev_addr, sock->sa_data, dev->addr_len); - - mpc52xx_fec_set_paddr(dev, sock->sa_data); - return 0; -} - -static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s) -{ - while (!bcom_queue_empty(s)) { - struct bcom_fec_bd *bd; - struct sk_buff *skb; - - skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd); - dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, - DMA_FROM_DEVICE); - kfree_skb(skb); - } -} - -static void -mpc52xx_fec_rx_submit(struct net_device *dev, struct sk_buff *rskb) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct bcom_fec_bd *bd; - - bd = (struct bcom_fec_bd *) bcom_prepare_next_buffer(priv->rx_dmatsk); - bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(dev->dev.parent, rskb->data, - FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); - bcom_submit_next_buffer(priv->rx_dmatsk, rskb); -} - -static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) -{ - struct sk_buff *skb; - - while (!bcom_queue_full(rxtsk)) { - skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); - if (!skb) - return -EAGAIN; - - /* zero out the initial receive buffers to aid debugging */ - memset(skb->data, 0, FEC_RX_BUFFER_SIZE); - mpc52xx_fec_rx_submit(dev, skb); - } - return 0; -} - -/* based on generic_adjust_link from fs_enet-main.c */ -static void mpc52xx_fec_adjust_link(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct phy_device *phydev = priv->phydev; - int new_state = 0; - - if (phydev->link != PHY_DOWN) { - if (phydev->duplex != priv->duplex) { - struct mpc52xx_fec __iomem *fec = priv->fec; - u32 rcntrl; - u32 tcntrl; - - new_state = 1; - priv->duplex = phydev->duplex; - - rcntrl = in_be32(&fec->r_cntrl); - tcntrl = in_be32(&fec->x_cntrl); - - rcntrl &= ~FEC_RCNTRL_DRT; - tcntrl &= ~FEC_TCNTRL_FDEN; - if (phydev->duplex == DUPLEX_FULL) - tcntrl |= FEC_TCNTRL_FDEN; /* FD enable */ - else - rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ - - out_be32(&fec->r_cntrl, rcntrl); - out_be32(&fec->x_cntrl, tcntrl); - } - - if (phydev->speed != priv->speed) { - new_state = 1; - priv->speed = phydev->speed; - } - - if (priv->link == PHY_DOWN) { - new_state = 1; - priv->link = phydev->link; - } - - } else if (priv->link) { - new_state = 1; - priv->link = PHY_DOWN; - priv->speed = 0; - priv->duplex = -1; - } - - if (new_state && netif_msg_link(priv)) - phy_print_status(phydev); -} - -static int mpc52xx_fec_open(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - int err = -EBUSY; - - if (priv->phy_node) { - priv->phydev = of_phy_connect(priv->ndev, priv->phy_node, - mpc52xx_fec_adjust_link, 0, 0); - if (!priv->phydev) { - dev_err(&dev->dev, "of_phy_connect failed\n"); - return -ENODEV; - } - phy_start(priv->phydev); - } - - if (request_irq(dev->irq, mpc52xx_fec_interrupt, IRQF_SHARED, - DRIVER_NAME "_ctrl", dev)) { - dev_err(&dev->dev, "ctrl interrupt request failed\n"); - goto free_phy; - } - if (request_irq(priv->r_irq, mpc52xx_fec_rx_interrupt, 0, - DRIVER_NAME "_rx", dev)) { - dev_err(&dev->dev, "rx interrupt request failed\n"); - goto free_ctrl_irq; - } - if (request_irq(priv->t_irq, mpc52xx_fec_tx_interrupt, 0, - DRIVER_NAME "_tx", dev)) { - dev_err(&dev->dev, "tx interrupt request failed\n"); - goto free_2irqs; - } - - bcom_fec_rx_reset(priv->rx_dmatsk); - bcom_fec_tx_reset(priv->tx_dmatsk); - - err = mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); - if (err) { - dev_err(&dev->dev, "mpc52xx_fec_alloc_rx_buffers failed\n"); - goto free_irqs; - } - - bcom_enable(priv->rx_dmatsk); - bcom_enable(priv->tx_dmatsk); - - mpc52xx_fec_start(dev); - - netif_start_queue(dev); - - return 0; - - free_irqs: - free_irq(priv->t_irq, dev); - free_2irqs: - free_irq(priv->r_irq, dev); - free_ctrl_irq: - free_irq(dev->irq, dev); - free_phy: - if (priv->phydev) { - phy_stop(priv->phydev); - phy_disconnect(priv->phydev); - priv->phydev = NULL; - } - - return err; -} - -static int mpc52xx_fec_close(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - netif_stop_queue(dev); - - mpc52xx_fec_stop(dev); - - mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); - - free_irq(dev->irq, dev); - free_irq(priv->r_irq, dev); - free_irq(priv->t_irq, dev); - - if (priv->phydev) { - /* power down phy */ - phy_stop(priv->phydev); - phy_disconnect(priv->phydev); - priv->phydev = NULL; - } - - return 0; -} - -/* This will only be invoked if your driver is _not_ in XOFF state. - * What this means is that you need not check it, and that this - * invariant will hold if you make sure that the netif_*_queue() - * calls are done at the proper times. - */ -static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct bcom_fec_bd *bd; - unsigned long flags; - - if (bcom_queue_full(priv->tx_dmatsk)) { - if (net_ratelimit()) - dev_err(&dev->dev, "transmit queue overrun\n"); - return NETDEV_TX_BUSY; - } - - spin_lock_irqsave(&priv->lock, flags); - - bd = (struct bcom_fec_bd *) - bcom_prepare_next_buffer(priv->tx_dmatsk); - - bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC; - bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, skb->len, - DMA_TO_DEVICE); - - skb_tx_timestamp(skb); - bcom_submit_next_buffer(priv->tx_dmatsk, skb); - spin_unlock_irqrestore(&priv->lock, flags); - - if (bcom_queue_full(priv->tx_dmatsk)) { - netif_stop_queue(dev); - } - - return NETDEV_TX_OK; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void mpc52xx_fec_poll_controller(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - disable_irq(priv->t_irq); - mpc52xx_fec_tx_interrupt(priv->t_irq, dev); - enable_irq(priv->t_irq); - disable_irq(priv->r_irq); - mpc52xx_fec_rx_interrupt(priv->r_irq, dev); - enable_irq(priv->r_irq); -} -#endif - - -/* This handles BestComm transmit task interrupts - */ -static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - spin_lock(&priv->lock); - while (bcom_buffer_done(priv->tx_dmatsk)) { - struct sk_buff *skb; - struct bcom_fec_bd *bd; - skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, - (struct bcom_bd **)&bd); - dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len, - DMA_TO_DEVICE); - - dev_kfree_skb_irq(skb); - } - spin_unlock(&priv->lock); - - netif_wake_queue(dev); - - return IRQ_HANDLED; -} - -static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct sk_buff *rskb; /* received sk_buff */ - struct sk_buff *skb; /* new sk_buff to enqueue in its place */ - struct bcom_fec_bd *bd; - u32 status, physaddr; - int length; - - spin_lock(&priv->lock); - - while (bcom_buffer_done(priv->rx_dmatsk)) { - - rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, - (struct bcom_bd **)&bd); - physaddr = bd->skb_pa; - - /* Test for errors in received frame */ - if (status & BCOM_FEC_RX_BD_ERRORS) { - /* Drop packet and reuse the buffer */ - mpc52xx_fec_rx_submit(dev, rskb); - dev->stats.rx_dropped++; - continue; - } - - /* skbs are allocated on open, so now we allocate a new one, - * and remove the old (with the packet) */ - skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); - if (!skb) { - /* Can't get a new one : reuse the same & drop pkt */ - dev_notice(&dev->dev, "Low memory - dropped packet.\n"); - mpc52xx_fec_rx_submit(dev, rskb); - dev->stats.rx_dropped++; - continue; - } - - /* Enqueue the new sk_buff back on the hardware */ - mpc52xx_fec_rx_submit(dev, skb); - - /* Process the received skb - Drop the spin lock while - * calling into the network stack */ - spin_unlock(&priv->lock); - - dma_unmap_single(dev->dev.parent, physaddr, rskb->len, - DMA_FROM_DEVICE); - length = status & BCOM_FEC_RX_BD_LEN_MASK; - skb_put(rskb, length - 4); /* length without CRC32 */ - rskb->protocol = eth_type_trans(rskb, dev); - if (!skb_defer_rx_timestamp(rskb)) - netif_rx(rskb); - - spin_lock(&priv->lock); - } - - spin_unlock(&priv->lock); - - return IRQ_HANDLED; -} - -static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - u32 ievent; - - ievent = in_be32(&fec->ievent); - - ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */ - if (!ievent) - return IRQ_NONE; - - out_be32(&fec->ievent, ievent); /* clear pending events */ - - /* on fifo error, soft-reset fec */ - if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) { - - if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR)) - dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n"); - if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR)) - dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n"); - - spin_lock(&priv->lock); - mpc52xx_fec_reset(dev); - spin_unlock(&priv->lock); - - return IRQ_HANDLED; - } - - if (ievent & ~FEC_IEVENT_TFINT) - dev_dbg(&dev->dev, "ievent: %08x\n", ievent); - - return IRQ_HANDLED; -} - -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ -static struct net_device_stats *mpc52xx_fec_get_stats(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; - struct mpc52xx_fec __iomem *fec = priv->fec; - - stats->rx_bytes = in_be32(&fec->rmon_r_octets); - stats->rx_packets = in_be32(&fec->rmon_r_packets); - stats->rx_errors = in_be32(&fec->rmon_r_crc_align) + - in_be32(&fec->rmon_r_undersize) + - in_be32(&fec->rmon_r_oversize) + - in_be32(&fec->rmon_r_frag) + - in_be32(&fec->rmon_r_jab); - - stats->tx_bytes = in_be32(&fec->rmon_t_octets); - stats->tx_packets = in_be32(&fec->rmon_t_packets); - stats->tx_errors = in_be32(&fec->rmon_t_crc_align) + - in_be32(&fec->rmon_t_undersize) + - in_be32(&fec->rmon_t_oversize) + - in_be32(&fec->rmon_t_frag) + - in_be32(&fec->rmon_t_jab); - - stats->multicast = in_be32(&fec->rmon_r_mc_pkt); - stats->collisions = in_be32(&fec->rmon_t_col); - - /* detailed rx_errors: */ - stats->rx_length_errors = in_be32(&fec->rmon_r_undersize) - + in_be32(&fec->rmon_r_oversize) - + in_be32(&fec->rmon_r_frag) - + in_be32(&fec->rmon_r_jab); - stats->rx_over_errors = in_be32(&fec->r_macerr); - stats->rx_crc_errors = in_be32(&fec->ieee_r_crc); - stats->rx_frame_errors = in_be32(&fec->ieee_r_align); - stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop); - stats->rx_missed_errors = in_be32(&fec->rmon_r_drop); - - /* detailed tx_errors: */ - stats->tx_aborted_errors = 0; - stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr); - stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop); - stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe); - stats->tx_window_errors = in_be32(&fec->ieee_t_lcol); - - return stats; -} - -/* - * Read MIB counters in order to reset them, - * then zero all the stats fields in memory - */ -static void mpc52xx_fec_reset_stats(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - - out_be32(&fec->mib_control, FEC_MIB_DISABLE); - memset_io(&fec->rmon_t_drop, 0, - offsetof(struct mpc52xx_fec, reserved10) - - offsetof(struct mpc52xx_fec, rmon_t_drop)); - out_be32(&fec->mib_control, 0); - - memset(&dev->stats, 0, sizeof(dev->stats)); -} - -/* - * Set or clear the multicast filter for this adaptor. - */ -static void mpc52xx_fec_set_multicast_list(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - u32 rx_control; - - rx_control = in_be32(&fec->r_cntrl); - - if (dev->flags & IFF_PROMISC) { - rx_control |= FEC_RCNTRL_PROM; - out_be32(&fec->r_cntrl, rx_control); - } else { - rx_control &= ~FEC_RCNTRL_PROM; - out_be32(&fec->r_cntrl, rx_control); - - if (dev->flags & IFF_ALLMULTI) { - out_be32(&fec->gaddr1, 0xffffffff); - out_be32(&fec->gaddr2, 0xffffffff); - } else { - u32 crc; - struct netdev_hw_addr *ha; - u32 gaddr1 = 0x00000000; - u32 gaddr2 = 0x00000000; - - netdev_for_each_mc_addr(ha, dev) { - crc = ether_crc_le(6, ha->addr) >> 26; - if (crc >= 32) - gaddr1 |= 1 << (crc-32); - else - gaddr2 |= 1 << crc; - } - out_be32(&fec->gaddr1, gaddr1); - out_be32(&fec->gaddr2, gaddr2); - } - } -} - -/** - * mpc52xx_fec_hw_init - * @dev: network device - * - * Setup various hardware setting, only needed once on start - */ -static void mpc52xx_fec_hw_init(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - int i; - - /* Whack a reset. We should wait for this. */ - out_be32(&fec->ecntrl, FEC_ECNTRL_RESET); - for (i = 0; i < FEC_RESET_DELAY; ++i) { - if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0) - break; - udelay(1); - } - if (i == FEC_RESET_DELAY) - dev_err(&dev->dev, "FEC Reset timeout!\n"); - - /* set pause to 0x20 frames */ - out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20); - - /* high service request will be deasserted when there's < 7 bytes in fifo - * low service request will be deasserted when there's < 4*7 bytes in fifo - */ - out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); - out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7); - - /* alarm when <= x bytes in FIFO */ - out_be32(&fec->rfifo_alarm, 0x0000030c); - out_be32(&fec->tfifo_alarm, 0x00000100); - - /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */ - out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B); - - /* enable crc generation */ - out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC); - out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */ - out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */ - - /* set phy speed. - * this can't be done in phy driver, since it needs to be called - * before fec stuff (even on resume) */ - out_be32(&fec->mii_speed, priv->mdio_speed); -} - -/** - * mpc52xx_fec_start - * @dev: network device - * - * This function is called to start or restart the FEC during a link - * change. This happens on fifo errors or when switching between half - * and full duplex. - */ -static void mpc52xx_fec_start(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - u32 rcntrl; - u32 tcntrl; - u32 tmp; - - /* clear sticky error bits */ - tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF; - out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp); - out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp); - - /* FIFOs will reset on mpc52xx_fec_enable */ - out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET); - - /* Set station address. */ - mpc52xx_fec_set_paddr(dev, dev->dev_addr); - - mpc52xx_fec_set_multicast_list(dev); - - /* set max frame len, enable flow control, select mii mode */ - rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ - rcntrl |= FEC_RCNTRL_FCE; - - if (!priv->seven_wire_mode) - rcntrl |= FEC_RCNTRL_MII_MODE; - - if (priv->duplex == DUPLEX_FULL) - tcntrl = FEC_TCNTRL_FDEN; /* FD enable */ - else { - rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */ - tcntrl = 0; - } - out_be32(&fec->r_cntrl, rcntrl); - out_be32(&fec->x_cntrl, tcntrl); - - /* Clear any outstanding interrupt. */ - out_be32(&fec->ievent, 0xffffffff); - - /* Enable interrupts we wish to service. */ - out_be32(&fec->imask, FEC_IMASK_ENABLE); - - /* And last, enable the transmit and receive processing. */ - out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN); - out_be32(&fec->r_des_active, 0x01000000); -} - -/** - * mpc52xx_fec_stop - * @dev: network device - * - * stop all activity on fec and empty dma buffers - */ -static void mpc52xx_fec_stop(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - unsigned long timeout; - - /* disable all interrupts */ - out_be32(&fec->imask, 0); - - /* Disable the rx task. */ - bcom_disable(priv->rx_dmatsk); - - /* Wait for tx queue to drain, but only if we're in process context */ - if (!in_interrupt()) { - timeout = jiffies + msecs_to_jiffies(2000); - while (time_before(jiffies, timeout) && - !bcom_queue_empty(priv->tx_dmatsk)) - msleep(100); - - if (time_after_eq(jiffies, timeout)) - dev_err(&dev->dev, "queues didn't drain\n"); -#if 1 - if (time_after_eq(jiffies, timeout)) { - dev_err(&dev->dev, " tx: index: %i, outdex: %i\n", - priv->tx_dmatsk->index, - priv->tx_dmatsk->outdex); - dev_err(&dev->dev, " rx: index: %i, outdex: %i\n", - priv->rx_dmatsk->index, - priv->rx_dmatsk->outdex); - } -#endif - } - - bcom_disable(priv->tx_dmatsk); - - /* Stop FEC */ - out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); -} - -/* reset fec and bestcomm tasks */ -static void mpc52xx_fec_reset(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct mpc52xx_fec __iomem *fec = priv->fec; - - mpc52xx_fec_stop(dev); - - out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status)); - out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO); - - mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); - - mpc52xx_fec_hw_init(dev); - - bcom_fec_rx_reset(priv->rx_dmatsk); - bcom_fec_tx_reset(priv->tx_dmatsk); - - mpc52xx_fec_alloc_rx_buffers(dev, priv->rx_dmatsk); - - bcom_enable(priv->rx_dmatsk); - bcom_enable(priv->tx_dmatsk); - - mpc52xx_fec_start(dev); - - netif_wake_queue(dev); -} - - -/* ethtool interface */ - -static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - if (!priv->phydev) - return -ENODEV; - - return phy_ethtool_gset(priv->phydev, cmd); -} - -static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - if (!priv->phydev) - return -ENODEV; - - return phy_ethtool_sset(priv->phydev, cmd); -} - -static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - return priv->msg_enable; -} - -static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - priv->msg_enable = level; -} - -static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { - .get_settings = mpc52xx_fec_get_settings, - .set_settings = mpc52xx_fec_set_settings, - .get_link = ethtool_op_get_link, - .get_msglevel = mpc52xx_fec_get_msglevel, - .set_msglevel = mpc52xx_fec_set_msglevel, -}; - - -static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - if (!priv->phydev) - return -ENOTSUPP; - - return phy_mii_ioctl(priv->phydev, rq, cmd); -} - -static const struct net_device_ops mpc52xx_fec_netdev_ops = { - .ndo_open = mpc52xx_fec_open, - .ndo_stop = mpc52xx_fec_close, - .ndo_start_xmit = mpc52xx_fec_start_xmit, - .ndo_set_rx_mode = mpc52xx_fec_set_multicast_list, - .ndo_set_mac_address = mpc52xx_fec_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = mpc52xx_fec_ioctl, - .ndo_change_mtu = eth_change_mtu, - .ndo_tx_timeout = mpc52xx_fec_tx_timeout, - .ndo_get_stats = mpc52xx_fec_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = mpc52xx_fec_poll_controller, -#endif -}; - -/* ======================================================================== */ -/* OF Driver */ -/* ======================================================================== */ - -static int __devinit mpc52xx_fec_probe(struct platform_device *op) -{ - int rv; - struct net_device *ndev; - struct mpc52xx_fec_priv *priv = NULL; - struct resource mem; - const u32 *prop; - int prop_size; - - phys_addr_t rx_fifo; - phys_addr_t tx_fifo; - - /* Get the ether ndev & it's private zone */ - ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv)); - if (!ndev) - return -ENOMEM; - - priv = netdev_priv(ndev); - priv->ndev = ndev; - - /* Reserve FEC control zone */ - rv = of_address_to_resource(op->dev.of_node, 0, &mem); - if (rv) { - printk(KERN_ERR DRIVER_NAME ": " - "Error while parsing device node resource\n" ); - goto err_netdev; - } - if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) { - printk(KERN_ERR DRIVER_NAME - " - invalid resource size (%lx < %x), check mpc52xx_devices.c\n", - (unsigned long)resource_size(&mem), - sizeof(struct mpc52xx_fec)); - rv = -EINVAL; - goto err_netdev; - } - - if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), - DRIVER_NAME)) { - rv = -EBUSY; - goto err_netdev; - } - - /* Init ether ndev with what we have */ - ndev->netdev_ops = &mpc52xx_fec_netdev_ops; - ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; - ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; - ndev->base_addr = mem.start; - SET_NETDEV_DEV(ndev, &op->dev); - - spin_lock_init(&priv->lock); - - /* ioremap the zones */ - priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec)); - - if (!priv->fec) { - rv = -ENOMEM; - goto err_mem_region; - } - - /* Bestcomm init */ - rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data); - tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data); - - priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE); - priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo); - - if (!priv->rx_dmatsk || !priv->tx_dmatsk) { - printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" ); - rv = -ENOMEM; - goto err_rx_tx_dmatsk; - } - - /* Get the IRQ we need one by one */ - /* Control */ - ndev->irq = irq_of_parse_and_map(op->dev.of_node, 0); - - /* RX */ - priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); - - /* TX */ - priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); - - /* MAC address init */ - if (!is_zero_ether_addr(mpc52xx_fec_mac_addr)) - memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6); - else - mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); - - priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); - - /* - * Link mode configuration - */ - - /* Start with safe defaults for link connection */ - priv->speed = 100; - priv->duplex = DUPLEX_HALF; - priv->mdio_speed = ((mpc5xxx_get_bus_frequency(op->dev.of_node) >> 20) / 5) << 1; - - /* The current speed preconfigures the speed of the MII link */ - prop = of_get_property(op->dev.of_node, "current-speed", &prop_size); - if (prop && (prop_size >= sizeof(u32) * 2)) { - priv->speed = prop[0]; - priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; - } - - /* If there is a phy handle, then get the PHY node */ - priv->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0); - - /* the 7-wire property means don't use MII mode */ - if (of_find_property(op->dev.of_node, "fsl,7-wire-mode", NULL)) { - priv->seven_wire_mode = 1; - dev_info(&ndev->dev, "using 7-wire PHY mode\n"); - } - - /* Hardware init */ - mpc52xx_fec_hw_init(ndev); - mpc52xx_fec_reset_stats(ndev); - - rv = register_netdev(ndev); - if (rv < 0) - goto err_node; - - /* We're done ! */ - dev_set_drvdata(&op->dev, ndev); - - return 0; - -err_node: - of_node_put(priv->phy_node); - irq_dispose_mapping(ndev->irq); -err_rx_tx_dmatsk: - if (priv->rx_dmatsk) - bcom_fec_rx_release(priv->rx_dmatsk); - if (priv->tx_dmatsk) - bcom_fec_tx_release(priv->tx_dmatsk); - iounmap(priv->fec); -err_mem_region: - release_mem_region(mem.start, sizeof(struct mpc52xx_fec)); -err_netdev: - free_netdev(ndev); - - return rv; -} - -static int -mpc52xx_fec_remove(struct platform_device *op) -{ - struct net_device *ndev; - struct mpc52xx_fec_priv *priv; - - ndev = dev_get_drvdata(&op->dev); - priv = netdev_priv(ndev); - - unregister_netdev(ndev); - - if (priv->phy_node) - of_node_put(priv->phy_node); - priv->phy_node = NULL; - - irq_dispose_mapping(ndev->irq); - - bcom_fec_rx_release(priv->rx_dmatsk); - bcom_fec_tx_release(priv->tx_dmatsk); - - iounmap(priv->fec); - - release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec)); - - free_netdev(ndev); - - dev_set_drvdata(&op->dev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) -{ - struct net_device *dev = dev_get_drvdata(&op->dev); - - if (netif_running(dev)) - mpc52xx_fec_close(dev); - - return 0; -} - -static int mpc52xx_fec_of_resume(struct platform_device *op) -{ - struct net_device *dev = dev_get_drvdata(&op->dev); - - mpc52xx_fec_hw_init(dev); - mpc52xx_fec_reset_stats(dev); - - if (netif_running(dev)) - mpc52xx_fec_open(dev); - - return 0; -} -#endif - -static struct of_device_id mpc52xx_fec_match[] = { - { .compatible = "fsl,mpc5200b-fec", }, - { .compatible = "fsl,mpc5200-fec", }, - { .compatible = "mpc5200-fec", }, - { } -}; - -MODULE_DEVICE_TABLE(of, mpc52xx_fec_match); - -static struct platform_driver mpc52xx_fec_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = mpc52xx_fec_match, - }, - .probe = mpc52xx_fec_probe, - .remove = mpc52xx_fec_remove, -#ifdef CONFIG_PM - .suspend = mpc52xx_fec_of_suspend, - .resume = mpc52xx_fec_of_resume, -#endif -}; - - -/* ======================================================================== */ -/* Module */ -/* ======================================================================== */ - -static int __init -mpc52xx_fec_init(void) -{ -#ifdef CONFIG_FEC_MPC52xx_MDIO - int ret; - ret = platform_driver_register(&mpc52xx_fec_mdio_driver); - if (ret) { - printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n"); - return ret; - } -#endif - return platform_driver_register(&mpc52xx_fec_driver); -} - -static void __exit -mpc52xx_fec_exit(void) -{ - platform_driver_unregister(&mpc52xx_fec_driver); -#ifdef CONFIG_FEC_MPC52xx_MDIO - platform_driver_unregister(&mpc52xx_fec_mdio_driver); -#endif -} - - -module_init(mpc52xx_fec_init); -module_exit(mpc52xx_fec_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Dale Farnsworth"); -MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx.h deleted file mode 100644 index 10afa54d..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * drivers/net/ethernet/freescale/fec_mpc52xx.h - * - * Driver for the MPC5200 Fast Ethernet Controller - * - * Author: Dale Farnsworth <dfarnsworth@mvista.com> - * - * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __DRIVERS_NET_MPC52XX_FEC_H__ -#define __DRIVERS_NET_MPC52XX_FEC_H__ - -#include <linux/phy.h> - -/* Tunable constant */ -/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */ -#define FEC_RX_BUFFER_SIZE 1522 /* max receive packet size */ -#define FEC_RX_NUM_BD 256 -#define FEC_TX_NUM_BD 64 - -#define FEC_RESET_DELAY 50 /* uS */ - -#define FEC_WATCHDOG_TIMEOUT ((400*HZ)/1000) - -/* ======================================================================== */ -/* Hardware register sets & bits */ -/* ======================================================================== */ - -struct mpc52xx_fec { - u32 fec_id; /* FEC + 0x000 */ - u32 ievent; /* FEC + 0x004 */ - u32 imask; /* FEC + 0x008 */ - - u32 reserved0[1]; /* FEC + 0x00C */ - u32 r_des_active; /* FEC + 0x010 */ - u32 x_des_active; /* FEC + 0x014 */ - u32 r_des_active_cl; /* FEC + 0x018 */ - u32 x_des_active_cl; /* FEC + 0x01C */ - u32 ivent_set; /* FEC + 0x020 */ - u32 ecntrl; /* FEC + 0x024 */ - - u32 reserved1[6]; /* FEC + 0x028-03C */ - u32 mii_data; /* FEC + 0x040 */ - u32 mii_speed; /* FEC + 0x044 */ - u32 mii_status; /* FEC + 0x048 */ - - u32 reserved2[5]; /* FEC + 0x04C-05C */ - u32 mib_data; /* FEC + 0x060 */ - u32 mib_control; /* FEC + 0x064 */ - - u32 reserved3[6]; /* FEC + 0x068-7C */ - u32 r_activate; /* FEC + 0x080 */ - u32 r_cntrl; /* FEC + 0x084 */ - u32 r_hash; /* FEC + 0x088 */ - u32 r_data; /* FEC + 0x08C */ - u32 ar_done; /* FEC + 0x090 */ - u32 r_test; /* FEC + 0x094 */ - u32 r_mib; /* FEC + 0x098 */ - u32 r_da_low; /* FEC + 0x09C */ - u32 r_da_high; /* FEC + 0x0A0 */ - - u32 reserved4[7]; /* FEC + 0x0A4-0BC */ - u32 x_activate; /* FEC + 0x0C0 */ - u32 x_cntrl; /* FEC + 0x0C4 */ - u32 backoff; /* FEC + 0x0C8 */ - u32 x_data; /* FEC + 0x0CC */ - u32 x_status; /* FEC + 0x0D0 */ - u32 x_mib; /* FEC + 0x0D4 */ - u32 x_test; /* FEC + 0x0D8 */ - u32 fdxfc_da1; /* FEC + 0x0DC */ - u32 fdxfc_da2; /* FEC + 0x0E0 */ - u32 paddr1; /* FEC + 0x0E4 */ - u32 paddr2; /* FEC + 0x0E8 */ - u32 op_pause; /* FEC + 0x0EC */ - - u32 reserved5[4]; /* FEC + 0x0F0-0FC */ - u32 instr_reg; /* FEC + 0x100 */ - u32 context_reg; /* FEC + 0x104 */ - u32 test_cntrl; /* FEC + 0x108 */ - u32 acc_reg; /* FEC + 0x10C */ - u32 ones; /* FEC + 0x110 */ - u32 zeros; /* FEC + 0x114 */ - u32 iaddr1; /* FEC + 0x118 */ - u32 iaddr2; /* FEC + 0x11C */ - u32 gaddr1; /* FEC + 0x120 */ - u32 gaddr2; /* FEC + 0x124 */ - u32 random; /* FEC + 0x128 */ - u32 rand1; /* FEC + 0x12C */ - u32 tmp; /* FEC + 0x130 */ - - u32 reserved6[3]; /* FEC + 0x134-13C */ - u32 fifo_id; /* FEC + 0x140 */ - u32 x_wmrk; /* FEC + 0x144 */ - u32 fcntrl; /* FEC + 0x148 */ - u32 r_bound; /* FEC + 0x14C */ - u32 r_fstart; /* FEC + 0x150 */ - u32 r_count; /* FEC + 0x154 */ - u32 r_lag; /* FEC + 0x158 */ - u32 r_read; /* FEC + 0x15C */ - u32 r_write; /* FEC + 0x160 */ - u32 x_count; /* FEC + 0x164 */ - u32 x_lag; /* FEC + 0x168 */ - u32 x_retry; /* FEC + 0x16C */ - u32 x_write; /* FEC + 0x170 */ - u32 x_read; /* FEC + 0x174 */ - - u32 reserved7[2]; /* FEC + 0x178-17C */ - u32 fm_cntrl; /* FEC + 0x180 */ - u32 rfifo_data; /* FEC + 0x184 */ - u32 rfifo_status; /* FEC + 0x188 */ - u32 rfifo_cntrl; /* FEC + 0x18C */ - u32 rfifo_lrf_ptr; /* FEC + 0x190 */ - u32 rfifo_lwf_ptr; /* FEC + 0x194 */ - u32 rfifo_alarm; /* FEC + 0x198 */ - u32 rfifo_rdptr; /* FEC + 0x19C */ - u32 rfifo_wrptr; /* FEC + 0x1A0 */ - u32 tfifo_data; /* FEC + 0x1A4 */ - u32 tfifo_status; /* FEC + 0x1A8 */ - u32 tfifo_cntrl; /* FEC + 0x1AC */ - u32 tfifo_lrf_ptr; /* FEC + 0x1B0 */ - u32 tfifo_lwf_ptr; /* FEC + 0x1B4 */ - u32 tfifo_alarm; /* FEC + 0x1B8 */ - u32 tfifo_rdptr; /* FEC + 0x1BC */ - u32 tfifo_wrptr; /* FEC + 0x1C0 */ - - u32 reset_cntrl; /* FEC + 0x1C4 */ - u32 xmit_fsm; /* FEC + 0x1C8 */ - - u32 reserved8[3]; /* FEC + 0x1CC-1D4 */ - u32 rdes_data0; /* FEC + 0x1D8 */ - u32 rdes_data1; /* FEC + 0x1DC */ - u32 r_length; /* FEC + 0x1E0 */ - u32 x_length; /* FEC + 0x1E4 */ - u32 x_addr; /* FEC + 0x1E8 */ - u32 cdes_data; /* FEC + 0x1EC */ - u32 status; /* FEC + 0x1F0 */ - u32 dma_control; /* FEC + 0x1F4 */ - u32 des_cmnd; /* FEC + 0x1F8 */ - u32 data; /* FEC + 0x1FC */ - - u32 rmon_t_drop; /* FEC + 0x200 */ - u32 rmon_t_packets; /* FEC + 0x204 */ - u32 rmon_t_bc_pkt; /* FEC + 0x208 */ - u32 rmon_t_mc_pkt; /* FEC + 0x20C */ - u32 rmon_t_crc_align; /* FEC + 0x210 */ - u32 rmon_t_undersize; /* FEC + 0x214 */ - u32 rmon_t_oversize; /* FEC + 0x218 */ - u32 rmon_t_frag; /* FEC + 0x21C */ - u32 rmon_t_jab; /* FEC + 0x220 */ - u32 rmon_t_col; /* FEC + 0x224 */ - u32 rmon_t_p64; /* FEC + 0x228 */ - u32 rmon_t_p65to127; /* FEC + 0x22C */ - u32 rmon_t_p128to255; /* FEC + 0x230 */ - u32 rmon_t_p256to511; /* FEC + 0x234 */ - u32 rmon_t_p512to1023; /* FEC + 0x238 */ - u32 rmon_t_p1024to2047; /* FEC + 0x23C */ - u32 rmon_t_p_gte2048; /* FEC + 0x240 */ - u32 rmon_t_octets; /* FEC + 0x244 */ - u32 ieee_t_drop; /* FEC + 0x248 */ - u32 ieee_t_frame_ok; /* FEC + 0x24C */ - u32 ieee_t_1col; /* FEC + 0x250 */ - u32 ieee_t_mcol; /* FEC + 0x254 */ - u32 ieee_t_def; /* FEC + 0x258 */ - u32 ieee_t_lcol; /* FEC + 0x25C */ - u32 ieee_t_excol; /* FEC + 0x260 */ - u32 ieee_t_macerr; /* FEC + 0x264 */ - u32 ieee_t_cserr; /* FEC + 0x268 */ - u32 ieee_t_sqe; /* FEC + 0x26C */ - u32 t_fdxfc; /* FEC + 0x270 */ - u32 ieee_t_octets_ok; /* FEC + 0x274 */ - - u32 reserved9[2]; /* FEC + 0x278-27C */ - u32 rmon_r_drop; /* FEC + 0x280 */ - u32 rmon_r_packets; /* FEC + 0x284 */ - u32 rmon_r_bc_pkt; /* FEC + 0x288 */ - u32 rmon_r_mc_pkt; /* FEC + 0x28C */ - u32 rmon_r_crc_align; /* FEC + 0x290 */ - u32 rmon_r_undersize; /* FEC + 0x294 */ - u32 rmon_r_oversize; /* FEC + 0x298 */ - u32 rmon_r_frag; /* FEC + 0x29C */ - u32 rmon_r_jab; /* FEC + 0x2A0 */ - - u32 rmon_r_resvd_0; /* FEC + 0x2A4 */ - - u32 rmon_r_p64; /* FEC + 0x2A8 */ - u32 rmon_r_p65to127; /* FEC + 0x2AC */ - u32 rmon_r_p128to255; /* FEC + 0x2B0 */ - u32 rmon_r_p256to511; /* FEC + 0x2B4 */ - u32 rmon_r_p512to1023; /* FEC + 0x2B8 */ - u32 rmon_r_p1024to2047; /* FEC + 0x2BC */ - u32 rmon_r_p_gte2048; /* FEC + 0x2C0 */ - u32 rmon_r_octets; /* FEC + 0x2C4 */ - u32 ieee_r_drop; /* FEC + 0x2C8 */ - u32 ieee_r_frame_ok; /* FEC + 0x2CC */ - u32 ieee_r_crc; /* FEC + 0x2D0 */ - u32 ieee_r_align; /* FEC + 0x2D4 */ - u32 r_macerr; /* FEC + 0x2D8 */ - u32 r_fdxfc; /* FEC + 0x2DC */ - u32 ieee_r_octets_ok; /* FEC + 0x2E0 */ - - u32 reserved10[7]; /* FEC + 0x2E4-2FC */ - - u32 reserved11[64]; /* FEC + 0x300-3FF */ -}; - -#define FEC_MIB_DISABLE 0x80000000 - -#define FEC_IEVENT_HBERR 0x80000000 -#define FEC_IEVENT_BABR 0x40000000 -#define FEC_IEVENT_BABT 0x20000000 -#define FEC_IEVENT_GRA 0x10000000 -#define FEC_IEVENT_TFINT 0x08000000 -#define FEC_IEVENT_MII 0x00800000 -#define FEC_IEVENT_LATE_COL 0x00200000 -#define FEC_IEVENT_COL_RETRY_LIM 0x00100000 -#define FEC_IEVENT_XFIFO_UN 0x00080000 -#define FEC_IEVENT_XFIFO_ERROR 0x00040000 -#define FEC_IEVENT_RFIFO_ERROR 0x00020000 - -#define FEC_IMASK_HBERR 0x80000000 -#define FEC_IMASK_BABR 0x40000000 -#define FEC_IMASK_BABT 0x20000000 -#define FEC_IMASK_GRA 0x10000000 -#define FEC_IMASK_MII 0x00800000 -#define FEC_IMASK_LATE_COL 0x00200000 -#define FEC_IMASK_COL_RETRY_LIM 0x00100000 -#define FEC_IMASK_XFIFO_UN 0x00080000 -#define FEC_IMASK_XFIFO_ERROR 0x00040000 -#define FEC_IMASK_RFIFO_ERROR 0x00020000 - -/* all but MII, which is enabled separately */ -#define FEC_IMASK_ENABLE (FEC_IMASK_HBERR | FEC_IMASK_BABR | \ - FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_LATE_COL | \ - FEC_IMASK_COL_RETRY_LIM | FEC_IMASK_XFIFO_UN | \ - FEC_IMASK_XFIFO_ERROR | FEC_IMASK_RFIFO_ERROR) - -#define FEC_RCNTRL_MAX_FL_SHIFT 16 -#define FEC_RCNTRL_LOOP 0x01 -#define FEC_RCNTRL_DRT 0x02 -#define FEC_RCNTRL_MII_MODE 0x04 -#define FEC_RCNTRL_PROM 0x08 -#define FEC_RCNTRL_BC_REJ 0x10 -#define FEC_RCNTRL_FCE 0x20 - -#define FEC_TCNTRL_GTS 0x00000001 -#define FEC_TCNTRL_HBC 0x00000002 -#define FEC_TCNTRL_FDEN 0x00000004 -#define FEC_TCNTRL_TFC_PAUSE 0x00000008 -#define FEC_TCNTRL_RFC_PAUSE 0x00000010 - -#define FEC_ECNTRL_RESET 0x00000001 -#define FEC_ECNTRL_ETHER_EN 0x00000002 - -#define FEC_MII_DATA_ST 0x40000000 /* Start frame */ -#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform read */ -#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform write */ -#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address mask */ -#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register mask */ -#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */ -#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data mask */ - -#define FEC_MII_READ_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA) -#define FEC_MII_WRITE_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA) - -#define FEC_MII_DATA_RA_SHIFT 0x12 /* MII reg addr bits */ -#define FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY addr bits */ - -#define FEC_PADDR2_TYPE 0x8808 - -#define FEC_OP_PAUSE_OPCODE 0x00010000 - -#define FEC_FIFO_WMRK_256B 0x3 - -#define FEC_FIFO_STATUS_ERR 0x00400000 -#define FEC_FIFO_STATUS_UF 0x00200000 -#define FEC_FIFO_STATUS_OF 0x00100000 - -#define FEC_FIFO_CNTRL_FRAME 0x08000000 -#define FEC_FIFO_CNTRL_LTG_7 0x07000000 - -#define FEC_RESET_CNTRL_RESET_FIFO 0x02000000 -#define FEC_RESET_CNTRL_ENABLE_IS_RESET 0x01000000 - -#define FEC_XMIT_FSM_APPEND_CRC 0x02000000 -#define FEC_XMIT_FSM_ENABLE_CRC 0x01000000 - - -extern struct platform_driver mpc52xx_fec_mdio_driver; - -#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c deleted file mode 100644 index 360a578c..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver - * - * Copyright (C) 2007 Domen Puncer, Telargo, Inc. - * Copyright (C) 2008 Wolfram Sang, Pengutronix - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/phy.h> -#include <linux/of_platform.h> -#include <linux/slab.h> -#include <linux/of_mdio.h> -#include <asm/io.h> -#include <asm/mpc52xx.h> -#include "fec_mpc52xx.h" - -struct mpc52xx_fec_mdio_priv { - struct mpc52xx_fec __iomem *regs; - int mdio_irqs[PHY_MAX_ADDR]; -}; - -static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, - int reg, u32 value) -{ - struct mpc52xx_fec_mdio_priv *priv = bus->priv; - struct mpc52xx_fec __iomem *fec = priv->regs; - int tries = 3; - - value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; - value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; - - out_be32(&fec->ievent, FEC_IEVENT_MII); - out_be32(&fec->mii_data, value); - - /* wait for it to finish, this takes about 23 us on lite5200b */ - while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) - msleep(1); - - if (!tries) - return -ETIMEDOUT; - - return value & FEC_MII_DATA_OP_RD ? - in_be32(&fec->mii_data) & FEC_MII_DATA_DATAMSK : 0; -} - -static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) -{ - return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, FEC_MII_READ_FRAME); -} - -static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, - u16 data) -{ - return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, - data | FEC_MII_WRITE_FRAME); -} - -static int mpc52xx_fec_mdio_probe(struct platform_device *of) -{ - struct device *dev = &of->dev; - struct device_node *np = of->dev.of_node; - struct mii_bus *bus; - struct mpc52xx_fec_mdio_priv *priv; - struct resource res; - int err; - - bus = mdiobus_alloc(); - if (bus == NULL) - return -ENOMEM; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) { - err = -ENOMEM; - goto out_free; - } - - bus->name = "mpc52xx MII bus"; - bus->read = mpc52xx_fec_mdio_read; - bus->write = mpc52xx_fec_mdio_write; - - /* setup irqs */ - bus->irq = priv->mdio_irqs; - - /* setup registers */ - err = of_address_to_resource(np, 0, &res); - if (err) - goto out_free; - priv->regs = ioremap(res.start, resource_size(&res)); - if (priv->regs == NULL) { - err = -ENOMEM; - goto out_free; - } - - snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); - bus->priv = priv; - - bus->parent = dev; - dev_set_drvdata(dev, bus); - - /* set MII speed */ - out_be32(&priv->regs->mii_speed, - ((mpc5xxx_get_bus_frequency(of->dev.of_node) >> 20) / 5) << 1); - - err = of_mdiobus_register(bus, np); - if (err) - goto out_unmap; - - return 0; - - out_unmap: - iounmap(priv->regs); - out_free: - kfree(priv); - mdiobus_free(bus); - - return err; -} - -static int mpc52xx_fec_mdio_remove(struct platform_device *of) -{ - struct device *dev = &of->dev; - struct mii_bus *bus = dev_get_drvdata(dev); - struct mpc52xx_fec_mdio_priv *priv = bus->priv; - - mdiobus_unregister(bus); - dev_set_drvdata(dev, NULL); - iounmap(priv->regs); - kfree(priv); - mdiobus_free(bus); - - return 0; -} - -static struct of_device_id mpc52xx_fec_mdio_match[] = { - { .compatible = "fsl,mpc5200b-mdio", }, - { .compatible = "fsl,mpc5200-mdio", }, - { .compatible = "mpc5200b-fec-phy", }, - {} -}; -MODULE_DEVICE_TABLE(of, mpc52xx_fec_mdio_match); - -struct platform_driver mpc52xx_fec_mdio_driver = { - .driver = { - .name = "mpc5200b-fec-phy", - .owner = THIS_MODULE, - .of_match_table = mpc52xx_fec_mdio_match, - }, - .probe = mpc52xx_fec_mdio_probe, - .remove = mpc52xx_fec_mdio_remove, -}; - -/* let fec driver call it, since this has to be registered before it */ -EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver); - -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/Kconfig b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/Kconfig deleted file mode 100644 index 268414d9..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/Kconfig +++ /dev/null @@ -1,35 +0,0 @@ -config FS_ENET - tristate "Freescale Ethernet Driver" - depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x) - select NET_CORE - select MII - select PHYLIB - -config FS_ENET_MPC5121_FEC - def_bool y if (FS_ENET && PPC_MPC512x) - select FS_ENET_HAS_FEC - -config FS_ENET_HAS_SCC - bool "Chip has an SCC usable for ethernet" - depends on FS_ENET && (CPM1 || CPM2) - default y - -config FS_ENET_HAS_FCC - bool "Chip has an FCC usable for ethernet" - depends on FS_ENET && CPM2 - default y - -config FS_ENET_HAS_FEC - bool "Chip has an FEC usable for ethernet" - depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) - select FS_ENET_MDIO_FEC - default y - -config FS_ENET_MDIO_FEC - tristate "MDIO driver for FEC" - depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) - -config FS_ENET_MDIO_FCC - tristate "MDIO driver for FCC" - depends on FS_ENET && CPM2 - select MDIO_BITBANG diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/Makefile b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/Makefile deleted file mode 100644 index d4a305ee..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile for the Freescale Ethernet controllers -# - -obj-$(CONFIG_FS_ENET) += fs_enet.o - -fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o -fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o -fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o - -obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o -obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o - -fs_enet-objs := fs_enet-main.o $(fs_enet-m) diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fec.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fec.h deleted file mode 100644 index b9fe5bde..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fec.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef FS_ENET_FEC_H -#define FS_ENET_FEC_H - -/* CRC polynomium used by the FEC for the multicast group filtering */ -#define FEC_CRC_POLY 0x04C11DB7 - -#define FEC_MAX_MULTICAST_ADDRS 64 - -/* Interrupt events/masks. -*/ -#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */ -#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */ -#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */ -#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */ -#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */ -#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */ -#define FEC_ENET_RXF 0x02000000U /* Full frame received */ -#define FEC_ENET_RXB 0x01000000U /* A buffer was received */ -#define FEC_ENET_MII 0x00800000U /* MII interrupt */ -#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */ - -#define FEC_ECNTRL_PINMUX 0x00000004 -#define FEC_ECNTRL_ETHER_EN 0x00000002 -#define FEC_ECNTRL_RESET 0x00000001 - -/* RMII mode enabled only when MII_MODE bit is set too. */ -#define FEC_RCNTRL_RMII_MODE (0x00000100 | \ - FEC_RCNTRL_MII_MODE | FEC_RCNTRL_FCE) -#define FEC_RCNTRL_FCE 0x00000020 -#define FEC_RCNTRL_BC_REJ 0x00000010 -#define FEC_RCNTRL_PROM 0x00000008 -#define FEC_RCNTRL_MII_MODE 0x00000004 -#define FEC_RCNTRL_DRT 0x00000002 -#define FEC_RCNTRL_LOOP 0x00000001 - -#define FEC_TCNTRL_FDEN 0x00000004 -#define FEC_TCNTRL_HBC 0x00000002 -#define FEC_TCNTRL_GTS 0x00000001 - -/* - * Delay to wait for FEC reset command to complete (in us) - */ -#define FEC_RESET_DELAY 50 -#endif diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c deleted file mode 100644 index e4e6cd2c..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ /dev/null @@ -1,1199 +0,0 @@ -/* - * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - * - * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com> - * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/bitops.h> -#include <linux/fs.h> -#include <linux/platform_device.h> -#include <linux/phy.h> -#include <linux/of.h> -#include <linux/of_mdio.h> -#include <linux/of_platform.h> -#include <linux/of_gpio.h> -#include <linux/of_net.h> - -#include <linux/vmalloc.h> -#include <asm/pgtable.h> -#include <asm/irq.h> -#include <asm/uaccess.h> - -#include "fs_enet.h" - -/*************************************************/ - -MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>"); -MODULE_DESCRIPTION("Freescale Ethernet Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_MODULE_VERSION); - -static int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */ -module_param(fs_enet_debug, int, 0); -MODULE_PARM_DESC(fs_enet_debug, - "Freescale bitmapped debugging message enable value"); - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void fs_enet_netpoll(struct net_device *dev); -#endif - -static void fs_set_multicast_list(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - (*fep->ops->set_multicast_list)(dev); -} - -static void skb_align(struct sk_buff *skb, int align) -{ - int off = ((unsigned long)skb->data) & (align - 1); - - if (off) - skb_reserve(skb, align - off); -} - -/* NAPI receive function */ -static int fs_enet_rx_napi(struct napi_struct *napi, int budget) -{ - struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi); - struct net_device *dev = fep->ndev; - const struct fs_platform_info *fpi = fep->fpi; - cbd_t __iomem *bdp; - struct sk_buff *skb, *skbn, *skbt; - int received = 0; - u16 pkt_len, sc; - int curidx; - - /* - * First, grab all of the stats for the incoming packet. - * These get messed up if we get called due to a busy condition. - */ - bdp = fep->cur_rx; - - /* clear RX status bits for napi*/ - (*fep->ops->napi_clear_rx_event)(dev); - - while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) { - curidx = bdp - fep->rx_bd_base; - - /* - * Since we have allocated space to hold a complete frame, - * the last indicator should be set. - */ - if ((sc & BD_ENET_RX_LAST) == 0) - dev_warn(fep->dev, "rcv is not +last\n"); - - /* - * Check for errors. - */ - if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL | - BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) { - fep->stats.rx_errors++; - /* Frame too long or too short. */ - if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) - fep->stats.rx_length_errors++; - /* Frame alignment */ - if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL)) - fep->stats.rx_frame_errors++; - /* CRC Error */ - if (sc & BD_ENET_RX_CR) - fep->stats.rx_crc_errors++; - /* FIFO overrun */ - if (sc & BD_ENET_RX_OV) - fep->stats.rx_crc_errors++; - - skb = fep->rx_skbuff[curidx]; - - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE); - - skbn = skb; - - } else { - skb = fep->rx_skbuff[curidx]; - - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE); - - /* - * Process the incoming frame. - */ - fep->stats.rx_packets++; - pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */ - fep->stats.rx_bytes += pkt_len + 4; - - if (pkt_len <= fpi->rx_copybreak) { - /* +2 to make IP header L1 cache aligned */ - skbn = netdev_alloc_skb(dev, pkt_len + 2); - if (skbn != NULL) { - skb_reserve(skbn, 2); /* align IP header */ - skb_copy_from_linear_data(skb, - skbn->data, pkt_len); - /* swap */ - skbt = skb; - skb = skbn; - skbn = skbt; - } - } else { - skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE); - - if (skbn) - skb_align(skbn, ENET_RX_ALIGN); - } - - if (skbn != NULL) { - skb_put(skb, pkt_len); /* Make room */ - skb->protocol = eth_type_trans(skb, dev); - received++; - netif_receive_skb(skb); - } else { - dev_warn(fep->dev, - "Memory squeeze, dropping packet.\n"); - fep->stats.rx_dropped++; - skbn = skb; - } - } - - fep->rx_skbuff[curidx] = skbn; - CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data, - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE)); - CBDW_DATLEN(bdp, 0); - CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY); - - /* - * Update BD pointer to next entry. - */ - if ((sc & BD_ENET_RX_WRAP) == 0) - bdp++; - else - bdp = fep->rx_bd_base; - - (*fep->ops->rx_bd_done)(dev); - - if (received >= budget) - break; - } - - fep->cur_rx = bdp; - - if (received < budget) { - /* done */ - napi_complete(napi); - (*fep->ops->napi_enable_rx)(dev); - } - return received; -} - -/* non NAPI receive function */ -static int fs_enet_rx_non_napi(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - cbd_t __iomem *bdp; - struct sk_buff *skb, *skbn, *skbt; - int received = 0; - u16 pkt_len, sc; - int curidx; - /* - * First, grab all of the stats for the incoming packet. - * These get messed up if we get called due to a busy condition. - */ - bdp = fep->cur_rx; - - while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) { - - curidx = bdp - fep->rx_bd_base; - - /* - * Since we have allocated space to hold a complete frame, - * the last indicator should be set. - */ - if ((sc & BD_ENET_RX_LAST) == 0) - dev_warn(fep->dev, "rcv is not +last\n"); - - /* - * Check for errors. - */ - if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL | - BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) { - fep->stats.rx_errors++; - /* Frame too long or too short. */ - if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) - fep->stats.rx_length_errors++; - /* Frame alignment */ - if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL)) - fep->stats.rx_frame_errors++; - /* CRC Error */ - if (sc & BD_ENET_RX_CR) - fep->stats.rx_crc_errors++; - /* FIFO overrun */ - if (sc & BD_ENET_RX_OV) - fep->stats.rx_crc_errors++; - - skb = fep->rx_skbuff[curidx]; - - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE); - - skbn = skb; - - } else { - - skb = fep->rx_skbuff[curidx]; - - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE); - - /* - * Process the incoming frame. - */ - fep->stats.rx_packets++; - pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */ - fep->stats.rx_bytes += pkt_len + 4; - - if (pkt_len <= fpi->rx_copybreak) { - /* +2 to make IP header L1 cache aligned */ - skbn = netdev_alloc_skb(dev, pkt_len + 2); - if (skbn != NULL) { - skb_reserve(skbn, 2); /* align IP header */ - skb_copy_from_linear_data(skb, - skbn->data, pkt_len); - /* swap */ - skbt = skb; - skb = skbn; - skbn = skbt; - } - } else { - skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE); - - if (skbn) - skb_align(skbn, ENET_RX_ALIGN); - } - - if (skbn != NULL) { - skb_put(skb, pkt_len); /* Make room */ - skb->protocol = eth_type_trans(skb, dev); - received++; - netif_rx(skb); - } else { - dev_warn(fep->dev, - "Memory squeeze, dropping packet.\n"); - fep->stats.rx_dropped++; - skbn = skb; - } - } - - fep->rx_skbuff[curidx] = skbn; - CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data, - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE)); - CBDW_DATLEN(bdp, 0); - CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY); - - /* - * Update BD pointer to next entry. - */ - if ((sc & BD_ENET_RX_WRAP) == 0) - bdp++; - else - bdp = fep->rx_bd_base; - - (*fep->ops->rx_bd_done)(dev); - } - - fep->cur_rx = bdp; - - return 0; -} - -static void fs_enet_tx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - cbd_t __iomem *bdp; - struct sk_buff *skb; - int dirtyidx, do_wake, do_restart; - u16 sc; - - spin_lock(&fep->tx_lock); - bdp = fep->dirty_tx; - - do_wake = do_restart = 0; - while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) { - dirtyidx = bdp - fep->tx_bd_base; - - if (fep->tx_free == fep->tx_ring) - break; - - skb = fep->tx_skbuff[dirtyidx]; - - /* - * Check for errors. - */ - if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC | - BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) { - - if (sc & BD_ENET_TX_HB) /* No heartbeat */ - fep->stats.tx_heartbeat_errors++; - if (sc & BD_ENET_TX_LC) /* Late collision */ - fep->stats.tx_window_errors++; - if (sc & BD_ENET_TX_RL) /* Retrans limit */ - fep->stats.tx_aborted_errors++; - if (sc & BD_ENET_TX_UN) /* Underrun */ - fep->stats.tx_fifo_errors++; - if (sc & BD_ENET_TX_CSL) /* Carrier lost */ - fep->stats.tx_carrier_errors++; - - if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) { - fep->stats.tx_errors++; - do_restart = 1; - } - } else - fep->stats.tx_packets++; - - if (sc & BD_ENET_TX_READY) { - dev_warn(fep->dev, - "HEY! Enet xmit interrupt and TX_READY.\n"); - } - - /* - * Deferred means some collisions occurred during transmit, - * but we eventually sent the packet OK. - */ - if (sc & BD_ENET_TX_DEF) - fep->stats.collisions++; - - /* unmap */ - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - skb->len, DMA_TO_DEVICE); - - /* - * Free the sk buffer associated with this last transmit. - */ - dev_kfree_skb_irq(skb); - fep->tx_skbuff[dirtyidx] = NULL; - - /* - * Update pointer to next buffer descriptor to be transmitted. - */ - if ((sc & BD_ENET_TX_WRAP) == 0) - bdp++; - else - bdp = fep->tx_bd_base; - - /* - * Since we have freed up a buffer, the ring is no longer - * full. - */ - if (!fep->tx_free++) - do_wake = 1; - } - - fep->dirty_tx = bdp; - - if (do_restart) - (*fep->ops->tx_restart)(dev); - - spin_unlock(&fep->tx_lock); - - if (do_wake) - netif_wake_queue(dev); -} - -/* - * The interrupt handler. - * This is called from the MPC core interrupt. - */ -static irqreturn_t -fs_enet_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct fs_enet_private *fep; - const struct fs_platform_info *fpi; - u32 int_events; - u32 int_clr_events; - int nr, napi_ok; - int handled; - - fep = netdev_priv(dev); - fpi = fep->fpi; - - nr = 0; - while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) { - nr++; - - int_clr_events = int_events; - if (fpi->use_napi) - int_clr_events &= ~fep->ev_napi_rx; - - (*fep->ops->clear_int_events)(dev, int_clr_events); - - if (int_events & fep->ev_err) - (*fep->ops->ev_error)(dev, int_events); - - if (int_events & fep->ev_rx) { - if (!fpi->use_napi) - fs_enet_rx_non_napi(dev); - else { - napi_ok = napi_schedule_prep(&fep->napi); - - (*fep->ops->napi_disable_rx)(dev); - (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx); - - /* NOTE: it is possible for FCCs in NAPI mode */ - /* to submit a spurious interrupt while in poll */ - if (napi_ok) - __napi_schedule(&fep->napi); - } - } - - if (int_events & fep->ev_tx) - fs_enet_tx(dev); - } - - handled = nr > 0; - return IRQ_RETVAL(handled); -} - -void fs_init_bds(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - cbd_t __iomem *bdp; - struct sk_buff *skb; - int i; - - fs_cleanup_bds(dev); - - fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; - fep->tx_free = fep->tx_ring; - fep->cur_rx = fep->rx_bd_base; - - /* - * Initialize the receive buffer descriptors. - */ - for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) { - skb = netdev_alloc_skb(dev, ENET_RX_FRSIZE); - if (skb == NULL) { - dev_warn(fep->dev, - "Memory squeeze, unable to allocate skb\n"); - break; - } - skb_align(skb, ENET_RX_ALIGN); - fep->rx_skbuff[i] = skb; - CBDW_BUFADDR(bdp, - dma_map_single(fep->dev, skb->data, - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE)); - CBDW_DATLEN(bdp, 0); /* zero */ - CBDW_SC(bdp, BD_ENET_RX_EMPTY | - ((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP)); - } - /* - * if we failed, fillup remainder - */ - for (; i < fep->rx_ring; i++, bdp++) { - fep->rx_skbuff[i] = NULL; - CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP); - } - - /* - * ...and the same for transmit. - */ - for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) { - fep->tx_skbuff[i] = NULL; - CBDW_BUFADDR(bdp, 0); - CBDW_DATLEN(bdp, 0); - CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP); - } -} - -void fs_cleanup_bds(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct sk_buff *skb; - cbd_t __iomem *bdp; - int i; - - /* - * Reset SKB transmit buffers. - */ - for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) { - if ((skb = fep->tx_skbuff[i]) == NULL) - continue; - - /* unmap */ - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - skb->len, DMA_TO_DEVICE); - - fep->tx_skbuff[i] = NULL; - dev_kfree_skb(skb); - } - - /* - * Reset SKB receive buffers - */ - for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) { - if ((skb = fep->rx_skbuff[i]) == NULL) - continue; - - /* unmap */ - dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), - L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), - DMA_FROM_DEVICE); - - fep->rx_skbuff[i] = NULL; - - dev_kfree_skb(skb); - } -} - -/**********************************************************************************/ - -#ifdef CONFIG_FS_ENET_MPC5121_FEC -/* - * MPC5121 FEC requeries 4-byte alignment for TX data buffer! - */ -static struct sk_buff *tx_skb_align_workaround(struct net_device *dev, - struct sk_buff *skb) -{ - struct sk_buff *new_skb; - struct fs_enet_private *fep = netdev_priv(dev); - - /* Alloc new skb */ - new_skb = netdev_alloc_skb(dev, skb->len + 4); - if (!new_skb) { - if (net_ratelimit()) { - dev_warn(fep->dev, - "Memory squeeze, dropping tx packet.\n"); - } - return NULL; - } - - /* Make sure new skb is properly aligned */ - skb_align(new_skb, 4); - - /* Copy data to new skb ... */ - skb_copy_from_linear_data(skb, new_skb->data, skb->len); - skb_put(new_skb, skb->len); - - /* ... and free an old one */ - dev_kfree_skb_any(skb); - - return new_skb; -} -#endif - -static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - cbd_t __iomem *bdp; - int curidx; - u16 sc; - unsigned long flags; - -#ifdef CONFIG_FS_ENET_MPC5121_FEC - if (((unsigned long)skb->data) & 0x3) { - skb = tx_skb_align_workaround(dev, skb); - if (!skb) { - /* - * We have lost packet due to memory allocation error - * in tx_skb_align_workaround(). Hopefully original - * skb is still valid, so try transmit it later. - */ - return NETDEV_TX_BUSY; - } - } -#endif - spin_lock_irqsave(&fep->tx_lock, flags); - - /* - * Fill in a Tx ring entry - */ - bdp = fep->cur_tx; - - if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) { - netif_stop_queue(dev); - spin_unlock_irqrestore(&fep->tx_lock, flags); - - /* - * Ooops. All transmit buffers are full. Bail out. - * This should not happen, since the tx queue should be stopped. - */ - dev_warn(fep->dev, "tx queue full!.\n"); - return NETDEV_TX_BUSY; - } - - curidx = bdp - fep->tx_bd_base; - /* - * Clear all of the status flags. - */ - CBDC_SC(bdp, BD_ENET_TX_STATS); - - /* - * Save skb pointer. - */ - fep->tx_skbuff[curidx] = skb; - - fep->stats.tx_bytes += skb->len; - - /* - * Push the data cache so the CPM does not get stale memory data. - */ - CBDW_BUFADDR(bdp, dma_map_single(fep->dev, - skb->data, skb->len, DMA_TO_DEVICE)); - CBDW_DATLEN(bdp, skb->len); - - /* - * If this was the last BD in the ring, start at the beginning again. - */ - if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) - fep->cur_tx++; - else - fep->cur_tx = fep->tx_bd_base; - - if (!--fep->tx_free) - netif_stop_queue(dev); - - /* Trigger transmission start */ - sc = BD_ENET_TX_READY | BD_ENET_TX_INTR | - BD_ENET_TX_LAST | BD_ENET_TX_TC; - - /* note that while FEC does not have this bit - * it marks it as available for software use - * yay for hw reuse :) */ - if (skb->len <= 60) - sc |= BD_ENET_TX_PAD; - CBDS_SC(bdp, sc); - - skb_tx_timestamp(skb); - - (*fep->ops->tx_kickstart)(dev); - - spin_unlock_irqrestore(&fep->tx_lock, flags); - - return NETDEV_TX_OK; -} - -static void fs_timeout(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - unsigned long flags; - int wake = 0; - - fep->stats.tx_errors++; - - spin_lock_irqsave(&fep->lock, flags); - - if (dev->flags & IFF_UP) { - phy_stop(fep->phydev); - (*fep->ops->stop)(dev); - (*fep->ops->restart)(dev); - phy_start(fep->phydev); - } - - phy_start(fep->phydev); - wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY); - spin_unlock_irqrestore(&fep->lock, flags); - - if (wake) - netif_wake_queue(dev); -} - -/*----------------------------------------------------------------------------- - * generic link-change handler - should be sufficient for most cases - *-----------------------------------------------------------------------------*/ -static void generic_adjust_link(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct phy_device *phydev = fep->phydev; - int new_state = 0; - - if (phydev->link) { - /* adjust to duplex mode */ - if (phydev->duplex != fep->oldduplex) { - new_state = 1; - fep->oldduplex = phydev->duplex; - } - - if (phydev->speed != fep->oldspeed) { - new_state = 1; - fep->oldspeed = phydev->speed; - } - - if (!fep->oldlink) { - new_state = 1; - fep->oldlink = 1; - } - - if (new_state) - fep->ops->restart(dev); - } else if (fep->oldlink) { - new_state = 1; - fep->oldlink = 0; - fep->oldspeed = 0; - fep->oldduplex = -1; - } - - if (new_state && netif_msg_link(fep)) - phy_print_status(phydev); -} - - -static void fs_adjust_link(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&fep->lock, flags); - - if(fep->ops->adjust_link) - fep->ops->adjust_link(dev); - else - generic_adjust_link(dev); - - spin_unlock_irqrestore(&fep->lock, flags); -} - -static int fs_init_phy(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct phy_device *phydev; - phy_interface_t iface; - - fep->oldlink = 0; - fep->oldspeed = 0; - fep->oldduplex = -1; - - iface = fep->fpi->use_rmii ? - PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII; - - phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0, - iface); - if (!phydev) { - phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link, - iface); - } - if (!phydev) { - dev_err(&dev->dev, "Could not attach to PHY\n"); - return -ENODEV; - } - - fep->phydev = phydev; - - return 0; -} - -static int fs_enet_open(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - int r; - int err; - - /* to initialize the fep->cur_rx,... */ - /* not doing this, will cause a crash in fs_enet_rx_napi */ - fs_init_bds(fep->ndev); - - if (fep->fpi->use_napi) - napi_enable(&fep->napi); - - /* Install our interrupt handler. */ - r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED, - "fs_enet-mac", dev); - if (r != 0) { - dev_err(fep->dev, "Could not allocate FS_ENET IRQ!"); - if (fep->fpi->use_napi) - napi_disable(&fep->napi); - return -EINVAL; - } - - err = fs_init_phy(dev); - if (err) { - free_irq(fep->interrupt, dev); - if (fep->fpi->use_napi) - napi_disable(&fep->napi); - return err; - } - phy_start(fep->phydev); - - netif_start_queue(dev); - - return 0; -} - -static int fs_enet_close(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - unsigned long flags; - - netif_stop_queue(dev); - netif_carrier_off(dev); - if (fep->fpi->use_napi) - napi_disable(&fep->napi); - phy_stop(fep->phydev); - - spin_lock_irqsave(&fep->lock, flags); - spin_lock(&fep->tx_lock); - (*fep->ops->stop)(dev); - spin_unlock(&fep->tx_lock); - spin_unlock_irqrestore(&fep->lock, flags); - - /* release any irqs */ - phy_disconnect(fep->phydev); - fep->phydev = NULL; - free_irq(fep->interrupt, dev); - - return 0; -} - -static struct net_device_stats *fs_enet_get_stats(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - return &fep->stats; -} - -/*************************************************************************/ - -static void fs_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, DRV_MODULE_NAME); - strcpy(info->version, DRV_MODULE_VERSION); -} - -static int fs_get_regs_len(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - return (*fep->ops->get_regs_len)(dev); -} - -static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct fs_enet_private *fep = netdev_priv(dev); - unsigned long flags; - int r, len; - - len = regs->len; - - spin_lock_irqsave(&fep->lock, flags); - r = (*fep->ops->get_regs)(dev, p, &len); - spin_unlock_irqrestore(&fep->lock, flags); - - if (r == 0) - regs->version = 0; -} - -static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (!fep->phydev) - return -ENODEV; - - return phy_ethtool_gset(fep->phydev, cmd); -} - -static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (!fep->phydev) - return -ENODEV; - - return phy_ethtool_sset(fep->phydev, cmd); -} - -static int fs_nway_reset(struct net_device *dev) -{ - return 0; -} - -static u32 fs_get_msglevel(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - return fep->msg_enable; -} - -static void fs_set_msglevel(struct net_device *dev, u32 value) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fep->msg_enable = value; -} - -static const struct ethtool_ops fs_ethtool_ops = { - .get_drvinfo = fs_get_drvinfo, - .get_regs_len = fs_get_regs_len, - .get_settings = fs_get_settings, - .set_settings = fs_set_settings, - .nway_reset = fs_nway_reset, - .get_link = ethtool_op_get_link, - .get_msglevel = fs_get_msglevel, - .set_msglevel = fs_set_msglevel, - .get_regs = fs_get_regs, -}; - -static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (!netif_running(dev)) - return -EINVAL; - - return phy_mii_ioctl(fep->phydev, rq, cmd); -} - -extern int fs_mii_connect(struct net_device *dev); -extern void fs_mii_disconnect(struct net_device *dev); - -/**************************************************************************************/ - -#ifdef CONFIG_FS_ENET_HAS_FEC -#define IS_FEC(match) ((match)->data == &fs_fec_ops) -#else -#define IS_FEC(match) 0 -#endif - -static const struct net_device_ops fs_enet_netdev_ops = { - .ndo_open = fs_enet_open, - .ndo_stop = fs_enet_close, - .ndo_get_stats = fs_enet_get_stats, - .ndo_start_xmit = fs_enet_start_xmit, - .ndo_tx_timeout = fs_timeout, - .ndo_set_rx_mode = fs_set_multicast_list, - .ndo_do_ioctl = fs_ioctl, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = fs_enet_netpoll, -#endif -}; - -static struct of_device_id fs_enet_match[]; -static int __devinit fs_enet_probe(struct platform_device *ofdev) -{ - const struct of_device_id *match; - struct net_device *ndev; - struct fs_enet_private *fep; - struct fs_platform_info *fpi; - const u32 *data; - const u8 *mac_addr; - const char *phy_connection_type; - int privsize, len, ret = -ENODEV; - - match = of_match_device(fs_enet_match, &ofdev->dev); - if (!match) - return -EINVAL; - - fpi = kzalloc(sizeof(*fpi), GFP_KERNEL); - if (!fpi) - return -ENOMEM; - - if (!IS_FEC(match)) { - data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len); - if (!data || len != 4) - goto out_free_fpi; - - fpi->cp_command = *data; - } - - fpi->rx_ring = 32; - fpi->tx_ring = 32; - fpi->rx_copybreak = 240; - fpi->use_napi = 1; - fpi->napi_weight = 17; - fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); - if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link", - NULL))) - goto out_free_fpi; - - if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) { - phy_connection_type = of_get_property(ofdev->dev.of_node, - "phy-connection-type", NULL); - if (phy_connection_type && !strcmp("rmii", phy_connection_type)) - fpi->use_rmii = 1; - } - - privsize = sizeof(*fep) + - sizeof(struct sk_buff **) * - (fpi->rx_ring + fpi->tx_ring); - - ndev = alloc_etherdev(privsize); - if (!ndev) { - ret = -ENOMEM; - goto out_put; - } - - SET_NETDEV_DEV(ndev, &ofdev->dev); - dev_set_drvdata(&ofdev->dev, ndev); - - fep = netdev_priv(ndev); - fep->dev = &ofdev->dev; - fep->ndev = ndev; - fep->fpi = fpi; - fep->ops = match->data; - - ret = fep->ops->setup_data(ndev); - if (ret) - goto out_free_dev; - - fep->rx_skbuff = (struct sk_buff **)&fep[1]; - fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring; - - spin_lock_init(&fep->lock); - spin_lock_init(&fep->tx_lock); - - mac_addr = of_get_mac_address(ofdev->dev.of_node); - if (mac_addr) - memcpy(ndev->dev_addr, mac_addr, 6); - - ret = fep->ops->allocate_bd(ndev); - if (ret) - goto out_cleanup_data; - - fep->rx_bd_base = fep->ring_base; - fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring; - - fep->tx_ring = fpi->tx_ring; - fep->rx_ring = fpi->rx_ring; - - ndev->netdev_ops = &fs_enet_netdev_ops; - ndev->watchdog_timeo = 2 * HZ; - if (fpi->use_napi) - netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, - fpi->napi_weight); - - ndev->ethtool_ops = &fs_ethtool_ops; - - init_timer(&fep->phy_timer_list); - - netif_carrier_off(ndev); - - ret = register_netdev(ndev); - if (ret) - goto out_free_bd; - - pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr); - - return 0; - -out_free_bd: - fep->ops->free_bd(ndev); -out_cleanup_data: - fep->ops->cleanup_data(ndev); -out_free_dev: - free_netdev(ndev); - dev_set_drvdata(&ofdev->dev, NULL); -out_put: - of_node_put(fpi->phy_node); -out_free_fpi: - kfree(fpi); - return ret; -} - -static int fs_enet_remove(struct platform_device *ofdev) -{ - struct net_device *ndev = dev_get_drvdata(&ofdev->dev); - struct fs_enet_private *fep = netdev_priv(ndev); - - unregister_netdev(ndev); - - fep->ops->free_bd(ndev); - fep->ops->cleanup_data(ndev); - dev_set_drvdata(fep->dev, NULL); - of_node_put(fep->fpi->phy_node); - free_netdev(ndev); - return 0; -} - -static struct of_device_id fs_enet_match[] = { -#ifdef CONFIG_FS_ENET_HAS_SCC - { - .compatible = "fsl,cpm1-scc-enet", - .data = (void *)&fs_scc_ops, - }, - { - .compatible = "fsl,cpm2-scc-enet", - .data = (void *)&fs_scc_ops, - }, -#endif -#ifdef CONFIG_FS_ENET_HAS_FCC - { - .compatible = "fsl,cpm2-fcc-enet", - .data = (void *)&fs_fcc_ops, - }, -#endif -#ifdef CONFIG_FS_ENET_HAS_FEC -#ifdef CONFIG_FS_ENET_MPC5121_FEC - { - .compatible = "fsl,mpc5121-fec", - .data = (void *)&fs_fec_ops, - }, - { - .compatible = "fsl,mpc5125-fec", - .data = (void *)&fs_fec_ops, - }, -#else - { - .compatible = "fsl,pq1-fec-enet", - .data = (void *)&fs_fec_ops, - }, -#endif -#endif - {} -}; -MODULE_DEVICE_TABLE(of, fs_enet_match); - -static struct platform_driver fs_enet_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "fs_enet", - .of_match_table = fs_enet_match, - }, - .probe = fs_enet_probe, - .remove = fs_enet_remove, -}; - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void fs_enet_netpoll(struct net_device *dev) -{ - disable_irq(dev->irq); - fs_enet_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -module_platform_driver(fs_enet_driver); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fs_enet.h deleted file mode 100644 index 1ece4b1a..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef FS_ENET_H -#define FS_ENET_H - -#include <linux/mii.h> -#include <linux/netdevice.h> -#include <linux/types.h> -#include <linux/list.h> -#include <linux/phy.h> -#include <linux/dma-mapping.h> - -#include <linux/fs_enet_pd.h> -#include <asm/fs_pd.h> - -#ifdef CONFIG_CPM1 -#include <asm/cpm1.h> -#endif - -#if defined(CONFIG_FS_ENET_HAS_FEC) -#include <asm/cpm.h> - -#if defined(CONFIG_FS_ENET_MPC5121_FEC) -/* MPC5121 FEC has different register layout */ -struct fec { - u32 fec_reserved0; - u32 fec_ievent; /* Interrupt event reg */ - u32 fec_imask; /* Interrupt mask reg */ - u32 fec_reserved1; - u32 fec_r_des_active; /* Receive descriptor reg */ - u32 fec_x_des_active; /* Transmit descriptor reg */ - u32 fec_reserved2[3]; - u32 fec_ecntrl; /* Ethernet control reg */ - u32 fec_reserved3[6]; - u32 fec_mii_data; /* MII manage frame reg */ - u32 fec_mii_speed; /* MII speed control reg */ - u32 fec_reserved4[7]; - u32 fec_mib_ctrlstat; /* MIB control/status reg */ - u32 fec_reserved5[7]; - u32 fec_r_cntrl; /* Receive control reg */ - u32 fec_reserved6[15]; - u32 fec_x_cntrl; /* Transmit Control reg */ - u32 fec_reserved7[7]; - u32 fec_addr_low; /* Low 32bits MAC address */ - u32 fec_addr_high; /* High 16bits MAC address */ - u32 fec_opd; /* Opcode + Pause duration */ - u32 fec_reserved8[10]; - u32 fec_hash_table_high; /* High 32bits hash table */ - u32 fec_hash_table_low; /* Low 32bits hash table */ - u32 fec_grp_hash_table_high; /* High 32bits hash table */ - u32 fec_grp_hash_table_low; /* Low 32bits hash table */ - u32 fec_reserved9[7]; - u32 fec_x_wmrk; /* FIFO transmit water mark */ - u32 fec_reserved10; - u32 fec_r_bound; /* FIFO receive bound reg */ - u32 fec_r_fstart; /* FIFO receive start reg */ - u32 fec_reserved11[11]; - u32 fec_r_des_start; /* Receive descriptor ring */ - u32 fec_x_des_start; /* Transmit descriptor ring */ - u32 fec_r_buff_size; /* Maximum receive buff size */ - u32 fec_reserved12[26]; - u32 fec_dma_control; /* DMA Endian and other ctrl */ -}; -#endif - -struct fec_info { - struct fec __iomem *fecp; - u32 mii_speed; -}; -#endif - -#ifdef CONFIG_CPM2 -#include <asm/cpm2.h> -#endif - -/* hw driver ops */ -struct fs_ops { - int (*setup_data)(struct net_device *dev); - int (*allocate_bd)(struct net_device *dev); - void (*free_bd)(struct net_device *dev); - void (*cleanup_data)(struct net_device *dev); - void (*set_multicast_list)(struct net_device *dev); - void (*adjust_link)(struct net_device *dev); - void (*restart)(struct net_device *dev); - void (*stop)(struct net_device *dev); - void (*napi_clear_rx_event)(struct net_device *dev); - void (*napi_enable_rx)(struct net_device *dev); - void (*napi_disable_rx)(struct net_device *dev); - void (*rx_bd_done)(struct net_device *dev); - void (*tx_kickstart)(struct net_device *dev); - u32 (*get_int_events)(struct net_device *dev); - void (*clear_int_events)(struct net_device *dev, u32 int_events); - void (*ev_error)(struct net_device *dev, u32 int_events); - int (*get_regs)(struct net_device *dev, void *p, int *sizep); - int (*get_regs_len)(struct net_device *dev); - void (*tx_restart)(struct net_device *dev); -}; - -struct phy_info { - unsigned int id; - const char *name; - void (*startup) (struct net_device * dev); - void (*shutdown) (struct net_device * dev); - void (*ack_int) (struct net_device * dev); -}; - -/* The FEC stores dest/src/type, data, and checksum for receive packets. - */ -#define MAX_MTU 1508 /* Allow fullsized pppoe packets over VLAN */ -#define MIN_MTU 46 /* this is data size */ -#define CRC_LEN 4 - -#define PKT_MAXBUF_SIZE (MAX_MTU+ETH_HLEN+CRC_LEN) -#define PKT_MINBUF_SIZE (MIN_MTU+ETH_HLEN+CRC_LEN) - -/* Must be a multiple of 32 (to cover both FEC & FCC) */ -#define PKT_MAXBLR_SIZE ((PKT_MAXBUF_SIZE + 31) & ~31) -/* This is needed so that invalidate_xxx wont invalidate too much */ -#define ENET_RX_ALIGN 16 -#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1) - -struct fs_enet_private { - struct napi_struct napi; - struct device *dev; /* pointer back to the device (must be initialized first) */ - struct net_device *ndev; - spinlock_t lock; /* during all ops except TX pckt processing */ - spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */ - struct fs_platform_info *fpi; - const struct fs_ops *ops; - int rx_ring, tx_ring; - dma_addr_t ring_mem_addr; - void __iomem *ring_base; - struct sk_buff **rx_skbuff; - struct sk_buff **tx_skbuff; - cbd_t __iomem *rx_bd_base; /* Address of Rx and Tx buffers. */ - cbd_t __iomem *tx_bd_base; - cbd_t __iomem *dirty_tx; /* ring entries to be free()ed. */ - cbd_t __iomem *cur_rx; - cbd_t __iomem *cur_tx; - int tx_free; - struct net_device_stats stats; - struct timer_list phy_timer_list; - const struct phy_info *phy; - u32 msg_enable; - struct mii_if_info mii_if; - unsigned int last_mii_status; - int interrupt; - - struct phy_device *phydev; - int oldduplex, oldspeed, oldlink; /* current settings */ - - /* event masks */ - u32 ev_napi_rx; /* mask of NAPI rx events */ - u32 ev_rx; /* rx event mask */ - u32 ev_tx; /* tx event mask */ - u32 ev_err; /* error event mask */ - - u16 bd_rx_empty; /* mask of BD rx empty */ - u16 bd_rx_err; /* mask of BD rx errors */ - - union { - struct { - int idx; /* FEC1 = 0, FEC2 = 1 */ - void __iomem *fecp; /* hw registers */ - u32 hthi, htlo; /* state for multicast */ - } fec; - - struct { - int idx; /* FCC1-3 = 0-2 */ - void __iomem *fccp; /* hw registers */ - void __iomem *ep; /* parameter ram */ - void __iomem *fcccp; /* hw registers cont. */ - void __iomem *mem; /* FCC DPRAM */ - u32 gaddrh, gaddrl; /* group address */ - } fcc; - - struct { - int idx; /* FEC1 = 0, FEC2 = 1 */ - void __iomem *sccp; /* hw registers */ - void __iomem *ep; /* parameter ram */ - u32 hthi, htlo; /* state for multicast */ - } scc; - - }; -}; - -/***************************************************************************/ - -void fs_init_bds(struct net_device *dev); -void fs_cleanup_bds(struct net_device *dev); - -/***************************************************************************/ - -#define DRV_MODULE_NAME "fs_enet" -#define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.0" -#define DRV_MODULE_RELDATE "Aug 8, 2005" - -/***************************************************************************/ - -int fs_enet_platform_init(void); -void fs_enet_platform_cleanup(void); - -/***************************************************************************/ -/* buffer descriptor access macros */ - -/* access macros */ -#if defined(CONFIG_CPM1) -/* for a a CPM1 __raw_xxx's are sufficient */ -#define __cbd_out32(addr, x) __raw_writel(x, addr) -#define __cbd_out16(addr, x) __raw_writew(x, addr) -#define __cbd_in32(addr) __raw_readl(addr) -#define __cbd_in16(addr) __raw_readw(addr) -#else -/* for others play it safe */ -#define __cbd_out32(addr, x) out_be32(addr, x) -#define __cbd_out16(addr, x) out_be16(addr, x) -#define __cbd_in32(addr) in_be32(addr) -#define __cbd_in16(addr) in_be16(addr) -#endif - -/* write */ -#define CBDW_SC(_cbd, _sc) __cbd_out16(&(_cbd)->cbd_sc, (_sc)) -#define CBDW_DATLEN(_cbd, _datlen) __cbd_out16(&(_cbd)->cbd_datlen, (_datlen)) -#define CBDW_BUFADDR(_cbd, _bufaddr) __cbd_out32(&(_cbd)->cbd_bufaddr, (_bufaddr)) - -/* read */ -#define CBDR_SC(_cbd) __cbd_in16(&(_cbd)->cbd_sc) -#define CBDR_DATLEN(_cbd) __cbd_in16(&(_cbd)->cbd_datlen) -#define CBDR_BUFADDR(_cbd) __cbd_in32(&(_cbd)->cbd_bufaddr) - -/* set bits */ -#define CBDS_SC(_cbd, _sc) CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc)) - -/* clear bits */ -#define CBDC_SC(_cbd, _sc) CBDW_SC(_cbd, CBDR_SC(_cbd) & ~(_sc)) - -/*******************************************************************/ - -extern const struct fs_ops fs_fec_ops; -extern const struct fs_ops fs_fcc_ops; -extern const struct fs_ops fs_scc_ops; - -/*******************************************************************/ - -#endif diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c deleted file mode 100644 index 7583a957..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * FCC driver for Motorola MPC82xx (PQ2). - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/bitops.h> -#include <linux/fs.h> -#include <linux/platform_device.h> -#include <linux/phy.h> -#include <linux/of_device.h> -#include <linux/gfp.h> - -#include <asm/immap_cpm2.h> -#include <asm/mpc8260.h> -#include <asm/cpm2.h> - -#include <asm/pgtable.h> -#include <asm/irq.h> -#include <asm/uaccess.h> - -#include "fs_enet.h" - -/*************************************************/ - -/* FCC access macros */ - -/* write, read, set bits, clear bits */ -#define W32(_p, _m, _v) out_be32(&(_p)->_m, (_v)) -#define R32(_p, _m) in_be32(&(_p)->_m) -#define S32(_p, _m, _v) W32(_p, _m, R32(_p, _m) | (_v)) -#define C32(_p, _m, _v) W32(_p, _m, R32(_p, _m) & ~(_v)) - -#define W16(_p, _m, _v) out_be16(&(_p)->_m, (_v)) -#define R16(_p, _m) in_be16(&(_p)->_m) -#define S16(_p, _m, _v) W16(_p, _m, R16(_p, _m) | (_v)) -#define C16(_p, _m, _v) W16(_p, _m, R16(_p, _m) & ~(_v)) - -#define W8(_p, _m, _v) out_8(&(_p)->_m, (_v)) -#define R8(_p, _m) in_8(&(_p)->_m) -#define S8(_p, _m, _v) W8(_p, _m, R8(_p, _m) | (_v)) -#define C8(_p, _m, _v) W8(_p, _m, R8(_p, _m) & ~(_v)) - -/*************************************************/ - -#define FCC_MAX_MULTICAST_ADDRS 64 - -#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) -#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) -#define mk_mii_end 0 - -#define MAX_CR_CMD_LOOPS 10000 - -static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op) -{ - const struct fs_platform_info *fpi = fep->fpi; - - return cpm_command(fpi->cp_command, op); -} - -static int do_pd_setup(struct fs_enet_private *fep) -{ - struct platform_device *ofdev = to_platform_device(fep->dev); - struct fs_platform_info *fpi = fep->fpi; - int ret = -EINVAL; - - fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); - if (fep->interrupt == NO_IRQ) - goto out; - - fep->fcc.fccp = of_iomap(ofdev->dev.of_node, 0); - if (!fep->fcc.fccp) - goto out; - - fep->fcc.ep = of_iomap(ofdev->dev.of_node, 1); - if (!fep->fcc.ep) - goto out_fccp; - - fep->fcc.fcccp = of_iomap(ofdev->dev.of_node, 2); - if (!fep->fcc.fcccp) - goto out_ep; - - fep->fcc.mem = (void __iomem *)cpm2_immr; - fpi->dpram_offset = cpm_dpalloc(128, 32); - if (IS_ERR_VALUE(fpi->dpram_offset)) { - ret = fpi->dpram_offset; - goto out_fcccp; - } - - return 0; - -out_fcccp: - iounmap(fep->fcc.fcccp); -out_ep: - iounmap(fep->fcc.ep); -out_fccp: - iounmap(fep->fcc.fccp); -out: - return ret; -} - -#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB) -#define FCC_RX_EVENT (FCC_ENET_RXF) -#define FCC_TX_EVENT (FCC_ENET_TXB) -#define FCC_ERR_EVENT_MSK (FCC_ENET_TXE) - -static int setup_data(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (do_pd_setup(fep) != 0) - return -EINVAL; - - fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK; - fep->ev_rx = FCC_RX_EVENT; - fep->ev_tx = FCC_TX_EVENT; - fep->ev_err = FCC_ERR_EVENT_MSK; - - return 0; -} - -static int allocate_bd(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - - fep->ring_base = (void __iomem __force *)dma_alloc_coherent(fep->dev, - (fpi->tx_ring + fpi->rx_ring) * - sizeof(cbd_t), &fep->ring_mem_addr, - GFP_KERNEL); - if (fep->ring_base == NULL) - return -ENOMEM; - - return 0; -} - -static void free_bd(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - - if (fep->ring_base) - dma_free_coherent(fep->dev, - (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t), - (void __force *)fep->ring_base, fep->ring_mem_addr); -} - -static void cleanup_data(struct net_device *dev) -{ - /* nothing */ -} - -static void set_promiscuous_mode(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - S32(fccp, fcc_fpsmr, FCC_PSMR_PRO); -} - -static void set_multicast_start(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_enet_t __iomem *ep = fep->fcc.ep; - - W32(ep, fen_gaddrh, 0); - W32(ep, fen_gaddrl, 0); -} - -static void set_multicast_one(struct net_device *dev, const u8 *mac) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_enet_t __iomem *ep = fep->fcc.ep; - u16 taddrh, taddrm, taddrl; - - taddrh = ((u16)mac[5] << 8) | mac[4]; - taddrm = ((u16)mac[3] << 8) | mac[2]; - taddrl = ((u16)mac[1] << 8) | mac[0]; - - W16(ep, fen_taddrh, taddrh); - W16(ep, fen_taddrm, taddrm); - W16(ep, fen_taddrl, taddrl); - fcc_cr_cmd(fep, CPM_CR_SET_GADDR); -} - -static void set_multicast_finish(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - fcc_enet_t __iomem *ep = fep->fcc.ep; - - /* clear promiscuous always */ - C32(fccp, fcc_fpsmr, FCC_PSMR_PRO); - - /* if all multi or too many multicasts; just enable all */ - if ((dev->flags & IFF_ALLMULTI) != 0 || - netdev_mc_count(dev) > FCC_MAX_MULTICAST_ADDRS) { - - W32(ep, fen_gaddrh, 0xffffffff); - W32(ep, fen_gaddrl, 0xffffffff); - } - - /* read back */ - fep->fcc.gaddrh = R32(ep, fen_gaddrh); - fep->fcc.gaddrl = R32(ep, fen_gaddrl); -} - -static void set_multicast_list(struct net_device *dev) -{ - struct netdev_hw_addr *ha; - - if ((dev->flags & IFF_PROMISC) == 0) { - set_multicast_start(dev); - netdev_for_each_mc_addr(ha, dev) - set_multicast_one(dev, ha->addr); - set_multicast_finish(dev); - } else - set_promiscuous_mode(dev); -} - -static void restart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - fcc_t __iomem *fccp = fep->fcc.fccp; - fcc_c_t __iomem *fcccp = fep->fcc.fcccp; - fcc_enet_t __iomem *ep = fep->fcc.ep; - dma_addr_t rx_bd_base_phys, tx_bd_base_phys; - u16 paddrh, paddrm, paddrl; - const unsigned char *mac; - int i; - - C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT); - - /* clear everything (slow & steady does it) */ - for (i = 0; i < sizeof(*ep); i++) - out_8((u8 __iomem *)ep + i, 0); - - /* get physical address */ - rx_bd_base_phys = fep->ring_mem_addr; - tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring; - - /* point to bds */ - W32(ep, fen_genfcc.fcc_rbase, rx_bd_base_phys); - W32(ep, fen_genfcc.fcc_tbase, tx_bd_base_phys); - - /* Set maximum bytes per receive buffer. - * It must be a multiple of 32. - */ - W16(ep, fen_genfcc.fcc_mrblr, PKT_MAXBLR_SIZE); - - W32(ep, fen_genfcc.fcc_rstate, (CPMFCR_GBL | CPMFCR_EB) << 24); - W32(ep, fen_genfcc.fcc_tstate, (CPMFCR_GBL | CPMFCR_EB) << 24); - - /* Allocate space in the reserved FCC area of DPRAM for the - * internal buffers. No one uses this space (yet), so we - * can do this. Later, we will add resource management for - * this area. - */ - - W16(ep, fen_genfcc.fcc_riptr, fpi->dpram_offset); - W16(ep, fen_genfcc.fcc_tiptr, fpi->dpram_offset + 32); - - W16(ep, fen_padptr, fpi->dpram_offset + 64); - - /* fill with special symbol... */ - memset_io(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32); - - W32(ep, fen_genfcc.fcc_rbptr, 0); - W32(ep, fen_genfcc.fcc_tbptr, 0); - W32(ep, fen_genfcc.fcc_rcrc, 0); - W32(ep, fen_genfcc.fcc_tcrc, 0); - W16(ep, fen_genfcc.fcc_res1, 0); - W32(ep, fen_genfcc.fcc_res2, 0); - - /* no CAM */ - W32(ep, fen_camptr, 0); - - /* Set CRC preset and mask */ - W32(ep, fen_cmask, 0xdebb20e3); - W32(ep, fen_cpres, 0xffffffff); - - W32(ep, fen_crcec, 0); /* CRC Error counter */ - W32(ep, fen_alec, 0); /* alignment error counter */ - W32(ep, fen_disfc, 0); /* discard frame counter */ - W16(ep, fen_retlim, 15); /* Retry limit threshold */ - W16(ep, fen_pper, 0); /* Normal persistence */ - - /* set group address */ - W32(ep, fen_gaddrh, fep->fcc.gaddrh); - W32(ep, fen_gaddrl, fep->fcc.gaddrh); - - /* Clear hash filter tables */ - W32(ep, fen_iaddrh, 0); - W32(ep, fen_iaddrl, 0); - - /* Clear the Out-of-sequence TxBD */ - W16(ep, fen_tfcstat, 0); - W16(ep, fen_tfclen, 0); - W32(ep, fen_tfcptr, 0); - - W16(ep, fen_mflr, PKT_MAXBUF_SIZE); /* maximum frame length register */ - W16(ep, fen_minflr, PKT_MINBUF_SIZE); /* minimum frame length register */ - - /* set address */ - mac = dev->dev_addr; - paddrh = ((u16)mac[5] << 8) | mac[4]; - paddrm = ((u16)mac[3] << 8) | mac[2]; - paddrl = ((u16)mac[1] << 8) | mac[0]; - - W16(ep, fen_paddrh, paddrh); - W16(ep, fen_paddrm, paddrm); - W16(ep, fen_paddrl, paddrl); - - W16(ep, fen_taddrh, 0); - W16(ep, fen_taddrm, 0); - W16(ep, fen_taddrl, 0); - - W16(ep, fen_maxd1, 1520); /* maximum DMA1 length */ - W16(ep, fen_maxd2, 1520); /* maximum DMA2 length */ - - /* Clear stat counters, in case we ever enable RMON */ - W32(ep, fen_octc, 0); - W32(ep, fen_colc, 0); - W32(ep, fen_broc, 0); - W32(ep, fen_mulc, 0); - W32(ep, fen_uspc, 0); - W32(ep, fen_frgc, 0); - W32(ep, fen_ospc, 0); - W32(ep, fen_jbrc, 0); - W32(ep, fen_p64c, 0); - W32(ep, fen_p65c, 0); - W32(ep, fen_p128c, 0); - W32(ep, fen_p256c, 0); - W32(ep, fen_p512c, 0); - W32(ep, fen_p1024c, 0); - - W16(ep, fen_rfthr, 0); /* Suggested by manual */ - W16(ep, fen_rfcnt, 0); - W16(ep, fen_cftype, 0); - - fs_init_bds(dev); - - /* adjust to speed (for RMII mode) */ - if (fpi->use_rmii) { - if (fep->phydev->speed == 100) - C8(fcccp, fcc_gfemr, 0x20); - else - S8(fcccp, fcc_gfemr, 0x20); - } - - fcc_cr_cmd(fep, CPM_CR_INIT_TRX); - - /* clear events */ - W16(fccp, fcc_fcce, 0xffff); - - /* Enable interrupts we wish to service */ - W16(fccp, fcc_fccm, FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB); - - /* Set GFMR to enable Ethernet operating mode */ - W32(fccp, fcc_gfmr, FCC_GFMR_TCI | FCC_GFMR_MODE_ENET); - - /* set sync/delimiters */ - W16(fccp, fcc_fdsr, 0xd555); - - W32(fccp, fcc_fpsmr, FCC_PSMR_ENCRC); - - if (fpi->use_rmii) - S32(fccp, fcc_fpsmr, FCC_PSMR_RMII); - - /* adjust to duplex mode */ - if (fep->phydev->duplex) - S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); - else - C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); - - /* Restore multicast and promiscuous settings */ - set_multicast_list(dev); - - S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT); -} - -static void stop(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - /* stop ethernet */ - C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT); - - /* clear events */ - W16(fccp, fcc_fcce, 0xffff); - - /* clear interrupt mask */ - W16(fccp, fcc_fccm, 0); - - fs_cleanup_bds(dev); -} - -static void napi_clear_rx_event(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - W16(fccp, fcc_fcce, FCC_NAPI_RX_EVENT_MSK); -} - -static void napi_enable_rx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - S16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK); -} - -static void napi_disable_rx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK); -} - -static void rx_bd_done(struct net_device *dev) -{ - /* nothing */ -} - -static void tx_kickstart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - S16(fccp, fcc_ftodr, 0x8000); -} - -static u32 get_int_events(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - return (u32)R16(fccp, fcc_fcce); -} - -static void clear_int_events(struct net_device *dev, u32 int_events) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - - W16(fccp, fcc_fcce, int_events & 0xffff); -} - -static void ev_error(struct net_device *dev, u32 int_events) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - dev_warn(fep->dev, "FS_ENET ERROR(s) 0x%x\n", int_events); -} - -static int get_regs(struct net_device *dev, void *p, int *sizep) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (*sizep < sizeof(fcc_t) + sizeof(fcc_enet_t) + 1) - return -EINVAL; - - memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t)); - p = (char *)p + sizeof(fcc_t); - - memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t)); - p = (char *)p + sizeof(fcc_enet_t); - - memcpy_fromio(p, fep->fcc.fcccp, 1); - return 0; -} - -static int get_regs_len(struct net_device *dev) -{ - return sizeof(fcc_t) + sizeof(fcc_enet_t) + 1; -} - -/* Some transmit errors cause the transmitter to shut - * down. We now issue a restart transmit. - * Also, to workaround 8260 device erratum CPM37, we must - * disable and then re-enable the transmitterfollowing a - * Late Collision, Underrun, or Retry Limit error. - * In addition, tbptr may point beyond BDs beyond still marked - * as ready due to internal pipelining, so we need to look back - * through the BDs and adjust tbptr to point to the last BD - * marked as ready. This may result in some buffers being - * retransmitted. - */ -static void tx_restart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t __iomem *fccp = fep->fcc.fccp; - const struct fs_platform_info *fpi = fep->fpi; - fcc_enet_t __iomem *ep = fep->fcc.ep; - cbd_t __iomem *curr_tbptr; - cbd_t __iomem *recheck_bd; - cbd_t __iomem *prev_bd; - cbd_t __iomem *last_tx_bd; - - last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t)); - - /* get the current bd held in TBPTR and scan back from this point */ - recheck_bd = curr_tbptr = (cbd_t __iomem *) - ((R32(ep, fen_genfcc.fcc_tbptr) - fep->ring_mem_addr) + - fep->ring_base); - - prev_bd = (recheck_bd == fep->tx_bd_base) ? last_tx_bd : recheck_bd - 1; - - /* Move through the bds in reverse, look for the earliest buffer - * that is not ready. Adjust TBPTR to the following buffer */ - while ((CBDR_SC(prev_bd) & BD_ENET_TX_READY) != 0) { - /* Go back one buffer */ - recheck_bd = prev_bd; - - /* update the previous buffer */ - prev_bd = (prev_bd == fep->tx_bd_base) ? last_tx_bd : prev_bd - 1; - - /* We should never see all bds marked as ready, check anyway */ - if (recheck_bd == curr_tbptr) - break; - } - /* Now update the TBPTR and dirty flag to the current buffer */ - W32(ep, fen_genfcc.fcc_tbptr, - (uint) (((void *)recheck_bd - fep->ring_base) + - fep->ring_mem_addr)); - fep->dirty_tx = recheck_bd; - - C32(fccp, fcc_gfmr, FCC_GFMR_ENT); - udelay(10); - S32(fccp, fcc_gfmr, FCC_GFMR_ENT); - - fcc_cr_cmd(fep, CPM_CR_RESTART_TX); -} - -/*************************************************************************/ - -const struct fs_ops fs_fcc_ops = { - .setup_data = setup_data, - .cleanup_data = cleanup_data, - .set_multicast_list = set_multicast_list, - .restart = restart, - .stop = stop, - .napi_clear_rx_event = napi_clear_rx_event, - .napi_enable_rx = napi_enable_rx, - .napi_disable_rx = napi_disable_rx, - .rx_bd_done = rx_bd_done, - .tx_kickstart = tx_kickstart, - .get_int_events = get_int_events, - .clear_int_events = clear_int_events, - .ev_error = ev_error, - .get_regs = get_regs, - .get_regs_len = get_regs_len, - .tx_restart = tx_restart, - .allocate_bd = allocate_bd, - .free_bd = free_bd, -}; diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-fec.c deleted file mode 100644 index 9ae6cdbc..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Freescale Ethernet controllers - * - * Copyright (c) 2005 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/bitops.h> -#include <linux/fs.h> -#include <linux/platform_device.h> -#include <linux/of_device.h> -#include <linux/gfp.h> - -#include <asm/irq.h> -#include <asm/uaccess.h> - -#ifdef CONFIG_8xx -#include <asm/8xx_immap.h> -#include <asm/pgtable.h> -#include <asm/mpc8xx.h> -#include <asm/cpm1.h> -#endif - -#include "fs_enet.h" -#include "fec.h" - -/*************************************************/ - -#if defined(CONFIG_CPM1) -/* for a CPM1 __raw_xxx's are sufficient */ -#define __fs_out32(addr, x) __raw_writel(x, addr) -#define __fs_out16(addr, x) __raw_writew(x, addr) -#define __fs_in32(addr) __raw_readl(addr) -#define __fs_in16(addr) __raw_readw(addr) -#else -/* for others play it safe */ -#define __fs_out32(addr, x) out_be32(addr, x) -#define __fs_out16(addr, x) out_be16(addr, x) -#define __fs_in32(addr) in_be32(addr) -#define __fs_in16(addr) in_be16(addr) -#endif - -/* write */ -#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v)) - -/* read */ -#define FR(_fecp, _reg) __fs_in32(&(_fecp)->fec_ ## _reg) - -/* set bits */ -#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v)) - -/* clear bits */ -#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v)) - -/* - * Delay to wait for FEC reset command to complete (in us) - */ -#define FEC_RESET_DELAY 50 - -static int whack_reset(struct fec __iomem *fecp) -{ - int i; - - FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET); - for (i = 0; i < FEC_RESET_DELAY; i++) { - if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0) - return 0; /* OK */ - udelay(1); - } - - return -1; -} - -static int do_pd_setup(struct fs_enet_private *fep) -{ - struct platform_device *ofdev = to_platform_device(fep->dev); - - fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); - if (fep->interrupt == NO_IRQ) - return -EINVAL; - - fep->fec.fecp = of_iomap(ofdev->dev.of_node, 0); - if (!fep->fcc.fccp) - return -EINVAL; - - return 0; -} - -#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB) -#define FEC_RX_EVENT (FEC_ENET_RXF) -#define FEC_TX_EVENT (FEC_ENET_TXF) -#define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \ - FEC_ENET_BABT | FEC_ENET_EBERR) - -static int setup_data(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (do_pd_setup(fep) != 0) - return -EINVAL; - - fep->fec.hthi = 0; - fep->fec.htlo = 0; - - fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK; - fep->ev_rx = FEC_RX_EVENT; - fep->ev_tx = FEC_TX_EVENT; - fep->ev_err = FEC_ERR_EVENT_MSK; - - return 0; -} - -static int allocate_bd(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - - fep->ring_base = (void __force __iomem *)dma_alloc_coherent(fep->dev, - (fpi->tx_ring + fpi->rx_ring) * - sizeof(cbd_t), &fep->ring_mem_addr, - GFP_KERNEL); - if (fep->ring_base == NULL) - return -ENOMEM; - - return 0; -} - -static void free_bd(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - - if(fep->ring_base) - dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) - * sizeof(cbd_t), - (void __force *)fep->ring_base, - fep->ring_mem_addr); -} - -static void cleanup_data(struct net_device *dev) -{ - /* nothing */ -} - -static void set_promiscuous_mode(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FS(fecp, r_cntrl, FEC_RCNTRL_PROM); -} - -static void set_multicast_start(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - fep->fec.hthi = 0; - fep->fec.htlo = 0; -} - -static void set_multicast_one(struct net_device *dev, const u8 *mac) -{ - struct fs_enet_private *fep = netdev_priv(dev); - int temp, hash_index, i, j; - u32 crc, csrVal; - u8 byte, msb; - - crc = 0xffffffff; - for (i = 0; i < 6; i++) { - byte = mac[i]; - for (j = 0; j < 8; j++) { - msb = crc >> 31; - crc <<= 1; - if (msb ^ (byte & 0x1)) - crc ^= FEC_CRC_POLY; - byte >>= 1; - } - } - - temp = (crc & 0x3f) >> 1; - hash_index = ((temp & 0x01) << 4) | - ((temp & 0x02) << 2) | - ((temp & 0x04)) | - ((temp & 0x08) >> 2) | - ((temp & 0x10) >> 4); - csrVal = 1 << hash_index; - if (crc & 1) - fep->fec.hthi |= csrVal; - else - fep->fec.htlo |= csrVal; -} - -static void set_multicast_finish(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - /* if all multi or too many multicasts; just enable all */ - if ((dev->flags & IFF_ALLMULTI) != 0 || - netdev_mc_count(dev) > FEC_MAX_MULTICAST_ADDRS) { - fep->fec.hthi = 0xffffffffU; - fep->fec.htlo = 0xffffffffU; - } - - FC(fecp, r_cntrl, FEC_RCNTRL_PROM); - FW(fecp, grp_hash_table_high, fep->fec.hthi); - FW(fecp, grp_hash_table_low, fep->fec.htlo); -} - -static void set_multicast_list(struct net_device *dev) -{ - struct netdev_hw_addr *ha; - - if ((dev->flags & IFF_PROMISC) == 0) { - set_multicast_start(dev); - netdev_for_each_mc_addr(ha, dev) - set_multicast_one(dev, ha->addr); - set_multicast_finish(dev); - } else - set_promiscuous_mode(dev); -} - -static void restart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - const struct fs_platform_info *fpi = fep->fpi; - dma_addr_t rx_bd_base_phys, tx_bd_base_phys; - int r; - u32 addrhi, addrlo; - - struct mii_bus* mii = fep->phydev->bus; - struct fec_info* fec_inf = mii->priv; - - r = whack_reset(fep->fec.fecp); - if (r != 0) - dev_err(fep->dev, "FEC Reset FAILED!\n"); - /* - * Set station address. - */ - addrhi = ((u32) dev->dev_addr[0] << 24) | - ((u32) dev->dev_addr[1] << 16) | - ((u32) dev->dev_addr[2] << 8) | - (u32) dev->dev_addr[3]; - addrlo = ((u32) dev->dev_addr[4] << 24) | - ((u32) dev->dev_addr[5] << 16); - FW(fecp, addr_low, addrhi); - FW(fecp, addr_high, addrlo); - - /* - * Reset all multicast. - */ - FW(fecp, grp_hash_table_high, fep->fec.hthi); - FW(fecp, grp_hash_table_low, fep->fec.htlo); - - /* - * Set maximum receive buffer size. - */ - FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); -#ifdef CONFIG_FS_ENET_MPC5121_FEC - FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16); -#else - FW(fecp, r_hash, PKT_MAXBUF_SIZE); -#endif - - /* get physical address */ - rx_bd_base_phys = fep->ring_mem_addr; - tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring; - - /* - * Set receive and transmit descriptor base. - */ - FW(fecp, r_des_start, rx_bd_base_phys); - FW(fecp, x_des_start, tx_bd_base_phys); - - fs_init_bds(dev); - - /* - * Enable big endian and don't care about SDMA FC. - */ -#ifdef CONFIG_FS_ENET_MPC5121_FEC - FS(fecp, dma_control, 0xC0000000); -#else - FW(fecp, fun_code, 0x78000000); -#endif - - /* - * Set MII speed. - */ - FW(fecp, mii_speed, fec_inf->mii_speed); - - /* - * Clear any outstanding interrupt. - */ - FW(fecp, ievent, 0xffc0); -#ifndef CONFIG_FS_ENET_MPC5121_FEC - FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); - - FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ -#else - /* - * Only set MII/RMII mode - do not touch maximum frame length - * configured before. - */ - FS(fecp, r_cntrl, fpi->use_rmii ? - FEC_RCNTRL_RMII_MODE : FEC_RCNTRL_MII_MODE); -#endif - /* - * adjust to duplex mode - */ - if (fep->phydev->duplex) { - FC(fecp, r_cntrl, FEC_RCNTRL_DRT); - FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ - } else { - FS(fecp, r_cntrl, FEC_RCNTRL_DRT); - FC(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */ - } - - /* - * Enable interrupts we wish to service. - */ - FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB | - FEC_ENET_RXF | FEC_ENET_RXB); - - /* - * And last, enable the transmit and receive processing. - */ - FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); - FW(fecp, r_des_active, 0x01000000); -} - -static void stop(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - struct fec __iomem *fecp = fep->fec.fecp; - - struct fec_info* feci= fep->phydev->bus->priv; - - int i; - - if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) - return; /* already down */ - - FW(fecp, x_cntrl, 0x01); /* Graceful transmit stop */ - for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) && - i < FEC_RESET_DELAY; i++) - udelay(1); - - if (i == FEC_RESET_DELAY) - dev_warn(fep->dev, "FEC timeout on graceful transmit stop\n"); - /* - * Disable FEC. Let only MII interrupts. - */ - FW(fecp, imask, 0); - FC(fecp, ecntrl, FEC_ECNTRL_ETHER_EN); - - fs_cleanup_bds(dev); - - /* shut down FEC1? that's where the mii bus is */ - if (fpi->has_phy) { - FS(fecp, r_cntrl, fpi->use_rmii ? - FEC_RCNTRL_RMII_MODE : - FEC_RCNTRL_MII_MODE); /* MII/RMII enable */ - FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); - FW(fecp, ievent, FEC_ENET_MII); - FW(fecp, mii_speed, feci->mii_speed); - } -} - -static void napi_clear_rx_event(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); -} - -static void napi_enable_rx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); -} - -static void napi_disable_rx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); -} - -static void rx_bd_done(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FW(fecp, r_des_active, 0x01000000); -} - -static void tx_kickstart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FW(fecp, x_des_active, 0x01000000); -} - -static u32 get_int_events(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - return FR(fecp, ievent) & FR(fecp, imask); -} - -static void clear_int_events(struct net_device *dev, u32 int_events) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; - - FW(fecp, ievent, int_events); -} - -static void ev_error(struct net_device *dev, u32 int_events) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - dev_warn(fep->dev, "FEC ERROR(s) 0x%x\n", int_events); -} - -static int get_regs(struct net_device *dev, void *p, int *sizep) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (*sizep < sizeof(struct fec)) - return -EINVAL; - - memcpy_fromio(p, fep->fec.fecp, sizeof(struct fec)); - - return 0; -} - -static int get_regs_len(struct net_device *dev) -{ - return sizeof(struct fec); -} - -static void tx_restart(struct net_device *dev) -{ - /* nothing */ -} - -/*************************************************************************/ - -const struct fs_ops fs_fec_ops = { - .setup_data = setup_data, - .cleanup_data = cleanup_data, - .set_multicast_list = set_multicast_list, - .restart = restart, - .stop = stop, - .napi_clear_rx_event = napi_clear_rx_event, - .napi_enable_rx = napi_enable_rx, - .napi_disable_rx = napi_disable_rx, - .rx_bd_done = rx_bd_done, - .tx_kickstart = tx_kickstart, - .get_int_events = get_int_events, - .clear_int_events = clear_int_events, - .ev_error = ev_error, - .get_regs = get_regs, - .get_regs_len = get_regs_len, - .tx_restart = tx_restart, - .allocate_bd = allocate_bd, - .free_bd = free_bd, -}; - diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-scc.c deleted file mode 100644 index 22a02a76..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Ethernet on Serial Communications Controller (SCC) driver for Motorola MPC8xx and MPC82xx. - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/bitops.h> -#include <linux/fs.h> -#include <linux/platform_device.h> -#include <linux/of_platform.h> - -#include <asm/irq.h> -#include <asm/uaccess.h> - -#ifdef CONFIG_8xx -#include <asm/8xx_immap.h> -#include <asm/pgtable.h> -#include <asm/mpc8xx.h> -#include <asm/cpm1.h> -#endif - -#include "fs_enet.h" - -/*************************************************/ -#if defined(CONFIG_CPM1) -/* for a 8xx __raw_xxx's are sufficient */ -#define __fs_out32(addr, x) __raw_writel(x, addr) -#define __fs_out16(addr, x) __raw_writew(x, addr) -#define __fs_out8(addr, x) __raw_writeb(x, addr) -#define __fs_in32(addr) __raw_readl(addr) -#define __fs_in16(addr) __raw_readw(addr) -#define __fs_in8(addr) __raw_readb(addr) -#else -/* for others play it safe */ -#define __fs_out32(addr, x) out_be32(addr, x) -#define __fs_out16(addr, x) out_be16(addr, x) -#define __fs_in32(addr) in_be32(addr) -#define __fs_in16(addr) in_be16(addr) -#define __fs_out8(addr, x) out_8(addr, x) -#define __fs_in8(addr) in_8(addr) -#endif - -/* write, read, set bits, clear bits */ -#define W32(_p, _m, _v) __fs_out32(&(_p)->_m, (_v)) -#define R32(_p, _m) __fs_in32(&(_p)->_m) -#define S32(_p, _m, _v) W32(_p, _m, R32(_p, _m) | (_v)) -#define C32(_p, _m, _v) W32(_p, _m, R32(_p, _m) & ~(_v)) - -#define W16(_p, _m, _v) __fs_out16(&(_p)->_m, (_v)) -#define R16(_p, _m) __fs_in16(&(_p)->_m) -#define S16(_p, _m, _v) W16(_p, _m, R16(_p, _m) | (_v)) -#define C16(_p, _m, _v) W16(_p, _m, R16(_p, _m) & ~(_v)) - -#define W8(_p, _m, _v) __fs_out8(&(_p)->_m, (_v)) -#define R8(_p, _m) __fs_in8(&(_p)->_m) -#define S8(_p, _m, _v) W8(_p, _m, R8(_p, _m) | (_v)) -#define C8(_p, _m, _v) W8(_p, _m, R8(_p, _m) & ~(_v)) - -#define SCC_MAX_MULTICAST_ADDRS 64 - -/* - * Delay to wait for SCC reset command to complete (in us) - */ -#define SCC_RESET_DELAY 50 - -static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op) -{ - const struct fs_platform_info *fpi = fep->fpi; - - return cpm_command(fpi->cp_command, op); -} - -static int do_pd_setup(struct fs_enet_private *fep) -{ - struct platform_device *ofdev = to_platform_device(fep->dev); - - fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); - if (fep->interrupt == NO_IRQ) - return -EINVAL; - - fep->scc.sccp = of_iomap(ofdev->dev.of_node, 0); - if (!fep->scc.sccp) - return -EINVAL; - - fep->scc.ep = of_iomap(ofdev->dev.of_node, 1); - if (!fep->scc.ep) { - iounmap(fep->scc.sccp); - return -EINVAL; - } - - return 0; -} - -#define SCC_NAPI_RX_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB) -#define SCC_RX_EVENT (SCCE_ENET_RXF) -#define SCC_TX_EVENT (SCCE_ENET_TXB) -#define SCC_ERR_EVENT_MSK (SCCE_ENET_TXE | SCCE_ENET_BSY) - -static int setup_data(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - do_pd_setup(fep); - - fep->scc.hthi = 0; - fep->scc.htlo = 0; - - fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK; - fep->ev_rx = SCC_RX_EVENT; - fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE; - fep->ev_err = SCC_ERR_EVENT_MSK; - - return 0; -} - -static int allocate_bd(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; - - fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) * - sizeof(cbd_t), 8); - if (IS_ERR_VALUE(fep->ring_mem_addr)) - return -ENOMEM; - - fep->ring_base = (void __iomem __force*) - cpm_dpram_addr(fep->ring_mem_addr); - - return 0; -} - -static void free_bd(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (fep->ring_base) - cpm_dpfree(fep->ring_mem_addr); -} - -static void cleanup_data(struct net_device *dev) -{ - /* nothing */ -} - -static void set_promiscuous_mode(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - - S16(sccp, scc_psmr, SCC_PSMR_PRO); -} - -static void set_multicast_start(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_enet_t __iomem *ep = fep->scc.ep; - - W16(ep, sen_gaddr1, 0); - W16(ep, sen_gaddr2, 0); - W16(ep, sen_gaddr3, 0); - W16(ep, sen_gaddr4, 0); -} - -static void set_multicast_one(struct net_device *dev, const u8 * mac) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_enet_t __iomem *ep = fep->scc.ep; - u16 taddrh, taddrm, taddrl; - - taddrh = ((u16) mac[5] << 8) | mac[4]; - taddrm = ((u16) mac[3] << 8) | mac[2]; - taddrl = ((u16) mac[1] << 8) | mac[0]; - - W16(ep, sen_taddrh, taddrh); - W16(ep, sen_taddrm, taddrm); - W16(ep, sen_taddrl, taddrl); - scc_cr_cmd(fep, CPM_CR_SET_GADDR); -} - -static void set_multicast_finish(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - scc_enet_t __iomem *ep = fep->scc.ep; - - /* clear promiscuous always */ - C16(sccp, scc_psmr, SCC_PSMR_PRO); - - /* if all multi or too many multicasts; just enable all */ - if ((dev->flags & IFF_ALLMULTI) != 0 || - netdev_mc_count(dev) > SCC_MAX_MULTICAST_ADDRS) { - - W16(ep, sen_gaddr1, 0xffff); - W16(ep, sen_gaddr2, 0xffff); - W16(ep, sen_gaddr3, 0xffff); - W16(ep, sen_gaddr4, 0xffff); - } -} - -static void set_multicast_list(struct net_device *dev) -{ - struct netdev_hw_addr *ha; - - if ((dev->flags & IFF_PROMISC) == 0) { - set_multicast_start(dev); - netdev_for_each_mc_addr(ha, dev) - set_multicast_one(dev, ha->addr); - set_multicast_finish(dev); - } else - set_promiscuous_mode(dev); -} - -/* - * This function is called to start or restart the FEC during a link - * change. This only happens when switching between half and full - * duplex. - */ -static void restart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - scc_enet_t __iomem *ep = fep->scc.ep; - const struct fs_platform_info *fpi = fep->fpi; - u16 paddrh, paddrm, paddrl; - const unsigned char *mac; - int i; - - C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); - - /* clear everything (slow & steady does it) */ - for (i = 0; i < sizeof(*ep); i++) - __fs_out8((u8 __iomem *)ep + i, 0); - - /* point to bds */ - W16(ep, sen_genscc.scc_rbase, fep->ring_mem_addr); - W16(ep, sen_genscc.scc_tbase, - fep->ring_mem_addr + sizeof(cbd_t) * fpi->rx_ring); - - /* Initialize function code registers for big-endian. - */ -#ifndef CONFIG_NOT_COHERENT_CACHE - W8(ep, sen_genscc.scc_rfcr, SCC_EB | SCC_GBL); - W8(ep, sen_genscc.scc_tfcr, SCC_EB | SCC_GBL); -#else - W8(ep, sen_genscc.scc_rfcr, SCC_EB); - W8(ep, sen_genscc.scc_tfcr, SCC_EB); -#endif - - /* Set maximum bytes per receive buffer. - * This appears to be an Ethernet frame size, not the buffer - * fragment size. It must be a multiple of four. - */ - W16(ep, sen_genscc.scc_mrblr, 0x5f0); - - /* Set CRC preset and mask. - */ - W32(ep, sen_cpres, 0xffffffff); - W32(ep, sen_cmask, 0xdebb20e3); - - W32(ep, sen_crcec, 0); /* CRC Error counter */ - W32(ep, sen_alec, 0); /* alignment error counter */ - W32(ep, sen_disfc, 0); /* discard frame counter */ - - W16(ep, sen_pads, 0x8888); /* Tx short frame pad character */ - W16(ep, sen_retlim, 15); /* Retry limit threshold */ - - W16(ep, sen_maxflr, 0x5ee); /* maximum frame length register */ - - W16(ep, sen_minflr, PKT_MINBUF_SIZE); /* minimum frame length register */ - - W16(ep, sen_maxd1, 0x000005f0); /* maximum DMA1 length */ - W16(ep, sen_maxd2, 0x000005f0); /* maximum DMA2 length */ - - /* Clear hash tables. - */ - W16(ep, sen_gaddr1, 0); - W16(ep, sen_gaddr2, 0); - W16(ep, sen_gaddr3, 0); - W16(ep, sen_gaddr4, 0); - W16(ep, sen_iaddr1, 0); - W16(ep, sen_iaddr2, 0); - W16(ep, sen_iaddr3, 0); - W16(ep, sen_iaddr4, 0); - - /* set address - */ - mac = dev->dev_addr; - paddrh = ((u16) mac[5] << 8) | mac[4]; - paddrm = ((u16) mac[3] << 8) | mac[2]; - paddrl = ((u16) mac[1] << 8) | mac[0]; - - W16(ep, sen_paddrh, paddrh); - W16(ep, sen_paddrm, paddrm); - W16(ep, sen_paddrl, paddrl); - - W16(ep, sen_pper, 0); - W16(ep, sen_taddrl, 0); - W16(ep, sen_taddrm, 0); - W16(ep, sen_taddrh, 0); - - fs_init_bds(dev); - - scc_cr_cmd(fep, CPM_CR_INIT_TRX); - - W16(sccp, scc_scce, 0xffff); - - /* Enable interrupts we wish to service. - */ - W16(sccp, scc_sccm, SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB); - - /* Set GSMR_H to enable all normal operating modes. - * Set GSMR_L to enable Ethernet to MC68160. - */ - W32(sccp, scc_gsmrh, 0); - W32(sccp, scc_gsmrl, - SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | - SCC_GSMRL_MODE_ENET); - - /* Set sync/delimiters. - */ - W16(sccp, scc_dsr, 0xd555); - - /* Set processing mode. Use Ethernet CRC, catch broadcast, and - * start frame search 22 bit times after RENA. - */ - W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22); - - /* Set full duplex mode if needed */ - if (fep->phydev->duplex) - S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE); - - S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); -} - -static void stop(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - int i; - - for (i = 0; (R16(sccp, scc_sccm) == 0) && i < SCC_RESET_DELAY; i++) - udelay(1); - - if (i == SCC_RESET_DELAY) - dev_warn(fep->dev, "SCC timeout on graceful transmit stop\n"); - - W16(sccp, scc_sccm, 0); - C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); - - fs_cleanup_bds(dev); -} - -static void napi_clear_rx_event(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - - W16(sccp, scc_scce, SCC_NAPI_RX_EVENT_MSK); -} - -static void napi_enable_rx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - - S16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK); -} - -static void napi_disable_rx(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - - C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK); -} - -static void rx_bd_done(struct net_device *dev) -{ - /* nothing */ -} - -static void tx_kickstart(struct net_device *dev) -{ - /* nothing */ -} - -static u32 get_int_events(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - - return (u32) R16(sccp, scc_scce); -} - -static void clear_int_events(struct net_device *dev, u32 int_events) -{ - struct fs_enet_private *fep = netdev_priv(dev); - scc_t __iomem *sccp = fep->scc.sccp; - - W16(sccp, scc_scce, int_events & 0xffff); -} - -static void ev_error(struct net_device *dev, u32 int_events) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - dev_warn(fep->dev, "SCC ERROR(s) 0x%x\n", int_events); -} - -static int get_regs(struct net_device *dev, void *p, int *sizep) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - if (*sizep < sizeof(scc_t) + sizeof(scc_enet_t __iomem *)) - return -EINVAL; - - memcpy_fromio(p, fep->scc.sccp, sizeof(scc_t)); - p = (char *)p + sizeof(scc_t); - - memcpy_fromio(p, fep->scc.ep, sizeof(scc_enet_t __iomem *)); - - return 0; -} - -static int get_regs_len(struct net_device *dev) -{ - return sizeof(scc_t) + sizeof(scc_enet_t __iomem *); -} - -static void tx_restart(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - scc_cr_cmd(fep, CPM_CR_RESTART_TX); -} - - - -/*************************************************************************/ - -const struct fs_ops fs_scc_ops = { - .setup_data = setup_data, - .cleanup_data = cleanup_data, - .set_multicast_list = set_multicast_list, - .restart = restart, - .stop = stop, - .napi_clear_rx_event = napi_clear_rx_event, - .napi_enable_rx = napi_enable_rx, - .napi_disable_rx = napi_disable_rx, - .rx_bd_done = rx_bd_done, - .tx_kickstart = tx_kickstart, - .get_int_events = get_int_events, - .clear_int_events = clear_int_events, - .ev_error = ev_error, - .get_regs = get_regs, - .get_regs_len = get_regs_len, - .tx_restart = tx_restart, - .allocate_bd = allocate_bd, - .free_bd = free_bd, -}; diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c deleted file mode 100644 index 0f2d1a71..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/mii.h> -#include <linux/platform_device.h> -#include <linux/mdio-bitbang.h> -#include <linux/of_mdio.h> -#include <linux/of_platform.h> - -#include "fs_enet.h" - -struct bb_info { - struct mdiobb_ctrl ctrl; - __be32 __iomem *dir; - __be32 __iomem *dat; - u32 mdio_msk; - u32 mdc_msk; -}; - -/* FIXME: If any other users of GPIO crop up, then these will have to - * have some sort of global synchronization to avoid races with other - * pins on the same port. The ideal solution would probably be to - * bind the ports to a GPIO driver, and have this be a client of it. - */ -static inline void bb_set(u32 __iomem *p, u32 m) -{ - out_be32(p, in_be32(p) | m); -} - -static inline void bb_clr(u32 __iomem *p, u32 m) -{ - out_be32(p, in_be32(p) & ~m); -} - -static inline int bb_read(u32 __iomem *p, u32 m) -{ - return (in_be32(p) & m) != 0; -} - -static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) -{ - struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); - - if (dir) - bb_set(bitbang->dir, bitbang->mdio_msk); - else - bb_clr(bitbang->dir, bitbang->mdio_msk); - - /* Read back to flush the write. */ - in_be32(bitbang->dir); -} - -static inline int mdio_read(struct mdiobb_ctrl *ctrl) -{ - struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); - return bb_read(bitbang->dat, bitbang->mdio_msk); -} - -static inline void mdio(struct mdiobb_ctrl *ctrl, int what) -{ - struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); - - if (what) - bb_set(bitbang->dat, bitbang->mdio_msk); - else - bb_clr(bitbang->dat, bitbang->mdio_msk); - - /* Read back to flush the write. */ - in_be32(bitbang->dat); -} - -static inline void mdc(struct mdiobb_ctrl *ctrl, int what) -{ - struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); - - if (what) - bb_set(bitbang->dat, bitbang->mdc_msk); - else - bb_clr(bitbang->dat, bitbang->mdc_msk); - - /* Read back to flush the write. */ - in_be32(bitbang->dat); -} - -static struct mdiobb_ops bb_ops = { - .owner = THIS_MODULE, - .set_mdc = mdc, - .set_mdio_dir = mdio_dir, - .set_mdio_data = mdio, - .get_mdio_data = mdio_read, -}; - -static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, - struct device_node *np) -{ - struct resource res; - const u32 *data; - int mdio_pin, mdc_pin, len; - struct bb_info *bitbang = bus->priv; - - int ret = of_address_to_resource(np, 0, &res); - if (ret) - return ret; - - if (resource_size(&res) <= 13) - return -ENODEV; - - /* This should really encode the pin number as well, but all - * we get is an int, and the odds of multiple bitbang mdio buses - * is low enough that it's not worth going too crazy. - */ - snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); - - data = of_get_property(np, "fsl,mdio-pin", &len); - if (!data || len != 4) - return -ENODEV; - mdio_pin = *data; - - data = of_get_property(np, "fsl,mdc-pin", &len); - if (!data || len != 4) - return -ENODEV; - mdc_pin = *data; - - bitbang->dir = ioremap(res.start, resource_size(&res)); - if (!bitbang->dir) - return -ENOMEM; - - bitbang->dat = bitbang->dir + 4; - bitbang->mdio_msk = 1 << (31 - mdio_pin); - bitbang->mdc_msk = 1 << (31 - mdc_pin); - - return 0; -} - -static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) -{ - struct mii_bus *new_bus; - struct bb_info *bitbang; - int ret = -ENOMEM; - - bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); - if (!bitbang) - goto out; - - bitbang->ctrl.ops = &bb_ops; - - new_bus = alloc_mdio_bitbang(&bitbang->ctrl); - if (!new_bus) - goto out_free_priv; - - new_bus->name = "CPM2 Bitbanged MII", - - ret = fs_mii_bitbang_init(new_bus, ofdev->dev.of_node); - if (ret) - goto out_free_bus; - - new_bus->phy_mask = ~0; - new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) - goto out_unmap_regs; - - new_bus->parent = &ofdev->dev; - dev_set_drvdata(&ofdev->dev, new_bus); - - ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); - if (ret) - goto out_free_irqs; - - return 0; - -out_free_irqs: - dev_set_drvdata(&ofdev->dev, NULL); - kfree(new_bus->irq); -out_unmap_regs: - iounmap(bitbang->dir); -out_free_bus: - free_mdio_bitbang(new_bus); -out_free_priv: - kfree(bitbang); -out: - return ret; -} - -static int fs_enet_mdio_remove(struct platform_device *ofdev) -{ - struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); - struct bb_info *bitbang = bus->priv; - - mdiobus_unregister(bus); - dev_set_drvdata(&ofdev->dev, NULL); - kfree(bus->irq); - free_mdio_bitbang(bus); - iounmap(bitbang->dir); - kfree(bitbang); - - return 0; -} - -static struct of_device_id fs_enet_mdio_bb_match[] = { - { - .compatible = "fsl,cpm2-mdio-bitbang", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, fs_enet_mdio_bb_match); - -static struct platform_driver fs_enet_bb_mdio_driver = { - .driver = { - .name = "fsl-bb-mdio", - .owner = THIS_MODULE, - .of_match_table = fs_enet_mdio_bb_match, - }, - .probe = fs_enet_mdio_probe, - .remove = fs_enet_mdio_remove, -}; - -module_platform_driver(fs_enet_bb_mdio_driver); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mii-fec.c deleted file mode 100644 index 55bb8672..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou <panto@intracom.gr> - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/bitops.h> -#include <linux/platform_device.h> -#include <linux/of_platform.h> - -#include <asm/pgtable.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/mpc5xxx.h> - -#include "fs_enet.h" -#include "fec.h" - -/* Make MII read/write commands for the FEC. -*/ -#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) -#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) -#define mk_mii_end 0 - -#define FEC_MII_LOOPS 10000 - -static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) -{ - struct fec_info* fec = bus->priv; - struct fec __iomem *fecp = fec->fecp; - int i, ret = -1; - - BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); - - /* Add PHY address to register command. */ - out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); - - for (i = 0; i < FEC_MII_LOOPS; i++) - if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) - break; - - if (i < FEC_MII_LOOPS) { - out_be32(&fecp->fec_ievent, FEC_ENET_MII); - ret = in_be32(&fecp->fec_mii_data) & 0xffff; - } - - return ret; -} - -static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) -{ - struct fec_info* fec = bus->priv; - struct fec __iomem *fecp = fec->fecp; - int i; - - /* this must never happen */ - BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); - - /* Add PHY address to register command. */ - out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); - - for (i = 0; i < FEC_MII_LOOPS; i++) - if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) - break; - - if (i < FEC_MII_LOOPS) - out_be32(&fecp->fec_ievent, FEC_ENET_MII); - - return 0; - -} - -static int fs_enet_fec_mii_reset(struct mii_bus *bus) -{ - /* nothing here - for now */ - return 0; -} - -static struct of_device_id fs_enet_mdio_fec_match[]; -static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) -{ - const struct of_device_id *match; - struct resource res; - struct mii_bus *new_bus; - struct fec_info *fec; - int (*get_bus_freq)(struct device_node *); - int ret = -ENOMEM, clock, speed; - - match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev); - if (!match) - return -EINVAL; - get_bus_freq = match->data; - - new_bus = mdiobus_alloc(); - if (!new_bus) - goto out; - - fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL); - if (!fec) - goto out_mii; - - new_bus->priv = fec; - new_bus->name = "FEC MII Bus"; - new_bus->read = &fs_enet_fec_mii_read; - new_bus->write = &fs_enet_fec_mii_write; - new_bus->reset = &fs_enet_fec_mii_reset; - - ret = of_address_to_resource(ofdev->dev.of_node, 0, &res); - if (ret) - goto out_res; - - snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start); - - fec->fecp = ioremap(res.start, resource_size(&res)); - if (!fec->fecp) - goto out_fec; - - if (get_bus_freq) { - clock = get_bus_freq(ofdev->dev.of_node); - if (!clock) { - /* Use maximum divider if clock is unknown */ - dev_warn(&ofdev->dev, "could not determine IPS clock\n"); - clock = 0x3F * 5000000; - } - } else - clock = ppc_proc_freq; - - /* - * Scale for a MII clock <= 2.5 MHz - * Note that only 6 bits (25:30) are available for MII speed. - */ - speed = (clock + 4999999) / 5000000; - if (speed > 0x3F) { - speed = 0x3F; - dev_err(&ofdev->dev, - "MII clock (%d Hz) exceeds max (2.5 MHz)\n", - clock / speed); - } - - fec->mii_speed = speed << 1; - - setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); - setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | - FEC_ECNTRL_ETHER_EN); - out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII); - clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed); - - new_bus->phy_mask = ~0; - new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - if (!new_bus->irq) - goto out_unmap_regs; - - new_bus->parent = &ofdev->dev; - dev_set_drvdata(&ofdev->dev, new_bus); - - ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); - if (ret) - goto out_free_irqs; - - return 0; - -out_free_irqs: - dev_set_drvdata(&ofdev->dev, NULL); - kfree(new_bus->irq); -out_unmap_regs: - iounmap(fec->fecp); -out_res: -out_fec: - kfree(fec); -out_mii: - mdiobus_free(new_bus); -out: - return ret; -} - -static int fs_enet_mdio_remove(struct platform_device *ofdev) -{ - struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); - struct fec_info *fec = bus->priv; - - mdiobus_unregister(bus); - dev_set_drvdata(&ofdev->dev, NULL); - kfree(bus->irq); - iounmap(fec->fecp); - kfree(fec); - mdiobus_free(bus); - - return 0; -} - -static struct of_device_id fs_enet_mdio_fec_match[] = { - { - .compatible = "fsl,pq1-fec-mdio", - }, -#if defined(CONFIG_PPC_MPC512x) - { - .compatible = "fsl,mpc5121-fec-mdio", - .data = mpc5xxx_get_bus_frequency, - }, -#endif - {}, -}; -MODULE_DEVICE_TABLE(of, fs_enet_mdio_fec_match); - -static struct platform_driver fs_enet_fec_mdio_driver = { - .driver = { - .name = "fsl-fec-mdio", - .owner = THIS_MODULE, - .of_match_table = fs_enet_mdio_fec_match, - }, - .probe = fs_enet_mdio_probe, - .remove = fs_enet_mdio_remove, -}; - -module_platform_driver(fs_enet_fec_mdio_driver); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fsl_pq_mdio.c deleted file mode 100644 index f7f0bf5d..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Freescale PowerQUICC Ethernet Driver -- MIIM bus implementation - * Provides Bus interface for MIIM regs - * - * Author: Andy Fleming <afleming@freescale.com> - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> - * - * Copyright 2002-2004, 2008-2009 Freescale Semiconductor, Inc. - * - * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips) - * - * 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. - * - */ - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/unistd.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/crc32.h> -#include <linux/mii.h> -#include <linux/phy.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_mdio.h> -#include <linux/of_platform.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/ucc.h> - -#include "gianfar.h" -#include "fsl_pq_mdio.h" - -struct fsl_pq_mdio_priv { - void __iomem *map; - struct fsl_pq_mdio __iomem *regs; -}; - -/* - * Write value to the PHY at mii_id at register regnum, - * on the bus attached to the local interface, which may be different from the - * generic mdio bus (tied to a single interface), waiting until the write is - * done before returning. This is helpful in programming interfaces like - * the TBI which control interfaces like onchip SERDES and are always tied to - * the local mdio pins, which may not be the same as system mdio bus, used for - * controlling the external PHYs, for example. - */ -int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, - int regnum, u16 value) -{ - /* Set the PHY address and the register address we want to write */ - out_be32(®s->miimadd, (mii_id << 8) | regnum); - - /* Write out the value we want */ - out_be32(®s->miimcon, value); - - /* Wait for the transaction to finish */ - while (in_be32(®s->miimind) & MIIMIND_BUSY) - cpu_relax(); - - return 0; -} - -/* - * Read the bus for PHY at addr mii_id, register regnum, and - * return the value. Clears miimcom first. All PHY operation - * done on the bus attached to the local interface, - * which may be different from the generic mdio bus - * This is helpful in programming interfaces like - * the TBI which, in turn, control interfaces like onchip SERDES - * and are always tied to the local mdio pins, which may not be the - * same as system mdio bus, used for controlling the external PHYs, for eg. - */ -int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, - int mii_id, int regnum) -{ - u16 value; - - /* Set the PHY address and the register address we want to read */ - out_be32(®s->miimadd, (mii_id << 8) | regnum); - - /* Clear miimcom, and then initiate a read */ - out_be32(®s->miimcom, 0); - out_be32(®s->miimcom, MII_READ_COMMAND); - - /* Wait for the transaction to finish */ - while (in_be32(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) - cpu_relax(); - - /* Grab the value of the register from miimstat */ - value = in_be32(®s->miimstat); - - return value; -} - -static struct fsl_pq_mdio __iomem *fsl_pq_mdio_get_regs(struct mii_bus *bus) -{ - struct fsl_pq_mdio_priv *priv = bus->priv; - - return priv->regs; -} - -/* - * Write value to the PHY at mii_id at register regnum, - * on the bus, waiting until the write is done before returning. - */ -int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) -{ - struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); - - /* Write to the local MII regs */ - return fsl_pq_local_mdio_write(regs, mii_id, regnum, value); -} - -/* - * Read the bus for PHY at addr mii_id, register regnum, and - * return the value. Clears miimcom first. - */ -int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); - - /* Read the local MII regs */ - return fsl_pq_local_mdio_read(regs, mii_id, regnum); -} - -/* Reset the MIIM registers, and wait for the bus to free */ -static int fsl_pq_mdio_reset(struct mii_bus *bus) -{ - struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); - int timeout = PHY_INIT_TIMEOUT; - - mutex_lock(&bus->mdio_lock); - - /* Reset the management interface */ - out_be32(®s->miimcfg, MIIMCFG_RESET); - - /* Setup the MII Mgmt clock speed */ - out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE); - - /* Wait until the bus is free */ - while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) - cpu_relax(); - - mutex_unlock(&bus->mdio_lock); - - if (timeout < 0) { - printk(KERN_ERR "%s: The MII Bus is stuck!\n", - bus->name); - return -EBUSY; - } - - return 0; -} - -void fsl_pq_mdio_bus_name(char *name, struct device_node *np) -{ - const u32 *addr; - u64 taddr = OF_BAD_ADDR; - - addr = of_get_address(np, 0, NULL, NULL); - if (addr) - taddr = of_translate_address(np, addr); - - snprintf(name, MII_BUS_ID_SIZE, "%s@%llx", np->name, - (unsigned long long)taddr); -} -EXPORT_SYMBOL_GPL(fsl_pq_mdio_bus_name); - - -static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np) -{ -#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) - struct gfar __iomem *enet_regs; - - /* - * This is mildly evil, but so is our hardware for doing this. - * Also, we have to cast back to struct gfar because of - * definition weirdness done in gianfar.h. - */ - if(of_device_is_compatible(np, "fsl,gianfar-mdio") || - of_device_is_compatible(np, "fsl,gianfar-tbi") || - of_device_is_compatible(np, "gianfar")) { - enet_regs = (struct gfar __iomem *)regs; - return &enet_regs->tbipa; - } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") || - of_device_is_compatible(np, "fsl,etsec2-tbi")) { - return of_iomap(np, 1); - } -#endif - return NULL; -} - - -static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) -{ -#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) - struct device_node *np = NULL; - int err = 0; - - for_each_compatible_node(np, NULL, "ucc_geth") { - struct resource tempres; - - err = of_address_to_resource(np, 0, &tempres); - if (err) - continue; - - /* if our mdio regs fall within this UCC regs range */ - if ((start >= tempres.start) && (end <= tempres.end)) { - /* Find the id of the UCC */ - const u32 *id; - - id = of_get_property(np, "cell-index", NULL); - if (!id) { - id = of_get_property(np, "device-id", NULL); - if (!id) - continue; - } - - *ucc_id = *id; - - return 0; - } - } - - if (err) - return err; - else - return -EINVAL; -#else - return -ENODEV; -#endif -} - -static int fsl_pq_mdio_probe(struct platform_device *ofdev) -{ - struct device_node *np = ofdev->dev.of_node; - struct device_node *tbi; - struct fsl_pq_mdio_priv *priv; - struct fsl_pq_mdio __iomem *regs = NULL; - void __iomem *map; - u32 __iomem *tbipa; - struct mii_bus *new_bus; - int tbiaddr = -1; - const u32 *addrp; - u64 addr = 0, size = 0; - int err; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - new_bus = mdiobus_alloc(); - if (!new_bus) { - err = -ENOMEM; - goto err_free_priv; - } - - new_bus->name = "Freescale PowerQUICC MII Bus", - new_bus->read = &fsl_pq_mdio_read, - new_bus->write = &fsl_pq_mdio_write, - new_bus->reset = &fsl_pq_mdio_reset, - new_bus->priv = priv; - fsl_pq_mdio_bus_name(new_bus->id, np); - - addrp = of_get_address(np, 0, &size, NULL); - if (!addrp) { - err = -EINVAL; - goto err_free_bus; - } - - /* Set the PHY base address */ - addr = of_translate_address(np, addrp); - if (addr == OF_BAD_ADDR) { - err = -EINVAL; - goto err_free_bus; - } - - map = ioremap(addr, size); - if (!map) { - err = -ENOMEM; - goto err_free_bus; - } - priv->map = map; - - if (of_device_is_compatible(np, "fsl,gianfar-mdio") || - of_device_is_compatible(np, "fsl,gianfar-tbi") || - of_device_is_compatible(np, "fsl,ucc-mdio") || - of_device_is_compatible(np, "ucc_geth_phy")) - map -= offsetof(struct fsl_pq_mdio, miimcfg); - regs = map; - priv->regs = regs; - - new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); - - if (NULL == new_bus->irq) { - err = -ENOMEM; - goto err_unmap_regs; - } - - new_bus->parent = &ofdev->dev; - dev_set_drvdata(&ofdev->dev, new_bus); - - if (of_device_is_compatible(np, "fsl,gianfar-mdio") || - of_device_is_compatible(np, "fsl,gianfar-tbi") || - of_device_is_compatible(np, "fsl,etsec2-mdio") || - of_device_is_compatible(np, "fsl,etsec2-tbi") || - of_device_is_compatible(np, "gianfar")) { - tbipa = get_gfar_tbipa(regs, np); - if (!tbipa) { - err = -EINVAL; - goto err_free_irqs; - } - } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || - of_device_is_compatible(np, "ucc_geth_phy")) { - u32 id; - static u32 mii_mng_master; - - tbipa = ®s->utbipar; - - if ((err = get_ucc_id_for_range(addr, addr + size, &id))) - goto err_free_irqs; - - if (!mii_mng_master) { - mii_mng_master = id; - ucc_set_qe_mux_mii_mng(id - 1); - } - } else { - err = -ENODEV; - goto err_free_irqs; - } - - for_each_child_of_node(np, tbi) { - if (!strncmp(tbi->type, "tbi-phy", 8)) - break; - } - - if (tbi) { - const u32 *prop = of_get_property(tbi, "reg", NULL); - - if (prop) - tbiaddr = *prop; - - if (tbiaddr == -1) { - err = -EBUSY; - goto err_free_irqs; - } else { - out_be32(tbipa, tbiaddr); - } - } - - err = of_mdiobus_register(new_bus, np); - if (err) { - printk (KERN_ERR "%s: Cannot register as MDIO bus\n", - new_bus->name); - goto err_free_irqs; - } - - return 0; - -err_free_irqs: - kfree(new_bus->irq); -err_unmap_regs: - iounmap(priv->map); -err_free_bus: - kfree(new_bus); -err_free_priv: - kfree(priv); - return err; -} - - -static int fsl_pq_mdio_remove(struct platform_device *ofdev) -{ - struct device *device = &ofdev->dev; - struct mii_bus *bus = dev_get_drvdata(device); - struct fsl_pq_mdio_priv *priv = bus->priv; - - mdiobus_unregister(bus); - - dev_set_drvdata(device, NULL); - - iounmap(priv->map); - bus->priv = NULL; - mdiobus_free(bus); - kfree(priv); - - return 0; -} - -static struct of_device_id fsl_pq_mdio_match[] = { - { - .type = "mdio", - .compatible = "ucc_geth_phy", - }, - { - .type = "mdio", - .compatible = "gianfar", - }, - { - .compatible = "fsl,ucc-mdio", - }, - { - .compatible = "fsl,gianfar-tbi", - }, - { - .compatible = "fsl,gianfar-mdio", - }, - { - .compatible = "fsl,etsec2-tbi", - }, - { - .compatible = "fsl,etsec2-mdio", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match); - -static struct platform_driver fsl_pq_mdio_driver = { - .driver = { - .name = "fsl-pq_mdio", - .owner = THIS_MODULE, - .of_match_table = fsl_pq_mdio_match, - }, - .probe = fsl_pq_mdio_probe, - .remove = fsl_pq_mdio_remove, -}; - -module_platform_driver(fsl_pq_mdio_driver); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fsl_pq_mdio.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/fsl_pq_mdio.h deleted file mode 100644 index bd17a2a0..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/fsl_pq_mdio.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Freescale PowerQUICC MDIO Driver -- MII Management Bus Implementation - * Driver for the MDIO bus controller on Freescale PowerQUICC processors - * - * Author: Andy Fleming - * Modifier: Sandeep Gopalpet - * - * Copyright 2002-2004, 2008-2009 Freescale Semiconductor, Inc. - * - * 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. - * - */ -#ifndef __FSL_PQ_MDIO_H -#define __FSL_PQ_MDIO_H - -#define MIIMIND_BUSY 0x00000001 -#define MIIMIND_NOTVALID 0x00000004 -#define MIIMCFG_INIT_VALUE 0x00000007 -#define MIIMCFG_RESET 0x80000000 - -#define MII_READ_COMMAND 0x00000001 - -struct fsl_pq_mdio { - u8 res1[16]; - u32 ieventm; /* MDIO Interrupt event register (for etsec2)*/ - u32 imaskm; /* MDIO Interrupt mask register (for etsec2)*/ - u8 res2[4]; - u32 emapm; /* MDIO Event mapping register (for etsec2)*/ - u8 res3[1280]; - u32 miimcfg; /* MII management configuration reg */ - u32 miimcom; /* MII management command reg */ - u32 miimadd; /* MII management address reg */ - u32 miimcon; /* MII management control reg */ - u32 miimstat; /* MII management status reg */ - u32 miimind; /* MII management indication reg */ - u8 reserved[28]; /* Space holder */ - u32 utbipar; /* TBI phy address reg (only on UCC) */ - u8 res4[2728]; -} __packed; - -int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum); -int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); -int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, - int regnum, u16 value); -int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum); -int __init fsl_pq_mdio_init(void); -void fsl_pq_mdio_exit(void); -void fsl_pq_mdio_bus_name(char *name, struct device_node *np); -#endif /* FSL_PQ_MDIO_H */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar.c deleted file mode 100644 index e7bed530..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar.c +++ /dev/null @@ -1,3283 +0,0 @@ -/* - * drivers/net/ethernet/freescale/gianfar.c - * - * Gianfar Ethernet Driver - * This driver is designed for the non-CPM ethernet controllers - * on the 85xx and 83xx family of integrated processors - * Based on 8260_io/fcc_enet.c - * - * Author: Andy Fleming - * Maintainer: Kumar Gala - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> - * - * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. - * Copyright 2007 MontaVista Software, Inc. - * - * 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. - * - * Gianfar: AKA Lambda Draconis, "Dragon" - * RA 11 31 24.2 - * Dec +69 19 52 - * V 3.84 - * B-V +1.62 - * - * Theory of operation - * - * The driver is initialized through of_device. Configuration information - * is therefore conveyed through an OF-style device tree. - * - * The Gianfar Ethernet Controller uses a ring of buffer - * descriptors. The beginning is indicated by a register - * pointing to the physical address of the start of the ring. - * The end is determined by a "wrap" bit being set in the - * last descriptor of the ring. - * - * When a packet is received, the RXF bit in the - * IEVENT register is set, triggering an interrupt when the - * corresponding bit in the IMASK register is also set (if - * interrupt coalescing is active, then the interrupt may not - * happen immediately, but will wait until either a set number - * of frames or amount of time have passed). In NAPI, the - * interrupt handler will signal there is work to be done, and - * exit. This method will start at the last known empty - * descriptor, and process every subsequent descriptor until there - * are none left with data (NAPI will stop after a set number of - * packets to give time to other tasks, but will eventually - * process all the packets). The data arrives inside a - * pre-allocated skb, and so after the skb is passed up to the - * stack, a new skb must be allocated, and the address field in - * the buffer descriptor must be updated to indicate this new - * skb. - * - * When the kernel requests that a packet be transmitted, the - * driver starts where it left off last time, and points the - * descriptor at the buffer which was passed in. The driver - * then informs the DMA engine that there are packets ready to - * be transmitted. Once the controller is finished transmitting - * the packet, an interrupt may be triggered (under the same - * conditions as for reception, but depending on the TXF bit). - * The driver then cleans up the buffer. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define DEBUG - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/unistd.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_vlan.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/of_mdio.h> -#include <linux/of_platform.h> -#include <linux/ip.h> -#include <linux/tcp.h> -#include <linux/udp.h> -#include <linux/in.h> -#include <linux/net_tstamp.h> - -#include <asm/io.h> -#include <asm/reg.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <linux/module.h> -#include <linux/dma-mapping.h> -#include <linux/crc32.h> -#include <linux/mii.h> -#include <linux/phy.h> -#include <linux/phy_fixed.h> -#include <linux/of.h> -#include <linux/of_net.h> - -#include "gianfar.h" -#include "fsl_pq_mdio.h" - -#define TX_TIMEOUT (1*HZ) - -const char gfar_driver_version[] = "1.3"; - -static int gfar_enet_open(struct net_device *dev); -static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void gfar_reset_task(struct work_struct *work); -static void gfar_timeout(struct net_device *dev); -static int gfar_close(struct net_device *dev); -struct sk_buff *gfar_new_skb(struct net_device *dev); -static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, - struct sk_buff *skb); -static int gfar_set_mac_address(struct net_device *dev); -static int gfar_change_mtu(struct net_device *dev, int new_mtu); -static irqreturn_t gfar_error(int irq, void *dev_id); -static irqreturn_t gfar_transmit(int irq, void *dev_id); -static irqreturn_t gfar_interrupt(int irq, void *dev_id); -static void adjust_link(struct net_device *dev); -static void init_registers(struct net_device *dev); -static int init_phy(struct net_device *dev); -static int gfar_probe(struct platform_device *ofdev); -static int gfar_remove(struct platform_device *ofdev); -static void free_skb_resources(struct gfar_private *priv); -static void gfar_set_multi(struct net_device *dev); -static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); -static void gfar_configure_serdes(struct net_device *dev); -static int gfar_poll(struct napi_struct *napi, int budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void gfar_netpoll(struct net_device *dev); -#endif -int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); -static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); -static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, - int amount_pull); -void gfar_halt(struct net_device *dev); -static void gfar_halt_nodisable(struct net_device *dev); -void gfar_start(struct net_device *dev); -static void gfar_clear_exact_match(struct net_device *dev); -static void gfar_set_mac_for_addr(struct net_device *dev, int num, - const u8 *addr); -static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); - -MODULE_AUTHOR("Freescale Semiconductor, Inc"); -MODULE_DESCRIPTION("Gianfar Ethernet Driver"); -MODULE_LICENSE("GPL"); - -static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, - dma_addr_t buf) -{ - u32 lstatus; - - bdp->bufPtr = buf; - - lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT); - if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1) - lstatus |= BD_LFLAG(RXBD_WRAP); - - eieio(); - - bdp->lstatus = lstatus; -} - -static int gfar_init_bds(struct net_device *ndev) -{ - struct gfar_private *priv = netdev_priv(ndev); - struct gfar_priv_tx_q *tx_queue = NULL; - struct gfar_priv_rx_q *rx_queue = NULL; - struct txbd8 *txbdp; - struct rxbd8 *rxbdp; - int i, j; - - for (i = 0; i < priv->num_tx_queues; i++) { - tx_queue = priv->tx_queue[i]; - /* Initialize some variables in our dev structure */ - tx_queue->num_txbdfree = tx_queue->tx_ring_size; - tx_queue->dirty_tx = tx_queue->tx_bd_base; - tx_queue->cur_tx = tx_queue->tx_bd_base; - tx_queue->skb_curtx = 0; - tx_queue->skb_dirtytx = 0; - - /* Initialize Transmit Descriptor Ring */ - txbdp = tx_queue->tx_bd_base; - for (j = 0; j < tx_queue->tx_ring_size; j++) { - txbdp->lstatus = 0; - txbdp->bufPtr = 0; - txbdp++; - } - - /* Set the last descriptor in the ring to indicate wrap */ - txbdp--; - txbdp->status |= TXBD_WRAP; - } - - for (i = 0; i < priv->num_rx_queues; i++) { - rx_queue = priv->rx_queue[i]; - rx_queue->cur_rx = rx_queue->rx_bd_base; - rx_queue->skb_currx = 0; - rxbdp = rx_queue->rx_bd_base; - - for (j = 0; j < rx_queue->rx_ring_size; j++) { - struct sk_buff *skb = rx_queue->rx_skbuff[j]; - - if (skb) { - gfar_init_rxbdp(rx_queue, rxbdp, - rxbdp->bufPtr); - } else { - skb = gfar_new_skb(ndev); - if (!skb) { - netdev_err(ndev, "Can't allocate RX buffers\n"); - goto err_rxalloc_fail; - } - rx_queue->rx_skbuff[j] = skb; - - gfar_new_rxbdp(rx_queue, rxbdp, skb); - } - - rxbdp++; - } - - } - - return 0; - -err_rxalloc_fail: - free_skb_resources(priv); - return -ENOMEM; -} - -static int gfar_alloc_skb_resources(struct net_device *ndev) -{ - void *vaddr; - dma_addr_t addr; - int i, j, k; - struct gfar_private *priv = netdev_priv(ndev); - struct device *dev = &priv->ofdev->dev; - struct gfar_priv_tx_q *tx_queue = NULL; - struct gfar_priv_rx_q *rx_queue = NULL; - - priv->total_tx_ring_size = 0; - for (i = 0; i < priv->num_tx_queues; i++) - priv->total_tx_ring_size += priv->tx_queue[i]->tx_ring_size; - - priv->total_rx_ring_size = 0; - for (i = 0; i < priv->num_rx_queues; i++) - priv->total_rx_ring_size += priv->rx_queue[i]->rx_ring_size; - - /* Allocate memory for the buffer descriptors */ - vaddr = dma_alloc_coherent(dev, - sizeof(struct txbd8) * priv->total_tx_ring_size + - sizeof(struct rxbd8) * priv->total_rx_ring_size, - &addr, GFP_KERNEL); - if (!vaddr) { - netif_err(priv, ifup, ndev, - "Could not allocate buffer descriptors!\n"); - return -ENOMEM; - } - - for (i = 0; i < priv->num_tx_queues; i++) { - tx_queue = priv->tx_queue[i]; - tx_queue->tx_bd_base = vaddr; - tx_queue->tx_bd_dma_base = addr; - tx_queue->dev = ndev; - /* enet DMA only understands physical addresses */ - addr += sizeof(struct txbd8) *tx_queue->tx_ring_size; - vaddr += sizeof(struct txbd8) *tx_queue->tx_ring_size; - } - - /* Start the rx descriptor ring where the tx ring leaves off */ - for (i = 0; i < priv->num_rx_queues; i++) { - rx_queue = priv->rx_queue[i]; - rx_queue->rx_bd_base = vaddr; - rx_queue->rx_bd_dma_base = addr; - rx_queue->dev = ndev; - addr += sizeof (struct rxbd8) * rx_queue->rx_ring_size; - vaddr += sizeof (struct rxbd8) * rx_queue->rx_ring_size; - } - - /* Setup the skbuff rings */ - for (i = 0; i < priv->num_tx_queues; i++) { - tx_queue = priv->tx_queue[i]; - tx_queue->tx_skbuff = kmalloc(sizeof(*tx_queue->tx_skbuff) * - tx_queue->tx_ring_size, GFP_KERNEL); - if (!tx_queue->tx_skbuff) { - netif_err(priv, ifup, ndev, - "Could not allocate tx_skbuff\n"); - goto cleanup; - } - - for (k = 0; k < tx_queue->tx_ring_size; k++) - tx_queue->tx_skbuff[k] = NULL; - } - - for (i = 0; i < priv->num_rx_queues; i++) { - rx_queue = priv->rx_queue[i]; - rx_queue->rx_skbuff = kmalloc(sizeof(*rx_queue->rx_skbuff) * - rx_queue->rx_ring_size, GFP_KERNEL); - - if (!rx_queue->rx_skbuff) { - netif_err(priv, ifup, ndev, - "Could not allocate rx_skbuff\n"); - goto cleanup; - } - - for (j = 0; j < rx_queue->rx_ring_size; j++) - rx_queue->rx_skbuff[j] = NULL; - } - - if (gfar_init_bds(ndev)) - goto cleanup; - - return 0; - -cleanup: - free_skb_resources(priv); - return -ENOMEM; -} - -static void gfar_init_tx_rx_base(struct gfar_private *priv) -{ - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 __iomem *baddr; - int i; - - baddr = ®s->tbase0; - for(i = 0; i < priv->num_tx_queues; i++) { - gfar_write(baddr, priv->tx_queue[i]->tx_bd_dma_base); - baddr += 2; - } - - baddr = ®s->rbase0; - for(i = 0; i < priv->num_rx_queues; i++) { - gfar_write(baddr, priv->rx_queue[i]->rx_bd_dma_base); - baddr += 2; - } -} - -static void gfar_init_mac(struct net_device *ndev) -{ - struct gfar_private *priv = netdev_priv(ndev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 rctrl = 0; - u32 tctrl = 0; - u32 attrs = 0; - - /* write the tx/rx base registers */ - gfar_init_tx_rx_base(priv); - - /* Configure the coalescing support */ - gfar_configure_coalescing(priv, 0xFF, 0xFF); - - if (priv->rx_filer_enable) { - rctrl |= RCTRL_FILREN; - /* Program the RIR0 reg with the required distribution */ - gfar_write(®s->rir0, DEFAULT_RIR0); - } - - if (ndev->features & NETIF_F_RXCSUM) - rctrl |= RCTRL_CHECKSUMMING; - - if (priv->extended_hash) { - rctrl |= RCTRL_EXTHASH; - - gfar_clear_exact_match(ndev); - rctrl |= RCTRL_EMEN; - } - - if (priv->padding) { - rctrl &= ~RCTRL_PAL_MASK; - rctrl |= RCTRL_PADDING(priv->padding); - } - - /* Insert receive time stamps into padding alignment bytes */ - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) { - rctrl &= ~RCTRL_PAL_MASK; - rctrl |= RCTRL_PADDING(8); - priv->padding = 8; - } - - /* Enable HW time stamping if requested from user space */ - if (priv->hwts_rx_en) - rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE; - - if (ndev->features & NETIF_F_HW_VLAN_RX) - rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; - - /* Init rctrl based on our settings */ - gfar_write(®s->rctrl, rctrl); - - if (ndev->features & NETIF_F_IP_CSUM) - tctrl |= TCTRL_INIT_CSUM; - - tctrl |= TCTRL_TXSCHED_PRIO; - - gfar_write(®s->tctrl, tctrl); - - /* Set the extraction length and index */ - attrs = ATTRELI_EL(priv->rx_stash_size) | - ATTRELI_EI(priv->rx_stash_index); - - gfar_write(®s->attreli, attrs); - - /* Start with defaults, and add stashing or locking - * depending on the approprate variables */ - attrs = ATTR_INIT_SETTINGS; - - if (priv->bd_stash_en) - attrs |= ATTR_BDSTASH; - - if (priv->rx_stash_size != 0) - attrs |= ATTR_BUFSTASH; - - gfar_write(®s->attr, attrs); - - gfar_write(®s->fifo_tx_thr, priv->fifo_threshold); - gfar_write(®s->fifo_tx_starve, priv->fifo_starve); - gfar_write(®s->fifo_tx_starve_shutoff, priv->fifo_starve_off); -} - -static struct net_device_stats *gfar_get_stats(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; - unsigned long tx_packets = 0, tx_bytes = 0; - int i = 0; - - for (i = 0; i < priv->num_rx_queues; i++) { - rx_packets += priv->rx_queue[i]->stats.rx_packets; - rx_bytes += priv->rx_queue[i]->stats.rx_bytes; - rx_dropped += priv->rx_queue[i]->stats.rx_dropped; - } - - dev->stats.rx_packets = rx_packets; - dev->stats.rx_bytes = rx_bytes; - dev->stats.rx_dropped = rx_dropped; - - for (i = 0; i < priv->num_tx_queues; i++) { - tx_bytes += priv->tx_queue[i]->stats.tx_bytes; - tx_packets += priv->tx_queue[i]->stats.tx_packets; - } - - dev->stats.tx_bytes = tx_bytes; - dev->stats.tx_packets = tx_packets; - - return &dev->stats; -} - -static const struct net_device_ops gfar_netdev_ops = { - .ndo_open = gfar_enet_open, - .ndo_start_xmit = gfar_start_xmit, - .ndo_stop = gfar_close, - .ndo_change_mtu = gfar_change_mtu, - .ndo_set_features = gfar_set_features, - .ndo_set_rx_mode = gfar_set_multi, - .ndo_tx_timeout = gfar_timeout, - .ndo_do_ioctl = gfar_ioctl, - .ndo_get_stats = gfar_get_stats, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = gfar_netpoll, -#endif -}; - -void lock_rx_qs(struct gfar_private *priv) -{ - int i = 0x0; - - for (i = 0; i < priv->num_rx_queues; i++) - spin_lock(&priv->rx_queue[i]->rxlock); -} - -void lock_tx_qs(struct gfar_private *priv) -{ - int i = 0x0; - - for (i = 0; i < priv->num_tx_queues; i++) - spin_lock(&priv->tx_queue[i]->txlock); -} - -void unlock_rx_qs(struct gfar_private *priv) -{ - int i = 0x0; - - for (i = 0; i < priv->num_rx_queues; i++) - spin_unlock(&priv->rx_queue[i]->rxlock); -} - -void unlock_tx_qs(struct gfar_private *priv) -{ - int i = 0x0; - - for (i = 0; i < priv->num_tx_queues; i++) - spin_unlock(&priv->tx_queue[i]->txlock); -} - -static bool gfar_is_vlan_on(struct gfar_private *priv) -{ - return (priv->ndev->features & NETIF_F_HW_VLAN_RX) || - (priv->ndev->features & NETIF_F_HW_VLAN_TX); -} - -/* Returns 1 if incoming frames use an FCB */ -static inline int gfar_uses_fcb(struct gfar_private *priv) -{ - return gfar_is_vlan_on(priv) || - (priv->ndev->features & NETIF_F_RXCSUM) || - (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER); -} - -static void free_tx_pointers(struct gfar_private *priv) -{ - int i = 0; - - for (i = 0; i < priv->num_tx_queues; i++) - kfree(priv->tx_queue[i]); -} - -static void free_rx_pointers(struct gfar_private *priv) -{ - int i = 0; - - for (i = 0; i < priv->num_rx_queues; i++) - kfree(priv->rx_queue[i]); -} - -static void unmap_group_regs(struct gfar_private *priv) -{ - int i = 0; - - for (i = 0; i < MAXGROUPS; i++) - if (priv->gfargrp[i].regs) - iounmap(priv->gfargrp[i].regs); -} - -static void disable_napi(struct gfar_private *priv) -{ - int i = 0; - - for (i = 0; i < priv->num_grps; i++) - napi_disable(&priv->gfargrp[i].napi); -} - -static void enable_napi(struct gfar_private *priv) -{ - int i = 0; - - for (i = 0; i < priv->num_grps; i++) - napi_enable(&priv->gfargrp[i].napi); -} - -static int gfar_parse_group(struct device_node *np, - struct gfar_private *priv, const char *model) -{ - u32 *queue_mask; - - priv->gfargrp[priv->num_grps].regs = of_iomap(np, 0); - if (!priv->gfargrp[priv->num_grps].regs) - return -ENOMEM; - - priv->gfargrp[priv->num_grps].interruptTransmit = - irq_of_parse_and_map(np, 0); - - /* If we aren't the FEC we have multiple interrupts */ - if (model && strcasecmp(model, "FEC")) { - priv->gfargrp[priv->num_grps].interruptReceive = - irq_of_parse_and_map(np, 1); - priv->gfargrp[priv->num_grps].interruptError = - irq_of_parse_and_map(np,2); - if (priv->gfargrp[priv->num_grps].interruptTransmit == NO_IRQ || - priv->gfargrp[priv->num_grps].interruptReceive == NO_IRQ || - priv->gfargrp[priv->num_grps].interruptError == NO_IRQ) - return -EINVAL; - } - - priv->gfargrp[priv->num_grps].grp_id = priv->num_grps; - priv->gfargrp[priv->num_grps].priv = priv; - spin_lock_init(&priv->gfargrp[priv->num_grps].grplock); - if(priv->mode == MQ_MG_MODE) { - queue_mask = (u32 *)of_get_property(np, - "fsl,rx-bit-map", NULL); - priv->gfargrp[priv->num_grps].rx_bit_map = - queue_mask ? *queue_mask :(DEFAULT_MAPPING >> priv->num_grps); - queue_mask = (u32 *)of_get_property(np, - "fsl,tx-bit-map", NULL); - priv->gfargrp[priv->num_grps].tx_bit_map = - queue_mask ? *queue_mask : (DEFAULT_MAPPING >> priv->num_grps); - } else { - priv->gfargrp[priv->num_grps].rx_bit_map = 0xFF; - priv->gfargrp[priv->num_grps].tx_bit_map = 0xFF; - } - priv->num_grps++; - - return 0; -} - -static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) -{ - const char *model; - const char *ctype; - const void *mac_addr; - int err = 0, i; - struct net_device *dev = NULL; - struct gfar_private *priv = NULL; - struct device_node *np = ofdev->dev.of_node; - struct device_node *child = NULL; - const u32 *stash; - const u32 *stash_len; - const u32 *stash_idx; - unsigned int num_tx_qs, num_rx_qs; - u32 *tx_queues, *rx_queues; - - if (!np || !of_device_is_available(np)) - return -ENODEV; - - /* parse the num of tx and rx queues */ - tx_queues = (u32 *)of_get_property(np, "fsl,num_tx_queues", NULL); - num_tx_qs = tx_queues ? *tx_queues : 1; - - if (num_tx_qs > MAX_TX_QS) { - pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n", - num_tx_qs, MAX_TX_QS); - pr_err("Cannot do alloc_etherdev, aborting\n"); - return -EINVAL; - } - - rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL); - num_rx_qs = rx_queues ? *rx_queues : 1; - - if (num_rx_qs > MAX_RX_QS) { - pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n", - num_rx_qs, MAX_RX_QS); - pr_err("Cannot do alloc_etherdev, aborting\n"); - return -EINVAL; - } - - *pdev = alloc_etherdev_mq(sizeof(*priv), num_tx_qs); - dev = *pdev; - if (NULL == dev) - return -ENOMEM; - - priv = netdev_priv(dev); - priv->node = ofdev->dev.of_node; - priv->ndev = dev; - - priv->num_tx_queues = num_tx_qs; - netif_set_real_num_rx_queues(dev, num_rx_qs); - priv->num_rx_queues = num_rx_qs; - priv->num_grps = 0x0; - - /* Init Rx queue filer rule set linked list*/ - INIT_LIST_HEAD(&priv->rx_list.list); - priv->rx_list.count = 0; - mutex_init(&priv->rx_queue_access); - - model = of_get_property(np, "model", NULL); - - for (i = 0; i < MAXGROUPS; i++) - priv->gfargrp[i].regs = NULL; - - /* Parse and initialize group specific information */ - if (of_device_is_compatible(np, "fsl,etsec2")) { - priv->mode = MQ_MG_MODE; - for_each_child_of_node(np, child) { - err = gfar_parse_group(child, priv, model); - if (err) - goto err_grp_init; - } - } else { - priv->mode = SQ_SG_MODE; - err = gfar_parse_group(np, priv, model); - if(err) - goto err_grp_init; - } - - for (i = 0; i < priv->num_tx_queues; i++) - priv->tx_queue[i] = NULL; - for (i = 0; i < priv->num_rx_queues; i++) - priv->rx_queue[i] = NULL; - - for (i = 0; i < priv->num_tx_queues; i++) { - priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q), - GFP_KERNEL); - if (!priv->tx_queue[i]) { - err = -ENOMEM; - goto tx_alloc_failed; - } - priv->tx_queue[i]->tx_skbuff = NULL; - priv->tx_queue[i]->qindex = i; - priv->tx_queue[i]->dev = dev; - spin_lock_init(&(priv->tx_queue[i]->txlock)); - } - - for (i = 0; i < priv->num_rx_queues; i++) { - priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q), - GFP_KERNEL); - if (!priv->rx_queue[i]) { - err = -ENOMEM; - goto rx_alloc_failed; - } - priv->rx_queue[i]->rx_skbuff = NULL; - priv->rx_queue[i]->qindex = i; - priv->rx_queue[i]->dev = dev; - spin_lock_init(&(priv->rx_queue[i]->rxlock)); - } - - - stash = of_get_property(np, "bd-stash", NULL); - - if (stash) { - priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING; - priv->bd_stash_en = 1; - } - - stash_len = of_get_property(np, "rx-stash-len", NULL); - - if (stash_len) - priv->rx_stash_size = *stash_len; - - stash_idx = of_get_property(np, "rx-stash-idx", NULL); - - if (stash_idx) - priv->rx_stash_index = *stash_idx; - - if (stash_len || stash_idx) - priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING; - - mac_addr = of_get_mac_address(np); - if (mac_addr) - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); - - if (model && !strcasecmp(model, "TSEC")) - priv->device_flags = - FSL_GIANFAR_DEV_HAS_GIGABIT | - FSL_GIANFAR_DEV_HAS_COALESCE | - FSL_GIANFAR_DEV_HAS_RMON | - FSL_GIANFAR_DEV_HAS_MULTI_INTR; - if (model && !strcasecmp(model, "eTSEC")) - priv->device_flags = - FSL_GIANFAR_DEV_HAS_GIGABIT | - FSL_GIANFAR_DEV_HAS_COALESCE | - FSL_GIANFAR_DEV_HAS_RMON | - FSL_GIANFAR_DEV_HAS_MULTI_INTR | - FSL_GIANFAR_DEV_HAS_PADDING | - FSL_GIANFAR_DEV_HAS_CSUM | - FSL_GIANFAR_DEV_HAS_VLAN | - FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | - FSL_GIANFAR_DEV_HAS_EXTENDED_HASH | - FSL_GIANFAR_DEV_HAS_TIMER; - - ctype = of_get_property(np, "phy-connection-type", NULL); - - /* We only care about rgmii-id. The rest are autodetected */ - if (ctype && !strcmp(ctype, "rgmii-id")) - priv->interface = PHY_INTERFACE_MODE_RGMII_ID; - else - priv->interface = PHY_INTERFACE_MODE_MII; - - if (of_get_property(np, "fsl,magic-packet", NULL)) - priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; - - priv->phy_node = of_parse_phandle(np, "phy-handle", 0); - - /* Find the TBI PHY. If it's not there, we don't support SGMII */ - priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0); - - return 0; - -rx_alloc_failed: - free_rx_pointers(priv); -tx_alloc_failed: - free_tx_pointers(priv); -err_grp_init: - unmap_group_regs(priv); - free_netdev(dev); - return err; -} - -static int gfar_hwtstamp_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct hwtstamp_config config; - struct gfar_private *priv = netdev_priv(netdev); - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - - switch (config.tx_type) { - case HWTSTAMP_TX_OFF: - priv->hwts_tx_en = 0; - break; - case HWTSTAMP_TX_ON: - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)) - return -ERANGE; - priv->hwts_tx_en = 1; - break; - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - if (priv->hwts_rx_en) { - stop_gfar(netdev); - priv->hwts_rx_en = 0; - startup_gfar(netdev); - } - break; - default: - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)) - return -ERANGE; - if (!priv->hwts_rx_en) { - stop_gfar(netdev); - priv->hwts_rx_en = 1; - startup_gfar(netdev); - } - config.rx_filter = HWTSTAMP_FILTER_ALL; - break; - } - - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; -} - -/* Ioctl MII Interface */ -static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (!netif_running(dev)) - return -EINVAL; - - if (cmd == SIOCSHWTSTAMP) - return gfar_hwtstamp_ioctl(dev, rq, cmd); - - if (!priv->phydev) - return -ENODEV; - - return phy_mii_ioctl(priv->phydev, rq, cmd); -} - -static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs) -{ - unsigned int new_bit_map = 0x0; - int mask = 0x1 << (max_qs - 1), i; - for (i = 0; i < max_qs; i++) { - if (bit_map & mask) - new_bit_map = new_bit_map + (1 << i); - mask = mask >> 0x1; - } - return new_bit_map; -} - -static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, - u32 class) -{ - u32 rqfpr = FPR_FILER_MASK; - u32 rqfcr = 0x0; - - rqfar--; - rqfcr = RQFCR_CLE | RQFCR_PID_MASK | RQFCR_CMP_EXACT; - priv->ftp_rqfpr[rqfar] = rqfpr; - priv->ftp_rqfcr[rqfar] = rqfcr; - gfar_write_filer(priv, rqfar, rqfcr, rqfpr); - - rqfar--; - rqfcr = RQFCR_CMP_NOMATCH; - priv->ftp_rqfpr[rqfar] = rqfpr; - priv->ftp_rqfcr[rqfar] = rqfcr; - gfar_write_filer(priv, rqfar, rqfcr, rqfpr); - - rqfar--; - rqfcr = RQFCR_CMP_EXACT | RQFCR_PID_PARSE | RQFCR_CLE | RQFCR_AND; - rqfpr = class; - priv->ftp_rqfcr[rqfar] = rqfcr; - priv->ftp_rqfpr[rqfar] = rqfpr; - gfar_write_filer(priv, rqfar, rqfcr, rqfpr); - - rqfar--; - rqfcr = RQFCR_CMP_EXACT | RQFCR_PID_MASK | RQFCR_AND; - rqfpr = class; - priv->ftp_rqfcr[rqfar] = rqfcr; - priv->ftp_rqfpr[rqfar] = rqfpr; - gfar_write_filer(priv, rqfar, rqfcr, rqfpr); - - return rqfar; -} - -static void gfar_init_filer_table(struct gfar_private *priv) -{ - int i = 0x0; - u32 rqfar = MAX_FILER_IDX; - u32 rqfcr = 0x0; - u32 rqfpr = FPR_FILER_MASK; - - /* Default rule */ - rqfcr = RQFCR_CMP_MATCH; - priv->ftp_rqfcr[rqfar] = rqfcr; - priv->ftp_rqfpr[rqfar] = rqfpr; - gfar_write_filer(priv, rqfar, rqfcr, rqfpr); - - rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV6); - rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV6 | RQFPR_UDP); - rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV6 | RQFPR_TCP); - rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV4); - rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV4 | RQFPR_UDP); - rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV4 | RQFPR_TCP); - - /* cur_filer_idx indicated the first non-masked rule */ - priv->cur_filer_idx = rqfar; - - /* Rest are masked rules */ - rqfcr = RQFCR_CMP_NOMATCH; - for (i = 0; i < rqfar; i++) { - priv->ftp_rqfcr[i] = rqfcr; - priv->ftp_rqfpr[i] = rqfpr; - gfar_write_filer(priv, i, rqfcr, rqfpr); - } -} - -static void gfar_detect_errata(struct gfar_private *priv) -{ - struct device *dev = &priv->ofdev->dev; - unsigned int pvr = mfspr(SPRN_PVR); - unsigned int svr = mfspr(SPRN_SVR); - unsigned int mod = (svr >> 16) & 0xfff6; /* w/o E suffix */ - unsigned int rev = svr & 0xffff; - - /* MPC8313 Rev 2.0 and higher; All MPC837x */ - if ((pvr == 0x80850010 && mod == 0x80b0 && rev >= 0x0020) || - (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) - priv->errata |= GFAR_ERRATA_74; - - /* MPC8313 and MPC837x all rev */ - if ((pvr == 0x80850010 && mod == 0x80b0) || - (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) - priv->errata |= GFAR_ERRATA_76; - - /* MPC8313 and MPC837x all rev */ - if ((pvr == 0x80850010 && mod == 0x80b0) || - (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) - priv->errata |= GFAR_ERRATA_A002; - - /* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */ - if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) || - (pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020)) - priv->errata |= GFAR_ERRATA_12; - - if (priv->errata) - dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", - priv->errata); -} - -/* Set up the ethernet device structure, private data, - * and anything else we need before we start */ -static int gfar_probe(struct platform_device *ofdev) -{ - u32 tempval; - struct net_device *dev = NULL; - struct gfar_private *priv = NULL; - struct gfar __iomem *regs = NULL; - int err = 0, i, grp_idx = 0; - u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0; - u32 isrg = 0; - u32 __iomem *baddr; - - err = gfar_of_init(ofdev, &dev); - - if (err) - return err; - - priv = netdev_priv(dev); - priv->ndev = dev; - priv->ofdev = ofdev; - priv->node = ofdev->dev.of_node; - SET_NETDEV_DEV(dev, &ofdev->dev); - - spin_lock_init(&priv->bflock); - INIT_WORK(&priv->reset_task, gfar_reset_task); - - dev_set_drvdata(&ofdev->dev, priv); - regs = priv->gfargrp[0].regs; - - gfar_detect_errata(priv); - - /* Stop the DMA engine now, in case it was running before */ - /* (The firmware could have used it, and left it running). */ - gfar_halt(dev); - - /* Reset MAC layer */ - gfar_write(®s->maccfg1, MACCFG1_SOFT_RESET); - - /* We need to delay at least 3 TX clocks */ - udelay(2); - - tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); - gfar_write(®s->maccfg1, tempval); - - /* Initialize MACCFG2. */ - tempval = MACCFG2_INIT_SETTINGS; - if (gfar_has_errata(priv, GFAR_ERRATA_74)) - tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK; - gfar_write(®s->maccfg2, tempval); - - /* Initialize ECNTRL */ - gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS); - - /* Set the dev->base_addr to the gfar reg region */ - dev->base_addr = (unsigned long) regs; - - SET_NETDEV_DEV(dev, &ofdev->dev); - - /* Fill in the dev structure */ - dev->watchdog_timeo = TX_TIMEOUT; - dev->mtu = 1500; - dev->netdev_ops = &gfar_netdev_ops; - dev->ethtool_ops = &gfar_ethtool_ops; - - /* Register for napi ...We are registering NAPI for each grp */ - for (i = 0; i < priv->num_grps; i++) - netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll, GFAR_DEV_WEIGHT); - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | - NETIF_F_RXCSUM; - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | - NETIF_F_RXCSUM | NETIF_F_HIGHDMA; - } - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { - dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - } - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { - priv->extended_hash = 1; - priv->hash_width = 9; - - priv->hash_regs[0] = ®s->igaddr0; - priv->hash_regs[1] = ®s->igaddr1; - priv->hash_regs[2] = ®s->igaddr2; - priv->hash_regs[3] = ®s->igaddr3; - priv->hash_regs[4] = ®s->igaddr4; - priv->hash_regs[5] = ®s->igaddr5; - priv->hash_regs[6] = ®s->igaddr6; - priv->hash_regs[7] = ®s->igaddr7; - priv->hash_regs[8] = ®s->gaddr0; - priv->hash_regs[9] = ®s->gaddr1; - priv->hash_regs[10] = ®s->gaddr2; - priv->hash_regs[11] = ®s->gaddr3; - priv->hash_regs[12] = ®s->gaddr4; - priv->hash_regs[13] = ®s->gaddr5; - priv->hash_regs[14] = ®s->gaddr6; - priv->hash_regs[15] = ®s->gaddr7; - - } else { - priv->extended_hash = 0; - priv->hash_width = 8; - - priv->hash_regs[0] = ®s->gaddr0; - priv->hash_regs[1] = ®s->gaddr1; - priv->hash_regs[2] = ®s->gaddr2; - priv->hash_regs[3] = ®s->gaddr3; - priv->hash_regs[4] = ®s->gaddr4; - priv->hash_regs[5] = ®s->gaddr5; - priv->hash_regs[6] = ®s->gaddr6; - priv->hash_regs[7] = ®s->gaddr7; - } - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) - priv->padding = DEFAULT_PADDING; - else - priv->padding = 0; - - if (dev->features & NETIF_F_IP_CSUM || - priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) - dev->hard_header_len += GMAC_FCB_LEN; - - /* Program the isrg regs only if number of grps > 1 */ - if (priv->num_grps > 1) { - baddr = ®s->isrg0; - for (i = 0; i < priv->num_grps; i++) { - isrg |= (priv->gfargrp[i].rx_bit_map << ISRG_SHIFT_RX); - isrg |= (priv->gfargrp[i].tx_bit_map << ISRG_SHIFT_TX); - gfar_write(baddr, isrg); - baddr++; - isrg = 0x0; - } - } - - /* Need to reverse the bit maps as bit_map's MSB is q0 - * but, for_each_set_bit parses from right to left, which - * basically reverses the queue numbers */ - for (i = 0; i< priv->num_grps; i++) { - priv->gfargrp[i].tx_bit_map = reverse_bitmap( - priv->gfargrp[i].tx_bit_map, MAX_TX_QS); - priv->gfargrp[i].rx_bit_map = reverse_bitmap( - priv->gfargrp[i].rx_bit_map, MAX_RX_QS); - } - - /* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values, - * also assign queues to groups */ - for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) { - priv->gfargrp[grp_idx].num_rx_queues = 0x0; - for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map, - priv->num_rx_queues) { - priv->gfargrp[grp_idx].num_rx_queues++; - priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx]; - rstat = rstat | (RSTAT_CLEAR_RHALT >> i); - rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i); - } - priv->gfargrp[grp_idx].num_tx_queues = 0x0; - for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map, - priv->num_tx_queues) { - priv->gfargrp[grp_idx].num_tx_queues++; - priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx]; - tstat = tstat | (TSTAT_CLEAR_THALT >> i); - tqueue = tqueue | (TQUEUE_EN0 >> i); - } - priv->gfargrp[grp_idx].rstat = rstat; - priv->gfargrp[grp_idx].tstat = tstat; - rstat = tstat =0; - } - - gfar_write(®s->rqueue, rqueue); - gfar_write(®s->tqueue, tqueue); - - priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; - - /* Initializing some of the rx/tx queue level parameters */ - for (i = 0; i < priv->num_tx_queues; i++) { - priv->tx_queue[i]->tx_ring_size = DEFAULT_TX_RING_SIZE; - priv->tx_queue[i]->num_txbdfree = DEFAULT_TX_RING_SIZE; - priv->tx_queue[i]->txcoalescing = DEFAULT_TX_COALESCE; - priv->tx_queue[i]->txic = DEFAULT_TXIC; - } - - for (i = 0; i < priv->num_rx_queues; i++) { - priv->rx_queue[i]->rx_ring_size = DEFAULT_RX_RING_SIZE; - priv->rx_queue[i]->rxcoalescing = DEFAULT_RX_COALESCE; - priv->rx_queue[i]->rxic = DEFAULT_RXIC; - } - - /* always enable rx filer*/ - priv->rx_filer_enable = 1; - /* Enable most messages by default */ - priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; - - /* Carrier starts down, phylib will bring it up */ - netif_carrier_off(dev); - - err = register_netdev(dev); - - if (err) { - pr_err("%s: Cannot register net device, aborting\n", dev->name); - goto register_fail; - } - - device_init_wakeup(&dev->dev, - priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); - - /* fill out IRQ number and name fields */ - for (i = 0; i < priv->num_grps; i++) { - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - sprintf(priv->gfargrp[i].int_name_tx, "%s%s%c%s", - dev->name, "_g", '0' + i, "_tx"); - sprintf(priv->gfargrp[i].int_name_rx, "%s%s%c%s", - dev->name, "_g", '0' + i, "_rx"); - sprintf(priv->gfargrp[i].int_name_er, "%s%s%c%s", - dev->name, "_g", '0' + i, "_er"); - } else - strcpy(priv->gfargrp[i].int_name_tx, dev->name); - } - - /* Initialize the filer table */ - gfar_init_filer_table(priv); - - /* Create all the sysfs files */ - gfar_init_sysfs(dev); - - /* Print out the device info */ - netdev_info(dev, "mac: %pM\n", dev->dev_addr); - - /* Even more device info helps when determining which kernel */ - /* provided which set of benchmarks. */ - netdev_info(dev, "Running with NAPI enabled\n"); - for (i = 0; i < priv->num_rx_queues; i++) - netdev_info(dev, "RX BD ring size for Q[%d]: %d\n", - i, priv->rx_queue[i]->rx_ring_size); - for(i = 0; i < priv->num_tx_queues; i++) - netdev_info(dev, "TX BD ring size for Q[%d]: %d\n", - i, priv->tx_queue[i]->tx_ring_size); - - return 0; - -register_fail: - unmap_group_regs(priv); - free_tx_pointers(priv); - free_rx_pointers(priv); - if (priv->phy_node) - of_node_put(priv->phy_node); - if (priv->tbi_node) - of_node_put(priv->tbi_node); - free_netdev(dev); - return err; -} - -static int gfar_remove(struct platform_device *ofdev) -{ - struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); - - if (priv->phy_node) - of_node_put(priv->phy_node); - if (priv->tbi_node) - of_node_put(priv->tbi_node); - - dev_set_drvdata(&ofdev->dev, NULL); - - unregister_netdev(priv->ndev); - unmap_group_regs(priv); - free_netdev(priv->ndev); - - return 0; -} - -#ifdef CONFIG_PM - -static int gfar_suspend(struct device *dev) -{ - struct gfar_private *priv = dev_get_drvdata(dev); - struct net_device *ndev = priv->ndev; - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned long flags; - u32 tempval; - - int magic_packet = priv->wol_en && - (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); - - netif_device_detach(ndev); - - if (netif_running(ndev)) { - - local_irq_save(flags); - lock_tx_qs(priv); - lock_rx_qs(priv); - - gfar_halt_nodisable(ndev); - - /* Disable Tx, and Rx if wake-on-LAN is disabled. */ - tempval = gfar_read(®s->maccfg1); - - tempval &= ~MACCFG1_TX_EN; - - if (!magic_packet) - tempval &= ~MACCFG1_RX_EN; - - gfar_write(®s->maccfg1, tempval); - - unlock_rx_qs(priv); - unlock_tx_qs(priv); - local_irq_restore(flags); - - disable_napi(priv); - - if (magic_packet) { - /* Enable interrupt on Magic Packet */ - gfar_write(®s->imask, IMASK_MAG); - - /* Enable Magic Packet mode */ - tempval = gfar_read(®s->maccfg2); - tempval |= MACCFG2_MPEN; - gfar_write(®s->maccfg2, tempval); - } else { - phy_stop(priv->phydev); - } - } - - return 0; -} - -static int gfar_resume(struct device *dev) -{ - struct gfar_private *priv = dev_get_drvdata(dev); - struct net_device *ndev = priv->ndev; - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned long flags; - u32 tempval; - int magic_packet = priv->wol_en && - (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); - - if (!netif_running(ndev)) { - netif_device_attach(ndev); - return 0; - } - - if (!magic_packet && priv->phydev) - phy_start(priv->phydev); - - /* Disable Magic Packet mode, in case something - * else woke us up. - */ - local_irq_save(flags); - lock_tx_qs(priv); - lock_rx_qs(priv); - - tempval = gfar_read(®s->maccfg2); - tempval &= ~MACCFG2_MPEN; - gfar_write(®s->maccfg2, tempval); - - gfar_start(ndev); - - unlock_rx_qs(priv); - unlock_tx_qs(priv); - local_irq_restore(flags); - - netif_device_attach(ndev); - - enable_napi(priv); - - return 0; -} - -static int gfar_restore(struct device *dev) -{ - struct gfar_private *priv = dev_get_drvdata(dev); - struct net_device *ndev = priv->ndev; - - if (!netif_running(ndev)) - return 0; - - gfar_init_bds(ndev); - init_registers(ndev); - gfar_set_mac_address(ndev); - gfar_init_mac(ndev); - gfar_start(ndev); - - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - - if (priv->phydev) - phy_start(priv->phydev); - - netif_device_attach(ndev); - enable_napi(priv); - - return 0; -} - -static struct dev_pm_ops gfar_pm_ops = { - .suspend = gfar_suspend, - .resume = gfar_resume, - .freeze = gfar_suspend, - .thaw = gfar_resume, - .restore = gfar_restore, -}; - -#define GFAR_PM_OPS (&gfar_pm_ops) - -#else - -#define GFAR_PM_OPS NULL - -#endif - -/* Reads the controller's registers to determine what interface - * connects it to the PHY. - */ -static phy_interface_t gfar_get_interface(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 ecntrl; - - ecntrl = gfar_read(®s->ecntrl); - - if (ecntrl & ECNTRL_SGMII_MODE) - return PHY_INTERFACE_MODE_SGMII; - - if (ecntrl & ECNTRL_TBI_MODE) { - if (ecntrl & ECNTRL_REDUCED_MODE) - return PHY_INTERFACE_MODE_RTBI; - else - return PHY_INTERFACE_MODE_TBI; - } - - if (ecntrl & ECNTRL_REDUCED_MODE) { - if (ecntrl & ECNTRL_REDUCED_MII_MODE) - return PHY_INTERFACE_MODE_RMII; - else { - phy_interface_t interface = priv->interface; - - /* - * This isn't autodetected right now, so it must - * be set by the device tree or platform code. - */ - if (interface == PHY_INTERFACE_MODE_RGMII_ID) - return PHY_INTERFACE_MODE_RGMII_ID; - - return PHY_INTERFACE_MODE_RGMII; - } - } - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) - return PHY_INTERFACE_MODE_GMII; - - return PHY_INTERFACE_MODE_MII; -} - - -/* Initializes driver's PHY state, and attaches to the PHY. - * Returns 0 on success. - */ -static int init_phy(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - uint gigabit_support = - priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? - SUPPORTED_1000baseT_Full : 0; - phy_interface_t interface; - - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - - interface = gfar_get_interface(dev); - - priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0, - interface); - if (!priv->phydev) - priv->phydev = of_phy_connect_fixed_link(dev, &adjust_link, - interface); - if (!priv->phydev) { - dev_err(&dev->dev, "could not attach to PHY\n"); - return -ENODEV; - } - - if (interface == PHY_INTERFACE_MODE_SGMII) - gfar_configure_serdes(dev); - - /* Remove any features not supported by the controller */ - priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support); - priv->phydev->advertising = priv->phydev->supported; - - return 0; -} - -/* - * Initialize TBI PHY interface for communicating with the - * SERDES lynx PHY on the chip. We communicate with this PHY - * through the MDIO bus on each controller, treating it as a - * "normal" PHY at the address found in the TBIPA register. We assume - * that the TBIPA register is valid. Either the MDIO bus code will set - * it to a value that doesn't conflict with other PHYs on the bus, or the - * value doesn't matter, as there are no other PHYs on the bus. - */ -static void gfar_configure_serdes(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct phy_device *tbiphy; - - if (!priv->tbi_node) { - dev_warn(&dev->dev, "error: SGMII mode requires that the " - "device tree specify a tbi-handle\n"); - return; - } - - tbiphy = of_phy_find_device(priv->tbi_node); - if (!tbiphy) { - dev_err(&dev->dev, "error: Could not get TBI device\n"); - return; - } - - /* - * If the link is already up, we must already be ok, and don't need to - * configure and reset the TBI<->SerDes link. Maybe U-Boot configured - * everything for us? Resetting it takes the link down and requires - * several seconds for it to come back. - */ - if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) - return; - - /* Single clk mode, mii mode off(for serdes communication) */ - phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT); - - phy_write(tbiphy, MII_ADVERTISE, - ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | - ADVERTISE_1000XPSE_ASYM); - - phy_write(tbiphy, MII_BMCR, BMCR_ANENABLE | - BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); -} - -static void init_registers(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = NULL; - int i = 0; - - for (i = 0; i < priv->num_grps; i++) { - regs = priv->gfargrp[i].regs; - /* Clear IEVENT */ - gfar_write(®s->ievent, IEVENT_INIT_CLEAR); - - /* Initialize IMASK */ - gfar_write(®s->imask, IMASK_INIT_CLEAR); - } - - regs = priv->gfargrp[0].regs; - /* Init hash registers to zero */ - gfar_write(®s->igaddr0, 0); - gfar_write(®s->igaddr1, 0); - gfar_write(®s->igaddr2, 0); - gfar_write(®s->igaddr3, 0); - gfar_write(®s->igaddr4, 0); - gfar_write(®s->igaddr5, 0); - gfar_write(®s->igaddr6, 0); - gfar_write(®s->igaddr7, 0); - - gfar_write(®s->gaddr0, 0); - gfar_write(®s->gaddr1, 0); - gfar_write(®s->gaddr2, 0); - gfar_write(®s->gaddr3, 0); - gfar_write(®s->gaddr4, 0); - gfar_write(®s->gaddr5, 0); - gfar_write(®s->gaddr6, 0); - gfar_write(®s->gaddr7, 0); - - /* Zero out the rmon mib registers if it has them */ - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - memset_io(&(regs->rmon), 0, sizeof (struct rmon_mib)); - - /* Mask off the CAM interrupts */ - gfar_write(®s->rmon.cam1, 0xffffffff); - gfar_write(®s->rmon.cam2, 0xffffffff); - } - - /* Initialize the max receive buffer length */ - gfar_write(®s->mrblr, priv->rx_buffer_size); - - /* Initialize the Minimum Frame Length Register */ - gfar_write(®s->minflr, MINFLR_INIT_SETTINGS); -} - -static int __gfar_is_rx_idle(struct gfar_private *priv) -{ - u32 res; - - /* - * Normaly TSEC should not hang on GRS commands, so we should - * actually wait for IEVENT_GRSC flag. - */ - if (likely(!gfar_has_errata(priv, GFAR_ERRATA_A002))) - return 0; - - /* - * Read the eTSEC register at offset 0xD1C. If bits 7-14 are - * the same as bits 23-30, the eTSEC Rx is assumed to be idle - * and the Rx can be safely reset. - */ - res = gfar_read((void __iomem *)priv->gfargrp[0].regs + 0xd1c); - res &= 0x7f807f80; - if ((res & 0xffff) == (res >> 16)) - return 1; - - return 0; -} - -/* Halt the receive and transmit queues */ -static void gfar_halt_nodisable(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = NULL; - u32 tempval; - int i = 0; - - for (i = 0; i < priv->num_grps; i++) { - regs = priv->gfargrp[i].regs; - /* Mask all interrupts */ - gfar_write(®s->imask, IMASK_INIT_CLEAR); - - /* Clear all interrupts */ - gfar_write(®s->ievent, IEVENT_INIT_CLEAR); - } - - regs = priv->gfargrp[0].regs; - /* Stop the DMA, and wait for it to stop */ - tempval = gfar_read(®s->dmactrl); - if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) - != (DMACTRL_GRS | DMACTRL_GTS)) { - int ret; - - tempval |= (DMACTRL_GRS | DMACTRL_GTS); - gfar_write(®s->dmactrl, tempval); - - do { - ret = spin_event_timeout(((gfar_read(®s->ievent) & - (IEVENT_GRSC | IEVENT_GTSC)) == - (IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0); - if (!ret && !(gfar_read(®s->ievent) & IEVENT_GRSC)) - ret = __gfar_is_rx_idle(priv); - } while (!ret); - } -} - -/* Halt the receive and transmit queues */ -void gfar_halt(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 tempval; - - gfar_halt_nodisable(dev); - - /* Disable Rx and Tx */ - tempval = gfar_read(®s->maccfg1); - tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); - gfar_write(®s->maccfg1, tempval); -} - -static void free_grp_irqs(struct gfar_priv_grp *grp) -{ - free_irq(grp->interruptError, grp); - free_irq(grp->interruptTransmit, grp); - free_irq(grp->interruptReceive, grp); -} - -void stop_gfar(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; - int i; - - phy_stop(priv->phydev); - - - /* Lock it down */ - local_irq_save(flags); - lock_tx_qs(priv); - lock_rx_qs(priv); - - gfar_halt(dev); - - unlock_rx_qs(priv); - unlock_tx_qs(priv); - local_irq_restore(flags); - - /* Free the IRQs */ - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - for (i = 0; i < priv->num_grps; i++) - free_grp_irqs(&priv->gfargrp[i]); - } else { - for (i = 0; i < priv->num_grps; i++) - free_irq(priv->gfargrp[i].interruptTransmit, - &priv->gfargrp[i]); - } - - free_skb_resources(priv); -} - -static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue) -{ - struct txbd8 *txbdp; - struct gfar_private *priv = netdev_priv(tx_queue->dev); - int i, j; - - txbdp = tx_queue->tx_bd_base; - - for (i = 0; i < tx_queue->tx_ring_size; i++) { - if (!tx_queue->tx_skbuff[i]) - continue; - - dma_unmap_single(&priv->ofdev->dev, txbdp->bufPtr, - txbdp->length, DMA_TO_DEVICE); - txbdp->lstatus = 0; - for (j = 0; j < skb_shinfo(tx_queue->tx_skbuff[i])->nr_frags; - j++) { - txbdp++; - dma_unmap_page(&priv->ofdev->dev, txbdp->bufPtr, - txbdp->length, DMA_TO_DEVICE); - } - txbdp++; - dev_kfree_skb_any(tx_queue->tx_skbuff[i]); - tx_queue->tx_skbuff[i] = NULL; - } - kfree(tx_queue->tx_skbuff); -} - -static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) -{ - struct rxbd8 *rxbdp; - struct gfar_private *priv = netdev_priv(rx_queue->dev); - int i; - - rxbdp = rx_queue->rx_bd_base; - - for (i = 0; i < rx_queue->rx_ring_size; i++) { - if (rx_queue->rx_skbuff[i]) { - dma_unmap_single(&priv->ofdev->dev, - rxbdp->bufPtr, priv->rx_buffer_size, - DMA_FROM_DEVICE); - dev_kfree_skb_any(rx_queue->rx_skbuff[i]); - rx_queue->rx_skbuff[i] = NULL; - } - rxbdp->lstatus = 0; - rxbdp->bufPtr = 0; - rxbdp++; - } - kfree(rx_queue->rx_skbuff); -} - -/* If there are any tx skbs or rx skbs still around, free them. - * Then free tx_skbuff and rx_skbuff */ -static void free_skb_resources(struct gfar_private *priv) -{ - struct gfar_priv_tx_q *tx_queue = NULL; - struct gfar_priv_rx_q *rx_queue = NULL; - int i; - - /* Go through all the buffer descriptors and free their data buffers */ - for (i = 0; i < priv->num_tx_queues; i++) { - struct netdev_queue *txq; - tx_queue = priv->tx_queue[i]; - txq = netdev_get_tx_queue(tx_queue->dev, tx_queue->qindex); - if(tx_queue->tx_skbuff) - free_skb_tx_queue(tx_queue); - netdev_tx_reset_queue(txq); - } - - for (i = 0; i < priv->num_rx_queues; i++) { - rx_queue = priv->rx_queue[i]; - if(rx_queue->rx_skbuff) - free_skb_rx_queue(rx_queue); - } - - dma_free_coherent(&priv->ofdev->dev, - sizeof(struct txbd8) * priv->total_tx_ring_size + - sizeof(struct rxbd8) * priv->total_rx_ring_size, - priv->tx_queue[0]->tx_bd_base, - priv->tx_queue[0]->tx_bd_dma_base); - skb_queue_purge(&priv->rx_recycle); -} - -void gfar_start(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 tempval; - int i = 0; - - /* Enable Rx and Tx in MACCFG1 */ - tempval = gfar_read(®s->maccfg1); - tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); - gfar_write(®s->maccfg1, tempval); - - /* Initialize DMACTRL to have WWR and WOP */ - tempval = gfar_read(®s->dmactrl); - tempval |= DMACTRL_INIT_SETTINGS; - gfar_write(®s->dmactrl, tempval); - - /* Make sure we aren't stopped */ - tempval = gfar_read(®s->dmactrl); - tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); - gfar_write(®s->dmactrl, tempval); - - for (i = 0; i < priv->num_grps; i++) { - regs = priv->gfargrp[i].regs; - /* Clear THLT/RHLT, so that the DMA starts polling now */ - gfar_write(®s->tstat, priv->gfargrp[i].tstat); - gfar_write(®s->rstat, priv->gfargrp[i].rstat); - /* Unmask the interrupts we look for */ - gfar_write(®s->imask, IMASK_DEFAULT); - } - - dev->trans_start = jiffies; /* prevent tx timeout */ -} - -void gfar_configure_coalescing(struct gfar_private *priv, - unsigned long tx_mask, unsigned long rx_mask) -{ - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 __iomem *baddr; - int i = 0; - - /* Backward compatible case ---- even if we enable - * multiple queues, there's only single reg to program - */ - gfar_write(®s->txic, 0); - if(likely(priv->tx_queue[0]->txcoalescing)) - gfar_write(®s->txic, priv->tx_queue[0]->txic); - - gfar_write(®s->rxic, 0); - if(unlikely(priv->rx_queue[0]->rxcoalescing)) - gfar_write(®s->rxic, priv->rx_queue[0]->rxic); - - if (priv->mode == MQ_MG_MODE) { - baddr = ®s->txic0; - for_each_set_bit(i, &tx_mask, priv->num_tx_queues) { - if (likely(priv->tx_queue[i]->txcoalescing)) { - gfar_write(baddr + i, 0); - gfar_write(baddr + i, priv->tx_queue[i]->txic); - } - } - - baddr = ®s->rxic0; - for_each_set_bit(i, &rx_mask, priv->num_rx_queues) { - if (likely(priv->rx_queue[i]->rxcoalescing)) { - gfar_write(baddr + i, 0); - gfar_write(baddr + i, priv->rx_queue[i]->rxic); - } - } - } -} - -static int register_grp_irqs(struct gfar_priv_grp *grp) -{ - struct gfar_private *priv = grp->priv; - struct net_device *dev = priv->ndev; - int err; - - /* If the device has multiple interrupts, register for - * them. Otherwise, only register for the one */ - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - /* Install our interrupt handlers for Error, - * Transmit, and Receive */ - if ((err = request_irq(grp->interruptError, gfar_error, 0, - grp->int_name_er,grp)) < 0) { - netif_err(priv, intr, dev, "Can't get IRQ %d\n", - grp->interruptError); - - goto err_irq_fail; - } - - if ((err = request_irq(grp->interruptTransmit, gfar_transmit, - 0, grp->int_name_tx, grp)) < 0) { - netif_err(priv, intr, dev, "Can't get IRQ %d\n", - grp->interruptTransmit); - goto tx_irq_fail; - } - - if ((err = request_irq(grp->interruptReceive, gfar_receive, 0, - grp->int_name_rx, grp)) < 0) { - netif_err(priv, intr, dev, "Can't get IRQ %d\n", - grp->interruptReceive); - goto rx_irq_fail; - } - } else { - if ((err = request_irq(grp->interruptTransmit, gfar_interrupt, 0, - grp->int_name_tx, grp)) < 0) { - netif_err(priv, intr, dev, "Can't get IRQ %d\n", - grp->interruptTransmit); - goto err_irq_fail; - } - } - - return 0; - -rx_irq_fail: - free_irq(grp->interruptTransmit, grp); -tx_irq_fail: - free_irq(grp->interruptError, grp); -err_irq_fail: - return err; - -} - -/* Bring the controller up and running */ -int startup_gfar(struct net_device *ndev) -{ - struct gfar_private *priv = netdev_priv(ndev); - struct gfar __iomem *regs = NULL; - int err, i, j; - - for (i = 0; i < priv->num_grps; i++) { - regs= priv->gfargrp[i].regs; - gfar_write(®s->imask, IMASK_INIT_CLEAR); - } - - regs= priv->gfargrp[0].regs; - err = gfar_alloc_skb_resources(ndev); - if (err) - return err; - - gfar_init_mac(ndev); - - for (i = 0; i < priv->num_grps; i++) { - err = register_grp_irqs(&priv->gfargrp[i]); - if (err) { - for (j = 0; j < i; j++) - free_grp_irqs(&priv->gfargrp[j]); - goto irq_fail; - } - } - - /* Start the controller */ - gfar_start(ndev); - - phy_start(priv->phydev); - - gfar_configure_coalescing(priv, 0xFF, 0xFF); - - return 0; - -irq_fail: - free_skb_resources(priv); - return err; -} - -/* Called when something needs to use the ethernet device */ -/* Returns 0 for success. */ -static int gfar_enet_open(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - int err; - - enable_napi(priv); - - skb_queue_head_init(&priv->rx_recycle); - - /* Initialize a bunch of registers */ - init_registers(dev); - - gfar_set_mac_address(dev); - - err = init_phy(dev); - - if (err) { - disable_napi(priv); - return err; - } - - err = startup_gfar(dev); - if (err) { - disable_napi(priv); - return err; - } - - netif_tx_start_all_queues(dev); - - device_set_wakeup_enable(&dev->dev, priv->wol_en); - - return err; -} - -static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb) -{ - struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN); - - memset(fcb, 0, GMAC_FCB_LEN); - - return fcb; -} - -static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb, - int fcb_length) -{ - u8 flags = 0; - - /* If we're here, it's a IP packet with a TCP or UDP - * payload. We set it to checksum, using a pseudo-header - * we provide - */ - flags = TXFCB_DEFAULT; - - /* Tell the controller what the protocol is */ - /* And provide the already calculated phcs */ - if (ip_hdr(skb)->protocol == IPPROTO_UDP) { - flags |= TXFCB_UDP; - fcb->phcs = udp_hdr(skb)->check; - } else - fcb->phcs = tcp_hdr(skb)->check; - - /* l3os is the distance between the start of the - * frame (skb->data) and the start of the IP hdr. - * l4os is the distance between the start of the - * l3 hdr and the l4 hdr */ - fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length); - fcb->l4os = skb_network_header_len(skb); - - fcb->flags = flags; -} - -void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) -{ - fcb->flags |= TXFCB_VLN; - fcb->vlctl = vlan_tx_tag_get(skb); -} - -static inline struct txbd8 *skip_txbd(struct txbd8 *bdp, int stride, - struct txbd8 *base, int ring_size) -{ - struct txbd8 *new_bd = bdp + stride; - - return (new_bd >= (base + ring_size)) ? (new_bd - ring_size) : new_bd; -} - -static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base, - int ring_size) -{ - return skip_txbd(bdp, 1, base, ring_size); -} - -/* This is called by the kernel when a frame is ready for transmission. */ -/* It is pointed to by the dev->hard_start_xmit function pointer */ -static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar_priv_tx_q *tx_queue = NULL; - struct netdev_queue *txq; - struct gfar __iomem *regs = NULL; - struct txfcb *fcb = NULL; - struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL; - u32 lstatus; - int i, rq = 0, do_tstamp = 0; - u32 bufaddr; - unsigned long flags; - unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN; - - /* - * TOE=1 frames larger than 2500 bytes may see excess delays - * before start of transmission. - */ - if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_76) && - skb->ip_summed == CHECKSUM_PARTIAL && - skb->len > 2500)) { - int ret; - - ret = skb_checksum_help(skb); - if (ret) - return ret; - } - - rq = skb->queue_mapping; - tx_queue = priv->tx_queue[rq]; - txq = netdev_get_tx_queue(dev, rq); - base = tx_queue->tx_bd_base; - regs = tx_queue->grp->regs; - - /* check if time stamp should be generated */ - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && - priv->hwts_tx_en)) { - do_tstamp = 1; - fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN; - } - - /* make space for additional header when fcb is needed */ - if (((skb->ip_summed == CHECKSUM_PARTIAL) || - vlan_tx_tag_present(skb) || - unlikely(do_tstamp)) && - (skb_headroom(skb) < fcb_length)) { - struct sk_buff *skb_new; - - skb_new = skb_realloc_headroom(skb, fcb_length); - if (!skb_new) { - dev->stats.tx_errors++; - kfree_skb(skb); - return NETDEV_TX_OK; - } - - /* Steal sock reference for processing TX time stamps */ - swap(skb_new->sk, skb->sk); - swap(skb_new->destructor, skb->destructor); - kfree_skb(skb); - skb = skb_new; - } - - /* total number of fragments in the SKB */ - nr_frags = skb_shinfo(skb)->nr_frags; - - /* calculate the required number of TxBDs for this skb */ - if (unlikely(do_tstamp)) - nr_txbds = nr_frags + 2; - else - nr_txbds = nr_frags + 1; - - /* check if there is space to queue this packet */ - if (nr_txbds > tx_queue->num_txbdfree) { - /* no space, stop the queue */ - netif_tx_stop_queue(txq); - dev->stats.tx_fifo_errors++; - return NETDEV_TX_BUSY; - } - - /* Update transmit stats */ - tx_queue->stats.tx_bytes += skb->len; - tx_queue->stats.tx_packets++; - - txbdp = txbdp_start = tx_queue->cur_tx; - lstatus = txbdp->lstatus; - - /* Time stamp insertion requires one additional TxBD */ - if (unlikely(do_tstamp)) - txbdp_tstamp = txbdp = next_txbd(txbdp, base, - tx_queue->tx_ring_size); - - if (nr_frags == 0) { - if (unlikely(do_tstamp)) - txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_LAST | - TXBD_INTERRUPT); - else - lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); - } else { - /* Place the fragment addresses and lengths into the TxBDs */ - for (i = 0; i < nr_frags; i++) { - /* Point at the next BD, wrapping as needed */ - txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); - - length = skb_shinfo(skb)->frags[i].size; - - lstatus = txbdp->lstatus | length | - BD_LFLAG(TXBD_READY); - - /* Handle the last BD specially */ - if (i == nr_frags - 1) - lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); - - bufaddr = skb_frag_dma_map(&priv->ofdev->dev, - &skb_shinfo(skb)->frags[i], - 0, - length, - DMA_TO_DEVICE); - - /* set the TxBD length and buffer pointer */ - txbdp->bufPtr = bufaddr; - txbdp->lstatus = lstatus; - } - - lstatus = txbdp_start->lstatus; - } - - /* Add TxPAL between FCB and frame if required */ - if (unlikely(do_tstamp)) { - skb_push(skb, GMAC_TXPAL_LEN); - memset(skb->data, 0, GMAC_TXPAL_LEN); - } - - /* Set up checksumming */ - if (CHECKSUM_PARTIAL == skb->ip_summed) { - fcb = gfar_add_fcb(skb); - /* as specified by errata */ - if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12) - && ((unsigned long)fcb % 0x20) > 0x18)) { - __skb_pull(skb, GMAC_FCB_LEN); - skb_checksum_help(skb); - } else { - lstatus |= BD_LFLAG(TXBD_TOE); - gfar_tx_checksum(skb, fcb, fcb_length); - } - } - - if (vlan_tx_tag_present(skb)) { - if (unlikely(NULL == fcb)) { - fcb = gfar_add_fcb(skb); - lstatus |= BD_LFLAG(TXBD_TOE); - } - - gfar_tx_vlan(skb, fcb); - } - - /* Setup tx hardware time stamping if requested */ - if (unlikely(do_tstamp)) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - if (fcb == NULL) - fcb = gfar_add_fcb(skb); - fcb->ptp = 1; - lstatus |= BD_LFLAG(TXBD_TOE); - } - - txbdp_start->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data, - skb_headlen(skb), DMA_TO_DEVICE); - - /* - * If time stamping is requested one additional TxBD must be set up. The - * first TxBD points to the FCB and must have a data length of - * GMAC_FCB_LEN. The second TxBD points to the actual frame data with - * the full frame length. - */ - if (unlikely(do_tstamp)) { - txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length; - txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) | - (skb_headlen(skb) - fcb_length); - lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; - } else { - lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); - } - - netdev_tx_sent_queue(txq, skb->len); - - /* - * We can work in parallel with gfar_clean_tx_ring(), except - * when modifying num_txbdfree. Note that we didn't grab the lock - * when we were reading the num_txbdfree and checking for available - * space, that's because outside of this function it can only grow, - * and once we've got needed space, it cannot suddenly disappear. - * - * The lock also protects us from gfar_error(), which can modify - * regs->tstat and thus retrigger the transfers, which is why we - * also must grab the lock before setting ready bit for the first - * to be transmitted BD. - */ - spin_lock_irqsave(&tx_queue->txlock, flags); - - /* - * The powerpc-specific eieio() is used, as wmb() has too strong - * semantics (it requires synchronization between cacheable and - * uncacheable mappings, which eieio doesn't provide and which we - * don't need), thus requiring a more expensive sync instruction. At - * some point, the set of architecture-independent barrier functions - * should be expanded to include weaker barriers. - */ - eieio(); - - txbdp_start->lstatus = lstatus; - - eieio(); /* force lstatus write before tx_skbuff */ - - tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb; - - /* Update the current skb pointer to the next entry we will use - * (wrapping if necessary) */ - tx_queue->skb_curtx = (tx_queue->skb_curtx + 1) & - TX_RING_MOD_MASK(tx_queue->tx_ring_size); - - tx_queue->cur_tx = next_txbd(txbdp, base, tx_queue->tx_ring_size); - - /* reduce TxBD free count */ - tx_queue->num_txbdfree -= (nr_txbds); - - /* If the next BD still needs to be cleaned up, then the bds - are full. We need to tell the kernel to stop sending us stuff. */ - if (!tx_queue->num_txbdfree) { - netif_tx_stop_queue(txq); - - dev->stats.tx_fifo_errors++; - } - - /* Tell the DMA to go go go */ - gfar_write(®s->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex); - - /* Unlock priv */ - spin_unlock_irqrestore(&tx_queue->txlock, flags); - - return NETDEV_TX_OK; -} - -/* Stops the kernel queue, and halts the controller */ -static int gfar_close(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - - disable_napi(priv); - - cancel_work_sync(&priv->reset_task); - stop_gfar(dev); - - /* Disconnect from the PHY */ - phy_disconnect(priv->phydev); - priv->phydev = NULL; - - netif_tx_stop_all_queues(dev); - - return 0; -} - -/* Changes the mac address if the controller is not running. */ -static int gfar_set_mac_address(struct net_device *dev) -{ - gfar_set_mac_for_addr(dev, 0, dev->dev_addr); - - return 0; -} - -/* Check if rx parser should be activated */ -void gfar_check_rx_parser_mode(struct gfar_private *priv) -{ - struct gfar __iomem *regs; - u32 tempval; - - regs = priv->gfargrp[0].regs; - - tempval = gfar_read(®s->rctrl); - /* If parse is no longer required, then disable parser */ - if (tempval & RCTRL_REQ_PARSER) - tempval |= RCTRL_PRSDEP_INIT; - else - tempval &= ~RCTRL_PRSDEP_INIT; - gfar_write(®s->rctrl, tempval); -} - -/* Enables and disables VLAN insertion/extraction */ -void gfar_vlan_mode(struct net_device *dev, netdev_features_t features) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = NULL; - unsigned long flags; - u32 tempval; - - regs = priv->gfargrp[0].regs; - local_irq_save(flags); - lock_rx_qs(priv); - - if (features & NETIF_F_HW_VLAN_TX) { - /* Enable VLAN tag insertion */ - tempval = gfar_read(®s->tctrl); - tempval |= TCTRL_VLINS; - gfar_write(®s->tctrl, tempval); - } else { - /* Disable VLAN tag insertion */ - tempval = gfar_read(®s->tctrl); - tempval &= ~TCTRL_VLINS; - gfar_write(®s->tctrl, tempval); - } - - if (features & NETIF_F_HW_VLAN_RX) { - /* Enable VLAN tag extraction */ - tempval = gfar_read(®s->rctrl); - tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT); - gfar_write(®s->rctrl, tempval); - } else { - /* Disable VLAN tag extraction */ - tempval = gfar_read(®s->rctrl); - tempval &= ~RCTRL_VLEX; - gfar_write(®s->rctrl, tempval); - - gfar_check_rx_parser_mode(priv); - } - - gfar_change_mtu(dev, dev->mtu); - - unlock_rx_qs(priv); - local_irq_restore(flags); -} - -static int gfar_change_mtu(struct net_device *dev, int new_mtu) -{ - int tempsize, tempval; - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - int oldsize = priv->rx_buffer_size; - int frame_size = new_mtu + ETH_HLEN; - - if (gfar_is_vlan_on(priv)) - frame_size += VLAN_HLEN; - - if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { - netif_err(priv, drv, dev, "Invalid MTU setting\n"); - return -EINVAL; - } - - if (gfar_uses_fcb(priv)) - frame_size += GMAC_FCB_LEN; - - frame_size += priv->padding; - - tempsize = - (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) + - INCREMENTAL_BUFFER_SIZE; - - /* Only stop and start the controller if it isn't already - * stopped, and we changed something */ - if ((oldsize != tempsize) && (dev->flags & IFF_UP)) - stop_gfar(dev); - - priv->rx_buffer_size = tempsize; - - dev->mtu = new_mtu; - - gfar_write(®s->mrblr, priv->rx_buffer_size); - gfar_write(®s->maxfrm, priv->rx_buffer_size); - - /* If the mtu is larger than the max size for standard - * ethernet frames (ie, a jumbo frame), then set maccfg2 - * to allow huge frames, and to check the length */ - tempval = gfar_read(®s->maccfg2); - - if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE || - gfar_has_errata(priv, GFAR_ERRATA_74)) - tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); - else - tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); - - gfar_write(®s->maccfg2, tempval); - - if ((oldsize != tempsize) && (dev->flags & IFF_UP)) - startup_gfar(dev); - - return 0; -} - -/* gfar_reset_task gets scheduled when a packet has not been - * transmitted after a set amount of time. - * For now, assume that clearing out all the structures, and - * starting over will fix the problem. - */ -static void gfar_reset_task(struct work_struct *work) -{ - struct gfar_private *priv = container_of(work, struct gfar_private, - reset_task); - struct net_device *dev = priv->ndev; - - if (dev->flags & IFF_UP) { - netif_tx_stop_all_queues(dev); - stop_gfar(dev); - startup_gfar(dev); - netif_tx_start_all_queues(dev); - } - - netif_tx_schedule_all(dev); -} - -static void gfar_timeout(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - - dev->stats.tx_errors++; - schedule_work(&priv->reset_task); -} - -static void gfar_align_skb(struct sk_buff *skb) -{ - /* We need the data buffer to be aligned properly. We will reserve - * as many bytes as needed to align the data properly - */ - skb_reserve(skb, RXBUF_ALIGNMENT - - (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1))); -} - -/* Interrupt Handler for Transmit complete */ -static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) -{ - struct net_device *dev = tx_queue->dev; - struct netdev_queue *txq; - struct gfar_private *priv = netdev_priv(dev); - struct gfar_priv_rx_q *rx_queue = NULL; - struct txbd8 *bdp, *next = NULL; - struct txbd8 *lbdp = NULL; - struct txbd8 *base = tx_queue->tx_bd_base; - struct sk_buff *skb; - int skb_dirtytx; - int tx_ring_size = tx_queue->tx_ring_size; - int frags = 0, nr_txbds = 0; - int i; - int howmany = 0; - int tqi = tx_queue->qindex; - unsigned int bytes_sent = 0; - u32 lstatus; - size_t buflen; - - rx_queue = priv->rx_queue[tqi]; - txq = netdev_get_tx_queue(dev, tqi); - bdp = tx_queue->dirty_tx; - skb_dirtytx = tx_queue->skb_dirtytx; - - while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) { - unsigned long flags; - - frags = skb_shinfo(skb)->nr_frags; - - /* - * When time stamping, one additional TxBD must be freed. - * Also, we need to dma_unmap_single() the TxPAL. - */ - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) - nr_txbds = frags + 2; - else - nr_txbds = frags + 1; - - lbdp = skip_txbd(bdp, nr_txbds - 1, base, tx_ring_size); - - lstatus = lbdp->lstatus; - - /* Only clean completed frames */ - if ((lstatus & BD_LFLAG(TXBD_READY)) && - (lstatus & BD_LENGTH_MASK)) - break; - - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { - next = next_txbd(bdp, base, tx_ring_size); - buflen = next->length + GMAC_FCB_LEN + GMAC_TXPAL_LEN; - } else - buflen = bdp->length; - - dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, - buflen, DMA_TO_DEVICE); - - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { - struct skb_shared_hwtstamps shhwtstamps; - u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7); - memset(&shhwtstamps, 0, sizeof(shhwtstamps)); - shhwtstamps.hwtstamp = ns_to_ktime(*ns); - skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN); - skb_tstamp_tx(skb, &shhwtstamps); - bdp->lstatus &= BD_LFLAG(TXBD_WRAP); - bdp = next; - } - - bdp->lstatus &= BD_LFLAG(TXBD_WRAP); - bdp = next_txbd(bdp, base, tx_ring_size); - - for (i = 0; i < frags; i++) { - dma_unmap_page(&priv->ofdev->dev, - bdp->bufPtr, - bdp->length, - DMA_TO_DEVICE); - bdp->lstatus &= BD_LFLAG(TXBD_WRAP); - bdp = next_txbd(bdp, base, tx_ring_size); - } - - bytes_sent += skb->len; - - /* - * If there's room in the queue (limit it to rx_buffer_size) - * we add this skb back into the pool, if it's the right size - */ - if (skb_queue_len(&priv->rx_recycle) < rx_queue->rx_ring_size && - skb_recycle_check(skb, priv->rx_buffer_size + - RXBUF_ALIGNMENT)) { - gfar_align_skb(skb); - skb_queue_head(&priv->rx_recycle, skb); - } else - dev_kfree_skb_any(skb); - - tx_queue->tx_skbuff[skb_dirtytx] = NULL; - - skb_dirtytx = (skb_dirtytx + 1) & - TX_RING_MOD_MASK(tx_ring_size); - - howmany++; - spin_lock_irqsave(&tx_queue->txlock, flags); - tx_queue->num_txbdfree += nr_txbds; - spin_unlock_irqrestore(&tx_queue->txlock, flags); - } - - /* If we freed a buffer, we can restart transmission, if necessary */ - if (netif_tx_queue_stopped(txq) && tx_queue->num_txbdfree) - netif_wake_subqueue(dev, tqi); - - /* Update dirty indicators */ - tx_queue->skb_dirtytx = skb_dirtytx; - tx_queue->dirty_tx = bdp; - - netdev_tx_completed_queue(txq, howmany, bytes_sent); - - return howmany; -} - -static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp) -{ - unsigned long flags; - - spin_lock_irqsave(&gfargrp->grplock, flags); - if (napi_schedule_prep(&gfargrp->napi)) { - gfar_write(&gfargrp->regs->imask, IMASK_RTX_DISABLED); - __napi_schedule(&gfargrp->napi); - } else { - /* - * Clear IEVENT, so interrupts aren't called again - * because of the packets that have already arrived. - */ - gfar_write(&gfargrp->regs->ievent, IEVENT_RTX_MASK); - } - spin_unlock_irqrestore(&gfargrp->grplock, flags); - -} - -/* Interrupt Handler for Transmit complete */ -static irqreturn_t gfar_transmit(int irq, void *grp_id) -{ - gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); - return IRQ_HANDLED; -} - -static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, - struct sk_buff *skb) -{ - struct net_device *dev = rx_queue->dev; - struct gfar_private *priv = netdev_priv(dev); - dma_addr_t buf; - - buf = dma_map_single(&priv->ofdev->dev, skb->data, - priv->rx_buffer_size, DMA_FROM_DEVICE); - gfar_init_rxbdp(rx_queue, bdp, buf); -} - -static struct sk_buff * gfar_alloc_skb(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct sk_buff *skb = NULL; - - skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT); - if (!skb) - return NULL; - - gfar_align_skb(skb); - - return skb; -} - -struct sk_buff * gfar_new_skb(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct sk_buff *skb = NULL; - - skb = skb_dequeue(&priv->rx_recycle); - if (!skb) - skb = gfar_alloc_skb(dev); - - return skb; -} - -static inline void count_errors(unsigned short status, struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; - struct gfar_extra_stats *estats = &priv->extra_stats; - - /* If the packet was truncated, none of the other errors - * matter */ - if (status & RXBD_TRUNCATED) { - stats->rx_length_errors++; - - estats->rx_trunc++; - - return; - } - /* Count the errors, if there were any */ - if (status & (RXBD_LARGE | RXBD_SHORT)) { - stats->rx_length_errors++; - - if (status & RXBD_LARGE) - estats->rx_large++; - else - estats->rx_short++; - } - if (status & RXBD_NONOCTET) { - stats->rx_frame_errors++; - estats->rx_nonoctet++; - } - if (status & RXBD_CRCERR) { - estats->rx_crcerr++; - stats->rx_crc_errors++; - } - if (status & RXBD_OVERRUN) { - estats->rx_overrun++; - stats->rx_crc_errors++; - } -} - -irqreturn_t gfar_receive(int irq, void *grp_id) -{ - gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); - return IRQ_HANDLED; -} - -static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) -{ - /* If valid headers were found, and valid sums - * were verified, then we tell the kernel that no - * checksumming is necessary. Otherwise, it is */ - if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb_checksum_none_assert(skb); -} - - -/* gfar_process_frame() -- handle one incoming packet if skb - * isn't NULL. */ -static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, - int amount_pull) -{ - struct gfar_private *priv = netdev_priv(dev); - struct rxfcb *fcb = NULL; - - int ret; - - /* fcb is at the beginning if exists */ - fcb = (struct rxfcb *)skb->data; - - /* Remove the FCB from the skb */ - /* Remove the padded bytes, if there are any */ - if (amount_pull) { - skb_record_rx_queue(skb, fcb->rq); - skb_pull(skb, amount_pull); - } - - /* Get receive timestamp from the skb */ - if (priv->hwts_rx_en) { - struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); - u64 *ns = (u64 *) skb->data; - memset(shhwtstamps, 0, sizeof(*shhwtstamps)); - shhwtstamps->hwtstamp = ns_to_ktime(*ns); - } - - if (priv->padding) - skb_pull(skb, priv->padding); - - if (dev->features & NETIF_F_RXCSUM) - gfar_rx_checksum(skb, fcb); - - /* Tell the skb what kind of packet this is */ - skb->protocol = eth_type_trans(skb, dev); - - /* - * There's need to check for NETIF_F_HW_VLAN_RX here. - * Even if vlan rx accel is disabled, on some chips - * RXFCB_VLN is pseudo randomly set. - */ - if (dev->features & NETIF_F_HW_VLAN_RX && - fcb->flags & RXFCB_VLN) - __vlan_hwaccel_put_tag(skb, fcb->vlctl); - - /* Send the packet up the stack */ - ret = netif_receive_skb(skb); - - if (NET_RX_DROP == ret) - priv->extra_stats.kernel_dropped++; - - return 0; -} - -/* gfar_clean_rx_ring() -- Processes each frame in the rx ring - * until the budget/quota has been reached. Returns the number - * of frames handled - */ -int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) -{ - struct net_device *dev = rx_queue->dev; - struct rxbd8 *bdp, *base; - struct sk_buff *skb; - int pkt_len; - int amount_pull; - int howmany = 0; - struct gfar_private *priv = netdev_priv(dev); - - /* Get the first full descriptor */ - bdp = rx_queue->cur_rx; - base = rx_queue->rx_bd_base; - - amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0); - - while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) { - struct sk_buff *newskb; - rmb(); - - /* Add another skb for the future */ - newskb = gfar_new_skb(dev); - - skb = rx_queue->rx_skbuff[rx_queue->skb_currx]; - - dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, - priv->rx_buffer_size, DMA_FROM_DEVICE); - - if (unlikely(!(bdp->status & RXBD_ERR) && - bdp->length > priv->rx_buffer_size)) - bdp->status = RXBD_LARGE; - - /* We drop the frame if we failed to allocate a new buffer */ - if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || - bdp->status & RXBD_ERR)) { - count_errors(bdp->status, dev); - - if (unlikely(!newskb)) - newskb = skb; - else if (skb) - skb_queue_head(&priv->rx_recycle, skb); - } else { - /* Increment the number of packets */ - rx_queue->stats.rx_packets++; - howmany++; - - if (likely(skb)) { - pkt_len = bdp->length - ETH_FCS_LEN; - /* Remove the FCS from the packet length */ - skb_put(skb, pkt_len); - rx_queue->stats.rx_bytes += pkt_len; - skb_record_rx_queue(skb, rx_queue->qindex); - gfar_process_frame(dev, skb, amount_pull); - - } else { - netif_warn(priv, rx_err, dev, "Missing skb!\n"); - rx_queue->stats.rx_dropped++; - priv->extra_stats.rx_skbmissing++; - } - - } - - rx_queue->rx_skbuff[rx_queue->skb_currx] = newskb; - - /* Setup the new bdp */ - gfar_new_rxbdp(rx_queue, bdp, newskb); - - /* Update to the next pointer */ - bdp = next_bd(bdp, base, rx_queue->rx_ring_size); - - /* update to point at the next skb */ - rx_queue->skb_currx = - (rx_queue->skb_currx + 1) & - RX_RING_MOD_MASK(rx_queue->rx_ring_size); - } - - /* Update the current rxbd pointer to be the next one */ - rx_queue->cur_rx = bdp; - - return howmany; -} - -static int gfar_poll(struct napi_struct *napi, int budget) -{ - struct gfar_priv_grp *gfargrp = container_of(napi, - struct gfar_priv_grp, napi); - struct gfar_private *priv = gfargrp->priv; - struct gfar __iomem *regs = gfargrp->regs; - struct gfar_priv_tx_q *tx_queue = NULL; - struct gfar_priv_rx_q *rx_queue = NULL; - int rx_cleaned = 0, budget_per_queue = 0, rx_cleaned_per_queue = 0; - int tx_cleaned = 0, i, left_over_budget = budget; - unsigned long serviced_queues = 0; - int num_queues = 0; - - num_queues = gfargrp->num_rx_queues; - budget_per_queue = budget/num_queues; - - /* Clear IEVENT, so interrupts aren't called again - * because of the packets that have already arrived */ - gfar_write(®s->ievent, IEVENT_RTX_MASK); - - while (num_queues && left_over_budget) { - - budget_per_queue = left_over_budget/num_queues; - left_over_budget = 0; - - for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { - if (test_bit(i, &serviced_queues)) - continue; - rx_queue = priv->rx_queue[i]; - tx_queue = priv->tx_queue[rx_queue->qindex]; - - tx_cleaned += gfar_clean_tx_ring(tx_queue); - rx_cleaned_per_queue = gfar_clean_rx_ring(rx_queue, - budget_per_queue); - rx_cleaned += rx_cleaned_per_queue; - if(rx_cleaned_per_queue < budget_per_queue) { - left_over_budget = left_over_budget + - (budget_per_queue - rx_cleaned_per_queue); - set_bit(i, &serviced_queues); - num_queues--; - } - } - } - - if (tx_cleaned) - return budget; - - if (rx_cleaned < budget) { - napi_complete(napi); - - /* Clear the halt bit in RSTAT */ - gfar_write(®s->rstat, gfargrp->rstat); - - gfar_write(®s->imask, IMASK_DEFAULT); - - /* If we are coalescing interrupts, update the timer */ - /* Otherwise, clear it */ - gfar_configure_coalescing(priv, - gfargrp->rx_bit_map, gfargrp->tx_bit_map); - } - - return rx_cleaned; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void gfar_netpoll(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - int i = 0; - - /* If the device has multiple interrupts, run tx/rx */ - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - for (i = 0; i < priv->num_grps; i++) { - disable_irq(priv->gfargrp[i].interruptTransmit); - disable_irq(priv->gfargrp[i].interruptReceive); - disable_irq(priv->gfargrp[i].interruptError); - gfar_interrupt(priv->gfargrp[i].interruptTransmit, - &priv->gfargrp[i]); - enable_irq(priv->gfargrp[i].interruptError); - enable_irq(priv->gfargrp[i].interruptReceive); - enable_irq(priv->gfargrp[i].interruptTransmit); - } - } else { - for (i = 0; i < priv->num_grps; i++) { - disable_irq(priv->gfargrp[i].interruptTransmit); - gfar_interrupt(priv->gfargrp[i].interruptTransmit, - &priv->gfargrp[i]); - enable_irq(priv->gfargrp[i].interruptTransmit); - } - } -} -#endif - -/* The interrupt handler for devices with one interrupt */ -static irqreturn_t gfar_interrupt(int irq, void *grp_id) -{ - struct gfar_priv_grp *gfargrp = grp_id; - - /* Save ievent for future reference */ - u32 events = gfar_read(&gfargrp->regs->ievent); - - /* Check for reception */ - if (events & IEVENT_RX_MASK) - gfar_receive(irq, grp_id); - - /* Check for transmit completion */ - if (events & IEVENT_TX_MASK) - gfar_transmit(irq, grp_id); - - /* Check for errors */ - if (events & IEVENT_ERR_MASK) - gfar_error(irq, grp_id); - - return IRQ_HANDLED; -} - -/* Called every time the controller might need to be made - * aware of new link state. The PHY code conveys this - * information through variables in the phydev structure, and this - * function converts those variables into the appropriate - * register values, and can bring down the device if needed. - */ -static void adjust_link(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned long flags; - struct phy_device *phydev = priv->phydev; - int new_state = 0; - - local_irq_save(flags); - lock_tx_qs(priv); - - if (phydev->link) { - u32 tempval = gfar_read(®s->maccfg2); - u32 ecntrl = gfar_read(®s->ecntrl); - - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (phydev->duplex != priv->oldduplex) { - new_state = 1; - if (!(phydev->duplex)) - tempval &= ~(MACCFG2_FULL_DUPLEX); - else - tempval |= MACCFG2_FULL_DUPLEX; - - priv->oldduplex = phydev->duplex; - } - - if (phydev->speed != priv->oldspeed) { - new_state = 1; - switch (phydev->speed) { - case 1000: - tempval = - ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); - - ecntrl &= ~(ECNTRL_R100); - break; - case 100: - case 10: - tempval = - ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); - - /* Reduced mode distinguishes - * between 10 and 100 */ - if (phydev->speed == SPEED_100) - ecntrl |= ECNTRL_R100; - else - ecntrl &= ~(ECNTRL_R100); - break; - default: - netif_warn(priv, link, dev, - "Ack! Speed (%d) is not 10/100/1000!\n", - phydev->speed); - break; - } - - priv->oldspeed = phydev->speed; - } - - gfar_write(®s->maccfg2, tempval); - gfar_write(®s->ecntrl, ecntrl); - - if (!priv->oldlink) { - new_state = 1; - priv->oldlink = 1; - } - } else if (priv->oldlink) { - new_state = 1; - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - } - - if (new_state && netif_msg_link(priv)) - phy_print_status(phydev); - unlock_tx_qs(priv); - local_irq_restore(flags); -} - -/* Update the hash table based on the current list of multicast - * addresses we subscribe to. Also, change the promiscuity of - * the device based on the flags (this function is called - * whenever dev->flags is changed */ -static void gfar_set_multi(struct net_device *dev) -{ - struct netdev_hw_addr *ha; - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 tempval; - - if (dev->flags & IFF_PROMISC) { - /* Set RCTRL to PROM */ - tempval = gfar_read(®s->rctrl); - tempval |= RCTRL_PROM; - gfar_write(®s->rctrl, tempval); - } else { - /* Set RCTRL to not PROM */ - tempval = gfar_read(®s->rctrl); - tempval &= ~(RCTRL_PROM); - gfar_write(®s->rctrl, tempval); - } - - if (dev->flags & IFF_ALLMULTI) { - /* Set the hash to rx all multicast frames */ - gfar_write(®s->igaddr0, 0xffffffff); - gfar_write(®s->igaddr1, 0xffffffff); - gfar_write(®s->igaddr2, 0xffffffff); - gfar_write(®s->igaddr3, 0xffffffff); - gfar_write(®s->igaddr4, 0xffffffff); - gfar_write(®s->igaddr5, 0xffffffff); - gfar_write(®s->igaddr6, 0xffffffff); - gfar_write(®s->igaddr7, 0xffffffff); - gfar_write(®s->gaddr0, 0xffffffff); - gfar_write(®s->gaddr1, 0xffffffff); - gfar_write(®s->gaddr2, 0xffffffff); - gfar_write(®s->gaddr3, 0xffffffff); - gfar_write(®s->gaddr4, 0xffffffff); - gfar_write(®s->gaddr5, 0xffffffff); - gfar_write(®s->gaddr6, 0xffffffff); - gfar_write(®s->gaddr7, 0xffffffff); - } else { - int em_num; - int idx; - - /* zero out the hash */ - gfar_write(®s->igaddr0, 0x0); - gfar_write(®s->igaddr1, 0x0); - gfar_write(®s->igaddr2, 0x0); - gfar_write(®s->igaddr3, 0x0); - gfar_write(®s->igaddr4, 0x0); - gfar_write(®s->igaddr5, 0x0); - gfar_write(®s->igaddr6, 0x0); - gfar_write(®s->igaddr7, 0x0); - gfar_write(®s->gaddr0, 0x0); - gfar_write(®s->gaddr1, 0x0); - gfar_write(®s->gaddr2, 0x0); - gfar_write(®s->gaddr3, 0x0); - gfar_write(®s->gaddr4, 0x0); - gfar_write(®s->gaddr5, 0x0); - gfar_write(®s->gaddr6, 0x0); - gfar_write(®s->gaddr7, 0x0); - - /* If we have extended hash tables, we need to - * clear the exact match registers to prepare for - * setting them */ - if (priv->extended_hash) { - em_num = GFAR_EM_NUM + 1; - gfar_clear_exact_match(dev); - idx = 1; - } else { - idx = 0; - em_num = 0; - } - - if (netdev_mc_empty(dev)) - return; - - /* Parse the list, and set the appropriate bits */ - netdev_for_each_mc_addr(ha, dev) { - if (idx < em_num) { - gfar_set_mac_for_addr(dev, idx, ha->addr); - idx++; - } else - gfar_set_hash_for_addr(dev, ha->addr); - } - } -} - - -/* Clears each of the exact match registers to zero, so they - * don't interfere with normal reception */ -static void gfar_clear_exact_match(struct net_device *dev) -{ - int idx; - static const u8 zero_arr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - - for(idx = 1;idx < GFAR_EM_NUM + 1;idx++) - gfar_set_mac_for_addr(dev, idx, zero_arr); -} - -/* Set the appropriate hash bit for the given addr */ -/* The algorithm works like so: - * 1) Take the Destination Address (ie the multicast address), and - * do a CRC on it (little endian), and reverse the bits of the - * result. - * 2) Use the 8 most significant bits as a hash into a 256-entry - * table. The table is controlled through 8 32-bit registers: - * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is - * gaddr7. This means that the 3 most significant bits in the - * hash index which gaddr register to use, and the 5 other bits - * indicate which bit (assuming an IBM numbering scheme, which - * for PowerPC (tm) is usually the case) in the register holds - * the entry. */ -static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) -{ - u32 tempval; - struct gfar_private *priv = netdev_priv(dev); - u32 result = ether_crc(ETH_ALEN, addr); - int width = priv->hash_width; - u8 whichbit = (result >> (32 - width)) & 0x1f; - u8 whichreg = result >> (32 - width + 5); - u32 value = (1 << (31-whichbit)); - - tempval = gfar_read(priv->hash_regs[whichreg]); - tempval |= value; - gfar_write(priv->hash_regs[whichreg], tempval); -} - - -/* There are multiple MAC Address register pairs on some controllers - * This function sets the numth pair to a given address - */ -static void gfar_set_mac_for_addr(struct net_device *dev, int num, - const u8 *addr) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - int idx; - char tmpbuf[ETH_ALEN]; - u32 tempval; - u32 __iomem *macptr = ®s->macstnaddr1; - - macptr += num*2; - - /* Now copy it into the mac registers backwards, cuz */ - /* little endian is silly */ - for (idx = 0; idx < ETH_ALEN; idx++) - tmpbuf[ETH_ALEN - 1 - idx] = addr[idx]; - - gfar_write(macptr, *((u32 *) (tmpbuf))); - - tempval = *((u32 *) (tmpbuf + 4)); - - gfar_write(macptr+1, tempval); -} - -/* GFAR error interrupt handler */ -static irqreturn_t gfar_error(int irq, void *grp_id) -{ - struct gfar_priv_grp *gfargrp = grp_id; - struct gfar __iomem *regs = gfargrp->regs; - struct gfar_private *priv= gfargrp->priv; - struct net_device *dev = priv->ndev; - - /* Save ievent for future reference */ - u32 events = gfar_read(®s->ievent); - - /* Clear IEVENT */ - gfar_write(®s->ievent, events & IEVENT_ERR_MASK); - - /* Magic Packet is not an error. */ - if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && - (events & IEVENT_MAG)) - events &= ~IEVENT_MAG; - - /* Hmm... */ - if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv)) - netdev_dbg(dev, "error interrupt (ievent=0x%08x imask=0x%08x)\n", - events, gfar_read(®s->imask)); - - /* Update the error counters */ - if (events & IEVENT_TXE) { - dev->stats.tx_errors++; - - if (events & IEVENT_LC) - dev->stats.tx_window_errors++; - if (events & IEVENT_CRL) - dev->stats.tx_aborted_errors++; - if (events & IEVENT_XFUN) { - unsigned long flags; - - netif_dbg(priv, tx_err, dev, - "TX FIFO underrun, packet dropped\n"); - dev->stats.tx_dropped++; - priv->extra_stats.tx_underrun++; - - local_irq_save(flags); - lock_tx_qs(priv); - - /* Reactivate the Tx Queues */ - gfar_write(®s->tstat, gfargrp->tstat); - - unlock_tx_qs(priv); - local_irq_restore(flags); - } - netif_dbg(priv, tx_err, dev, "Transmit Error\n"); - } - if (events & IEVENT_BSY) { - dev->stats.rx_errors++; - priv->extra_stats.rx_bsy++; - - gfar_receive(irq, grp_id); - - netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n", - gfar_read(®s->rstat)); - } - if (events & IEVENT_BABR) { - dev->stats.rx_errors++; - priv->extra_stats.rx_babr++; - - netif_dbg(priv, rx_err, dev, "babbling RX error\n"); - } - if (events & IEVENT_EBERR) { - priv->extra_stats.eberr++; - netif_dbg(priv, rx_err, dev, "bus error\n"); - } - if (events & IEVENT_RXC) - netif_dbg(priv, rx_status, dev, "control frame\n"); - - if (events & IEVENT_BABT) { - priv->extra_stats.tx_babt++; - netif_dbg(priv, tx_err, dev, "babbling TX error\n"); - } - return IRQ_HANDLED; -} - -static struct of_device_id gfar_match[] = -{ - { - .type = "network", - .compatible = "gianfar", - }, - { - .compatible = "fsl,etsec2", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, gfar_match); - -/* Structure for a device driver */ -static struct platform_driver gfar_driver = { - .driver = { - .name = "fsl-gianfar", - .owner = THIS_MODULE, - .pm = GFAR_PM_OPS, - .of_match_table = gfar_match, - }, - .probe = gfar_probe, - .remove = gfar_remove, -}; - -module_platform_driver(gfar_driver); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar.h deleted file mode 100644 index 4c9f8d48..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar.h +++ /dev/null @@ -1,1213 +0,0 @@ -/* - * drivers/net/ethernet/freescale/gianfar.h - * - * Gianfar Ethernet Driver - * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560 - * Based on 8260_io/fcc_enet.c - * - * Author: Andy Fleming - * Maintainer: Kumar Gala - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> - * - * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. - * - * 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. - * - * Still left to do: - * -Add support for module parameters - * -Add patch for ethtool phys id - */ -#ifndef __GIANFAR_H -#define __GIANFAR_H - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/mii.h> -#include <linux/phy.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <linux/module.h> -#include <linux/crc32.h> -#include <linux/workqueue.h> -#include <linux/ethtool.h> - -struct ethtool_flow_spec_container { - struct ethtool_rx_flow_spec fs; - struct list_head list; -}; - -struct ethtool_rx_list { - struct list_head list; - unsigned int count; -}; - -/* The maximum number of packets to be handled in one call of gfar_poll */ -#define GFAR_DEV_WEIGHT 64 - -/* Length for FCB */ -#define GMAC_FCB_LEN 8 - -/* Length for TxPAL */ -#define GMAC_TXPAL_LEN 16 - -/* Default padding amount */ -#define DEFAULT_PADDING 2 - -/* Number of bytes to align the rx bufs to */ -#define RXBUF_ALIGNMENT 64 - -/* The number of bytes which composes a unit for the purpose of - * allocating data buffers. ie-for any given MTU, the data buffer - * will be the next highest multiple of 512 bytes. */ -#define INCREMENTAL_BUFFER_SIZE 512 - -#define PHY_INIT_TIMEOUT 100000 - -#define DRV_NAME "gfar-enet" -extern const char gfar_driver_version[]; - -/* MAXIMUM NUMBER OF QUEUES SUPPORTED */ -#define MAX_TX_QS 0x8 -#define MAX_RX_QS 0x8 - -/* MAXIMUM NUMBER OF GROUPS SUPPORTED */ -#define MAXGROUPS 0x2 - -/* These need to be powers of 2 for this driver */ -#define DEFAULT_TX_RING_SIZE 256 -#define DEFAULT_RX_RING_SIZE 256 - -#define GFAR_RX_MAX_RING_SIZE 256 -#define GFAR_TX_MAX_RING_SIZE 256 - -#define GFAR_MAX_FIFO_THRESHOLD 511 -#define GFAR_MAX_FIFO_STARVE 511 -#define GFAR_MAX_FIFO_STARVE_OFF 511 - -#define DEFAULT_RX_BUFFER_SIZE 1536 -#define TX_RING_MOD_MASK(size) (size-1) -#define RX_RING_MOD_MASK(size) (size-1) -#define JUMBO_BUFFER_SIZE 9728 -#define JUMBO_FRAME_SIZE 9600 - -#define DEFAULT_FIFO_TX_THR 0x100 -#define DEFAULT_FIFO_TX_STARVE 0x40 -#define DEFAULT_FIFO_TX_STARVE_OFF 0x80 -#define DEFAULT_BD_STASH 1 -#define DEFAULT_STASH_LENGTH 96 -#define DEFAULT_STASH_INDEX 0 - -/* The number of Exact Match registers */ -#define GFAR_EM_NUM 15 - -/* Latency of interface clock in nanoseconds */ -/* Interface clock latency , in this case, means the - * time described by a value of 1 in the interrupt - * coalescing registers' time fields. Since those fields - * refer to the time it takes for 64 clocks to pass, the - * latencies are as such: - * GBIT = 125MHz => 8ns/clock => 8*64 ns / tick - * 100 = 25 MHz => 40ns/clock => 40*64 ns / tick - * 10 = 2.5 MHz => 400ns/clock => 400*64 ns / tick - */ -#define GFAR_GBIT_TIME 512 -#define GFAR_100_TIME 2560 -#define GFAR_10_TIME 25600 - -#define DEFAULT_TX_COALESCE 1 -#define DEFAULT_TXCOUNT 16 -#define DEFAULT_TXTIME 21 - -#define DEFAULT_RXTIME 21 - -#define DEFAULT_RX_COALESCE 0 -#define DEFAULT_RXCOUNT 0 - -#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \ - | SUPPORTED_10baseT_Full \ - | SUPPORTED_100baseT_Half \ - | SUPPORTED_100baseT_Full \ - | SUPPORTED_Autoneg \ - | SUPPORTED_MII) - -/* TBI register addresses */ -#define MII_TBICON 0x11 - -/* TBICON register bit fields */ -#define TBICON_CLK_SELECT 0x0020 - -/* MAC register bits */ -#define MACCFG1_SOFT_RESET 0x80000000 -#define MACCFG1_RESET_RX_MC 0x00080000 -#define MACCFG1_RESET_TX_MC 0x00040000 -#define MACCFG1_RESET_RX_FUN 0x00020000 -#define MACCFG1_RESET_TX_FUN 0x00010000 -#define MACCFG1_LOOPBACK 0x00000100 -#define MACCFG1_RX_FLOW 0x00000020 -#define MACCFG1_TX_FLOW 0x00000010 -#define MACCFG1_SYNCD_RX_EN 0x00000008 -#define MACCFG1_RX_EN 0x00000004 -#define MACCFG1_SYNCD_TX_EN 0x00000002 -#define MACCFG1_TX_EN 0x00000001 - -#define MACCFG2_INIT_SETTINGS 0x00007205 -#define MACCFG2_FULL_DUPLEX 0x00000001 -#define MACCFG2_IF 0x00000300 -#define MACCFG2_MII 0x00000100 -#define MACCFG2_GMII 0x00000200 -#define MACCFG2_HUGEFRAME 0x00000020 -#define MACCFG2_LENGTHCHECK 0x00000010 -#define MACCFG2_MPEN 0x00000008 - -#define ECNTRL_FIFM 0x00008000 -#define ECNTRL_INIT_SETTINGS 0x00001000 -#define ECNTRL_TBI_MODE 0x00000020 -#define ECNTRL_REDUCED_MODE 0x00000010 -#define ECNTRL_R100 0x00000008 -#define ECNTRL_REDUCED_MII_MODE 0x00000004 -#define ECNTRL_SGMII_MODE 0x00000002 - -#define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE - -#define MINFLR_INIT_SETTINGS 0x00000040 - -/* Tqueue control */ -#define TQUEUE_EN0 0x00008000 -#define TQUEUE_EN1 0x00004000 -#define TQUEUE_EN2 0x00002000 -#define TQUEUE_EN3 0x00001000 -#define TQUEUE_EN4 0x00000800 -#define TQUEUE_EN5 0x00000400 -#define TQUEUE_EN6 0x00000200 -#define TQUEUE_EN7 0x00000100 -#define TQUEUE_EN_ALL 0x0000FF00 - -#define TR03WT_WT0_MASK 0xFF000000 -#define TR03WT_WT1_MASK 0x00FF0000 -#define TR03WT_WT2_MASK 0x0000FF00 -#define TR03WT_WT3_MASK 0x000000FF - -#define TR47WT_WT4_MASK 0xFF000000 -#define TR47WT_WT5_MASK 0x00FF0000 -#define TR47WT_WT6_MASK 0x0000FF00 -#define TR47WT_WT7_MASK 0x000000FF - -/* Rqueue control */ -#define RQUEUE_EX0 0x00800000 -#define RQUEUE_EX1 0x00400000 -#define RQUEUE_EX2 0x00200000 -#define RQUEUE_EX3 0x00100000 -#define RQUEUE_EX4 0x00080000 -#define RQUEUE_EX5 0x00040000 -#define RQUEUE_EX6 0x00020000 -#define RQUEUE_EX7 0x00010000 -#define RQUEUE_EX_ALL 0x00FF0000 - -#define RQUEUE_EN0 0x00000080 -#define RQUEUE_EN1 0x00000040 -#define RQUEUE_EN2 0x00000020 -#define RQUEUE_EN3 0x00000010 -#define RQUEUE_EN4 0x00000008 -#define RQUEUE_EN5 0x00000004 -#define RQUEUE_EN6 0x00000002 -#define RQUEUE_EN7 0x00000001 -#define RQUEUE_EN_ALL 0x000000FF - -/* Init to do tx snooping for buffers and descriptors */ -#define DMACTRL_INIT_SETTINGS 0x000000c3 -#define DMACTRL_GRS 0x00000010 -#define DMACTRL_GTS 0x00000008 - -#define TSTAT_CLEAR_THALT_ALL 0xFF000000 -#define TSTAT_CLEAR_THALT 0x80000000 -#define TSTAT_CLEAR_THALT0 0x80000000 -#define TSTAT_CLEAR_THALT1 0x40000000 -#define TSTAT_CLEAR_THALT2 0x20000000 -#define TSTAT_CLEAR_THALT3 0x10000000 -#define TSTAT_CLEAR_THALT4 0x08000000 -#define TSTAT_CLEAR_THALT5 0x04000000 -#define TSTAT_CLEAR_THALT6 0x02000000 -#define TSTAT_CLEAR_THALT7 0x01000000 - -/* Interrupt coalescing macros */ -#define IC_ICEN 0x80000000 -#define IC_ICFT_MASK 0x1fe00000 -#define IC_ICFT_SHIFT 21 -#define mk_ic_icft(x) \ - (((unsigned int)x << IC_ICFT_SHIFT)&IC_ICFT_MASK) -#define IC_ICTT_MASK 0x0000ffff -#define mk_ic_ictt(x) (x&IC_ICTT_MASK) - -#define mk_ic_value(count, time) (IC_ICEN | \ - mk_ic_icft(count) | \ - mk_ic_ictt(time)) -#define get_icft_value(ic) (((unsigned long)ic & IC_ICFT_MASK) >> \ - IC_ICFT_SHIFT) -#define get_ictt_value(ic) ((unsigned long)ic & IC_ICTT_MASK) - -#define DEFAULT_TXIC mk_ic_value(DEFAULT_TXCOUNT, DEFAULT_TXTIME) -#define DEFAULT_RXIC mk_ic_value(DEFAULT_RXCOUNT, DEFAULT_RXTIME) - -#define skip_bd(bdp, stride, base, ring_size) ({ \ - typeof(bdp) new_bd = (bdp) + (stride); \ - (new_bd >= (base) + (ring_size)) ? (new_bd - (ring_size)) : new_bd; }) - -#define next_bd(bdp, base, ring_size) skip_bd(bdp, 1, base, ring_size) - -#define RCTRL_TS_ENABLE 0x01000000 -#define RCTRL_PAL_MASK 0x001f0000 -#define RCTRL_VLEX 0x00002000 -#define RCTRL_FILREN 0x00001000 -#define RCTRL_GHTX 0x00000400 -#define RCTRL_IPCSEN 0x00000200 -#define RCTRL_TUCSEN 0x00000100 -#define RCTRL_PRSDEP_MASK 0x000000c0 -#define RCTRL_PRSDEP_INIT 0x000000c0 -#define RCTRL_PRSFM 0x00000020 -#define RCTRL_PROM 0x00000008 -#define RCTRL_EMEN 0x00000002 -#define RCTRL_REQ_PARSER (RCTRL_VLEX | RCTRL_IPCSEN | \ - RCTRL_TUCSEN | RCTRL_FILREN) -#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN | RCTRL_TUCSEN | \ - RCTRL_PRSDEP_INIT) -#define RCTRL_EXTHASH (RCTRL_GHTX) -#define RCTRL_VLAN (RCTRL_PRSDEP_INIT) -#define RCTRL_PADDING(x) ((x << 16) & RCTRL_PAL_MASK) - - -#define RSTAT_CLEAR_RHALT 0x00800000 - -#define TCTRL_IPCSEN 0x00004000 -#define TCTRL_TUCSEN 0x00002000 -#define TCTRL_VLINS 0x00001000 -#define TCTRL_THDF 0x00000800 -#define TCTRL_RFCPAUSE 0x00000010 -#define TCTRL_TFCPAUSE 0x00000008 -#define TCTRL_TXSCHED_MASK 0x00000006 -#define TCTRL_TXSCHED_INIT 0x00000000 -#define TCTRL_TXSCHED_PRIO 0x00000002 -#define TCTRL_TXSCHED_WRRS 0x00000004 -#define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN) - -#define IEVENT_INIT_CLEAR 0xffffffff -#define IEVENT_BABR 0x80000000 -#define IEVENT_RXC 0x40000000 -#define IEVENT_BSY 0x20000000 -#define IEVENT_EBERR 0x10000000 -#define IEVENT_MSRO 0x04000000 -#define IEVENT_GTSC 0x02000000 -#define IEVENT_BABT 0x01000000 -#define IEVENT_TXC 0x00800000 -#define IEVENT_TXE 0x00400000 -#define IEVENT_TXB 0x00200000 -#define IEVENT_TXF 0x00100000 -#define IEVENT_LC 0x00040000 -#define IEVENT_CRL 0x00020000 -#define IEVENT_XFUN 0x00010000 -#define IEVENT_RXB0 0x00008000 -#define IEVENT_MAG 0x00000800 -#define IEVENT_GRSC 0x00000100 -#define IEVENT_RXF0 0x00000080 -#define IEVENT_FIR 0x00000008 -#define IEVENT_FIQ 0x00000004 -#define IEVENT_DPE 0x00000002 -#define IEVENT_PERR 0x00000001 -#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0 | IEVENT_BSY) -#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) -#define IEVENT_RTX_MASK (IEVENT_RX_MASK | IEVENT_TX_MASK) -#define IEVENT_ERR_MASK \ -(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ - IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ - | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \ - | IEVENT_MAG | IEVENT_BABR) - -#define IMASK_INIT_CLEAR 0x00000000 -#define IMASK_BABR 0x80000000 -#define IMASK_RXC 0x40000000 -#define IMASK_BSY 0x20000000 -#define IMASK_EBERR 0x10000000 -#define IMASK_MSRO 0x04000000 -#define IMASK_GTSC 0x02000000 -#define IMASK_BABT 0x01000000 -#define IMASK_TXC 0x00800000 -#define IMASK_TXEEN 0x00400000 -#define IMASK_TXBEN 0x00200000 -#define IMASK_TXFEN 0x00100000 -#define IMASK_LC 0x00040000 -#define IMASK_CRL 0x00020000 -#define IMASK_XFUN 0x00010000 -#define IMASK_RXB0 0x00008000 -#define IMASK_MAG 0x00000800 -#define IMASK_GRSC 0x00000100 -#define IMASK_RXFEN0 0x00000080 -#define IMASK_FIR 0x00000008 -#define IMASK_FIQ 0x00000004 -#define IMASK_DPE 0x00000002 -#define IMASK_PERR 0x00000001 -#define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ - IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ - IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ - | IMASK_PERR) -#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \ - & IMASK_DEFAULT) - -/* Fifo management */ -#define FIFO_TX_THR_MASK 0x01ff -#define FIFO_TX_STARVE_MASK 0x01ff -#define FIFO_TX_STARVE_OFF_MASK 0x01ff - -/* Attribute fields */ - -/* This enables rx snooping for buffers and descriptors */ -#define ATTR_BDSTASH 0x00000800 - -#define ATTR_BUFSTASH 0x00004000 - -#define ATTR_SNOOPING 0x000000c0 -#define ATTR_INIT_SETTINGS ATTR_SNOOPING - -#define ATTRELI_INIT_SETTINGS 0x0 -#define ATTRELI_EL_MASK 0x3fff0000 -#define ATTRELI_EL(x) (x << 16) -#define ATTRELI_EI_MASK 0x00003fff -#define ATTRELI_EI(x) (x) - -#define BD_LFLAG(flags) ((flags) << 16) -#define BD_LENGTH_MASK 0x0000ffff - -#define FPR_FILER_MASK 0xFFFFFFFF -#define MAX_FILER_IDX 0xFF - -/* This default RIR value directly corresponds - * to the 3-bit hash value generated */ -#define DEFAULT_RIR0 0x05397700 - -/* RQFCR register bits */ -#define RQFCR_GPI 0x80000000 -#define RQFCR_HASHTBL_Q 0x00000000 -#define RQFCR_HASHTBL_0 0x00020000 -#define RQFCR_HASHTBL_1 0x00040000 -#define RQFCR_HASHTBL_2 0x00060000 -#define RQFCR_HASHTBL_3 0x00080000 -#define RQFCR_HASH 0x00010000 -#define RQFCR_QUEUE 0x0000FC00 -#define RQFCR_CLE 0x00000200 -#define RQFCR_RJE 0x00000100 -#define RQFCR_AND 0x00000080 -#define RQFCR_CMP_EXACT 0x00000000 -#define RQFCR_CMP_MATCH 0x00000020 -#define RQFCR_CMP_NOEXACT 0x00000040 -#define RQFCR_CMP_NOMATCH 0x00000060 - -/* RQFCR PID values */ -#define RQFCR_PID_MASK 0x00000000 -#define RQFCR_PID_PARSE 0x00000001 -#define RQFCR_PID_ARB 0x00000002 -#define RQFCR_PID_DAH 0x00000003 -#define RQFCR_PID_DAL 0x00000004 -#define RQFCR_PID_SAH 0x00000005 -#define RQFCR_PID_SAL 0x00000006 -#define RQFCR_PID_ETY 0x00000007 -#define RQFCR_PID_VID 0x00000008 -#define RQFCR_PID_PRI 0x00000009 -#define RQFCR_PID_TOS 0x0000000A -#define RQFCR_PID_L4P 0x0000000B -#define RQFCR_PID_DIA 0x0000000C -#define RQFCR_PID_SIA 0x0000000D -#define RQFCR_PID_DPT 0x0000000E -#define RQFCR_PID_SPT 0x0000000F - -/* RQFPR when PID is 0x0001 */ -#define RQFPR_HDR_GE_512 0x00200000 -#define RQFPR_LERR 0x00100000 -#define RQFPR_RAR 0x00080000 -#define RQFPR_RARQ 0x00040000 -#define RQFPR_AR 0x00020000 -#define RQFPR_ARQ 0x00010000 -#define RQFPR_EBC 0x00008000 -#define RQFPR_VLN 0x00004000 -#define RQFPR_CFI 0x00002000 -#define RQFPR_JUM 0x00001000 -#define RQFPR_IPF 0x00000800 -#define RQFPR_FIF 0x00000400 -#define RQFPR_IPV4 0x00000200 -#define RQFPR_IPV6 0x00000100 -#define RQFPR_ICC 0x00000080 -#define RQFPR_ICV 0x00000040 -#define RQFPR_TCP 0x00000020 -#define RQFPR_UDP 0x00000010 -#define RQFPR_TUC 0x00000008 -#define RQFPR_TUV 0x00000004 -#define RQFPR_PER 0x00000002 -#define RQFPR_EER 0x00000001 - -/* TxBD status field bits */ -#define TXBD_READY 0x8000 -#define TXBD_PADCRC 0x4000 -#define TXBD_WRAP 0x2000 -#define TXBD_INTERRUPT 0x1000 -#define TXBD_LAST 0x0800 -#define TXBD_CRC 0x0400 -#define TXBD_DEF 0x0200 -#define TXBD_HUGEFRAME 0x0080 -#define TXBD_LATECOLLISION 0x0080 -#define TXBD_RETRYLIMIT 0x0040 -#define TXBD_RETRYCOUNTMASK 0x003c -#define TXBD_UNDERRUN 0x0002 -#define TXBD_TOE 0x0002 - -/* Tx FCB param bits */ -#define TXFCB_VLN 0x80 -#define TXFCB_IP 0x40 -#define TXFCB_IP6 0x20 -#define TXFCB_TUP 0x10 -#define TXFCB_UDP 0x08 -#define TXFCB_CIP 0x04 -#define TXFCB_CTU 0x02 -#define TXFCB_NPH 0x01 -#define TXFCB_DEFAULT (TXFCB_IP|TXFCB_TUP|TXFCB_CTU|TXFCB_NPH) - -/* RxBD status field bits */ -#define RXBD_EMPTY 0x8000 -#define RXBD_RO1 0x4000 -#define RXBD_WRAP 0x2000 -#define RXBD_INTERRUPT 0x1000 -#define RXBD_LAST 0x0800 -#define RXBD_FIRST 0x0400 -#define RXBD_MISS 0x0100 -#define RXBD_BROADCAST 0x0080 -#define RXBD_MULTICAST 0x0040 -#define RXBD_LARGE 0x0020 -#define RXBD_NONOCTET 0x0010 -#define RXBD_SHORT 0x0008 -#define RXBD_CRCERR 0x0004 -#define RXBD_OVERRUN 0x0002 -#define RXBD_TRUNCATED 0x0001 -#define RXBD_STATS 0x01ff -#define RXBD_ERR (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET \ - | RXBD_CRCERR | RXBD_OVERRUN \ - | RXBD_TRUNCATED) - -/* Rx FCB status field bits */ -#define RXFCB_VLN 0x8000 -#define RXFCB_IP 0x4000 -#define RXFCB_IP6 0x2000 -#define RXFCB_TUP 0x1000 -#define RXFCB_CIP 0x0800 -#define RXFCB_CTU 0x0400 -#define RXFCB_EIP 0x0200 -#define RXFCB_ETU 0x0100 -#define RXFCB_CSUM_MASK 0x0f00 -#define RXFCB_PERR_MASK 0x000c -#define RXFCB_PERR_BADL3 0x0008 - -#define GFAR_INT_NAME_MAX (IFNAMSIZ + 6) /* '_g#_xx' */ - -struct txbd8 -{ - union { - struct { - u16 status; /* Status Fields */ - u16 length; /* Buffer length */ - }; - u32 lstatus; - }; - u32 bufPtr; /* Buffer Pointer */ -}; - -struct txfcb { - u8 flags; - u8 ptp; /* Flag to enable tx timestamping */ - u8 l4os; /* Level 4 Header Offset */ - u8 l3os; /* Level 3 Header Offset */ - u16 phcs; /* Pseudo-header Checksum */ - u16 vlctl; /* VLAN control word */ -}; - -struct rxbd8 -{ - union { - struct { - u16 status; /* Status Fields */ - u16 length; /* Buffer Length */ - }; - u32 lstatus; - }; - u32 bufPtr; /* Buffer Pointer */ -}; - -struct rxfcb { - u16 flags; - u8 rq; /* Receive Queue index */ - u8 pro; /* Layer 4 Protocol */ - u16 reserved; - u16 vlctl; /* VLAN control word */ -}; - -struct gianfar_skb_cb { - int alignamount; -}; - -#define GFAR_CB(skb) ((struct gianfar_skb_cb *)((skb)->cb)) - -struct rmon_mib -{ - u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */ - u32 tr127; /* 0x.684 - Transmit and Receive 65-127 byte Frame Counter */ - u32 tr255; /* 0x.688 - Transmit and Receive 128-255 byte Frame Counter */ - u32 tr511; /* 0x.68c - Transmit and Receive 256-511 byte Frame Counter */ - u32 tr1k; /* 0x.690 - Transmit and Receive 512-1023 byte Frame Counter */ - u32 trmax; /* 0x.694 - Transmit and Receive 1024-1518 byte Frame Counter */ - u32 trmgv; /* 0x.698 - Transmit and Receive 1519-1522 byte Good VLAN Frame */ - u32 rbyt; /* 0x.69c - Receive Byte Counter */ - u32 rpkt; /* 0x.6a0 - Receive Packet Counter */ - u32 rfcs; /* 0x.6a4 - Receive FCS Error Counter */ - u32 rmca; /* 0x.6a8 - Receive Multicast Packet Counter */ - u32 rbca; /* 0x.6ac - Receive Broadcast Packet Counter */ - u32 rxcf; /* 0x.6b0 - Receive Control Frame Packet Counter */ - u32 rxpf; /* 0x.6b4 - Receive Pause Frame Packet Counter */ - u32 rxuo; /* 0x.6b8 - Receive Unknown OP Code Counter */ - u32 raln; /* 0x.6bc - Receive Alignment Error Counter */ - u32 rflr; /* 0x.6c0 - Receive Frame Length Error Counter */ - u32 rcde; /* 0x.6c4 - Receive Code Error Counter */ - u32 rcse; /* 0x.6c8 - Receive Carrier Sense Error Counter */ - u32 rund; /* 0x.6cc - Receive Undersize Packet Counter */ - u32 rovr; /* 0x.6d0 - Receive Oversize Packet Counter */ - u32 rfrg; /* 0x.6d4 - Receive Fragments Counter */ - u32 rjbr; /* 0x.6d8 - Receive Jabber Counter */ - u32 rdrp; /* 0x.6dc - Receive Drop Counter */ - u32 tbyt; /* 0x.6e0 - Transmit Byte Counter Counter */ - u32 tpkt; /* 0x.6e4 - Transmit Packet Counter */ - u32 tmca; /* 0x.6e8 - Transmit Multicast Packet Counter */ - u32 tbca; /* 0x.6ec - Transmit Broadcast Packet Counter */ - u32 txpf; /* 0x.6f0 - Transmit Pause Control Frame Counter */ - u32 tdfr; /* 0x.6f4 - Transmit Deferral Packet Counter */ - u32 tedf; /* 0x.6f8 - Transmit Excessive Deferral Packet Counter */ - u32 tscl; /* 0x.6fc - Transmit Single Collision Packet Counter */ - u32 tmcl; /* 0x.700 - Transmit Multiple Collision Packet Counter */ - u32 tlcl; /* 0x.704 - Transmit Late Collision Packet Counter */ - u32 txcl; /* 0x.708 - Transmit Excessive Collision Packet Counter */ - u32 tncl; /* 0x.70c - Transmit Total Collision Counter */ - u8 res1[4]; - u32 tdrp; /* 0x.714 - Transmit Drop Frame Counter */ - u32 tjbr; /* 0x.718 - Transmit Jabber Frame Counter */ - u32 tfcs; /* 0x.71c - Transmit FCS Error Counter */ - u32 txcf; /* 0x.720 - Transmit Control Frame Counter */ - u32 tovr; /* 0x.724 - Transmit Oversize Frame Counter */ - u32 tund; /* 0x.728 - Transmit Undersize Frame Counter */ - u32 tfrg; /* 0x.72c - Transmit Fragments Frame Counter */ - u32 car1; /* 0x.730 - Carry Register One */ - u32 car2; /* 0x.734 - Carry Register Two */ - u32 cam1; /* 0x.738 - Carry Mask Register One */ - u32 cam2; /* 0x.73c - Carry Mask Register Two */ -}; - -struct gfar_extra_stats { - u64 kernel_dropped; - u64 rx_large; - u64 rx_short; - u64 rx_nonoctet; - u64 rx_crcerr; - u64 rx_overrun; - u64 rx_bsy; - u64 rx_babr; - u64 rx_trunc; - u64 eberr; - u64 tx_babt; - u64 tx_underrun; - u64 rx_skbmissing; - u64 tx_timeout; -}; - -#define GFAR_RMON_LEN ((sizeof(struct rmon_mib) - 16)/sizeof(u32)) -#define GFAR_EXTRA_STATS_LEN (sizeof(struct gfar_extra_stats)/sizeof(u64)) - -/* Number of stats in the stats structure (ignore car and cam regs)*/ -#define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN) - -#define GFAR_INFOSTR_LEN 32 - -struct gfar_stats { - u64 extra[GFAR_EXTRA_STATS_LEN]; - u64 rmon[GFAR_RMON_LEN]; -}; - - -struct gfar { - u32 tsec_id; /* 0x.000 - Controller ID register */ - u32 tsec_id2; /* 0x.004 - Controller ID2 register */ - u8 res1[8]; - u32 ievent; /* 0x.010 - Interrupt Event Register */ - u32 imask; /* 0x.014 - Interrupt Mask Register */ - u32 edis; /* 0x.018 - Error Disabled Register */ - u32 emapg; /* 0x.01c - Group Error mapping register */ - u32 ecntrl; /* 0x.020 - Ethernet Control Register */ - u32 minflr; /* 0x.024 - Minimum Frame Length Register */ - u32 ptv; /* 0x.028 - Pause Time Value Register */ - u32 dmactrl; /* 0x.02c - DMA Control Register */ - u32 tbipa; /* 0x.030 - TBI PHY Address Register */ - u8 res2[28]; - u32 fifo_rx_pause; /* 0x.050 - FIFO receive pause start threshold - register */ - u32 fifo_rx_pause_shutoff; /* x.054 - FIFO receive starve shutoff - register */ - u32 fifo_rx_alarm; /* 0x.058 - FIFO receive alarm start threshold - register */ - u32 fifo_rx_alarm_shutoff; /*0x.05c - FIFO receive alarm starve - shutoff register */ - u8 res3[44]; - u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ - u8 res4[8]; - u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ - u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */ - u8 res5[96]; - u32 tctrl; /* 0x.100 - Transmit Control Register */ - u32 tstat; /* 0x.104 - Transmit Status Register */ - u32 dfvlan; /* 0x.108 - Default VLAN Control word */ - u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ - u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ - u32 tqueue; /* 0x.114 - Transmit queue control register */ - u8 res7[40]; - u32 tr03wt; /* 0x.140 - TxBD Rings 0-3 round-robin weightings */ - u32 tr47wt; /* 0x.144 - TxBD Rings 4-7 round-robin weightings */ - u8 res8[52]; - u32 tbdbph; /* 0x.17c - Tx data buffer pointer high */ - u8 res9a[4]; - u32 tbptr0; /* 0x.184 - TxBD Pointer for ring 0 */ - u8 res9b[4]; - u32 tbptr1; /* 0x.18c - TxBD Pointer for ring 1 */ - u8 res9c[4]; - u32 tbptr2; /* 0x.194 - TxBD Pointer for ring 2 */ - u8 res9d[4]; - u32 tbptr3; /* 0x.19c - TxBD Pointer for ring 3 */ - u8 res9e[4]; - u32 tbptr4; /* 0x.1a4 - TxBD Pointer for ring 4 */ - u8 res9f[4]; - u32 tbptr5; /* 0x.1ac - TxBD Pointer for ring 5 */ - u8 res9g[4]; - u32 tbptr6; /* 0x.1b4 - TxBD Pointer for ring 6 */ - u8 res9h[4]; - u32 tbptr7; /* 0x.1bc - TxBD Pointer for ring 7 */ - u8 res9[64]; - u32 tbaseh; /* 0x.200 - TxBD base address high */ - u32 tbase0; /* 0x.204 - TxBD Base Address of ring 0 */ - u8 res10a[4]; - u32 tbase1; /* 0x.20c - TxBD Base Address of ring 1 */ - u8 res10b[4]; - u32 tbase2; /* 0x.214 - TxBD Base Address of ring 2 */ - u8 res10c[4]; - u32 tbase3; /* 0x.21c - TxBD Base Address of ring 3 */ - u8 res10d[4]; - u32 tbase4; /* 0x.224 - TxBD Base Address of ring 4 */ - u8 res10e[4]; - u32 tbase5; /* 0x.22c - TxBD Base Address of ring 5 */ - u8 res10f[4]; - u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */ - u8 res10g[4]; - u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */ - u8 res10[192]; - u32 rctrl; /* 0x.300 - Receive Control Register */ - u32 rstat; /* 0x.304 - Receive Status Register */ - u8 res12[8]; - u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ - u32 rqueue; /* 0x.314 - Receive queue control register */ - u32 rir0; /* 0x.318 - Ring mapping register 0 */ - u32 rir1; /* 0x.31c - Ring mapping register 1 */ - u32 rir2; /* 0x.320 - Ring mapping register 2 */ - u32 rir3; /* 0x.324 - Ring mapping register 3 */ - u8 res13[8]; - u32 rbifx; /* 0x.330 - Receive bit field extract control register */ - u32 rqfar; /* 0x.334 - Receive queue filing table address register */ - u32 rqfcr; /* 0x.338 - Receive queue filing table control register */ - u32 rqfpr; /* 0x.33c - Receive queue filing table property register */ - u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ - u8 res14[56]; - u32 rbdbph; /* 0x.37c - Rx data buffer pointer high */ - u8 res15a[4]; - u32 rbptr0; /* 0x.384 - RxBD pointer for ring 0 */ - u8 res15b[4]; - u32 rbptr1; /* 0x.38c - RxBD pointer for ring 1 */ - u8 res15c[4]; - u32 rbptr2; /* 0x.394 - RxBD pointer for ring 2 */ - u8 res15d[4]; - u32 rbptr3; /* 0x.39c - RxBD pointer for ring 3 */ - u8 res15e[4]; - u32 rbptr4; /* 0x.3a4 - RxBD pointer for ring 4 */ - u8 res15f[4]; - u32 rbptr5; /* 0x.3ac - RxBD pointer for ring 5 */ - u8 res15g[4]; - u32 rbptr6; /* 0x.3b4 - RxBD pointer for ring 6 */ - u8 res15h[4]; - u32 rbptr7; /* 0x.3bc - RxBD pointer for ring 7 */ - u8 res16[64]; - u32 rbaseh; /* 0x.400 - RxBD base address high */ - u32 rbase0; /* 0x.404 - RxBD base address of ring 0 */ - u8 res17a[4]; - u32 rbase1; /* 0x.40c - RxBD base address of ring 1 */ - u8 res17b[4]; - u32 rbase2; /* 0x.414 - RxBD base address of ring 2 */ - u8 res17c[4]; - u32 rbase3; /* 0x.41c - RxBD base address of ring 3 */ - u8 res17d[4]; - u32 rbase4; /* 0x.424 - RxBD base address of ring 4 */ - u8 res17e[4]; - u32 rbase5; /* 0x.42c - RxBD base address of ring 5 */ - u8 res17f[4]; - u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */ - u8 res17g[4]; - u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */ - u8 res17[192]; - u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ - u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ - u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ - u32 hafdup; /* 0x.50c - Half Duplex Register */ - u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ - u8 res18[12]; - u8 gfar_mii_regs[24]; /* See gianfar_phy.h */ - u32 ifctrl; /* 0x.538 - Interface control register */ - u32 ifstat; /* 0x.53c - Interface Status Register */ - u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ - u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ - u32 mac01addr1; /* 0x.548 - MAC exact match address 1, part 1 */ - u32 mac01addr2; /* 0x.54c - MAC exact match address 1, part 2 */ - u32 mac02addr1; /* 0x.550 - MAC exact match address 2, part 1 */ - u32 mac02addr2; /* 0x.554 - MAC exact match address 2, part 2 */ - u32 mac03addr1; /* 0x.558 - MAC exact match address 3, part 1 */ - u32 mac03addr2; /* 0x.55c - MAC exact match address 3, part 2 */ - u32 mac04addr1; /* 0x.560 - MAC exact match address 4, part 1 */ - u32 mac04addr2; /* 0x.564 - MAC exact match address 4, part 2 */ - u32 mac05addr1; /* 0x.568 - MAC exact match address 5, part 1 */ - u32 mac05addr2; /* 0x.56c - MAC exact match address 5, part 2 */ - u32 mac06addr1; /* 0x.570 - MAC exact match address 6, part 1 */ - u32 mac06addr2; /* 0x.574 - MAC exact match address 6, part 2 */ - u32 mac07addr1; /* 0x.578 - MAC exact match address 7, part 1 */ - u32 mac07addr2; /* 0x.57c - MAC exact match address 7, part 2 */ - u32 mac08addr1; /* 0x.580 - MAC exact match address 8, part 1 */ - u32 mac08addr2; /* 0x.584 - MAC exact match address 8, part 2 */ - u32 mac09addr1; /* 0x.588 - MAC exact match address 9, part 1 */ - u32 mac09addr2; /* 0x.58c - MAC exact match address 9, part 2 */ - u32 mac10addr1; /* 0x.590 - MAC exact match address 10, part 1*/ - u32 mac10addr2; /* 0x.594 - MAC exact match address 10, part 2*/ - u32 mac11addr1; /* 0x.598 - MAC exact match address 11, part 1*/ - u32 mac11addr2; /* 0x.59c - MAC exact match address 11, part 2*/ - u32 mac12addr1; /* 0x.5a0 - MAC exact match address 12, part 1*/ - u32 mac12addr2; /* 0x.5a4 - MAC exact match address 12, part 2*/ - u32 mac13addr1; /* 0x.5a8 - MAC exact match address 13, part 1*/ - u32 mac13addr2; /* 0x.5ac - MAC exact match address 13, part 2*/ - u32 mac14addr1; /* 0x.5b0 - MAC exact match address 14, part 1*/ - u32 mac14addr2; /* 0x.5b4 - MAC exact match address 14, part 2*/ - u32 mac15addr1; /* 0x.5b8 - MAC exact match address 15, part 1*/ - u32 mac15addr2; /* 0x.5bc - MAC exact match address 15, part 2*/ - u8 res20[192]; - struct rmon_mib rmon; /* 0x.680-0x.73c */ - u32 rrej; /* 0x.740 - Receive filer rejected packet counter */ - u8 res21[188]; - u32 igaddr0; /* 0x.800 - Indivdual/Group address register 0*/ - u32 igaddr1; /* 0x.804 - Indivdual/Group address register 1*/ - u32 igaddr2; /* 0x.808 - Indivdual/Group address register 2*/ - u32 igaddr3; /* 0x.80c - Indivdual/Group address register 3*/ - u32 igaddr4; /* 0x.810 - Indivdual/Group address register 4*/ - u32 igaddr5; /* 0x.814 - Indivdual/Group address register 5*/ - u32 igaddr6; /* 0x.818 - Indivdual/Group address register 6*/ - u32 igaddr7; /* 0x.81c - Indivdual/Group address register 7*/ - u8 res22[96]; - u32 gaddr0; /* 0x.880 - Group address register 0 */ - u32 gaddr1; /* 0x.884 - Group address register 1 */ - u32 gaddr2; /* 0x.888 - Group address register 2 */ - u32 gaddr3; /* 0x.88c - Group address register 3 */ - u32 gaddr4; /* 0x.890 - Group address register 4 */ - u32 gaddr5; /* 0x.894 - Group address register 5 */ - u32 gaddr6; /* 0x.898 - Group address register 6 */ - u32 gaddr7; /* 0x.89c - Group address register 7 */ - u8 res23a[352]; - u32 fifocfg; /* 0x.a00 - FIFO interface config register */ - u8 res23b[252]; - u8 res23c[248]; - u32 attr; /* 0x.bf8 - Attributes Register */ - u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ - u8 res24[688]; - u32 isrg0; /* 0x.eb0 - Interrupt steering group 0 register */ - u32 isrg1; /* 0x.eb4 - Interrupt steering group 1 register */ - u32 isrg2; /* 0x.eb8 - Interrupt steering group 2 register */ - u32 isrg3; /* 0x.ebc - Interrupt steering group 3 register */ - u8 res25[16]; - u32 rxic0; /* 0x.ed0 - Ring 0 Rx interrupt coalescing */ - u32 rxic1; /* 0x.ed4 - Ring 1 Rx interrupt coalescing */ - u32 rxic2; /* 0x.ed8 - Ring 2 Rx interrupt coalescing */ - u32 rxic3; /* 0x.edc - Ring 3 Rx interrupt coalescing */ - u32 rxic4; /* 0x.ee0 - Ring 4 Rx interrupt coalescing */ - u32 rxic5; /* 0x.ee4 - Ring 5 Rx interrupt coalescing */ - u32 rxic6; /* 0x.ee8 - Ring 6 Rx interrupt coalescing */ - u32 rxic7; /* 0x.eec - Ring 7 Rx interrupt coalescing */ - u8 res26[32]; - u32 txic0; /* 0x.f10 - Ring 0 Tx interrupt coalescing */ - u32 txic1; /* 0x.f14 - Ring 1 Tx interrupt coalescing */ - u32 txic2; /* 0x.f18 - Ring 2 Tx interrupt coalescing */ - u32 txic3; /* 0x.f1c - Ring 3 Tx interrupt coalescing */ - u32 txic4; /* 0x.f20 - Ring 4 Tx interrupt coalescing */ - u32 txic5; /* 0x.f24 - Ring 5 Tx interrupt coalescing */ - u32 txic6; /* 0x.f28 - Ring 6 Tx interrupt coalescing */ - u32 txic7; /* 0x.f2c - Ring 7 Tx interrupt coalescing */ - u8 res27[208]; -}; - -/* Flags related to gianfar device features */ -#define FSL_GIANFAR_DEV_HAS_GIGABIT 0x00000001 -#define FSL_GIANFAR_DEV_HAS_COALESCE 0x00000002 -#define FSL_GIANFAR_DEV_HAS_RMON 0x00000004 -#define FSL_GIANFAR_DEV_HAS_MULTI_INTR 0x00000008 -#define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010 -#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020 -#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040 -#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080 -#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100 -#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200 -#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400 -#define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800 - -#if (MAXGROUPS == 2) -#define DEFAULT_MAPPING 0xAA -#else -#define DEFAULT_MAPPING 0xFF -#endif - -#define ISRG_SHIFT_TX 0x10 -#define ISRG_SHIFT_RX 0x18 - -/* The same driver can operate in two modes */ -/* SQ_SG_MODE: Single Queue Single Group Mode - * (Backward compatible mode) - * MQ_MG_MODE: Multi Queue Multi Group mode - */ -enum { - SQ_SG_MODE = 0, - MQ_MG_MODE -}; - -/* - * Per TX queue stats - */ -struct tx_q_stats { - unsigned long tx_packets; - unsigned long tx_bytes; -}; - -/** - * struct gfar_priv_tx_q - per tx queue structure - * @txlock: per queue tx spin lock - * @tx_skbuff:skb pointers - * @skb_curtx: to be used skb pointer - * @skb_dirtytx:the last used skb pointer - * @stats: bytes/packets stats - * @qindex: index of this queue - * @dev: back pointer to the dev structure - * @grp: back pointer to the group to which this queue belongs - * @tx_bd_base: First tx buffer descriptor - * @cur_tx: Next free ring entry - * @dirty_tx: First buffer in line to be transmitted - * @tx_ring_size: Tx ring size - * @num_txbdfree: number of free TxBds - * @txcoalescing: enable/disable tx coalescing - * @txic: transmit interrupt coalescing value - * @txcount: coalescing value if based on tx frame count - * @txtime: coalescing value if based on time - */ -struct gfar_priv_tx_q { - spinlock_t txlock __attribute__ ((aligned (SMP_CACHE_BYTES))); - struct sk_buff ** tx_skbuff; - /* Buffer descriptor pointers */ - dma_addr_t tx_bd_dma_base; - struct txbd8 *tx_bd_base; - struct txbd8 *cur_tx; - struct txbd8 *dirty_tx; - struct tx_q_stats stats; - struct net_device *dev; - struct gfar_priv_grp *grp; - u16 skb_curtx; - u16 skb_dirtytx; - u16 qindex; - unsigned int tx_ring_size; - unsigned int num_txbdfree; - /* Configuration info for the coalescing features */ - unsigned char txcoalescing; - unsigned long txic; - unsigned short txcount; - unsigned short txtime; -}; - -/* - * Per RX queue stats - */ -struct rx_q_stats { - unsigned long rx_packets; - unsigned long rx_bytes; - unsigned long rx_dropped; -}; - -/** - * struct gfar_priv_rx_q - per rx queue structure - * @rxlock: per queue rx spin lock - * @rx_skbuff: skb pointers - * @skb_currx: currently use skb pointer - * @rx_bd_base: First rx buffer descriptor - * @cur_rx: Next free rx ring entry - * @qindex: index of this queue - * @dev: back pointer to the dev structure - * @rx_ring_size: Rx ring size - * @rxcoalescing: enable/disable rx-coalescing - * @rxic: receive interrupt coalescing vlaue - */ - -struct gfar_priv_rx_q { - spinlock_t rxlock __attribute__ ((aligned (SMP_CACHE_BYTES))); - struct sk_buff ** rx_skbuff; - dma_addr_t rx_bd_dma_base; - struct rxbd8 *rx_bd_base; - struct rxbd8 *cur_rx; - struct net_device *dev; - struct gfar_priv_grp *grp; - struct rx_q_stats stats; - u16 skb_currx; - u16 qindex; - unsigned int rx_ring_size; - /* RX Coalescing values */ - unsigned char rxcoalescing; - unsigned long rxic; -}; - -/** - * struct gfar_priv_grp - per group structure - * @napi: the napi poll function - * @priv: back pointer to the priv structure - * @regs: the ioremapped register space for this group - * @grp_id: group id for this group - * @interruptTransmit: The TX interrupt number for this group - * @interruptReceive: The RX interrupt number for this group - * @interruptError: The ERROR interrupt number for this group - * @int_name_tx: tx interrupt name for this group - * @int_name_rx: rx interrupt name for this group - * @int_name_er: er interrupt name for this group - */ - -struct gfar_priv_grp { - spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES))); - struct napi_struct napi; - struct gfar_private *priv; - struct gfar __iomem *regs; - unsigned int grp_id; - unsigned long rx_bit_map; - unsigned long tx_bit_map; - unsigned long num_tx_queues; - unsigned long num_rx_queues; - unsigned int rstat; - unsigned int tstat; - unsigned int imask; - unsigned int ievent; - unsigned int interruptTransmit; - unsigned int interruptReceive; - unsigned int interruptError; - - char int_name_tx[GFAR_INT_NAME_MAX]; - char int_name_rx[GFAR_INT_NAME_MAX]; - char int_name_er[GFAR_INT_NAME_MAX]; -}; - -enum gfar_errata { - GFAR_ERRATA_74 = 0x01, - GFAR_ERRATA_76 = 0x02, - GFAR_ERRATA_A002 = 0x04, - GFAR_ERRATA_12 = 0x08, /* a.k.a errata eTSEC49 */ -}; - -/* Struct stolen almost completely (and shamelessly) from the FCC enet source - * (Ok, that's not so true anymore, but there is a family resemblance) - * The GFAR buffer descriptors track the ring buffers. The rx_bd_base - * and tx_bd_base always point to the currently available buffer. - * The dirty_tx tracks the current buffer that is being sent by the - * controller. The cur_tx and dirty_tx are equal under both completely - * empty and completely full conditions. The empty/ready indicator in - * the buffer descriptor determines the actual condition. - */ -struct gfar_private { - - /* Indicates how many tx, rx queues are enabled */ - unsigned int num_tx_queues; - unsigned int num_rx_queues; - unsigned int num_grps; - unsigned int mode; - - /* The total tx and rx ring size for the enabled queues */ - unsigned int total_tx_ring_size; - unsigned int total_rx_ring_size; - - struct device_node *node; - struct net_device *ndev; - struct platform_device *ofdev; - enum gfar_errata errata; - - struct gfar_priv_grp gfargrp[MAXGROUPS]; - struct gfar_priv_tx_q *tx_queue[MAX_TX_QS]; - struct gfar_priv_rx_q *rx_queue[MAX_RX_QS]; - - /* RX per device parameters */ - unsigned int rx_buffer_size; - unsigned int rx_stash_size; - unsigned int rx_stash_index; - - u32 cur_filer_idx; - - struct sk_buff_head rx_recycle; - - /* RX queue filer rule set*/ - struct ethtool_rx_list rx_list; - struct mutex rx_queue_access; - - /* Hash registers and their width */ - u32 __iomem *hash_regs[16]; - int hash_width; - - /* global parameters */ - unsigned int fifo_threshold; - unsigned int fifo_starve; - unsigned int fifo_starve_off; - - /* Bitfield update lock */ - spinlock_t bflock; - - phy_interface_t interface; - struct device_node *phy_node; - struct device_node *tbi_node; - u32 device_flags; - unsigned char - extended_hash:1, - bd_stash_en:1, - rx_filer_enable:1, - wol_en:1; /* Wake-on-LAN enabled */ - unsigned short padding; - - /* PHY stuff */ - struct phy_device *phydev; - struct mii_bus *mii_bus; - int oldspeed; - int oldduplex; - int oldlink; - - uint32_t msg_enable; - - struct work_struct reset_task; - - /* Network Statistics */ - struct gfar_extra_stats extra_stats; - - /* HW time stamping enabled flag */ - int hwts_rx_en; - int hwts_tx_en; - - /*Filer table*/ - unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; - unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; -}; - - -static inline int gfar_has_errata(struct gfar_private *priv, - enum gfar_errata err) -{ - return priv->errata & err; -} - -static inline u32 gfar_read(volatile unsigned __iomem *addr) -{ - u32 val; - val = in_be32(addr); - return val; -} - -static inline void gfar_write(volatile unsigned __iomem *addr, u32 val) -{ - out_be32(addr, val); -} - -static inline void gfar_write_filer(struct gfar_private *priv, - unsigned int far, unsigned int fcr, unsigned int fpr) -{ - struct gfar __iomem *regs = priv->gfargrp[0].regs; - - gfar_write(®s->rqfar, far); - gfar_write(®s->rqfcr, fcr); - gfar_write(®s->rqfpr, fpr); -} - -static inline void gfar_read_filer(struct gfar_private *priv, - unsigned int far, unsigned int *fcr, unsigned int *fpr) -{ - struct gfar __iomem *regs = priv->gfargrp[0].regs; - - gfar_write(®s->rqfar, far); - *fcr = gfar_read(®s->rqfcr); - *fpr = gfar_read(®s->rqfpr); -} - -extern void lock_rx_qs(struct gfar_private *priv); -extern void lock_tx_qs(struct gfar_private *priv); -extern void unlock_rx_qs(struct gfar_private *priv); -extern void unlock_tx_qs(struct gfar_private *priv); -extern irqreturn_t gfar_receive(int irq, void *dev_id); -extern int startup_gfar(struct net_device *dev); -extern void stop_gfar(struct net_device *dev); -extern void gfar_halt(struct net_device *dev); -extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, - int enable, u32 regnum, u32 read); -extern void gfar_configure_coalescing(struct gfar_private *priv, - unsigned long tx_mask, unsigned long rx_mask); -void gfar_init_sysfs(struct net_device *dev); -int gfar_set_features(struct net_device *dev, netdev_features_t features); -extern void gfar_check_rx_parser_mode(struct gfar_private *priv); -extern void gfar_vlan_mode(struct net_device *dev, netdev_features_t features); - -extern const struct ethtool_ops gfar_ethtool_ops; - -#define MAX_FILER_CACHE_IDX (2*(MAX_FILER_IDX)) - -#define RQFCR_PID_PRI_MASK 0xFFFFFFF8 -#define RQFCR_PID_L4P_MASK 0xFFFFFF00 -#define RQFCR_PID_VID_MASK 0xFFFFF000 -#define RQFCR_PID_PORT_MASK 0xFFFF0000 -#define RQFCR_PID_MAC_MASK 0xFF000000 - -struct gfar_mask_entry { - unsigned int mask; /* The mask value which is valid form start to end */ - unsigned int start; - unsigned int end; - unsigned int block; /* Same block values indicate depended entries */ -}; - -/* Represents a receive filer table entry */ -struct gfar_filer_entry { - u32 ctrl; - u32 prop; -}; - - -/* The 20 additional entries are a shadow for one extra element */ -struct filer_table { - u32 index; - struct gfar_filer_entry fe[MAX_FILER_CACHE_IDX + 20]; -}; - -#endif /* __GIANFAR_H */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_ethtool.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_ethtool.c deleted file mode 100644 index 8d74efd0..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ /dev/null @@ -1,1764 +0,0 @@ -/* - * drivers/net/ethernet/freescale/gianfar_ethtool.c - * - * Gianfar Ethernet Driver - * Ethtool support for Gianfar Enet - * Based on e1000 ethtool support - * - * Author: Andy Fleming - * Maintainer: Kumar Gala - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> - * - * Copyright 2003-2006, 2008-2009, 2011 Freescale Semiconductor, Inc. - * - * This software may be used and distributed according to - * the terms of the GNU Public License, Version 2, incorporated herein - * by reference. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <linux/module.h> -#include <linux/crc32.h> -#include <asm/types.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#include <linux/phy.h> -#include <linux/sort.h> -#include <linux/if_vlan.h> - -#include "gianfar.h" - -extern void gfar_start(struct net_device *dev); -extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); - -#define GFAR_MAX_COAL_USECS 0xffff -#define GFAR_MAX_COAL_FRAMES 0xff -static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, - u64 * buf); -static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); -static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); -static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); -static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); -static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); -static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); - -static const char stat_gstrings[][ETH_GSTRING_LEN] = { - "rx-dropped-by-kernel", - "rx-large-frame-errors", - "rx-short-frame-errors", - "rx-non-octet-errors", - "rx-crc-errors", - "rx-overrun-errors", - "rx-busy-errors", - "rx-babbling-errors", - "rx-truncated-frames", - "ethernet-bus-error", - "tx-babbling-errors", - "tx-underrun-errors", - "rx-skb-missing-errors", - "tx-timeout-errors", - "tx-rx-64-frames", - "tx-rx-65-127-frames", - "tx-rx-128-255-frames", - "tx-rx-256-511-frames", - "tx-rx-512-1023-frames", - "tx-rx-1024-1518-frames", - "tx-rx-1519-1522-good-vlan", - "rx-bytes", - "rx-packets", - "rx-fcs-errors", - "receive-multicast-packet", - "receive-broadcast-packet", - "rx-control-frame-packets", - "rx-pause-frame-packets", - "rx-unknown-op-code", - "rx-alignment-error", - "rx-frame-length-error", - "rx-code-error", - "rx-carrier-sense-error", - "rx-undersize-packets", - "rx-oversize-packets", - "rx-fragmented-frames", - "rx-jabber-frames", - "rx-dropped-frames", - "tx-byte-counter", - "tx-packets", - "tx-multicast-packets", - "tx-broadcast-packets", - "tx-pause-control-frames", - "tx-deferral-packets", - "tx-excessive-deferral-packets", - "tx-single-collision-packets", - "tx-multiple-collision-packets", - "tx-late-collision-packets", - "tx-excessive-collision-packets", - "tx-total-collision", - "reserved", - "tx-dropped-frames", - "tx-jabber-frames", - "tx-fcs-errors", - "tx-control-frames", - "tx-oversize-frames", - "tx-undersize-frames", - "tx-fragmented-frames", -}; - -/* Fill in a buffer with the strings which correspond to the - * stats */ -static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) - memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); - else - memcpy(buf, stat_gstrings, - GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); -} - -/* Fill in an array of 64-bit statistics from various sources. - * This array will be appended to the end of the ethtool_stats - * structure, and returned to user space - */ -static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) -{ - int i; - struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - u64 *extra = (u64 *) & priv->extra_stats; - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - u32 __iomem *rmon = (u32 __iomem *) ®s->rmon; - struct gfar_stats *stats = (struct gfar_stats *) buf; - - for (i = 0; i < GFAR_RMON_LEN; i++) - stats->rmon[i] = (u64) gfar_read(&rmon[i]); - - for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) - stats->extra[i] = extra[i]; - } else - for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) - buf[i] = extra[i]; -} - -static int gfar_sset_count(struct net_device *dev, int sset) -{ - struct gfar_private *priv = netdev_priv(dev); - - switch (sset) { - case ETH_SS_STATS: - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) - return GFAR_STATS_LEN; - else - return GFAR_EXTRA_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -/* Fills in the drvinfo structure with some basic info */ -static void gfar_gdrvinfo(struct net_device *dev, struct - ethtool_drvinfo *drvinfo) -{ - strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); - strncpy(drvinfo->version, gfar_driver_version, GFAR_INFOSTR_LEN); - strncpy(drvinfo->fw_version, "N/A", GFAR_INFOSTR_LEN); - strncpy(drvinfo->bus_info, "N/A", GFAR_INFOSTR_LEN); - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; -} - - -static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct gfar_private *priv = netdev_priv(dev); - struct phy_device *phydev = priv->phydev; - - if (NULL == phydev) - return -ENODEV; - - return phy_ethtool_sset(phydev, cmd); -} - - -/* Return the current settings in the ethtool_cmd structure */ -static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct gfar_private *priv = netdev_priv(dev); - struct phy_device *phydev = priv->phydev; - struct gfar_priv_rx_q *rx_queue = NULL; - struct gfar_priv_tx_q *tx_queue = NULL; - - if (NULL == phydev) - return -ENODEV; - tx_queue = priv->tx_queue[0]; - rx_queue = priv->rx_queue[0]; - - /* etsec-1.7 and older versions have only one txic - * and rxic regs although they support multiple queues */ - cmd->maxtxpkt = get_icft_value(tx_queue->txic); - cmd->maxrxpkt = get_icft_value(rx_queue->rxic); - - return phy_ethtool_gset(phydev, cmd); -} - -/* Return the length of the register structure */ -static int gfar_reglen(struct net_device *dev) -{ - return sizeof (struct gfar); -} - -/* Return a dump of the GFAR register space */ -static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) -{ - int i; - struct gfar_private *priv = netdev_priv(dev); - u32 __iomem *theregs = (u32 __iomem *) priv->gfargrp[0].regs; - u32 *buf = (u32 *) regbuf; - - for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) - buf[i] = gfar_read(&theregs[i]); -} - -/* Convert microseconds to ethernet clock ticks, which changes - * depending on what speed the controller is running at */ -static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) -{ - unsigned int count; - - /* The timer is different, depending on the interface speed */ - switch (priv->phydev->speed) { - case SPEED_1000: - count = GFAR_GBIT_TIME; - break; - case SPEED_100: - count = GFAR_100_TIME; - break; - case SPEED_10: - default: - count = GFAR_10_TIME; - break; - } - - /* Make sure we return a number greater than 0 - * if usecs > 0 */ - return (usecs * 1000 + count - 1) / count; -} - -/* Convert ethernet clock ticks to microseconds */ -static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int ticks) -{ - unsigned int count; - - /* The timer is different, depending on the interface speed */ - switch (priv->phydev->speed) { - case SPEED_1000: - count = GFAR_GBIT_TIME; - break; - case SPEED_100: - count = GFAR_100_TIME; - break; - case SPEED_10: - default: - count = GFAR_10_TIME; - break; - } - - /* Make sure we return a number greater than 0 */ - /* if ticks is > 0 */ - return (ticks * count) / 1000; -} - -/* Get the coalescing parameters, and put them in the cvals - * structure. */ -static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar_priv_rx_q *rx_queue = NULL; - struct gfar_priv_tx_q *tx_queue = NULL; - unsigned long rxtime; - unsigned long rxcount; - unsigned long txtime; - unsigned long txcount; - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) - return -EOPNOTSUPP; - - if (NULL == priv->phydev) - return -ENODEV; - - rx_queue = priv->rx_queue[0]; - tx_queue = priv->tx_queue[0]; - - rxtime = get_ictt_value(rx_queue->rxic); - rxcount = get_icft_value(rx_queue->rxic); - txtime = get_ictt_value(tx_queue->txic); - txcount = get_icft_value(tx_queue->txic); - cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime); - cvals->rx_max_coalesced_frames = rxcount; - - cvals->tx_coalesce_usecs = gfar_ticks2usecs(priv, txtime); - cvals->tx_max_coalesced_frames = txcount; - - cvals->use_adaptive_rx_coalesce = 0; - cvals->use_adaptive_tx_coalesce = 0; - - cvals->pkt_rate_low = 0; - cvals->rx_coalesce_usecs_low = 0; - cvals->rx_max_coalesced_frames_low = 0; - cvals->tx_coalesce_usecs_low = 0; - cvals->tx_max_coalesced_frames_low = 0; - - /* When the packet rate is below pkt_rate_high but above - * pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ - - /* When the packet rate is (measured in packets per second) - * is above pkt_rate_high, the {rx,tx}_*_high parameters are - * used. - */ - cvals->pkt_rate_high = 0; - cvals->rx_coalesce_usecs_high = 0; - cvals->rx_max_coalesced_frames_high = 0; - cvals->tx_coalesce_usecs_high = 0; - cvals->tx_max_coalesced_frames_high = 0; - - /* How often to do adaptive coalescing packet rate sampling, - * measured in seconds. Must not be zero. - */ - cvals->rate_sample_interval = 0; - - return 0; -} - -/* Change the coalescing values. - * Both cvals->*_usecs and cvals->*_frames have to be > 0 - * in order for coalescing to be active - */ -static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) -{ - struct gfar_private *priv = netdev_priv(dev); - int i = 0; - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) - return -EOPNOTSUPP; - - /* Set up rx coalescing */ - /* As of now, we will enable/disable coalescing for all - * queues together in case of eTSEC2, this will be modified - * along with the ethtool interface */ - if ((cvals->rx_coalesce_usecs == 0) || - (cvals->rx_max_coalesced_frames == 0)) { - for (i = 0; i < priv->num_rx_queues; i++) - priv->rx_queue[i]->rxcoalescing = 0; - } else { - for (i = 0; i < priv->num_rx_queues; i++) - priv->rx_queue[i]->rxcoalescing = 1; - } - - if (NULL == priv->phydev) - return -ENODEV; - - /* Check the bounds of the values */ - if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) { - pr_info("Coalescing is limited to %d microseconds\n", - GFAR_MAX_COAL_USECS); - return -EINVAL; - } - - if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { - pr_info("Coalescing is limited to %d frames\n", - GFAR_MAX_COAL_FRAMES); - return -EINVAL; - } - - for (i = 0; i < priv->num_rx_queues; i++) { - priv->rx_queue[i]->rxic = mk_ic_value( - cvals->rx_max_coalesced_frames, - gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); - } - - /* Set up tx coalescing */ - if ((cvals->tx_coalesce_usecs == 0) || - (cvals->tx_max_coalesced_frames == 0)) { - for (i = 0; i < priv->num_tx_queues; i++) - priv->tx_queue[i]->txcoalescing = 0; - } else { - for (i = 0; i < priv->num_tx_queues; i++) - priv->tx_queue[i]->txcoalescing = 1; - } - - /* Check the bounds of the values */ - if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { - pr_info("Coalescing is limited to %d microseconds\n", - GFAR_MAX_COAL_USECS); - return -EINVAL; - } - - if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { - pr_info("Coalescing is limited to %d frames\n", - GFAR_MAX_COAL_FRAMES); - return -EINVAL; - } - - for (i = 0; i < priv->num_tx_queues; i++) { - priv->tx_queue[i]->txic = mk_ic_value( - cvals->tx_max_coalesced_frames, - gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); - } - - gfar_configure_coalescing(priv, 0xFF, 0xFF); - - return 0; -} - -/* Fills in rvals with the current ring parameters. Currently, - * rx, rx_mini, and rx_jumbo rings are the same size, as mini and - * jumbo are ignored by the driver */ -static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) -{ - struct gfar_private *priv = netdev_priv(dev); - struct gfar_priv_tx_q *tx_queue = NULL; - struct gfar_priv_rx_q *rx_queue = NULL; - - tx_queue = priv->tx_queue[0]; - rx_queue = priv->rx_queue[0]; - - rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE; - rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE; - rvals->rx_jumbo_max_pending = GFAR_RX_MAX_RING_SIZE; - rvals->tx_max_pending = GFAR_TX_MAX_RING_SIZE; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - rvals->rx_pending = rx_queue->rx_ring_size; - rvals->rx_mini_pending = rx_queue->rx_ring_size; - rvals->rx_jumbo_pending = rx_queue->rx_ring_size; - rvals->tx_pending = tx_queue->tx_ring_size; -} - -/* Change the current ring parameters, stopping the controller if - * necessary so that we don't mess things up while we're in - * motion. We wait for the ring to be clean before reallocating - * the rings. */ -static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) -{ - struct gfar_private *priv = netdev_priv(dev); - int err = 0, i = 0; - - if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) - return -EINVAL; - - if (!is_power_of_2(rvals->rx_pending)) { - netdev_err(dev, "Ring sizes must be a power of 2\n"); - return -EINVAL; - } - - if (rvals->tx_pending > GFAR_TX_MAX_RING_SIZE) - return -EINVAL; - - if (!is_power_of_2(rvals->tx_pending)) { - netdev_err(dev, "Ring sizes must be a power of 2\n"); - return -EINVAL; - } - - - if (dev->flags & IFF_UP) { - unsigned long flags; - - /* Halt TX and RX, and process the frames which - * have already been received */ - local_irq_save(flags); - lock_tx_qs(priv); - lock_rx_qs(priv); - - gfar_halt(dev); - - unlock_rx_qs(priv); - unlock_tx_qs(priv); - local_irq_restore(flags); - - for (i = 0; i < priv->num_rx_queues; i++) - gfar_clean_rx_ring(priv->rx_queue[i], - priv->rx_queue[i]->rx_ring_size); - - /* Now we take down the rings to rebuild them */ - stop_gfar(dev); - } - - /* Change the size */ - for (i = 0; i < priv->num_rx_queues; i++) { - priv->rx_queue[i]->rx_ring_size = rvals->rx_pending; - priv->tx_queue[i]->tx_ring_size = rvals->tx_pending; - priv->tx_queue[i]->num_txbdfree = priv->tx_queue[i]->tx_ring_size; - } - - /* Rebuild the rings with the new size */ - if (dev->flags & IFF_UP) { - err = startup_gfar(dev); - netif_tx_wake_all_queues(dev); - } - return err; -} - -int gfar_set_features(struct net_device *dev, netdev_features_t features) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; - int err = 0, i = 0; - netdev_features_t changed = dev->features ^ features; - - if (changed & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)) - gfar_vlan_mode(dev, features); - - if (!(changed & NETIF_F_RXCSUM)) - return 0; - - if (dev->flags & IFF_UP) { - /* Halt TX and RX, and process the frames which - * have already been received */ - local_irq_save(flags); - lock_tx_qs(priv); - lock_rx_qs(priv); - - gfar_halt(dev); - - unlock_tx_qs(priv); - unlock_rx_qs(priv); - local_irq_restore(flags); - - for (i = 0; i < priv->num_rx_queues; i++) - gfar_clean_rx_ring(priv->rx_queue[i], - priv->rx_queue[i]->rx_ring_size); - - /* Now we take down the rings to rebuild them */ - stop_gfar(dev); - - dev->features = features; - - err = startup_gfar(dev); - netif_tx_wake_all_queues(dev); - } - return err; -} - -static uint32_t gfar_get_msglevel(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - return priv->msg_enable; -} - -static void gfar_set_msglevel(struct net_device *dev, uint32_t data) -{ - struct gfar_private *priv = netdev_priv(dev); - priv->msg_enable = data; -} - -#ifdef CONFIG_PM -static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct gfar_private *priv = netdev_priv(dev); - - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) { - wol->supported = WAKE_MAGIC; - wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0; - } else { - wol->supported = wol->wolopts = 0; - } -} - -static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && - wol->wolopts != 0) - return -EINVAL; - - if (wol->wolopts & ~WAKE_MAGIC) - return -EINVAL; - - device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC); - - spin_lock_irqsave(&priv->bflock, flags); - priv->wol_en = !!device_may_wakeup(&dev->dev); - spin_unlock_irqrestore(&priv->bflock, flags); - - return 0; -} -#endif - -static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) -{ - u32 fcr = 0x0, fpr = FPR_FILER_MASK; - - if (ethflow & RXH_L2DA) { - fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH | - RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - - fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH | - RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - - if (ethflow & RXH_VLAN) { - fcr = RQFCR_PID_VID | RQFCR_CMP_NOMATCH | RQFCR_HASH | - RQFCR_AND | RQFCR_HASHTBL_0; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - - if (ethflow & RXH_IP_SRC) { - fcr = RQFCR_PID_SIA | RQFCR_CMP_NOMATCH | RQFCR_HASH | - RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - - if (ethflow & (RXH_IP_DST)) { - fcr = RQFCR_PID_DIA | RQFCR_CMP_NOMATCH | RQFCR_HASH | - RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - - if (ethflow & RXH_L3_PROTO) { - fcr = RQFCR_PID_L4P | RQFCR_CMP_NOMATCH | RQFCR_HASH | - RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - - if (ethflow & RXH_L4_B_0_1) { - fcr = RQFCR_PID_SPT | RQFCR_CMP_NOMATCH | RQFCR_HASH | - RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - - if (ethflow & RXH_L4_B_2_3) { - fcr = RQFCR_PID_DPT | RQFCR_CMP_NOMATCH | RQFCR_HASH | - RQFCR_AND | RQFCR_HASHTBL_0; - priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; - priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; - gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } -} - -static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u64 class) -{ - unsigned int last_rule_idx = priv->cur_filer_idx; - unsigned int cmp_rqfpr; - unsigned int *local_rqfpr; - unsigned int *local_rqfcr; - int i = 0x0, k = 0x0; - int j = MAX_FILER_IDX, l = 0x0; - int ret = 1; - - local_rqfpr = kmalloc(sizeof(unsigned int) * (MAX_FILER_IDX + 1), - GFP_KERNEL); - local_rqfcr = kmalloc(sizeof(unsigned int) * (MAX_FILER_IDX + 1), - GFP_KERNEL); - if (!local_rqfpr || !local_rqfcr) { - pr_err("Out of memory\n"); - ret = 0; - goto err; - } - - switch (class) { - case TCP_V4_FLOW: - cmp_rqfpr = RQFPR_IPV4 |RQFPR_TCP; - break; - case UDP_V4_FLOW: - cmp_rqfpr = RQFPR_IPV4 |RQFPR_UDP; - break; - case TCP_V6_FLOW: - cmp_rqfpr = RQFPR_IPV6 |RQFPR_TCP; - break; - case UDP_V6_FLOW: - cmp_rqfpr = RQFPR_IPV6 |RQFPR_UDP; - break; - default: - pr_err("Right now this class is not supported\n"); - ret = 0; - goto err; - } - - for (i = 0; i < MAX_FILER_IDX + 1; i++) { - local_rqfpr[j] = priv->ftp_rqfpr[i]; - local_rqfcr[j] = priv->ftp_rqfcr[i]; - j--; - if ((priv->ftp_rqfcr[i] == (RQFCR_PID_PARSE | - RQFCR_CLE |RQFCR_AND)) && - (priv->ftp_rqfpr[i] == cmp_rqfpr)) - break; - } - - if (i == MAX_FILER_IDX + 1) { - pr_err("No parse rule found, can't create hash rules\n"); - ret = 0; - goto err; - } - - /* If a match was found, then it begins the starting of a cluster rule - * if it was already programmed, we need to overwrite these rules - */ - for (l = i+1; l < MAX_FILER_IDX; l++) { - if ((priv->ftp_rqfcr[l] & RQFCR_CLE) && - !(priv->ftp_rqfcr[l] & RQFCR_AND)) { - priv->ftp_rqfcr[l] = RQFCR_CLE | RQFCR_CMP_EXACT | - RQFCR_HASHTBL_0 | RQFCR_PID_MASK; - priv->ftp_rqfpr[l] = FPR_FILER_MASK; - gfar_write_filer(priv, l, priv->ftp_rqfcr[l], - priv->ftp_rqfpr[l]); - break; - } - - if (!(priv->ftp_rqfcr[l] & RQFCR_CLE) && - (priv->ftp_rqfcr[l] & RQFCR_AND)) - continue; - else { - local_rqfpr[j] = priv->ftp_rqfpr[l]; - local_rqfcr[j] = priv->ftp_rqfcr[l]; - j--; - } - } - - priv->cur_filer_idx = l - 1; - last_rule_idx = l; - - /* hash rules */ - ethflow_to_filer_rules(priv, ethflow); - - /* Write back the popped out rules again */ - for (k = j+1; k < MAX_FILER_IDX; k++) { - priv->ftp_rqfpr[priv->cur_filer_idx] = local_rqfpr[k]; - priv->ftp_rqfcr[priv->cur_filer_idx] = local_rqfcr[k]; - gfar_write_filer(priv, priv->cur_filer_idx, - local_rqfcr[k], local_rqfpr[k]); - if (!priv->cur_filer_idx) - break; - priv->cur_filer_idx = priv->cur_filer_idx - 1; - } - -err: - kfree(local_rqfcr); - kfree(local_rqfpr); - return ret; -} - -static int gfar_set_hash_opts(struct gfar_private *priv, struct ethtool_rxnfc *cmd) -{ - /* write the filer rules here */ - if (!gfar_ethflow_to_filer_table(priv, cmd->data, cmd->flow_type)) - return -EINVAL; - - return 0; -} - -static int gfar_check_filer_hardware(struct gfar_private *priv) -{ - struct gfar __iomem *regs = NULL; - u32 i; - - regs = priv->gfargrp[0].regs; - - /* Check if we are in FIFO mode */ - i = gfar_read(®s->ecntrl); - i &= ECNTRL_FIFM; - if (i == ECNTRL_FIFM) { - netdev_notice(priv->ndev, "Interface in FIFO mode\n"); - i = gfar_read(®s->rctrl); - i &= RCTRL_PRSDEP_MASK | RCTRL_PRSFM; - if (i == (RCTRL_PRSDEP_MASK | RCTRL_PRSFM)) { - netdev_info(priv->ndev, - "Receive Queue Filtering enabled\n"); - } else { - netdev_warn(priv->ndev, - "Receive Queue Filtering disabled\n"); - return -EOPNOTSUPP; - } - } - /* Or in standard mode */ - else { - i = gfar_read(®s->rctrl); - i &= RCTRL_PRSDEP_MASK; - if (i == RCTRL_PRSDEP_MASK) { - netdev_info(priv->ndev, - "Receive Queue Filtering enabled\n"); - } else { - netdev_warn(priv->ndev, - "Receive Queue Filtering disabled\n"); - return -EOPNOTSUPP; - } - } - - /* Sets the properties for arbitrary filer rule - * to the first 4 Layer 4 Bytes */ - regs->rbifx = 0xC0C1C2C3; - return 0; -} - -static int gfar_comp_asc(const void *a, const void *b) -{ - return memcmp(a, b, 4); -} - -static int gfar_comp_desc(const void *a, const void *b) -{ - return -memcmp(a, b, 4); -} - -static void gfar_swap(void *a, void *b, int size) -{ - u32 *_a = a; - u32 *_b = b; - - swap(_a[0], _b[0]); - swap(_a[1], _b[1]); - swap(_a[2], _b[2]); - swap(_a[3], _b[3]); -} - -/* Write a mask to filer cache */ -static void gfar_set_mask(u32 mask, struct filer_table *tab) -{ - tab->fe[tab->index].ctrl = RQFCR_AND | RQFCR_PID_MASK | RQFCR_CMP_EXACT; - tab->fe[tab->index].prop = mask; - tab->index++; -} - -/* Sets parse bits (e.g. IP or TCP) */ -static void gfar_set_parse_bits(u32 value, u32 mask, struct filer_table *tab) -{ - gfar_set_mask(mask, tab); - tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_PID_PARSE - | RQFCR_AND; - tab->fe[tab->index].prop = value; - tab->index++; -} - -static void gfar_set_general_attribute(u32 value, u32 mask, u32 flag, - struct filer_table *tab) -{ - gfar_set_mask(mask, tab); - tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_AND | flag; - tab->fe[tab->index].prop = value; - tab->index++; -} - -/* - * For setting a tuple of value and mask of type flag - * Example: - * IP-Src = 10.0.0.0/255.0.0.0 - * value: 0x0A000000 mask: FF000000 flag: RQFPR_IPV4 - * - * Ethtool gives us a value=0 and mask=~0 for don't care a tuple - * For a don't care mask it gives us a 0 - * - * The check if don't care and the mask adjustment if mask=0 is done for VLAN - * and MAC stuff on an upper level (due to missing information on this level). - * For these guys we can discard them if they are value=0 and mask=0. - * - * Further the all masks are one-padded for better hardware efficiency. - */ -static void gfar_set_attribute(u32 value, u32 mask, u32 flag, - struct filer_table *tab) -{ - switch (flag) { - /* 3bit */ - case RQFCR_PID_PRI: - if (!(value | mask)) - return; - mask |= RQFCR_PID_PRI_MASK; - break; - /* 8bit */ - case RQFCR_PID_L4P: - case RQFCR_PID_TOS: - if (!~(mask | RQFCR_PID_L4P_MASK)) - return; - if (!mask) - mask = ~0; - else - mask |= RQFCR_PID_L4P_MASK; - break; - /* 12bit */ - case RQFCR_PID_VID: - if (!(value | mask)) - return; - mask |= RQFCR_PID_VID_MASK; - break; - /* 16bit */ - case RQFCR_PID_DPT: - case RQFCR_PID_SPT: - case RQFCR_PID_ETY: - if (!~(mask | RQFCR_PID_PORT_MASK)) - return; - if (!mask) - mask = ~0; - else - mask |= RQFCR_PID_PORT_MASK; - break; - /* 24bit */ - case RQFCR_PID_DAH: - case RQFCR_PID_DAL: - case RQFCR_PID_SAH: - case RQFCR_PID_SAL: - if (!(value | mask)) - return; - mask |= RQFCR_PID_MAC_MASK; - break; - /* for all real 32bit masks */ - default: - if (!~mask) - return; - if (!mask) - mask = ~0; - break; - } - gfar_set_general_attribute(value, mask, flag, tab); -} - -/* Translates value and mask for UDP, TCP or SCTP */ -static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value, - struct ethtool_tcpip4_spec *mask, struct filer_table *tab) -{ - gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab); - gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab); - gfar_set_attribute(value->pdst, mask->pdst, RQFCR_PID_DPT, tab); - gfar_set_attribute(value->psrc, mask->psrc, RQFCR_PID_SPT, tab); - gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab); -} - -/* Translates value and mask for RAW-IP4 */ -static void gfar_set_user_ip(struct ethtool_usrip4_spec *value, - struct ethtool_usrip4_spec *mask, struct filer_table *tab) -{ - gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab); - gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab); - gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab); - gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab); - gfar_set_attribute(value->l4_4_bytes, mask->l4_4_bytes, RQFCR_PID_ARB, - tab); - -} - -/* Translates value and mask for ETHER spec */ -static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask, - struct filer_table *tab) -{ - u32 upper_temp_mask = 0; - u32 lower_temp_mask = 0; - /* Source address */ - if (!is_broadcast_ether_addr(mask->h_source)) { - - if (is_zero_ether_addr(mask->h_source)) { - upper_temp_mask = 0xFFFFFFFF; - lower_temp_mask = 0xFFFFFFFF; - } else { - upper_temp_mask = mask->h_source[0] << 16 - | mask->h_source[1] << 8 - | mask->h_source[2]; - lower_temp_mask = mask->h_source[3] << 16 - | mask->h_source[4] << 8 - | mask->h_source[5]; - } - /* Upper 24bit */ - gfar_set_attribute( - value->h_source[0] << 16 | value->h_source[1] - << 8 | value->h_source[2], - upper_temp_mask, RQFCR_PID_SAH, tab); - /* And the same for the lower part */ - gfar_set_attribute( - value->h_source[3] << 16 | value->h_source[4] - << 8 | value->h_source[5], - lower_temp_mask, RQFCR_PID_SAL, tab); - } - /* Destination address */ - if (!is_broadcast_ether_addr(mask->h_dest)) { - - /* Special for destination is limited broadcast */ - if ((is_broadcast_ether_addr(value->h_dest) - && is_zero_ether_addr(mask->h_dest))) { - gfar_set_parse_bits(RQFPR_EBC, RQFPR_EBC, tab); - } else { - - if (is_zero_ether_addr(mask->h_dest)) { - upper_temp_mask = 0xFFFFFFFF; - lower_temp_mask = 0xFFFFFFFF; - } else { - upper_temp_mask = mask->h_dest[0] << 16 - | mask->h_dest[1] << 8 - | mask->h_dest[2]; - lower_temp_mask = mask->h_dest[3] << 16 - | mask->h_dest[4] << 8 - | mask->h_dest[5]; - } - - /* Upper 24bit */ - gfar_set_attribute( - value->h_dest[0] << 16 - | value->h_dest[1] << 8 - | value->h_dest[2], - upper_temp_mask, RQFCR_PID_DAH, tab); - /* And the same for the lower part */ - gfar_set_attribute( - value->h_dest[3] << 16 - | value->h_dest[4] << 8 - | value->h_dest[5], - lower_temp_mask, RQFCR_PID_DAL, tab); - } - } - - gfar_set_attribute(value->h_proto, mask->h_proto, RQFCR_PID_ETY, tab); - -} - -/* Convert a rule to binary filter format of gianfar */ -static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule, - struct filer_table *tab) -{ - u32 vlan = 0, vlan_mask = 0; - u32 id = 0, id_mask = 0; - u32 cfi = 0, cfi_mask = 0; - u32 prio = 0, prio_mask = 0; - - u32 old_index = tab->index; - - /* Check if vlan is wanted */ - if ((rule->flow_type & FLOW_EXT) && (rule->m_ext.vlan_tci != 0xFFFF)) { - if (!rule->m_ext.vlan_tci) - rule->m_ext.vlan_tci = 0xFFFF; - - vlan = RQFPR_VLN; - vlan_mask = RQFPR_VLN; - - /* Separate the fields */ - id = rule->h_ext.vlan_tci & VLAN_VID_MASK; - id_mask = rule->m_ext.vlan_tci & VLAN_VID_MASK; - cfi = rule->h_ext.vlan_tci & VLAN_CFI_MASK; - cfi_mask = rule->m_ext.vlan_tci & VLAN_CFI_MASK; - prio = (rule->h_ext.vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; - prio_mask = (rule->m_ext.vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; - - if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) { - vlan |= RQFPR_CFI; - vlan_mask |= RQFPR_CFI; - } else if (cfi != VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) { - vlan_mask |= RQFPR_CFI; - } - } - - switch (rule->flow_type & ~FLOW_EXT) { - case TCP_V4_FLOW: - gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_TCP | vlan, - RQFPR_IPV4 | RQFPR_TCP | vlan_mask, tab); - gfar_set_basic_ip(&rule->h_u.tcp_ip4_spec, - &rule->m_u.tcp_ip4_spec, tab); - break; - case UDP_V4_FLOW: - gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_UDP | vlan, - RQFPR_IPV4 | RQFPR_UDP | vlan_mask, tab); - gfar_set_basic_ip(&rule->h_u.udp_ip4_spec, - &rule->m_u.udp_ip4_spec, tab); - break; - case SCTP_V4_FLOW: - gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask, - tab); - gfar_set_attribute(132, 0, RQFCR_PID_L4P, tab); - gfar_set_basic_ip((struct ethtool_tcpip4_spec *) &rule->h_u, - (struct ethtool_tcpip4_spec *) &rule->m_u, tab); - break; - case IP_USER_FLOW: - gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask, - tab); - gfar_set_user_ip((struct ethtool_usrip4_spec *) &rule->h_u, - (struct ethtool_usrip4_spec *) &rule->m_u, tab); - break; - case ETHER_FLOW: - if (vlan) - gfar_set_parse_bits(vlan, vlan_mask, tab); - gfar_set_ether((struct ethhdr *) &rule->h_u, - (struct ethhdr *) &rule->m_u, tab); - break; - default: - return -1; - } - - /* Set the vlan attributes in the end */ - if (vlan) { - gfar_set_attribute(id, id_mask, RQFCR_PID_VID, tab); - gfar_set_attribute(prio, prio_mask, RQFCR_PID_PRI, tab); - } - - /* If there has been nothing written till now, it must be a default */ - if (tab->index == old_index) { - gfar_set_mask(0xFFFFFFFF, tab); - tab->fe[tab->index].ctrl = 0x20; - tab->fe[tab->index].prop = 0x0; - tab->index++; - } - - /* Remove last AND */ - tab->fe[tab->index - 1].ctrl &= (~RQFCR_AND); - - /* Specify which queue to use or to drop */ - if (rule->ring_cookie == RX_CLS_FLOW_DISC) - tab->fe[tab->index - 1].ctrl |= RQFCR_RJE; - else - tab->fe[tab->index - 1].ctrl |= (rule->ring_cookie << 10); - - /* Only big enough entries can be clustered */ - if (tab->index > (old_index + 2)) { - tab->fe[old_index + 1].ctrl |= RQFCR_CLE; - tab->fe[tab->index - 1].ctrl |= RQFCR_CLE; - } - - /* In rare cases the cache can be full while there is free space in hw */ - if (tab->index > MAX_FILER_CACHE_IDX - 1) - return -EBUSY; - - return 0; -} - -/* Copy size filer entries */ -static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0], - struct gfar_filer_entry src[0], s32 size) -{ - while (size > 0) { - size--; - dst[size].ctrl = src[size].ctrl; - dst[size].prop = src[size].prop; - } -} - -/* Delete the contents of the filer-table between start and end - * and collapse them */ -static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab) -{ - int length; - if (end > MAX_FILER_CACHE_IDX || end < begin) - return -EINVAL; - - end++; - length = end - begin; - - /* Copy */ - while (end < tab->index) { - tab->fe[begin].ctrl = tab->fe[end].ctrl; - tab->fe[begin++].prop = tab->fe[end++].prop; - - } - /* Fill up with don't cares */ - while (begin < tab->index) { - tab->fe[begin].ctrl = 0x60; - tab->fe[begin].prop = 0xFFFFFFFF; - begin++; - } - - tab->index -= length; - return 0; -} - -/* Make space on the wanted location */ -static int gfar_expand_filer_entries(u32 begin, u32 length, - struct filer_table *tab) -{ - if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX || begin - > MAX_FILER_CACHE_IDX) - return -EINVAL; - - gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]), - tab->index - length + 1); - - tab->index += length; - return 0; -} - -static int gfar_get_next_cluster_start(int start, struct filer_table *tab) -{ - for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) { - if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) - == (RQFCR_AND | RQFCR_CLE)) - return start; - } - return -1; -} - -static int gfar_get_next_cluster_end(int start, struct filer_table *tab) -{ - for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) { - if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) - == (RQFCR_CLE)) - return start; - } - return -1; -} - -/* - * Uses hardwares clustering option to reduce - * the number of filer table entries - */ -static void gfar_cluster_filer(struct filer_table *tab) -{ - s32 i = -1, j, iend, jend; - - while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) { - j = i; - while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) { - /* - * The cluster entries self and the previous one - * (a mask) must be identical! - */ - if (tab->fe[i].ctrl != tab->fe[j].ctrl) - break; - if (tab->fe[i].prop != tab->fe[j].prop) - break; - if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl) - break; - if (tab->fe[i - 1].prop != tab->fe[j - 1].prop) - break; - iend = gfar_get_next_cluster_end(i, tab); - jend = gfar_get_next_cluster_end(j, tab); - if (jend == -1 || iend == -1) - break; - /* - * First we make some free space, where our cluster - * element should be. Then we copy it there and finally - * delete in from its old location. - */ - - if (gfar_expand_filer_entries(iend, (jend - j), tab) - == -EINVAL) - break; - - gfar_copy_filer_entries(&(tab->fe[iend + 1]), - &(tab->fe[jend + 1]), jend - j); - - if (gfar_trim_filer_entries(jend - 1, - jend + (jend - j), tab) == -EINVAL) - return; - - /* Mask out cluster bit */ - tab->fe[iend].ctrl &= ~(RQFCR_CLE); - } - } -} - -/* Swaps the masked bits of a1<>a2 and b1<>b2 */ -static void gfar_swap_bits(struct gfar_filer_entry *a1, - struct gfar_filer_entry *a2, struct gfar_filer_entry *b1, - struct gfar_filer_entry *b2, u32 mask) -{ - u32 temp[4]; - temp[0] = a1->ctrl & mask; - temp[1] = a2->ctrl & mask; - temp[2] = b1->ctrl & mask; - temp[3] = b2->ctrl & mask; - - a1->ctrl &= ~mask; - a2->ctrl &= ~mask; - b1->ctrl &= ~mask; - b2->ctrl &= ~mask; - - a1->ctrl |= temp[1]; - a2->ctrl |= temp[0]; - b1->ctrl |= temp[3]; - b2->ctrl |= temp[2]; -} - -/* - * Generate a list consisting of masks values with their start and - * end of validity and block as indicator for parts belonging - * together (glued by ANDs) in mask_table - */ -static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table, - struct filer_table *tab) -{ - u32 i, and_index = 0, block_index = 1; - - for (i = 0; i < tab->index; i++) { - - /* LSByte of control = 0 sets a mask */ - if (!(tab->fe[i].ctrl & 0xF)) { - mask_table[and_index].mask = tab->fe[i].prop; - mask_table[and_index].start = i; - mask_table[and_index].block = block_index; - if (and_index >= 1) - mask_table[and_index - 1].end = i - 1; - and_index++; - } - /* cluster starts and ends will be separated because they should - * hold their position */ - if (tab->fe[i].ctrl & RQFCR_CLE) - block_index++; - /* A not set AND indicates the end of a depended block */ - if (!(tab->fe[i].ctrl & RQFCR_AND)) - block_index++; - - } - - mask_table[and_index - 1].end = i - 1; - - return and_index; -} - -/* - * Sorts the entries of mask_table by the values of the masks. - * Important: The 0xFF80 flags of the first and last entry of a - * block must hold their position (which queue, CLusterEnable, ReJEct, - * AND) - */ -static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table, - struct filer_table *temp_table, u32 and_index) -{ - /* Pointer to compare function (_asc or _desc) */ - int (*gfar_comp)(const void *, const void *); - - u32 i, size = 0, start = 0, prev = 1; - u32 old_first, old_last, new_first, new_last; - - gfar_comp = &gfar_comp_desc; - - for (i = 0; i < and_index; i++) { - - if (prev != mask_table[i].block) { - old_first = mask_table[start].start + 1; - old_last = mask_table[i - 1].end; - sort(mask_table + start, size, - sizeof(struct gfar_mask_entry), - gfar_comp, &gfar_swap); - - /* Toggle order for every block. This makes the - * thing more efficient! */ - if (gfar_comp == gfar_comp_desc) - gfar_comp = &gfar_comp_asc; - else - gfar_comp = &gfar_comp_desc; - - new_first = mask_table[start].start + 1; - new_last = mask_table[i - 1].end; - - gfar_swap_bits(&temp_table->fe[new_first], - &temp_table->fe[old_first], - &temp_table->fe[new_last], - &temp_table->fe[old_last], - RQFCR_QUEUE | RQFCR_CLE | - RQFCR_RJE | RQFCR_AND - ); - - start = i; - size = 0; - } - size++; - prev = mask_table[i].block; - } - -} - -/* - * Reduces the number of masks needed in the filer table to save entries - * This is done by sorting the masks of a depended block. A depended block is - * identified by gluing ANDs or CLE. The sorting order toggles after every - * block. Of course entries in scope of a mask must change their location with - * it. - */ -static int gfar_optimize_filer_masks(struct filer_table *tab) -{ - struct filer_table *temp_table; - struct gfar_mask_entry *mask_table; - - u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0; - s32 ret = 0; - - /* We need a copy of the filer table because - * we want to change its order */ - temp_table = kmemdup(tab, sizeof(*temp_table), GFP_KERNEL); - if (temp_table == NULL) - return -ENOMEM; - - mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1, - sizeof(struct gfar_mask_entry), GFP_KERNEL); - - if (mask_table == NULL) { - ret = -ENOMEM; - goto end; - } - - and_index = gfar_generate_mask_table(mask_table, tab); - - gfar_sort_mask_table(mask_table, temp_table, and_index); - - /* Now we can copy the data from our duplicated filer table to - * the real one in the order the mask table says */ - for (i = 0; i < and_index; i++) { - size = mask_table[i].end - mask_table[i].start + 1; - gfar_copy_filer_entries(&(tab->fe[j]), - &(temp_table->fe[mask_table[i].start]), size); - j += size; - } - - /* And finally we just have to check for duplicated masks and drop the - * second ones */ - for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) { - if (tab->fe[i].ctrl == 0x80) { - previous_mask = i++; - break; - } - } - for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) { - if (tab->fe[i].ctrl == 0x80) { - if (tab->fe[i].prop == tab->fe[previous_mask].prop) { - /* Two identical ones found! - * So drop the second one! */ - gfar_trim_filer_entries(i, i, tab); - } else - /* Not identical! */ - previous_mask = i; - } - } - - kfree(mask_table); -end: kfree(temp_table); - return ret; -} - -/* Write the bit-pattern from software's buffer to hardware registers */ -static int gfar_write_filer_table(struct gfar_private *priv, - struct filer_table *tab) -{ - u32 i = 0; - if (tab->index > MAX_FILER_IDX - 1) - return -EBUSY; - - /* Avoid inconsistent filer table to be processed */ - lock_rx_qs(priv); - - /* Fill regular entries */ - for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); i++) - gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop); - /* Fill the rest with fall-troughs */ - for (; i < MAX_FILER_IDX - 1; i++) - gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF); - /* Last entry must be default accept - * because that's what people expect */ - gfar_write_filer(priv, i, 0x20, 0x0); - - unlock_rx_qs(priv); - - return 0; -} - -static int gfar_check_capability(struct ethtool_rx_flow_spec *flow, - struct gfar_private *priv) -{ - - if (flow->flow_type & FLOW_EXT) { - if (~flow->m_ext.data[0] || ~flow->m_ext.data[1]) - netdev_warn(priv->ndev, - "User-specific data not supported!\n"); - if (~flow->m_ext.vlan_etype) - netdev_warn(priv->ndev, - "VLAN-etype not supported!\n"); - } - if (flow->flow_type == IP_USER_FLOW) - if (flow->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4) - netdev_warn(priv->ndev, - "IP-Version differing from IPv4 not supported!\n"); - - return 0; -} - -static int gfar_process_filer_changes(struct gfar_private *priv) -{ - struct ethtool_flow_spec_container *j; - struct filer_table *tab; - s32 i = 0; - s32 ret = 0; - - /* So index is set to zero, too! */ - tab = kzalloc(sizeof(*tab), GFP_KERNEL); - if (tab == NULL) - return -ENOMEM; - - /* Now convert the existing filer data from flow_spec into - * filer tables binary format */ - list_for_each_entry(j, &priv->rx_list.list, list) { - ret = gfar_convert_to_filer(&j->fs, tab); - if (ret == -EBUSY) { - netdev_err(priv->ndev, "Rule not added: No free space!\n"); - goto end; - } - if (ret == -1) { - netdev_err(priv->ndev, "Rule not added: Unsupported Flow-type!\n"); - goto end; - } - } - - i = tab->index; - - /* Optimizations to save entries */ - gfar_cluster_filer(tab); - gfar_optimize_filer_masks(tab); - - pr_debug("\n\tSummary:\n" - "\tData on hardware: %d\n" - "\tCompression rate: %d%%\n", - tab->index, 100 - (100 * tab->index) / i); - - /* Write everything to hardware */ - ret = gfar_write_filer_table(priv, tab); - if (ret == -EBUSY) { - netdev_err(priv->ndev, "Rule not added: No free space!\n"); - goto end; - } - -end: kfree(tab); - return ret; -} - -static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow) -{ - u32 i = 0; - - for (i = 0; i < sizeof(flow->m_u); i++) - flow->m_u.hdata[i] ^= 0xFF; - - flow->m_ext.vlan_etype ^= 0xFFFF; - flow->m_ext.vlan_tci ^= 0xFFFF; - flow->m_ext.data[0] ^= ~0; - flow->m_ext.data[1] ^= ~0; -} - -static int gfar_add_cls(struct gfar_private *priv, - struct ethtool_rx_flow_spec *flow) -{ - struct ethtool_flow_spec_container *temp, *comp; - int ret = 0; - - temp = kmalloc(sizeof(*temp), GFP_KERNEL); - if (temp == NULL) - return -ENOMEM; - memcpy(&temp->fs, flow, sizeof(temp->fs)); - - gfar_invert_masks(&temp->fs); - ret = gfar_check_capability(&temp->fs, priv); - if (ret) - goto clean_mem; - /* Link in the new element at the right @location */ - if (list_empty(&priv->rx_list.list)) { - ret = gfar_check_filer_hardware(priv); - if (ret != 0) - goto clean_mem; - list_add(&temp->list, &priv->rx_list.list); - goto process; - } else { - - list_for_each_entry(comp, &priv->rx_list.list, list) { - if (comp->fs.location > flow->location) { - list_add_tail(&temp->list, &comp->list); - goto process; - } - if (comp->fs.location == flow->location) { - netdev_err(priv->ndev, - "Rule not added: ID %d not free!\n", - flow->location); - ret = -EBUSY; - goto clean_mem; - } - } - list_add_tail(&temp->list, &priv->rx_list.list); - } - -process: - ret = gfar_process_filer_changes(priv); - if (ret) - goto clean_list; - priv->rx_list.count++; - return ret; - -clean_list: - list_del(&temp->list); -clean_mem: - kfree(temp); - return ret; -} - -static int gfar_del_cls(struct gfar_private *priv, u32 loc) -{ - struct ethtool_flow_spec_container *comp; - u32 ret = -EINVAL; - - if (list_empty(&priv->rx_list.list)) - return ret; - - list_for_each_entry(comp, &priv->rx_list.list, list) { - if (comp->fs.location == loc) { - list_del(&comp->list); - kfree(comp); - priv->rx_list.count--; - gfar_process_filer_changes(priv); - ret = 0; - break; - } - } - - return ret; - -} - -static int gfar_get_cls(struct gfar_private *priv, struct ethtool_rxnfc *cmd) -{ - struct ethtool_flow_spec_container *comp; - u32 ret = -EINVAL; - - list_for_each_entry(comp, &priv->rx_list.list, list) { - if (comp->fs.location == cmd->fs.location) { - memcpy(&cmd->fs, &comp->fs, sizeof(cmd->fs)); - gfar_invert_masks(&cmd->fs); - ret = 0; - break; - } - } - - return ret; -} - -static int gfar_get_cls_all(struct gfar_private *priv, - struct ethtool_rxnfc *cmd, u32 *rule_locs) -{ - struct ethtool_flow_spec_container *comp; - u32 i = 0; - - list_for_each_entry(comp, &priv->rx_list.list, list) { - if (i == cmd->rule_cnt) - return -EMSGSIZE; - rule_locs[i] = comp->fs.location; - i++; - } - - cmd->data = MAX_FILER_IDX; - cmd->rule_cnt = i; - - return 0; -} - -static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct gfar_private *priv = netdev_priv(dev); - int ret = 0; - - mutex_lock(&priv->rx_queue_access); - - switch (cmd->cmd) { - case ETHTOOL_SRXFH: - ret = gfar_set_hash_opts(priv, cmd); - break; - case ETHTOOL_SRXCLSRLINS: - if ((cmd->fs.ring_cookie != RX_CLS_FLOW_DISC && - cmd->fs.ring_cookie >= priv->num_rx_queues) || - cmd->fs.location >= MAX_FILER_IDX) { - ret = -EINVAL; - break; - } - ret = gfar_add_cls(priv, &cmd->fs); - break; - case ETHTOOL_SRXCLSRLDEL: - ret = gfar_del_cls(priv, cmd->fs.location); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&priv->rx_queue_access); - - return ret; -} - -static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs) -{ - struct gfar_private *priv = netdev_priv(dev); - int ret = 0; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = priv->num_rx_queues; - break; - case ETHTOOL_GRXCLSRLCNT: - cmd->rule_cnt = priv->rx_list.count; - break; - case ETHTOOL_GRXCLSRULE: - ret = gfar_get_cls(priv, cmd); - break; - case ETHTOOL_GRXCLSRLALL: - ret = gfar_get_cls_all(priv, cmd, rule_locs); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -const struct ethtool_ops gfar_ethtool_ops = { - .get_settings = gfar_gsettings, - .set_settings = gfar_ssettings, - .get_drvinfo = gfar_gdrvinfo, - .get_regs_len = gfar_reglen, - .get_regs = gfar_get_regs, - .get_link = ethtool_op_get_link, - .get_coalesce = gfar_gcoalesce, - .set_coalesce = gfar_scoalesce, - .get_ringparam = gfar_gringparam, - .set_ringparam = gfar_sringparam, - .get_strings = gfar_gstrings, - .get_sset_count = gfar_sset_count, - .get_ethtool_stats = gfar_fill_stats, - .get_msglevel = gfar_get_msglevel, - .set_msglevel = gfar_set_msglevel, -#ifdef CONFIG_PM - .get_wol = gfar_get_wol, - .set_wol = gfar_set_wol, -#endif - .set_rxnfc = gfar_set_nfc, - .get_rxnfc = gfar_get_nfc, -}; diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_ptp.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_ptp.c deleted file mode 100644 index 5fd620be..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_ptp.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * PTP 1588 clock using the eTSEC - * - * Copyright (C) 2010 OMICRON electronics GmbH - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <linux/device.h> -#include <linux/hrtimer.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_platform.h> -#include <linux/timex.h> -#include <linux/io.h> - -#include <linux/ptp_clock_kernel.h> - -#include "gianfar.h" - -/* - * gianfar ptp registers - * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010 - */ -struct gianfar_ptp_registers { - u32 tmr_ctrl; /* Timer control register */ - u32 tmr_tevent; /* Timestamp event register */ - u32 tmr_temask; /* Timer event mask register */ - u32 tmr_pevent; /* Timestamp event register */ - u32 tmr_pemask; /* Timer event mask register */ - u32 tmr_stat; /* Timestamp status register */ - u32 tmr_cnt_h; /* Timer counter high register */ - u32 tmr_cnt_l; /* Timer counter low register */ - u32 tmr_add; /* Timer drift compensation addend register */ - u32 tmr_acc; /* Timer accumulator register */ - u32 tmr_prsc; /* Timer prescale */ - u8 res1[4]; - u32 tmroff_h; /* Timer offset high */ - u32 tmroff_l; /* Timer offset low */ - u8 res2[8]; - u32 tmr_alarm1_h; /* Timer alarm 1 high register */ - u32 tmr_alarm1_l; /* Timer alarm 1 high register */ - u32 tmr_alarm2_h; /* Timer alarm 2 high register */ - u32 tmr_alarm2_l; /* Timer alarm 2 high register */ - u8 res3[48]; - u32 tmr_fiper1; /* Timer fixed period interval */ - u32 tmr_fiper2; /* Timer fixed period interval */ - u32 tmr_fiper3; /* Timer fixed period interval */ - u8 res4[20]; - u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */ - u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */ - u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */ - u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */ -}; - -/* Bit definitions for the TMR_CTRL register */ -#define ALM1P (1<<31) /* Alarm1 output polarity */ -#define ALM2P (1<<30) /* Alarm2 output polarity */ -#define FS (1<<28) /* FIPER start indication */ -#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */ -#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */ -#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */ -#define TCLK_PERIOD_MASK (0x3ff) -#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */ -#define FRD (1<<14) /* FIPER Realignment Disable */ -#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */ -#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */ -#define ETEP2 (1<<9) /* External trigger 2 edge polarity */ -#define ETEP1 (1<<8) /* External trigger 1 edge polarity */ -#define COPH (1<<7) /* Generated clock output phase. */ -#define CIPH (1<<6) /* External oscillator input clock phase */ -#define TMSR (1<<5) /* Timer soft reset. */ -#define BYP (1<<3) /* Bypass drift compensated clock */ -#define TE (1<<2) /* 1588 timer enable. */ -#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */ -#define CKSEL_MASK (0x3) - -/* Bit definitions for the TMR_TEVENT register */ -#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */ -#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */ -#define ALM2 (1<<17) /* Current time = alarm time register 2 */ -#define ALM1 (1<<16) /* Current time = alarm time register 1 */ -#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */ -#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */ -#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */ - -/* Bit definitions for the TMR_TEMASK register */ -#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */ -#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */ -#define ALM2EN (1<<17) /* Timer ALM2 event enable */ -#define ALM1EN (1<<16) /* Timer ALM1 event enable */ -#define PP1EN (1<<7) /* Periodic pulse event 1 enable */ -#define PP2EN (1<<6) /* Periodic pulse event 2 enable */ - -/* Bit definitions for the TMR_PEVENT register */ -#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */ -#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */ -#define RXP (1<<0) /* PTP frame has been received */ - -/* Bit definitions for the TMR_PEMASK register */ -#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */ -#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */ -#define RXPEN (1<<0) /* Receive PTP packet event enable */ - -/* Bit definitions for the TMR_STAT register */ -#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ -#define STAT_VEC_MASK (0x3f) - -/* Bit definitions for the TMR_PRSC register */ -#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ -#define PRSC_OCK_MASK (0xffff) - - -#define DRIVER "gianfar_ptp" -#define DEFAULT_CKSEL 1 -#define N_ALARM 1 /* first alarm is used internally to reset fipers */ -#define N_EXT_TS 2 -#define REG_SIZE sizeof(struct gianfar_ptp_registers) - -struct etsects { - struct gianfar_ptp_registers *regs; - spinlock_t lock; /* protects regs */ - struct ptp_clock *clock; - struct ptp_clock_info caps; - struct resource *rsrc; - int irq; - u64 alarm_interval; /* for periodic alarm */ - u64 alarm_value; - u32 tclk_period; /* nanoseconds */ - u32 tmr_prsc; - u32 tmr_add; - u32 cksel; - u32 tmr_fiper1; - u32 tmr_fiper2; -}; - -/* - * Register access functions - */ - -/* Caller must hold etsects->lock. */ -static u64 tmr_cnt_read(struct etsects *etsects) -{ - u64 ns; - u32 lo, hi; - - lo = gfar_read(&etsects->regs->tmr_cnt_l); - hi = gfar_read(&etsects->regs->tmr_cnt_h); - ns = ((u64) hi) << 32; - ns |= lo; - return ns; -} - -/* Caller must hold etsects->lock. */ -static void tmr_cnt_write(struct etsects *etsects, u64 ns) -{ - u32 hi = ns >> 32; - u32 lo = ns & 0xffffffff; - - gfar_write(&etsects->regs->tmr_cnt_l, lo); - gfar_write(&etsects->regs->tmr_cnt_h, hi); -} - -/* Caller must hold etsects->lock. */ -static void set_alarm(struct etsects *etsects) -{ - u64 ns; - u32 lo, hi; - - ns = tmr_cnt_read(etsects) + 1500000000ULL; - ns = div_u64(ns, 1000000000UL) * 1000000000ULL; - ns -= etsects->tclk_period; - hi = ns >> 32; - lo = ns & 0xffffffff; - gfar_write(&etsects->regs->tmr_alarm1_l, lo); - gfar_write(&etsects->regs->tmr_alarm1_h, hi); -} - -/* Caller must hold etsects->lock. */ -static void set_fipers(struct etsects *etsects) -{ - set_alarm(etsects); - gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); - gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); -} - -/* - * Interrupt service routine - */ - -static irqreturn_t isr(int irq, void *priv) -{ - struct etsects *etsects = priv; - struct ptp_clock_event event; - u64 ns; - u32 ack = 0, lo, hi, mask, val; - - val = gfar_read(&etsects->regs->tmr_tevent); - - if (val & ETS1) { - ack |= ETS1; - hi = gfar_read(&etsects->regs->tmr_etts1_h); - lo = gfar_read(&etsects->regs->tmr_etts1_l); - event.type = PTP_CLOCK_EXTTS; - event.index = 0; - event.timestamp = ((u64) hi) << 32; - event.timestamp |= lo; - ptp_clock_event(etsects->clock, &event); - } - - if (val & ETS2) { - ack |= ETS2; - hi = gfar_read(&etsects->regs->tmr_etts2_h); - lo = gfar_read(&etsects->regs->tmr_etts2_l); - event.type = PTP_CLOCK_EXTTS; - event.index = 1; - event.timestamp = ((u64) hi) << 32; - event.timestamp |= lo; - ptp_clock_event(etsects->clock, &event); - } - - if (val & ALM2) { - ack |= ALM2; - if (etsects->alarm_value) { - event.type = PTP_CLOCK_ALARM; - event.index = 0; - event.timestamp = etsects->alarm_value; - ptp_clock_event(etsects->clock, &event); - } - if (etsects->alarm_interval) { - ns = etsects->alarm_value + etsects->alarm_interval; - hi = ns >> 32; - lo = ns & 0xffffffff; - spin_lock(&etsects->lock); - gfar_write(&etsects->regs->tmr_alarm2_l, lo); - gfar_write(&etsects->regs->tmr_alarm2_h, hi); - spin_unlock(&etsects->lock); - etsects->alarm_value = ns; - } else { - gfar_write(&etsects->regs->tmr_tevent, ALM2); - spin_lock(&etsects->lock); - mask = gfar_read(&etsects->regs->tmr_temask); - mask &= ~ALM2EN; - gfar_write(&etsects->regs->tmr_temask, mask); - spin_unlock(&etsects->lock); - etsects->alarm_value = 0; - etsects->alarm_interval = 0; - } - } - - if (val & PP1) { - ack |= PP1; - event.type = PTP_CLOCK_PPS; - ptp_clock_event(etsects->clock, &event); - } - - if (ack) { - gfar_write(&etsects->regs->tmr_tevent, ack); - return IRQ_HANDLED; - } else - return IRQ_NONE; -} - -/* - * PTP clock operations - */ - -static int ptp_gianfar_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - u64 adj; - u32 diff, tmr_add; - int neg_adj = 0; - struct etsects *etsects = container_of(ptp, struct etsects, caps); - - if (ppb < 0) { - neg_adj = 1; - ppb = -ppb; - } - tmr_add = etsects->tmr_add; - adj = tmr_add; - adj *= ppb; - diff = div_u64(adj, 1000000000ULL); - - tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; - - gfar_write(&etsects->regs->tmr_add, tmr_add); - - return 0; -} - -static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - s64 now; - unsigned long flags; - struct etsects *etsects = container_of(ptp, struct etsects, caps); - - spin_lock_irqsave(&etsects->lock, flags); - - now = tmr_cnt_read(etsects); - now += delta; - tmr_cnt_write(etsects, now); - - spin_unlock_irqrestore(&etsects->lock, flags); - - set_fipers(etsects); - - return 0; -} - -static int ptp_gianfar_gettime(struct ptp_clock_info *ptp, struct timespec *ts) -{ - u64 ns; - u32 remainder; - unsigned long flags; - struct etsects *etsects = container_of(ptp, struct etsects, caps); - - spin_lock_irqsave(&etsects->lock, flags); - - ns = tmr_cnt_read(etsects); - - spin_unlock_irqrestore(&etsects->lock, flags); - - ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); - ts->tv_nsec = remainder; - return 0; -} - -static int ptp_gianfar_settime(struct ptp_clock_info *ptp, - const struct timespec *ts) -{ - u64 ns; - unsigned long flags; - struct etsects *etsects = container_of(ptp, struct etsects, caps); - - ns = ts->tv_sec * 1000000000ULL; - ns += ts->tv_nsec; - - spin_lock_irqsave(&etsects->lock, flags); - - tmr_cnt_write(etsects, ns); - set_fipers(etsects); - - spin_unlock_irqrestore(&etsects->lock, flags); - - return 0; -} - -static int ptp_gianfar_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) -{ - struct etsects *etsects = container_of(ptp, struct etsects, caps); - unsigned long flags; - u32 bit, mask; - - switch (rq->type) { - case PTP_CLK_REQ_EXTTS: - switch (rq->extts.index) { - case 0: - bit = ETS1EN; - break; - case 1: - bit = ETS2EN; - break; - default: - return -EINVAL; - } - spin_lock_irqsave(&etsects->lock, flags); - mask = gfar_read(&etsects->regs->tmr_temask); - if (on) - mask |= bit; - else - mask &= ~bit; - gfar_write(&etsects->regs->tmr_temask, mask); - spin_unlock_irqrestore(&etsects->lock, flags); - return 0; - - case PTP_CLK_REQ_PPS: - spin_lock_irqsave(&etsects->lock, flags); - mask = gfar_read(&etsects->regs->tmr_temask); - if (on) - mask |= PP1EN; - else - mask &= ~PP1EN; - gfar_write(&etsects->regs->tmr_temask, mask); - spin_unlock_irqrestore(&etsects->lock, flags); - return 0; - - default: - break; - } - - return -EOPNOTSUPP; -} - -static struct ptp_clock_info ptp_gianfar_caps = { - .owner = THIS_MODULE, - .name = "gianfar clock", - .max_adj = 512000, - .n_alarm = N_ALARM, - .n_ext_ts = N_EXT_TS, - .n_per_out = 0, - .pps = 1, - .adjfreq = ptp_gianfar_adjfreq, - .adjtime = ptp_gianfar_adjtime, - .gettime = ptp_gianfar_gettime, - .settime = ptp_gianfar_settime, - .enable = ptp_gianfar_enable, -}; - -/* OF device tree */ - -static int get_of_u32(struct device_node *node, char *str, u32 *val) -{ - int plen; - const u32 *prop = of_get_property(node, str, &plen); - - if (!prop || plen != sizeof(*prop)) - return -1; - *val = *prop; - return 0; -} - -static int gianfar_ptp_probe(struct platform_device *dev) -{ - struct device_node *node = dev->dev.of_node; - struct etsects *etsects; - struct timespec now; - int err = -ENOMEM; - u32 tmr_ctrl; - unsigned long flags; - - etsects = kzalloc(sizeof(*etsects), GFP_KERNEL); - if (!etsects) - goto no_memory; - - err = -ENODEV; - - etsects->caps = ptp_gianfar_caps; - etsects->cksel = DEFAULT_CKSEL; - - if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) || - get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) || - get_of_u32(node, "fsl,tmr-add", &etsects->tmr_add) || - get_of_u32(node, "fsl,tmr-fiper1", &etsects->tmr_fiper1) || - get_of_u32(node, "fsl,tmr-fiper2", &etsects->tmr_fiper2) || - get_of_u32(node, "fsl,max-adj", &etsects->caps.max_adj)) { - pr_err("device tree node missing required elements\n"); - goto no_node; - } - - etsects->irq = platform_get_irq(dev, 0); - - if (etsects->irq == NO_IRQ) { - pr_err("irq not in device tree\n"); - goto no_node; - } - if (request_irq(etsects->irq, isr, 0, DRIVER, etsects)) { - pr_err("request_irq failed\n"); - goto no_node; - } - - etsects->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!etsects->rsrc) { - pr_err("no resource\n"); - goto no_resource; - } - if (request_resource(&ioport_resource, etsects->rsrc)) { - pr_err("resource busy\n"); - goto no_resource; - } - - spin_lock_init(&etsects->lock); - - etsects->regs = ioremap(etsects->rsrc->start, - resource_size(etsects->rsrc)); - if (!etsects->regs) { - pr_err("ioremap ptp registers failed\n"); - goto no_ioremap; - } - getnstimeofday(&now); - ptp_gianfar_settime(&etsects->caps, &now); - - tmr_ctrl = - (etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | - (etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT; - - spin_lock_irqsave(&etsects->lock, flags); - - gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl); - gfar_write(&etsects->regs->tmr_add, etsects->tmr_add); - gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); - gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); - gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); - set_alarm(etsects); - gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE|FRD); - - spin_unlock_irqrestore(&etsects->lock, flags); - - etsects->clock = ptp_clock_register(&etsects->caps); - if (IS_ERR(etsects->clock)) { - err = PTR_ERR(etsects->clock); - goto no_clock; - } - - dev_set_drvdata(&dev->dev, etsects); - - return 0; - -no_clock: -no_ioremap: - release_resource(etsects->rsrc); -no_resource: - free_irq(etsects->irq, etsects); -no_node: - kfree(etsects); -no_memory: - return err; -} - -static int gianfar_ptp_remove(struct platform_device *dev) -{ - struct etsects *etsects = dev_get_drvdata(&dev->dev); - - gfar_write(&etsects->regs->tmr_temask, 0); - gfar_write(&etsects->regs->tmr_ctrl, 0); - - ptp_clock_unregister(etsects->clock); - iounmap(etsects->regs); - release_resource(etsects->rsrc); - free_irq(etsects->irq, etsects); - kfree(etsects); - - return 0; -} - -static struct of_device_id match_table[] = { - { .compatible = "fsl,etsec-ptp" }, - {}, -}; - -static struct platform_driver gianfar_ptp_driver = { - .driver = { - .name = "gianfar_ptp", - .of_match_table = match_table, - .owner = THIS_MODULE, - }, - .probe = gianfar_ptp_probe, - .remove = gianfar_ptp_remove, -}; - -module_platform_driver(gianfar_ptp_driver); - -MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>"); -MODULE_DESCRIPTION("PTP clock using the eTSEC"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_sysfs.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_sysfs.c deleted file mode 100644 index cd14a4d4..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/gianfar_sysfs.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * drivers/net/ethernet/freescale/gianfar_sysfs.c - * - * Gianfar Ethernet Driver - * This driver is designed for the non-CPM ethernet controllers - * on the 85xx and 83xx family of integrated processors - * Based on 8260_io/fcc_enet.c - * - * Author: Andy Fleming - * Maintainer: Kumar Gala (galak@kernel.crashing.org) - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> - * - * Copyright 2002-2009 Freescale Semiconductor, Inc. - * - * 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. - * - * Sysfs file creation and management - */ - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/unistd.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/device.h> - -#include <asm/uaccess.h> -#include <linux/module.h> - -#include "gianfar.h" - -static ssize_t gfar_show_bd_stash(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - - return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off"); -} - -static ssize_t gfar_set_bd_stash(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - int new_setting = 0; - u32 temp; - unsigned long flags; - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) - return count; - - - /* Find out the new setting */ - if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) - new_setting = 1; - else if (!strncmp("off", buf, count - 1) || - !strncmp("0", buf, count - 1)) - new_setting = 0; - else - return count; - - - local_irq_save(flags); - lock_rx_qs(priv); - - /* Set the new stashing value */ - priv->bd_stash_en = new_setting; - - temp = gfar_read(®s->attr); - - if (new_setting) - temp |= ATTR_BDSTASH; - else - temp &= ~(ATTR_BDSTASH); - - gfar_write(®s->attr, temp); - - unlock_rx_qs(priv); - local_irq_restore(flags); - - return count; -} - -static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash); - -static ssize_t gfar_show_rx_stash_size(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - - return sprintf(buf, "%d\n", priv->rx_stash_size); -} - -static ssize_t gfar_set_rx_stash_size(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned int length = simple_strtoul(buf, NULL, 0); - u32 temp; - unsigned long flags; - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) - return count; - - local_irq_save(flags); - lock_rx_qs(priv); - - if (length > priv->rx_buffer_size) - goto out; - - if (length == priv->rx_stash_size) - goto out; - - priv->rx_stash_size = length; - - temp = gfar_read(®s->attreli); - temp &= ~ATTRELI_EL_MASK; - temp |= ATTRELI_EL(length); - gfar_write(®s->attreli, temp); - - /* Turn stashing on/off as appropriate */ - temp = gfar_read(®s->attr); - - if (length) - temp |= ATTR_BUFSTASH; - else - temp &= ~(ATTR_BUFSTASH); - - gfar_write(®s->attr, temp); - -out: - unlock_rx_qs(priv); - local_irq_restore(flags); - - return count; -} - -static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size, - gfar_set_rx_stash_size); - -/* Stashing will only be enabled when rx_stash_size != 0 */ -static ssize_t gfar_show_rx_stash_index(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - - return sprintf(buf, "%d\n", priv->rx_stash_index); -} - -static ssize_t gfar_set_rx_stash_index(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned short index = simple_strtoul(buf, NULL, 0); - u32 temp; - unsigned long flags; - - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) - return count; - - local_irq_save(flags); - lock_rx_qs(priv); - - if (index > priv->rx_stash_size) - goto out; - - if (index == priv->rx_stash_index) - goto out; - - priv->rx_stash_index = index; - - temp = gfar_read(®s->attreli); - temp &= ~ATTRELI_EI_MASK; - temp |= ATTRELI_EI(index); - gfar_write(®s->attreli, temp); - -out: - unlock_rx_qs(priv); - local_irq_restore(flags); - - return count; -} - -static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index, - gfar_set_rx_stash_index); - -static ssize_t gfar_show_fifo_threshold(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - - return sprintf(buf, "%d\n", priv->fifo_threshold); -} - -static ssize_t gfar_set_fifo_threshold(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned int length = simple_strtoul(buf, NULL, 0); - u32 temp; - unsigned long flags; - - if (length > GFAR_MAX_FIFO_THRESHOLD) - return count; - - local_irq_save(flags); - lock_tx_qs(priv); - - priv->fifo_threshold = length; - - temp = gfar_read(®s->fifo_tx_thr); - temp &= ~FIFO_TX_THR_MASK; - temp |= length; - gfar_write(®s->fifo_tx_thr, temp); - - unlock_tx_qs(priv); - local_irq_restore(flags); - - return count; -} - -static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold, - gfar_set_fifo_threshold); - -static ssize_t gfar_show_fifo_starve(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - - return sprintf(buf, "%d\n", priv->fifo_starve); -} - -static ssize_t gfar_set_fifo_starve(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned int num = simple_strtoul(buf, NULL, 0); - u32 temp; - unsigned long flags; - - if (num > GFAR_MAX_FIFO_STARVE) - return count; - - local_irq_save(flags); - lock_tx_qs(priv); - - priv->fifo_starve = num; - - temp = gfar_read(®s->fifo_tx_starve); - temp &= ~FIFO_TX_STARVE_MASK; - temp |= num; - gfar_write(®s->fifo_tx_starve, temp); - - unlock_tx_qs(priv); - local_irq_restore(flags); - - return count; -} - -static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, - gfar_set_fifo_starve); - -static ssize_t gfar_show_fifo_starve_off(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - - return sprintf(buf, "%d\n", priv->fifo_starve_off); -} - -static ssize_t gfar_set_fifo_starve_off(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned int num = simple_strtoul(buf, NULL, 0); - u32 temp; - unsigned long flags; - - if (num > GFAR_MAX_FIFO_STARVE_OFF) - return count; - - local_irq_save(flags); - lock_tx_qs(priv); - - priv->fifo_starve_off = num; - - temp = gfar_read(®s->fifo_tx_starve_shutoff); - temp &= ~FIFO_TX_STARVE_OFF_MASK; - temp |= num; - gfar_write(®s->fifo_tx_starve_shutoff, temp); - - unlock_tx_qs(priv); - local_irq_restore(flags); - - return count; -} - -static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off, - gfar_set_fifo_starve_off); - -void gfar_init_sysfs(struct net_device *dev) -{ - struct gfar_private *priv = netdev_priv(dev); - int rc; - - /* Initialize the default values */ - priv->fifo_threshold = DEFAULT_FIFO_TX_THR; - priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; - priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; - - /* Create our sysfs files */ - rc = device_create_file(&dev->dev, &dev_attr_bd_stash); - rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size); - rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index); - rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold); - rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve); - rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off); - if (rc) - dev_err(&dev->dev, "Error creating gianfar sysfs files.\n"); -} diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth.c deleted file mode 100644 index 9ac14f80..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth.c +++ /dev/null @@ -1,4089 +0,0 @@ -/* - * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved. - * - * Author: Shlomi Gridish <gridish@freescale.com> - * Li Yang <leoli@freescale.com> - * - * Description: - * QE UCC Gigabit Ethernet Driver - * - * 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. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/stddef.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/dma-mapping.h> -#include <linux/mii.h> -#include <linux/phy.h> -#include <linux/workqueue.h> -#include <linux/of_mdio.h> -#include <linux/of_net.h> -#include <linux/of_platform.h> - -#include <asm/uaccess.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/immap_qe.h> -#include <asm/qe.h> -#include <asm/ucc.h> -#include <asm/ucc_fast.h> -#include <asm/machdep.h> - -#include "ucc_geth.h" -#include "fsl_pq_mdio.h" - -#undef DEBUG - -#define ugeth_printk(level, format, arg...) \ - printk(level format "\n", ## arg) - -#define ugeth_dbg(format, arg...) \ - ugeth_printk(KERN_DEBUG , format , ## arg) -#define ugeth_err(format, arg...) \ - ugeth_printk(KERN_ERR , format , ## arg) -#define ugeth_info(format, arg...) \ - ugeth_printk(KERN_INFO , format , ## arg) -#define ugeth_warn(format, arg...) \ - ugeth_printk(KERN_WARNING , format , ## arg) - -#ifdef UGETH_VERBOSE_DEBUG -#define ugeth_vdbg ugeth_dbg -#else -#define ugeth_vdbg(fmt, args...) do { } while (0) -#endif /* UGETH_VERBOSE_DEBUG */ -#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 - - -static DEFINE_SPINLOCK(ugeth_lock); - -static struct { - u32 msg_enable; -} debug = { -1 }; - -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)"); - -static struct ucc_geth_info ugeth_primary_info = { - .uf_info = { - .bd_mem_part = MEM_PART_SYSTEM, - .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, - .max_rx_buf_length = 1536, - /* adjusted at startup if max-speed 1000 */ - .urfs = UCC_GETH_URFS_INIT, - .urfet = UCC_GETH_URFET_INIT, - .urfset = UCC_GETH_URFSET_INIT, - .utfs = UCC_GETH_UTFS_INIT, - .utfet = UCC_GETH_UTFET_INIT, - .utftt = UCC_GETH_UTFTT_INIT, - .ufpt = 256, - .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, - .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, - .tenc = UCC_FAST_TX_ENCODING_NRZ, - .renc = UCC_FAST_RX_ENCODING_NRZ, - .tcrc = UCC_FAST_16_BIT_CRC, - .synl = UCC_FAST_SYNC_LEN_NOT_USED, - }, - .numQueuesTx = 1, - .numQueuesRx = 1, - .extendedFilteringChainPointer = ((uint32_t) NULL), - .typeorlen = 3072 /*1536 */ , - .nonBackToBackIfgPart1 = 0x40, - .nonBackToBackIfgPart2 = 0x60, - .miminumInterFrameGapEnforcement = 0x50, - .backToBackInterFrameGap = 0x60, - .mblinterval = 128, - .nortsrbytetime = 5, - .fracsiz = 1, - .strictpriorityq = 0xff, - .altBebTruncation = 0xa, - .excessDefer = 1, - .maxRetransmission = 0xf, - .collisionWindow = 0x37, - .receiveFlowControl = 1, - .transmitFlowControl = 1, - .maxGroupAddrInHash = 4, - .maxIndAddrInHash = 4, - .prel = 7, - .maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */ - .minFrameLength = 64, - .maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */ - .maxD2Length = 1520+16, /* Add extra bytes for VLANs etc. */ - .vlantype = 0x8100, - .ecamptr = ((uint32_t) NULL), - .eventRegMask = UCCE_OTHER, - .pausePeriod = 0xf000, - .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1}, - .bdRingLenTx = { - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN}, - - .bdRingLenRx = { - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN}, - - .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1, - .largestexternallookupkeysize = - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE, - .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE | - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX | - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX, - .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP, - .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP, - .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT, - .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE, - .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC, - .numThreadsTx = UCC_GETH_NUM_OF_THREADS_1, - .numThreadsRx = UCC_GETH_NUM_OF_THREADS_1, - .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, - .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, -}; - -static struct ucc_geth_info ugeth_info[8]; - -#ifdef DEBUG -static void mem_disp(u8 *addr, int size) -{ - u8 *i; - int size16Aling = (size >> 4) << 4; - int size4Aling = (size >> 2) << 2; - int notAlign = 0; - if (size % 16) - notAlign = 1; - - for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16) - printk("0x%08x: %08x %08x %08x %08x\r\n", - (u32) i, - *((u32 *) (i)), - *((u32 *) (i + 4)), - *((u32 *) (i + 8)), *((u32 *) (i + 12))); - if (notAlign == 1) - printk("0x%08x: ", (u32) i); - for (; (u32) i < (u32) addr + size4Aling; i += 4) - printk("%08x ", *((u32 *) (i))); - for (; (u32) i < (u32) addr + size; i++) - printk("%02x", *((u8 *) (i))); - if (notAlign == 1) - printk("\r\n"); -} -#endif /* DEBUG */ - -static struct list_head *dequeue(struct list_head *lh) -{ - unsigned long flags; - - spin_lock_irqsave(&ugeth_lock, flags); - if (!list_empty(lh)) { - struct list_head *node = lh->next; - list_del(node); - spin_unlock_irqrestore(&ugeth_lock, flags); - return node; - } else { - spin_unlock_irqrestore(&ugeth_lock, flags); - return NULL; - } -} - -static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, - u8 __iomem *bd) -{ - struct sk_buff *skb = NULL; - - skb = __skb_dequeue(&ugeth->rx_recycle); - if (!skb) - skb = netdev_alloc_skb(ugeth->ndev, - ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT); - if (skb == NULL) - return NULL; - - /* We need the data buffer to be aligned properly. We will reserve - * as many bytes as needed to align the data properly - */ - skb_reserve(skb, - UCC_GETH_RX_DATA_BUF_ALIGNMENT - - (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - - 1))); - - out_be32(&((struct qe_bd __iomem *)bd)->buf, - dma_map_single(ugeth->dev, - skb->data, - ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT, - DMA_FROM_DEVICE)); - - out_be32((u32 __iomem *)bd, - (R_E | R_I | (in_be32((u32 __iomem*)bd) & R_W))); - - return skb; -} - -static int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ) -{ - u8 __iomem *bd; - u32 bd_status; - struct sk_buff *skb; - int i; - - bd = ugeth->p_rx_bd_ring[rxQ]; - i = 0; - - do { - bd_status = in_be32((u32 __iomem *)bd); - skb = get_new_skb(ugeth, bd); - - if (!skb) /* If can not allocate data buffer, - abort. Cleanup will be elsewhere */ - return -ENOMEM; - - ugeth->rx_skbuff[rxQ][i] = skb; - - /* advance the BD pointer */ - bd += sizeof(struct qe_bd); - i++; - } while (!(bd_status & R_W)); - - return 0; -} - -static int fill_init_enet_entries(struct ucc_geth_private *ugeth, - u32 *p_start, - u8 num_entries, - u32 thread_size, - u32 thread_alignment, - unsigned int risc, - int skip_page_for_first_entry) -{ - u32 init_enet_offset; - u8 i; - int snum; - - for (i = 0; i < num_entries; i++) { - if ((snum = qe_get_snum()) < 0) { - if (netif_msg_ifup(ugeth)) - ugeth_err("fill_init_enet_entries: Can not get SNUM."); - return snum; - } - if ((i == 0) && skip_page_for_first_entry) - /* First entry of Rx does not have page */ - init_enet_offset = 0; - else { - init_enet_offset = - qe_muram_alloc(thread_size, thread_alignment); - if (IS_ERR_VALUE(init_enet_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err("fill_init_enet_entries: Can not allocate DPRAM memory."); - qe_put_snum((u8) snum); - return -ENOMEM; - } - } - *(p_start++) = - ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset - | risc; - } - - return 0; -} - -static int return_init_enet_entries(struct ucc_geth_private *ugeth, - u32 *p_start, - u8 num_entries, - unsigned int risc, - int skip_page_for_first_entry) -{ - u32 init_enet_offset; - u8 i; - int snum; - - for (i = 0; i < num_entries; i++) { - u32 val = *p_start; - - /* Check that this entry was actually valid -- - needed in case failed in allocations */ - if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) { - snum = - (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >> - ENET_INIT_PARAM_SNUM_SHIFT; - qe_put_snum((u8) snum); - if (!((i == 0) && skip_page_for_first_entry)) { - /* First entry of Rx does not have page */ - init_enet_offset = - (val & ENET_INIT_PARAM_PTR_MASK); - qe_muram_free(init_enet_offset); - } - *p_start++ = 0; - } - } - - return 0; -} - -#ifdef DEBUG -static int dump_init_enet_entries(struct ucc_geth_private *ugeth, - u32 __iomem *p_start, - u8 num_entries, - u32 thread_size, - unsigned int risc, - int skip_page_for_first_entry) -{ - u32 init_enet_offset; - u8 i; - int snum; - - for (i = 0; i < num_entries; i++) { - u32 val = in_be32(p_start); - - /* Check that this entry was actually valid -- - needed in case failed in allocations */ - if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) { - snum = - (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >> - ENET_INIT_PARAM_SNUM_SHIFT; - qe_put_snum((u8) snum); - if (!((i == 0) && skip_page_for_first_entry)) { - /* First entry of Rx does not have page */ - init_enet_offset = - (in_be32(p_start) & - ENET_INIT_PARAM_PTR_MASK); - ugeth_info("Init enet entry %d:", i); - ugeth_info("Base address: 0x%08x", - (u32) - qe_muram_addr(init_enet_offset)); - mem_disp(qe_muram_addr(init_enet_offset), - thread_size); - } - p_start++; - } - } - - return 0; -} -#endif - -static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont) -{ - kfree(enet_addr_cont); -} - -static void set_mac_addr(__be16 __iomem *reg, u8 *mac) -{ - out_be16(®[0], ((u16)mac[5] << 8) | mac[4]); - out_be16(®[1], ((u16)mac[3] << 8) | mac[2]); - out_be16(®[2], ((u16)mac[1] << 8) | mac[0]); -} - -static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) -{ - struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; - - if (!(paddr_num < NUM_OF_PADDRS)) { - ugeth_warn("%s: Illagel paddr_num.", __func__); - return -EINVAL; - } - - p_82xx_addr_filt = - (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - /* Writing address ff.ff.ff.ff.ff.ff disables address - recognition for this register */ - out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff); - - return 0; -} - -static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth, - u8 *p_enet_addr) -{ - struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; - u32 cecr_subblock; - - p_82xx_addr_filt = - (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - - /* Ethernet frames are defined in Little Endian mode, - therefore to insert */ - /* the address to the hash (Big Endian mode), we reverse the bytes.*/ - - set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr); - - qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock, - QE_CR_PROTOCOL_ETHERNET, 0); -} - -static inline int compare_addr(u8 **addr1, u8 **addr2) -{ - return memcmp(addr1, addr2, ETH_ALEN); -} - -#ifdef DEBUG -static void get_statistics(struct ucc_geth_private *ugeth, - struct ucc_geth_tx_firmware_statistics * - tx_firmware_statistics, - struct ucc_geth_rx_firmware_statistics * - rx_firmware_statistics, - struct ucc_geth_hardware_statistics *hardware_statistics) -{ - struct ucc_fast __iomem *uf_regs; - struct ucc_geth __iomem *ug_regs; - struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram; - struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram; - - ug_regs = ugeth->ug_regs; - uf_regs = (struct ucc_fast __iomem *) ug_regs; - p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram; - p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram; - - /* Tx firmware only if user handed pointer and driver actually - gathers Tx firmware statistics */ - if (tx_firmware_statistics && p_tx_fw_statistics_pram) { - tx_firmware_statistics->sicoltx = - in_be32(&p_tx_fw_statistics_pram->sicoltx); - tx_firmware_statistics->mulcoltx = - in_be32(&p_tx_fw_statistics_pram->mulcoltx); - tx_firmware_statistics->latecoltxfr = - in_be32(&p_tx_fw_statistics_pram->latecoltxfr); - tx_firmware_statistics->frabortduecol = - in_be32(&p_tx_fw_statistics_pram->frabortduecol); - tx_firmware_statistics->frlostinmactxer = - in_be32(&p_tx_fw_statistics_pram->frlostinmactxer); - tx_firmware_statistics->carriersenseertx = - in_be32(&p_tx_fw_statistics_pram->carriersenseertx); - tx_firmware_statistics->frtxok = - in_be32(&p_tx_fw_statistics_pram->frtxok); - tx_firmware_statistics->txfrexcessivedefer = - in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer); - tx_firmware_statistics->txpkts256 = - in_be32(&p_tx_fw_statistics_pram->txpkts256); - tx_firmware_statistics->txpkts512 = - in_be32(&p_tx_fw_statistics_pram->txpkts512); - tx_firmware_statistics->txpkts1024 = - in_be32(&p_tx_fw_statistics_pram->txpkts1024); - tx_firmware_statistics->txpktsjumbo = - in_be32(&p_tx_fw_statistics_pram->txpktsjumbo); - } - - /* Rx firmware only if user handed pointer and driver actually - * gathers Rx firmware statistics */ - if (rx_firmware_statistics && p_rx_fw_statistics_pram) { - int i; - rx_firmware_statistics->frrxfcser = - in_be32(&p_rx_fw_statistics_pram->frrxfcser); - rx_firmware_statistics->fraligner = - in_be32(&p_rx_fw_statistics_pram->fraligner); - rx_firmware_statistics->inrangelenrxer = - in_be32(&p_rx_fw_statistics_pram->inrangelenrxer); - rx_firmware_statistics->outrangelenrxer = - in_be32(&p_rx_fw_statistics_pram->outrangelenrxer); - rx_firmware_statistics->frtoolong = - in_be32(&p_rx_fw_statistics_pram->frtoolong); - rx_firmware_statistics->runt = - in_be32(&p_rx_fw_statistics_pram->runt); - rx_firmware_statistics->verylongevent = - in_be32(&p_rx_fw_statistics_pram->verylongevent); - rx_firmware_statistics->symbolerror = - in_be32(&p_rx_fw_statistics_pram->symbolerror); - rx_firmware_statistics->dropbsy = - in_be32(&p_rx_fw_statistics_pram->dropbsy); - for (i = 0; i < 0x8; i++) - rx_firmware_statistics->res0[i] = - p_rx_fw_statistics_pram->res0[i]; - rx_firmware_statistics->mismatchdrop = - in_be32(&p_rx_fw_statistics_pram->mismatchdrop); - rx_firmware_statistics->underpkts = - in_be32(&p_rx_fw_statistics_pram->underpkts); - rx_firmware_statistics->pkts256 = - in_be32(&p_rx_fw_statistics_pram->pkts256); - rx_firmware_statistics->pkts512 = - in_be32(&p_rx_fw_statistics_pram->pkts512); - rx_firmware_statistics->pkts1024 = - in_be32(&p_rx_fw_statistics_pram->pkts1024); - rx_firmware_statistics->pktsjumbo = - in_be32(&p_rx_fw_statistics_pram->pktsjumbo); - rx_firmware_statistics->frlossinmacer = - in_be32(&p_rx_fw_statistics_pram->frlossinmacer); - rx_firmware_statistics->pausefr = - in_be32(&p_rx_fw_statistics_pram->pausefr); - for (i = 0; i < 0x4; i++) - rx_firmware_statistics->res1[i] = - p_rx_fw_statistics_pram->res1[i]; - rx_firmware_statistics->removevlan = - in_be32(&p_rx_fw_statistics_pram->removevlan); - rx_firmware_statistics->replacevlan = - in_be32(&p_rx_fw_statistics_pram->replacevlan); - rx_firmware_statistics->insertvlan = - in_be32(&p_rx_fw_statistics_pram->insertvlan); - } - - /* Hardware only if user handed pointer and driver actually - gathers hardware statistics */ - if (hardware_statistics && - (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) { - hardware_statistics->tx64 = in_be32(&ug_regs->tx64); - hardware_statistics->tx127 = in_be32(&ug_regs->tx127); - hardware_statistics->tx255 = in_be32(&ug_regs->tx255); - hardware_statistics->rx64 = in_be32(&ug_regs->rx64); - hardware_statistics->rx127 = in_be32(&ug_regs->rx127); - hardware_statistics->rx255 = in_be32(&ug_regs->rx255); - hardware_statistics->txok = in_be32(&ug_regs->txok); - hardware_statistics->txcf = in_be16(&ug_regs->txcf); - hardware_statistics->tmca = in_be32(&ug_regs->tmca); - hardware_statistics->tbca = in_be32(&ug_regs->tbca); - hardware_statistics->rxfok = in_be32(&ug_regs->rxfok); - hardware_statistics->rxbok = in_be32(&ug_regs->rxbok); - hardware_statistics->rbyt = in_be32(&ug_regs->rbyt); - hardware_statistics->rmca = in_be32(&ug_regs->rmca); - hardware_statistics->rbca = in_be32(&ug_regs->rbca); - } -} - -static void dump_bds(struct ucc_geth_private *ugeth) -{ - int i; - int length; - - for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { - if (ugeth->p_tx_bd_ring[i]) { - length = - (ugeth->ug_info->bdRingLenTx[i] * - sizeof(struct qe_bd)); - ugeth_info("TX BDs[%d]", i); - mem_disp(ugeth->p_tx_bd_ring[i], length); - } - } - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - if (ugeth->p_rx_bd_ring[i]) { - length = - (ugeth->ug_info->bdRingLenRx[i] * - sizeof(struct qe_bd)); - ugeth_info("RX BDs[%d]", i); - mem_disp(ugeth->p_rx_bd_ring[i], length); - } - } -} - -static void dump_regs(struct ucc_geth_private *ugeth) -{ - int i; - - ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num + 1); - ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs); - - ugeth_info("maccfg1 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->maccfg1, - in_be32(&ugeth->ug_regs->maccfg1)); - ugeth_info("maccfg2 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->maccfg2, - in_be32(&ugeth->ug_regs->maccfg2)); - ugeth_info("ipgifg : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->ipgifg, - in_be32(&ugeth->ug_regs->ipgifg)); - ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->hafdup, - in_be32(&ugeth->ug_regs->hafdup)); - ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->ifctl, - in_be32(&ugeth->ug_regs->ifctl)); - ugeth_info("ifstat : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->ifstat, - in_be32(&ugeth->ug_regs->ifstat)); - ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->macstnaddr1, - in_be32(&ugeth->ug_regs->macstnaddr1)); - ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->macstnaddr2, - in_be32(&ugeth->ug_regs->macstnaddr2)); - ugeth_info("uempr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->uempr, - in_be32(&ugeth->ug_regs->uempr)); - ugeth_info("utbipar : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->utbipar, - in_be32(&ugeth->ug_regs->utbipar)); - ugeth_info("uescr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->ug_regs->uescr, - in_be16(&ugeth->ug_regs->uescr)); - ugeth_info("tx64 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tx64, - in_be32(&ugeth->ug_regs->tx64)); - ugeth_info("tx127 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tx127, - in_be32(&ugeth->ug_regs->tx127)); - ugeth_info("tx255 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tx255, - in_be32(&ugeth->ug_regs->tx255)); - ugeth_info("rx64 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rx64, - in_be32(&ugeth->ug_regs->rx64)); - ugeth_info("rx127 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rx127, - in_be32(&ugeth->ug_regs->rx127)); - ugeth_info("rx255 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rx255, - in_be32(&ugeth->ug_regs->rx255)); - ugeth_info("txok : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->txok, - in_be32(&ugeth->ug_regs->txok)); - ugeth_info("txcf : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->ug_regs->txcf, - in_be16(&ugeth->ug_regs->txcf)); - ugeth_info("tmca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tmca, - in_be32(&ugeth->ug_regs->tmca)); - ugeth_info("tbca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tbca, - in_be32(&ugeth->ug_regs->tbca)); - ugeth_info("rxfok : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rxfok, - in_be32(&ugeth->ug_regs->rxfok)); - ugeth_info("rxbok : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rxbok, - in_be32(&ugeth->ug_regs->rxbok)); - ugeth_info("rbyt : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rbyt, - in_be32(&ugeth->ug_regs->rbyt)); - ugeth_info("rmca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rmca, - in_be32(&ugeth->ug_regs->rmca)); - ugeth_info("rbca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rbca, - in_be32(&ugeth->ug_regs->rbca)); - ugeth_info("scar : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->scar, - in_be32(&ugeth->ug_regs->scar)); - ugeth_info("scam : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->scam, - in_be32(&ugeth->ug_regs->scam)); - - if (ugeth->p_thread_data_tx) { - int numThreadsTxNumerical; - switch (ugeth->ug_info->numThreadsTx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsTxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsTxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsTxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsTxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsTxNumerical = 8; - break; - default: - numThreadsTxNumerical = 0; - break; - } - - ugeth_info("Thread data TXs:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_thread_data_tx); - for (i = 0; i < numThreadsTxNumerical; i++) { - ugeth_info("Thread data TX[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_thread_data_tx[i]); - mem_disp((u8 *) & ugeth->p_thread_data_tx[i], - sizeof(struct ucc_geth_thread_data_tx)); - } - } - if (ugeth->p_thread_data_rx) { - int numThreadsRxNumerical; - switch (ugeth->ug_info->numThreadsRx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsRxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsRxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsRxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsRxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsRxNumerical = 8; - break; - default: - numThreadsRxNumerical = 0; - break; - } - - ugeth_info("Thread data RX:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_thread_data_rx); - for (i = 0; i < numThreadsRxNumerical; i++) { - ugeth_info("Thread data RX[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_thread_data_rx[i]); - mem_disp((u8 *) & ugeth->p_thread_data_rx[i], - sizeof(struct ucc_geth_thread_data_rx)); - } - } - if (ugeth->p_exf_glbl_param) { - ugeth_info("EXF global param:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_exf_glbl_param); - mem_disp((u8 *) ugeth->p_exf_glbl_param, - sizeof(*ugeth->p_exf_glbl_param)); - } - if (ugeth->p_tx_glbl_pram) { - ugeth_info("TX global param:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram); - ugeth_info("temoder : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_tx_glbl_pram->temoder, - in_be16(&ugeth->p_tx_glbl_pram->temoder)); - ugeth_info("sqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->sqptr, - in_be32(&ugeth->p_tx_glbl_pram->sqptr)); - ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer, - in_be32(&ugeth->p_tx_glbl_pram-> - schedulerbasepointer)); - ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr, - in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr)); - ugeth_info("tstate : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->tstate, - in_be32(&ugeth->p_tx_glbl_pram->tstate)); - ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[0], - ugeth->p_tx_glbl_pram->iphoffset[0]); - ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[1], - ugeth->p_tx_glbl_pram->iphoffset[1]); - ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[2], - ugeth->p_tx_glbl_pram->iphoffset[2]); - ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[3], - ugeth->p_tx_glbl_pram->iphoffset[3]); - ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[4], - ugeth->p_tx_glbl_pram->iphoffset[4]); - ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[5], - ugeth->p_tx_glbl_pram->iphoffset[5]); - ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[6], - ugeth->p_tx_glbl_pram->iphoffset[6]); - ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[7], - ugeth->p_tx_glbl_pram->iphoffset[7]); - ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[0], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0])); - ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[1], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1])); - ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[2], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2])); - ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[3], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3])); - ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[4], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4])); - ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[5], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5])); - ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[6], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6])); - ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[7], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7])); - ugeth_info("tqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->tqptr, - in_be32(&ugeth->p_tx_glbl_pram->tqptr)); - } - if (ugeth->p_rx_glbl_pram) { - ugeth_info("RX global param:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram); - ugeth_info("remoder : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->remoder, - in_be32(&ugeth->p_rx_glbl_pram->remoder)); - ugeth_info("rqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->rqptr, - in_be32(&ugeth->p_rx_glbl_pram->rqptr)); - ugeth_info("typeorlen : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->typeorlen, - in_be16(&ugeth->p_rx_glbl_pram->typeorlen)); - ugeth_info("rxgstpack : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_rx_glbl_pram->rxgstpack, - ugeth->p_rx_glbl_pram->rxgstpack); - ugeth_info("rxrmonbaseptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr, - in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr)); - ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr, - in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr)); - ugeth_info("rstate : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_rx_glbl_pram->rstate, - ugeth->p_rx_glbl_pram->rstate); - ugeth_info("mrblr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->mrblr, - in_be16(&ugeth->p_rx_glbl_pram->mrblr)); - ugeth_info("rbdqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->rbdqptr, - in_be32(&ugeth->p_rx_glbl_pram->rbdqptr)); - ugeth_info("mflr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->mflr, - in_be16(&ugeth->p_rx_glbl_pram->mflr)); - ugeth_info("minflr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->minflr, - in_be16(&ugeth->p_rx_glbl_pram->minflr)); - ugeth_info("maxd1 : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->maxd1, - in_be16(&ugeth->p_rx_glbl_pram->maxd1)); - ugeth_info("maxd2 : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->maxd2, - in_be16(&ugeth->p_rx_glbl_pram->maxd2)); - ugeth_info("ecamptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->ecamptr, - in_be32(&ugeth->p_rx_glbl_pram->ecamptr)); - ugeth_info("l2qt : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l2qt, - in_be32(&ugeth->p_rx_glbl_pram->l2qt)); - ugeth_info("l3qt[0] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[0], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[0])); - ugeth_info("l3qt[1] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[1], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[1])); - ugeth_info("l3qt[2] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[2], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[2])); - ugeth_info("l3qt[3] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[3], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[3])); - ugeth_info("l3qt[4] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[4], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[4])); - ugeth_info("l3qt[5] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[5], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[5])); - ugeth_info("l3qt[6] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[6], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[6])); - ugeth_info("l3qt[7] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[7], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[7])); - ugeth_info("vlantype : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->vlantype, - in_be16(&ugeth->p_rx_glbl_pram->vlantype)); - ugeth_info("vlantci : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->vlantci, - in_be16(&ugeth->p_rx_glbl_pram->vlantci)); - for (i = 0; i < 64; i++) - ugeth_info - ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x", - i, - (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i], - ugeth->p_rx_glbl_pram->addressfiltering[i]); - ugeth_info("exfGlobalParam : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam, - in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam)); - } - if (ugeth->p_send_q_mem_reg) { - ugeth_info("Send Q memory registers:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_send_q_mem_reg); - for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { - ugeth_info("SQQD[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_send_q_mem_reg->sqqd[i]); - mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i], - sizeof(struct ucc_geth_send_queue_qd)); - } - } - if (ugeth->p_scheduler) { - ugeth_info("Scheduler:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler); - mem_disp((u8 *) ugeth->p_scheduler, - sizeof(*ugeth->p_scheduler)); - } - if (ugeth->p_tx_fw_statistics_pram) { - ugeth_info("TX FW statistics pram:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_tx_fw_statistics_pram); - mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram, - sizeof(*ugeth->p_tx_fw_statistics_pram)); - } - if (ugeth->p_rx_fw_statistics_pram) { - ugeth_info("RX FW statistics pram:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_rx_fw_statistics_pram); - mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram, - sizeof(*ugeth->p_rx_fw_statistics_pram)); - } - if (ugeth->p_rx_irq_coalescing_tbl) { - ugeth_info("RX IRQ coalescing tables:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_rx_irq_coalescing_tbl); - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - ugeth_info("RX IRQ coalescing table entry[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i]); - ugeth_info - ("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i].interruptcoalescingmaxvalue, - in_be32(&ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i]. - interruptcoalescingmaxvalue)); - ugeth_info - ("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i].interruptcoalescingcounter, - in_be32(&ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i]. - interruptcoalescingcounter)); - } - } - if (ugeth->p_rx_bd_qs_tbl) { - ugeth_info("RX BD QS tables:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl); - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - ugeth_info("RX BD QS table[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i]); - ugeth_info - ("bdbaseptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr)); - ugeth_info - ("bdptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr)); - ugeth_info - ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i]. - externalbdbaseptr)); - ugeth_info - ("externalbdptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr)); - ugeth_info("ucode RX Prefetched BDs:"); - ugeth_info("Base address: 0x%08x", - (u32) - qe_muram_addr(in_be32 - (&ugeth->p_rx_bd_qs_tbl[i]. - bdbaseptr))); - mem_disp((u8 *) - qe_muram_addr(in_be32 - (&ugeth->p_rx_bd_qs_tbl[i]. - bdbaseptr)), - sizeof(struct ucc_geth_rx_prefetched_bds)); - } - } - if (ugeth->p_init_enet_param_shadow) { - int size; - ugeth_info("Init enet param shadow:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_init_enet_param_shadow); - mem_disp((u8 *) ugeth->p_init_enet_param_shadow, - sizeof(*ugeth->p_init_enet_param_shadow)); - - size = sizeof(struct ucc_geth_thread_rx_pram); - if (ugeth->ug_info->rxExtendedFiltering) { - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; - if (ugeth->ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; - if (ugeth->ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; - } - - dump_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - txthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_TX, - sizeof(struct ucc_geth_thread_tx_pram), - ugeth->ug_info->riscTx, 0); - dump_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - rxthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_RX, size, - ugeth->ug_info->riscRx, 1); - } -} -#endif /* DEBUG */ - -static void init_default_reg_vals(u32 __iomem *upsmr_register, - u32 __iomem *maccfg1_register, - u32 __iomem *maccfg2_register) -{ - out_be32(upsmr_register, UCC_GETH_UPSMR_INIT); - out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT); - out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT); -} - -static int init_half_duplex_params(int alt_beb, - int back_pressure_no_backoff, - int no_backoff, - int excess_defer, - u8 alt_beb_truncation, - u8 max_retransmissions, - u8 collision_window, - u32 __iomem *hafdup_register) -{ - u32 value = 0; - - if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) || - (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) || - (collision_window > HALFDUP_COLLISION_WINDOW_MAX)) - return -EINVAL; - - value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT); - - if (alt_beb) - value |= HALFDUP_ALT_BEB; - if (back_pressure_no_backoff) - value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF; - if (no_backoff) - value |= HALFDUP_NO_BACKOFF; - if (excess_defer) - value |= HALFDUP_EXCESSIVE_DEFER; - - value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT); - - value |= collision_window; - - out_be32(hafdup_register, value); - return 0; -} - -static int init_inter_frame_gap_params(u8 non_btb_cs_ipg, - u8 non_btb_ipg, - u8 min_ifg, - u8 btb_ipg, - u32 __iomem *ipgifg_register) -{ - u32 value = 0; - - /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back - IPG part 2 */ - if (non_btb_cs_ipg > non_btb_ipg) - return -EINVAL; - - if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) || - (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) || - /*(min_ifg > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */ - (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX)) - return -EINVAL; - - value |= - ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) & - IPGIFG_NBTB_CS_IPG_MASK); - value |= - ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) & - IPGIFG_NBTB_IPG_MASK); - value |= - ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) & - IPGIFG_MIN_IFG_MASK); - value |= (btb_ipg & IPGIFG_BTB_IPG_MASK); - - out_be32(ipgifg_register, value); - return 0; -} - -int init_flow_control_params(u32 automatic_flow_control_mode, - int rx_flow_control_enable, - int tx_flow_control_enable, - u16 pause_period, - u16 extension_field, - u32 __iomem *upsmr_register, - u32 __iomem *uempr_register, - u32 __iomem *maccfg1_register) -{ - u32 value = 0; - - /* Set UEMPR register */ - value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT; - value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT; - out_be32(uempr_register, value); - - /* Set UPSMR register */ - setbits32(upsmr_register, automatic_flow_control_mode); - - value = in_be32(maccfg1_register); - if (rx_flow_control_enable) - value |= MACCFG1_FLOW_RX; - if (tx_flow_control_enable) - value |= MACCFG1_FLOW_TX; - out_be32(maccfg1_register, value); - - return 0; -} - -static int init_hw_statistics_gathering_mode(int enable_hardware_statistics, - int auto_zero_hardware_statistics, - u32 __iomem *upsmr_register, - u16 __iomem *uescr_register) -{ - u16 uescr_value = 0; - - /* Enable hardware statistics gathering if requested */ - if (enable_hardware_statistics) - setbits32(upsmr_register, UCC_GETH_UPSMR_HSE); - - /* Clear hardware statistics counters */ - uescr_value = in_be16(uescr_register); - uescr_value |= UESCR_CLRCNT; - /* Automatically zero hardware statistics counters on read, - if requested */ - if (auto_zero_hardware_statistics) - uescr_value |= UESCR_AUTOZ; - out_be16(uescr_register, uescr_value); - - return 0; -} - -static int init_firmware_statistics_gathering_mode(int - enable_tx_firmware_statistics, - int enable_rx_firmware_statistics, - u32 __iomem *tx_rmon_base_ptr, - u32 tx_firmware_statistics_structure_address, - u32 __iomem *rx_rmon_base_ptr, - u32 rx_firmware_statistics_structure_address, - u16 __iomem *temoder_register, - u32 __iomem *remoder_register) -{ - /* Note: this function does not check if */ - /* the parameters it receives are NULL */ - - if (enable_tx_firmware_statistics) { - out_be32(tx_rmon_base_ptr, - tx_firmware_statistics_structure_address); - setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE); - } - - if (enable_rx_firmware_statistics) { - out_be32(rx_rmon_base_ptr, - rx_firmware_statistics_structure_address); - setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE); - } - - return 0; -} - -static int init_mac_station_addr_regs(u8 address_byte_0, - u8 address_byte_1, - u8 address_byte_2, - u8 address_byte_3, - u8 address_byte_4, - u8 address_byte_5, - u32 __iomem *macstnaddr1_register, - u32 __iomem *macstnaddr2_register) -{ - u32 value = 0; - - /* Example: for a station address of 0x12345678ABCD, */ - /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */ - - /* MACSTNADDR1 Register: */ - - /* 0 7 8 15 */ - /* station address byte 5 station address byte 4 */ - /* 16 23 24 31 */ - /* station address byte 3 station address byte 2 */ - value |= (u32) ((address_byte_2 << 0) & 0x000000FF); - value |= (u32) ((address_byte_3 << 8) & 0x0000FF00); - value |= (u32) ((address_byte_4 << 16) & 0x00FF0000); - value |= (u32) ((address_byte_5 << 24) & 0xFF000000); - - out_be32(macstnaddr1_register, value); - - /* MACSTNADDR2 Register: */ - - /* 0 7 8 15 */ - /* station address byte 1 station address byte 0 */ - /* 16 23 24 31 */ - /* reserved reserved */ - value = 0; - value |= (u32) ((address_byte_0 << 16) & 0x00FF0000); - value |= (u32) ((address_byte_1 << 24) & 0xFF000000); - - out_be32(macstnaddr2_register, value); - - return 0; -} - -static int init_check_frame_length_mode(int length_check, - u32 __iomem *maccfg2_register) -{ - u32 value = 0; - - value = in_be32(maccfg2_register); - - if (length_check) - value |= MACCFG2_LC; - else - value &= ~MACCFG2_LC; - - out_be32(maccfg2_register, value); - return 0; -} - -static int init_preamble_length(u8 preamble_length, - u32 __iomem *maccfg2_register) -{ - if ((preamble_length < 3) || (preamble_length > 7)) - return -EINVAL; - - clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK, - preamble_length << MACCFG2_PREL_SHIFT); - - return 0; -} - -static int init_rx_parameters(int reject_broadcast, - int receive_short_frames, - int promiscuous, u32 __iomem *upsmr_register) -{ - u32 value = 0; - - value = in_be32(upsmr_register); - - if (reject_broadcast) - value |= UCC_GETH_UPSMR_BRO; - else - value &= ~UCC_GETH_UPSMR_BRO; - - if (receive_short_frames) - value |= UCC_GETH_UPSMR_RSH; - else - value &= ~UCC_GETH_UPSMR_RSH; - - if (promiscuous) - value |= UCC_GETH_UPSMR_PRO; - else - value &= ~UCC_GETH_UPSMR_PRO; - - out_be32(upsmr_register, value); - - return 0; -} - -static int init_max_rx_buff_len(u16 max_rx_buf_len, - u16 __iomem *mrblr_register) -{ - /* max_rx_buf_len value must be a multiple of 128 */ - if ((max_rx_buf_len == 0) || - (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT)) - return -EINVAL; - - out_be16(mrblr_register, max_rx_buf_len); - return 0; -} - -static int init_min_frame_len(u16 min_frame_length, - u16 __iomem *minflr_register, - u16 __iomem *mrblr_register) -{ - u16 mrblr_value = 0; - - mrblr_value = in_be16(mrblr_register); - if (min_frame_length >= (mrblr_value - 4)) - return -EINVAL; - - out_be16(minflr_register, min_frame_length); - return 0; -} - -static int adjust_enet_interface(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_info *ug_info; - struct ucc_geth __iomem *ug_regs; - struct ucc_fast __iomem *uf_regs; - int ret_val; - u32 upsmr, maccfg2; - u16 value; - - ugeth_vdbg("%s: IN", __func__); - - ug_info = ugeth->ug_info; - ug_regs = ugeth->ug_regs; - uf_regs = ugeth->uccf->uf_regs; - - /* Set MACCFG2 */ - maccfg2 = in_be32(&ug_regs->maccfg2); - maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; - if ((ugeth->max_speed == SPEED_10) || - (ugeth->max_speed == SPEED_100)) - maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; - else if (ugeth->max_speed == SPEED_1000) - maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - maccfg2 |= ug_info->padAndCrc; - out_be32(&ug_regs->maccfg2, maccfg2); - - /* Set UPSMR */ - upsmr = in_be32(&uf_regs->upsmr); - upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M | - UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM); - if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - if (ugeth->phy_interface != PHY_INTERFACE_MODE_RMII) - upsmr |= UCC_GETH_UPSMR_RPM; - switch (ugeth->max_speed) { - case SPEED_10: - upsmr |= UCC_GETH_UPSMR_R10M; - /* FALLTHROUGH */ - case SPEED_100: - if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) - upsmr |= UCC_GETH_UPSMR_RMM; - } - } - if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - upsmr |= UCC_GETH_UPSMR_TBIM; - } - if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)) - upsmr |= UCC_GETH_UPSMR_SGMM; - - out_be32(&uf_regs->upsmr, upsmr); - - /* Disable autonegotiation in tbi mode, because by default it - comes up in autonegotiation mode. */ - /* Note that this depends on proper setting in utbipar register. */ - if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - struct ucc_geth_info *ug_info = ugeth->ug_info; - struct phy_device *tbiphy; - - if (!ug_info->tbi_node) - ugeth_warn("TBI mode requires that the device " - "tree specify a tbi-handle\n"); - - tbiphy = of_phy_find_device(ug_info->tbi_node); - if (!tbiphy) - ugeth_warn("Could not get TBI device\n"); - - value = phy_read(tbiphy, ENET_TBI_MII_CR); - value &= ~0x1000; /* Turn off autonegotiation */ - phy_write(tbiphy, ENET_TBI_MII_CR, value); - } - - init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); - - ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); - if (ret_val != 0) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.", - __func__); - return ret_val; - } - - return 0; -} - -static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) -{ - struct ucc_fast_private *uccf; - u32 cecr_subblock; - u32 temp; - int i = 10; - - uccf = ugeth->uccf; - - /* Mask GRACEFUL STOP TX interrupt bit and clear it */ - clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA); - out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */ - - /* Issue host command */ - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, - QE_CR_PROTOCOL_ETHERNET, 0); - - /* Wait for command to complete */ - do { - msleep(10); - temp = in_be32(uccf->p_ucce); - } while (!(temp & UCC_GETH_UCCE_GRA) && --i); - - uccf->stopped_tx = 1; - - return 0; -} - -static int ugeth_graceful_stop_rx(struct ucc_geth_private *ugeth) -{ - struct ucc_fast_private *uccf; - u32 cecr_subblock; - u8 temp; - int i = 10; - - uccf = ugeth->uccf; - - /* Clear acknowledge bit */ - temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); - temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; - out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp); - - /* Keep issuing command and checking acknowledge bit until - it is asserted, according to spec */ - do { - /* Issue host command */ - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. - ucc_num); - qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, - QE_CR_PROTOCOL_ETHERNET, 0); - msleep(10); - temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); - } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i); - - uccf->stopped_rx = 1; - - return 0; -} - -static int ugeth_restart_tx(struct ucc_geth_private *ugeth) -{ - struct ucc_fast_private *uccf; - u32 cecr_subblock; - - uccf = ugeth->uccf; - - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); - uccf->stopped_tx = 0; - - return 0; -} - -static int ugeth_restart_rx(struct ucc_geth_private *ugeth) -{ - struct ucc_fast_private *uccf; - u32 cecr_subblock; - - uccf = ugeth->uccf; - - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, - 0); - uccf->stopped_rx = 0; - - return 0; -} - -static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) -{ - struct ucc_fast_private *uccf; - int enabled_tx, enabled_rx; - - uccf = ugeth->uccf; - - /* check if the UCC number is in range. */ - if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: ucc_num out of range.", __func__); - return -EINVAL; - } - - enabled_tx = uccf->enabled_tx; - enabled_rx = uccf->enabled_rx; - - /* Get Tx and Rx going again, in case this channel was actively - disabled. */ - if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx) - ugeth_restart_tx(ugeth); - if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx) - ugeth_restart_rx(ugeth); - - ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */ - - return 0; - -} - -static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode) -{ - struct ucc_fast_private *uccf; - - uccf = ugeth->uccf; - - /* check if the UCC number is in range. */ - if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: ucc_num out of range.", __func__); - return -EINVAL; - } - - /* Stop any transmissions */ - if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx) - ugeth_graceful_stop_tx(ugeth); - - /* Stop any receptions */ - if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx) - ugeth_graceful_stop_rx(ugeth); - - ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */ - - return 0; -} - -static void ugeth_quiesce(struct ucc_geth_private *ugeth) -{ - /* Prevent any further xmits, plus detach the device. */ - netif_device_detach(ugeth->ndev); - - /* Wait for any current xmits to finish. */ - netif_tx_disable(ugeth->ndev); - - /* Disable the interrupt to avoid NAPI rescheduling. */ - disable_irq(ugeth->ug_info->uf_info.irq); - - /* Stop NAPI, and possibly wait for its completion. */ - napi_disable(&ugeth->napi); -} - -static void ugeth_activate(struct ucc_geth_private *ugeth) -{ - napi_enable(&ugeth->napi); - enable_irq(ugeth->ug_info->uf_info.irq); - netif_device_attach(ugeth->ndev); -} - -/* Called every time the controller might need to be made - * aware of new link state. The PHY code conveys this - * information through variables in the ugeth structure, and this - * function converts those variables into the appropriate - * register values, and can bring down the device if needed. - */ - -static void adjust_link(struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - struct ucc_geth __iomem *ug_regs; - struct ucc_fast __iomem *uf_regs; - struct phy_device *phydev = ugeth->phydev; - int new_state = 0; - - ug_regs = ugeth->ug_regs; - uf_regs = ugeth->uccf->uf_regs; - - if (phydev->link) { - u32 tempval = in_be32(&ug_regs->maccfg2); - u32 upsmr = in_be32(&uf_regs->upsmr); - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (phydev->duplex != ugeth->oldduplex) { - new_state = 1; - if (!(phydev->duplex)) - tempval &= ~(MACCFG2_FDX); - else - tempval |= MACCFG2_FDX; - ugeth->oldduplex = phydev->duplex; - } - - if (phydev->speed != ugeth->oldspeed) { - new_state = 1; - switch (phydev->speed) { - case SPEED_1000: - tempval = ((tempval & - ~(MACCFG2_INTERFACE_MODE_MASK)) | - MACCFG2_INTERFACE_MODE_BYTE); - break; - case SPEED_100: - case SPEED_10: - tempval = ((tempval & - ~(MACCFG2_INTERFACE_MODE_MASK)) | - MACCFG2_INTERFACE_MODE_NIBBLE); - /* if reduced mode, re-set UPSMR.R10M */ - if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || - (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - if (phydev->speed == SPEED_10) - upsmr |= UCC_GETH_UPSMR_R10M; - else - upsmr &= ~UCC_GETH_UPSMR_R10M; - } - break; - default: - if (netif_msg_link(ugeth)) - ugeth_warn( - "%s: Ack! Speed (%d) is not 10/100/1000!", - dev->name, phydev->speed); - break; - } - ugeth->oldspeed = phydev->speed; - } - - if (!ugeth->oldlink) { - new_state = 1; - ugeth->oldlink = 1; - } - - if (new_state) { - /* - * To change the MAC configuration we need to disable - * the controller. To do so, we have to either grab - * ugeth->lock, which is a bad idea since 'graceful - * stop' commands might take quite a while, or we can - * quiesce driver's activity. - */ - ugeth_quiesce(ugeth); - ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); - - out_be32(&ug_regs->maccfg2, tempval); - out_be32(&uf_regs->upsmr, upsmr); - - ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); - ugeth_activate(ugeth); - } - } else if (ugeth->oldlink) { - new_state = 1; - ugeth->oldlink = 0; - ugeth->oldspeed = 0; - ugeth->oldduplex = -1; - } - - if (new_state && netif_msg_link(ugeth)) - phy_print_status(phydev); -} - -/* Initialize TBI PHY interface for communicating with the - * SERDES lynx PHY on the chip. We communicate with this PHY - * through the MDIO bus on each controller, treating it as a - * "normal" PHY at the address found in the UTBIPA register. We assume - * that the UTBIPA register is valid. Either the MDIO bus code will set - * it to a value that doesn't conflict with other PHYs on the bus, or the - * value doesn't matter, as there are no other PHYs on the bus. - */ -static void uec_configure_serdes(struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - struct ucc_geth_info *ug_info = ugeth->ug_info; - struct phy_device *tbiphy; - - if (!ug_info->tbi_node) { - dev_warn(&dev->dev, "SGMII mode requires that the device " - "tree specify a tbi-handle\n"); - return; - } - - tbiphy = of_phy_find_device(ug_info->tbi_node); - if (!tbiphy) { - dev_err(&dev->dev, "error: Could not get TBI device\n"); - return; - } - - /* - * If the link is already up, we must already be ok, and don't need to - * configure and reset the TBI<->SerDes link. Maybe U-Boot configured - * everything for us? Resetting it takes the link down and requires - * several seconds for it to come back. - */ - if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) - return; - - /* Single clk mode, mii mode off(for serdes communication) */ - phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS); - - phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT); - - phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS); -} - -/* Configure the PHY for dev. - * returns 0 if success. -1 if failure - */ -static int init_phy(struct net_device *dev) -{ - struct ucc_geth_private *priv = netdev_priv(dev); - struct ucc_geth_info *ug_info = priv->ug_info; - struct phy_device *phydev; - - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - - phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0, - priv->phy_interface); - if (!phydev) - phydev = of_phy_connect_fixed_link(dev, &adjust_link, - priv->phy_interface); - if (!phydev) { - dev_err(&dev->dev, "Could not attach to PHY\n"); - return -ENODEV; - } - - if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII) - uec_configure_serdes(dev); - - phydev->supported &= (SUPPORTED_MII | - SUPPORTED_Autoneg | - ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full); - - if (priv->max_speed == SPEED_1000) - phydev->supported |= ADVERTISED_1000baseT_Full; - - phydev->advertising = phydev->supported; - - priv->phydev = phydev; - - return 0; -} - -static void ugeth_dump_regs(struct ucc_geth_private *ugeth) -{ -#ifdef DEBUG - ucc_fast_dump_regs(ugeth->uccf); - dump_regs(ugeth); - dump_bds(ugeth); -#endif -} - -static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private * - ugeth, - enum enet_addr_type - enet_addr_type) -{ - struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; - struct ucc_fast_private *uccf; - enum comm_dir comm_dir; - struct list_head *p_lh; - u16 i, num; - u32 __iomem *addr_h; - u32 __iomem *addr_l; - u8 *p_counter; - - uccf = ugeth->uccf; - - p_82xx_addr_filt = - (struct ucc_geth_82xx_address_filtering_pram __iomem *) - ugeth->p_rx_glbl_pram->addressfiltering; - - if (enet_addr_type == ENET_ADDR_TYPE_GROUP) { - addr_h = &(p_82xx_addr_filt->gaddr_h); - addr_l = &(p_82xx_addr_filt->gaddr_l); - p_lh = &ugeth->group_hash_q; - p_counter = &(ugeth->numGroupAddrInHash); - } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) { - addr_h = &(p_82xx_addr_filt->iaddr_h); - addr_l = &(p_82xx_addr_filt->iaddr_l); - p_lh = &ugeth->ind_hash_q; - p_counter = &(ugeth->numIndAddrInHash); - } else - return -EINVAL; - - comm_dir = 0; - if (uccf->enabled_tx) - comm_dir |= COMM_DIR_TX; - if (uccf->enabled_rx) - comm_dir |= COMM_DIR_RX; - if (comm_dir) - ugeth_disable(ugeth, comm_dir); - - /* Clear the hash table. */ - out_be32(addr_h, 0x00000000); - out_be32(addr_l, 0x00000000); - - if (!p_lh) - return 0; - - num = *p_counter; - - /* Delete all remaining CQ elements */ - for (i = 0; i < num; i++) - put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh))); - - *p_counter = 0; - - if (comm_dir) - ugeth_enable(ugeth, comm_dir); - - return 0; -} - -static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth, - u8 paddr_num) -{ - ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */ - return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */ -} - -static void ucc_geth_free_rx(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_info *ug_info; - struct ucc_fast_info *uf_info; - u16 i, j; - u8 __iomem *bd; - - - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - if (ugeth->p_rx_bd_ring[i]) { - /* Return existing data buffers in ring */ - bd = ugeth->p_rx_bd_ring[i]; - for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { - if (ugeth->rx_skbuff[i][j]) { - dma_unmap_single(ugeth->dev, - in_be32(&((struct qe_bd __iomem *)bd)->buf), - ugeth->ug_info-> - uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT, - DMA_FROM_DEVICE); - dev_kfree_skb_any( - ugeth->rx_skbuff[i][j]); - ugeth->rx_skbuff[i][j] = NULL; - } - bd += sizeof(struct qe_bd); - } - - kfree(ugeth->rx_skbuff[i]); - - if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_SYSTEM) - kfree((void *)ugeth->rx_bd_ring_offset[i]); - else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) - qe_muram_free(ugeth->rx_bd_ring_offset[i]); - ugeth->p_rx_bd_ring[i] = NULL; - } - } - -} - -static void ucc_geth_free_tx(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_info *ug_info; - struct ucc_fast_info *uf_info; - u16 i, j; - u8 __iomem *bd; - - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - - for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { - bd = ugeth->p_tx_bd_ring[i]; - if (!bd) - continue; - for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { - if (ugeth->tx_skbuff[i][j]) { - dma_unmap_single(ugeth->dev, - in_be32(&((struct qe_bd __iomem *)bd)->buf), - (in_be32((u32 __iomem *)bd) & - BD_LENGTH_MASK), - DMA_TO_DEVICE); - dev_kfree_skb_any(ugeth->tx_skbuff[i][j]); - ugeth->tx_skbuff[i][j] = NULL; - } - } - - kfree(ugeth->tx_skbuff[i]); - - if (ugeth->p_tx_bd_ring[i]) { - if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_SYSTEM) - kfree((void *)ugeth->tx_bd_ring_offset[i]); - else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) - qe_muram_free(ugeth->tx_bd_ring_offset[i]); - ugeth->p_tx_bd_ring[i] = NULL; - } - } - -} - -static void ucc_geth_memclean(struct ucc_geth_private *ugeth) -{ - if (!ugeth) - return; - - if (ugeth->uccf) { - ucc_fast_free(ugeth->uccf); - ugeth->uccf = NULL; - } - - if (ugeth->p_thread_data_tx) { - qe_muram_free(ugeth->thread_dat_tx_offset); - ugeth->p_thread_data_tx = NULL; - } - if (ugeth->p_thread_data_rx) { - qe_muram_free(ugeth->thread_dat_rx_offset); - ugeth->p_thread_data_rx = NULL; - } - if (ugeth->p_exf_glbl_param) { - qe_muram_free(ugeth->exf_glbl_param_offset); - ugeth->p_exf_glbl_param = NULL; - } - if (ugeth->p_rx_glbl_pram) { - qe_muram_free(ugeth->rx_glbl_pram_offset); - ugeth->p_rx_glbl_pram = NULL; - } - if (ugeth->p_tx_glbl_pram) { - qe_muram_free(ugeth->tx_glbl_pram_offset); - ugeth->p_tx_glbl_pram = NULL; - } - if (ugeth->p_send_q_mem_reg) { - qe_muram_free(ugeth->send_q_mem_reg_offset); - ugeth->p_send_q_mem_reg = NULL; - } - if (ugeth->p_scheduler) { - qe_muram_free(ugeth->scheduler_offset); - ugeth->p_scheduler = NULL; - } - if (ugeth->p_tx_fw_statistics_pram) { - qe_muram_free(ugeth->tx_fw_statistics_pram_offset); - ugeth->p_tx_fw_statistics_pram = NULL; - } - if (ugeth->p_rx_fw_statistics_pram) { - qe_muram_free(ugeth->rx_fw_statistics_pram_offset); - ugeth->p_rx_fw_statistics_pram = NULL; - } - if (ugeth->p_rx_irq_coalescing_tbl) { - qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset); - ugeth->p_rx_irq_coalescing_tbl = NULL; - } - if (ugeth->p_rx_bd_qs_tbl) { - qe_muram_free(ugeth->rx_bd_qs_tbl_offset); - ugeth->p_rx_bd_qs_tbl = NULL; - } - if (ugeth->p_init_enet_param_shadow) { - return_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - rxthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_RX, - ugeth->ug_info->riscRx, 1); - return_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - txthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_TX, - ugeth->ug_info->riscTx, 0); - kfree(ugeth->p_init_enet_param_shadow); - ugeth->p_init_enet_param_shadow = NULL; - } - ucc_geth_free_tx(ugeth); - ucc_geth_free_rx(ugeth); - while (!list_empty(&ugeth->group_hash_q)) - put_enet_addr_container(ENET_ADDR_CONT_ENTRY - (dequeue(&ugeth->group_hash_q))); - while (!list_empty(&ugeth->ind_hash_q)) - put_enet_addr_container(ENET_ADDR_CONT_ENTRY - (dequeue(&ugeth->ind_hash_q))); - if (ugeth->ug_regs) { - iounmap(ugeth->ug_regs); - ugeth->ug_regs = NULL; - } - - skb_queue_purge(&ugeth->rx_recycle); -} - -static void ucc_geth_set_multi(struct net_device *dev) -{ - struct ucc_geth_private *ugeth; - struct netdev_hw_addr *ha; - struct ucc_fast __iomem *uf_regs; - struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; - - ugeth = netdev_priv(dev); - - uf_regs = ugeth->uccf->uf_regs; - - if (dev->flags & IFF_PROMISC) { - setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO); - } else { - clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO); - - p_82xx_addr_filt = - (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth-> - p_rx_glbl_pram->addressfiltering; - - if (dev->flags & IFF_ALLMULTI) { - /* Catch all multicast addresses, so set the - * filter to all 1's. - */ - out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff); - out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff); - } else { - /* Clear filter and add the addresses in the list. - */ - out_be32(&p_82xx_addr_filt->gaddr_h, 0x0); - out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); - - netdev_for_each_mc_addr(ha, dev) { - /* Ask CPM to run CRC and set bit in - * filter mask. - */ - hw_add_addr_in_hash(ugeth, ha->addr); - } - } - } -} - -static void ucc_geth_stop(struct ucc_geth_private *ugeth) -{ - struct ucc_geth __iomem *ug_regs = ugeth->ug_regs; - struct phy_device *phydev = ugeth->phydev; - - ugeth_vdbg("%s: IN", __func__); - - /* - * Tell the kernel the link is down. - * Must be done before disabling the controller - * or deadlock may happen. - */ - phy_stop(phydev); - - /* Disable the controller */ - ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); - - /* Mask all interrupts */ - out_be32(ugeth->uccf->p_uccm, 0x00000000); - - /* Clear all interrupts */ - out_be32(ugeth->uccf->p_ucce, 0xffffffff); - - /* Disable Rx and Tx */ - clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); - - ucc_geth_memclean(ugeth); -} - -static int ucc_struct_init(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_info *ug_info; - struct ucc_fast_info *uf_info; - int i; - - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - - if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || - (uf_info->bd_mem_part == MEM_PART_MURAM))) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: Bad memory partition value.", - __func__); - return -EINVAL; - } - - /* Rx BD lengths */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) || - (ug_info->bdRingLenRx[i] % - UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) { - if (netif_msg_probe(ugeth)) - ugeth_err - ("%s: Rx BD ring length must be multiple of 4, no smaller than 8.", - __func__); - return -EINVAL; - } - } - - /* Tx BD lengths */ - for (i = 0; i < ug_info->numQueuesTx; i++) { - if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) { - if (netif_msg_probe(ugeth)) - ugeth_err - ("%s: Tx BD ring length must be no smaller than 2.", - __func__); - return -EINVAL; - } - } - - /* mrblr */ - if ((uf_info->max_rx_buf_length == 0) || - (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) { - if (netif_msg_probe(ugeth)) - ugeth_err - ("%s: max_rx_buf_length must be non-zero multiple of 128.", - __func__); - return -EINVAL; - } - - /* num Tx queues */ - if (ug_info->numQueuesTx > NUM_TX_QUEUES) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: number of tx queues too large.", __func__); - return -EINVAL; - } - - /* num Rx queues */ - if (ug_info->numQueuesRx > NUM_RX_QUEUES) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: number of rx queues too large.", __func__); - return -EINVAL; - } - - /* l2qt */ - for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) { - if (ug_info->l2qt[i] >= ug_info->numQueuesRx) { - if (netif_msg_probe(ugeth)) - ugeth_err - ("%s: VLAN priority table entry must not be" - " larger than number of Rx queues.", - __func__); - return -EINVAL; - } - } - - /* l3qt */ - for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) { - if (ug_info->l3qt[i] >= ug_info->numQueuesRx) { - if (netif_msg_probe(ugeth)) - ugeth_err - ("%s: IP priority table entry must not be" - " larger than number of Rx queues.", - __func__); - return -EINVAL; - } - } - - if (ug_info->cam && !ug_info->ecamptr) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", - __func__); - return -EINVAL; - } - - if ((ug_info->numStationAddresses != - UCC_GETH_NUM_OF_STATION_ADDRESSES_1) && - ug_info->rxExtendedFiltering) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: Number of station addresses greater than 1 " - "not allowed in extended parsing mode.", - __func__); - return -EINVAL; - } - - /* Generate uccm_mask for receive */ - uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */ - for (i = 0; i < ug_info->numQueuesRx; i++) - uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i); - - for (i = 0; i < ug_info->numQueuesTx; i++) - uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i); - /* Initialize the general fast UCC block. */ - if (ucc_fast_init(uf_info, &ugeth->uccf)) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: Failed to init uccf.", __func__); - return -ENOMEM; - } - - /* read the number of risc engines, update the riscTx and riscRx - * if there are 4 riscs in QE - */ - if (qe_get_num_of_risc() == 4) { - ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS; - ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS; - } - - ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs)); - if (!ugeth->ug_regs) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: Failed to ioremap regs.", __func__); - return -ENOMEM; - } - - skb_queue_head_init(&ugeth->rx_recycle); - - return 0; -} - -static int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_info *ug_info; - struct ucc_fast_info *uf_info; - int length; - u16 i, j; - u8 __iomem *bd; - - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - - /* Allocate Tx bds */ - for (j = 0; j < ug_info->numQueuesTx; j++) { - /* Allocate in multiple of - UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT, - according to spec */ - length = ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) - / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) - * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; - if ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) % - UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) - length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; - if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { - u32 align = 4; - if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4) - align = UCC_GETH_TX_BD_RING_ALIGNMENT; - ugeth->tx_bd_ring_offset[j] = - (u32) kmalloc((u32) (length + align), GFP_KERNEL); - - if (ugeth->tx_bd_ring_offset[j] != 0) - ugeth->p_tx_bd_ring[j] = - (u8 __iomem *)((ugeth->tx_bd_ring_offset[j] + - align) & ~(align - 1)); - } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { - ugeth->tx_bd_ring_offset[j] = - qe_muram_alloc(length, - UCC_GETH_TX_BD_RING_ALIGNMENT); - if (!IS_ERR_VALUE(ugeth->tx_bd_ring_offset[j])) - ugeth->p_tx_bd_ring[j] = - (u8 __iomem *) qe_muram_addr(ugeth-> - tx_bd_ring_offset[j]); - } - if (!ugeth->p_tx_bd_ring[j]) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate memory for Tx bd rings.", - __func__); - return -ENOMEM; - } - /* Zero unused end of bd ring, according to spec */ - memset_io((void __iomem *)(ugeth->p_tx_bd_ring[j] + - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)), 0, - length - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)); - } - - /* Init Tx bds */ - for (j = 0; j < ug_info->numQueuesTx; j++) { - /* Setup the skbuff rings */ - ugeth->tx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenTx[j], - GFP_KERNEL); - - if (ugeth->tx_skbuff[j] == NULL) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Could not allocate tx_skbuff", - __func__); - return -ENOMEM; - } - - for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++) - ugeth->tx_skbuff[j][i] = NULL; - - ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0; - bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j]; - for (i = 0; i < ug_info->bdRingLenTx[j]; i++) { - /* clear bd buffer */ - out_be32(&((struct qe_bd __iomem *)bd)->buf, 0); - /* set bd status and length */ - out_be32((u32 __iomem *)bd, 0); - bd += sizeof(struct qe_bd); - } - bd -= sizeof(struct qe_bd); - /* set bd status and length */ - out_be32((u32 __iomem *)bd, T_W); /* for last BD set Wrap bit */ - } - - return 0; -} - -static int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_info *ug_info; - struct ucc_fast_info *uf_info; - int length; - u16 i, j; - u8 __iomem *bd; - - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - - /* Allocate Rx bds */ - for (j = 0; j < ug_info->numQueuesRx; j++) { - length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd); - if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { - u32 align = 4; - if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4) - align = UCC_GETH_RX_BD_RING_ALIGNMENT; - ugeth->rx_bd_ring_offset[j] = - (u32) kmalloc((u32) (length + align), GFP_KERNEL); - if (ugeth->rx_bd_ring_offset[j] != 0) - ugeth->p_rx_bd_ring[j] = - (u8 __iomem *)((ugeth->rx_bd_ring_offset[j] + - align) & ~(align - 1)); - } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { - ugeth->rx_bd_ring_offset[j] = - qe_muram_alloc(length, - UCC_GETH_RX_BD_RING_ALIGNMENT); - if (!IS_ERR_VALUE(ugeth->rx_bd_ring_offset[j])) - ugeth->p_rx_bd_ring[j] = - (u8 __iomem *) qe_muram_addr(ugeth-> - rx_bd_ring_offset[j]); - } - if (!ugeth->p_rx_bd_ring[j]) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate memory for Rx bd rings.", - __func__); - return -ENOMEM; - } - } - - /* Init Rx bds */ - for (j = 0; j < ug_info->numQueuesRx; j++) { - /* Setup the skbuff rings */ - ugeth->rx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenRx[j], - GFP_KERNEL); - - if (ugeth->rx_skbuff[j] == NULL) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Could not allocate rx_skbuff", - __func__); - return -ENOMEM; - } - - for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++) - ugeth->rx_skbuff[j][i] = NULL; - - ugeth->skb_currx[j] = 0; - bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j]; - for (i = 0; i < ug_info->bdRingLenRx[j]; i++) { - /* set bd status and length */ - out_be32((u32 __iomem *)bd, R_I); - /* clear bd buffer */ - out_be32(&((struct qe_bd __iomem *)bd)->buf, 0); - bd += sizeof(struct qe_bd); - } - bd -= sizeof(struct qe_bd); - /* set bd status and length */ - out_be32((u32 __iomem *)bd, R_W); /* for last BD set Wrap bit */ - } - - return 0; -} - -static int ucc_geth_startup(struct ucc_geth_private *ugeth) -{ - struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; - struct ucc_geth_init_pram __iomem *p_init_enet_pram; - struct ucc_fast_private *uccf; - struct ucc_geth_info *ug_info; - struct ucc_fast_info *uf_info; - struct ucc_fast __iomem *uf_regs; - struct ucc_geth __iomem *ug_regs; - int ret_val = -EINVAL; - u32 remoder = UCC_GETH_REMODER_INIT; - u32 init_enet_pram_offset, cecr_subblock, command; - u32 ifstat, i, j, size, l2qt, l3qt; - u16 temoder = UCC_GETH_TEMODER_INIT; - u16 test; - u8 function_code = 0; - u8 __iomem *endOfRing; - u8 numThreadsRxNumerical, numThreadsTxNumerical; - - ugeth_vdbg("%s: IN", __func__); - uccf = ugeth->uccf; - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - uf_regs = uccf->uf_regs; - ug_regs = ugeth->ug_regs; - - switch (ug_info->numThreadsRx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsRxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsRxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsRxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsRxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsRxNumerical = 8; - break; - default: - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Bad number of Rx threads value.", - __func__); - return -EINVAL; - break; - } - - switch (ug_info->numThreadsTx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsTxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsTxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsTxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsTxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsTxNumerical = 8; - break; - default: - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Bad number of Tx threads value.", - __func__); - return -EINVAL; - break; - } - - /* Calculate rx_extended_features */ - ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck || - ug_info->ipAddressAlignment || - (ug_info->numStationAddresses != - UCC_GETH_NUM_OF_STATION_ADDRESSES_1); - - ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features || - (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) || - (ug_info->vlanOperationNonTagged != - UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); - - init_default_reg_vals(&uf_regs->upsmr, - &ug_regs->maccfg1, &ug_regs->maccfg2); - - /* Set UPSMR */ - /* For more details see the hardware spec. */ - init_rx_parameters(ug_info->bro, - ug_info->rsh, ug_info->pro, &uf_regs->upsmr); - - /* We're going to ignore other registers for now, */ - /* except as needed to get up and running */ - - /* Set MACCFG1 */ - /* For more details see the hardware spec. */ - init_flow_control_params(ug_info->aufc, - ug_info->receiveFlowControl, - ug_info->transmitFlowControl, - ug_info->pausePeriod, - ug_info->extensionField, - &uf_regs->upsmr, - &ug_regs->uempr, &ug_regs->maccfg1); - - setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); - - /* Set IPGIFG */ - /* For more details see the hardware spec. */ - ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1, - ug_info->nonBackToBackIfgPart2, - ug_info-> - miminumInterFrameGapEnforcement, - ug_info->backToBackInterFrameGap, - &ug_regs->ipgifg); - if (ret_val != 0) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: IPGIFG initialization parameter too large.", - __func__); - return ret_val; - } - - /* Set HAFDUP */ - /* For more details see the hardware spec. */ - ret_val = init_half_duplex_params(ug_info->altBeb, - ug_info->backPressureNoBackoff, - ug_info->noBackoff, - ug_info->excessDefer, - ug_info->altBebTruncation, - ug_info->maxRetransmission, - ug_info->collisionWindow, - &ug_regs->hafdup); - if (ret_val != 0) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Half Duplex initialization parameter too large.", - __func__); - return ret_val; - } - - /* Set IFSTAT */ - /* For more details see the hardware spec. */ - /* Read only - resets upon read */ - ifstat = in_be32(&ug_regs->ifstat); - - /* Clear UEMPR */ - /* For more details see the hardware spec. */ - out_be32(&ug_regs->uempr, 0); - - /* Set UESCR */ - /* For more details see the hardware spec. */ - init_hw_statistics_gathering_mode((ug_info->statisticsMode & - UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE), - 0, &uf_regs->upsmr, &ug_regs->uescr); - - ret_val = ucc_geth_alloc_tx(ugeth); - if (ret_val != 0) - return ret_val; - - ret_val = ucc_geth_alloc_rx(ugeth); - if (ret_val != 0) - return ret_val; - - /* - * Global PRAM - */ - /* Tx global PRAM */ - /* Allocate global tx parameter RAM page */ - ugeth->tx_glbl_pram_offset = - qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram), - UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", - __func__); - return -ENOMEM; - } - ugeth->p_tx_glbl_pram = - (struct ucc_geth_tx_global_pram __iomem *) qe_muram_addr(ugeth-> - tx_glbl_pram_offset); - /* Zero out p_tx_glbl_pram */ - memset_io((void __iomem *)ugeth->p_tx_glbl_pram, 0, sizeof(struct ucc_geth_tx_global_pram)); - - /* Fill global PRAM */ - - /* TQPTR */ - /* Size varies with number of Tx threads */ - ugeth->thread_dat_tx_offset = - qe_muram_alloc(numThreadsTxNumerical * - sizeof(struct ucc_geth_thread_data_tx) + - 32 * (numThreadsTxNumerical == 1), - UCC_GETH_THREAD_DATA_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", - __func__); - return -ENOMEM; - } - - ugeth->p_thread_data_tx = - (struct ucc_geth_thread_data_tx __iomem *) qe_muram_addr(ugeth-> - thread_dat_tx_offset); - out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset); - - /* vtagtable */ - for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++) - out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i], - ug_info->vtagtable[i]); - - /* iphoffset */ - for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++) - out_8(&ugeth->p_tx_glbl_pram->iphoffset[i], - ug_info->iphoffset[i]); - - /* SQPTR */ - /* Size varies with number of Tx queues */ - ugeth->send_q_mem_reg_offset = - qe_muram_alloc(ug_info->numQueuesTx * - sizeof(struct ucc_geth_send_queue_qd), - UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", - __func__); - return -ENOMEM; - } - - ugeth->p_send_q_mem_reg = - (struct ucc_geth_send_queue_mem_region __iomem *) qe_muram_addr(ugeth-> - send_q_mem_reg_offset); - out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset); - - /* Setup the table */ - /* Assume BD rings are already established */ - for (i = 0; i < ug_info->numQueuesTx; i++) { - endOfRing = - ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] - - 1) * sizeof(struct qe_bd); - if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, - (u32) virt_to_phys(ugeth->p_tx_bd_ring[i])); - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. - last_bd_completed_address, - (u32) virt_to_phys(endOfRing)); - } else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) { - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, - (u32) immrbar_virt_to_phys(ugeth-> - p_tx_bd_ring[i])); - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. - last_bd_completed_address, - (u32) immrbar_virt_to_phys(endOfRing)); - } - } - - /* schedulerbasepointer */ - - if (ug_info->numQueuesTx > 1) { - /* scheduler exists only if more than 1 tx queue */ - ugeth->scheduler_offset = - qe_muram_alloc(sizeof(struct ucc_geth_scheduler), - UCC_GETH_SCHEDULER_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->scheduler_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_scheduler.", - __func__); - return -ENOMEM; - } - - ugeth->p_scheduler = - (struct ucc_geth_scheduler __iomem *) qe_muram_addr(ugeth-> - scheduler_offset); - out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer, - ugeth->scheduler_offset); - /* Zero out p_scheduler */ - memset_io((void __iomem *)ugeth->p_scheduler, 0, sizeof(struct ucc_geth_scheduler)); - - /* Set values in scheduler */ - out_be32(&ugeth->p_scheduler->mblinterval, - ug_info->mblinterval); - out_be16(&ugeth->p_scheduler->nortsrbytetime, - ug_info->nortsrbytetime); - out_8(&ugeth->p_scheduler->fracsiz, ug_info->fracsiz); - out_8(&ugeth->p_scheduler->strictpriorityq, - ug_info->strictpriorityq); - out_8(&ugeth->p_scheduler->txasap, ug_info->txasap); - out_8(&ugeth->p_scheduler->extrabw, ug_info->extrabw); - for (i = 0; i < NUM_TX_QUEUES; i++) - out_8(&ugeth->p_scheduler->weightfactor[i], - ug_info->weightfactor[i]); - - /* Set pointers to cpucount registers in scheduler */ - ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0); - ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1); - ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2); - ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3); - ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4); - ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5); - ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6); - ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7); - } - - /* schedulerbasepointer */ - /* TxRMON_PTR (statistics) */ - if (ug_info-> - statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { - ugeth->tx_fw_statistics_pram_offset = - qe_muram_alloc(sizeof - (struct ucc_geth_tx_firmware_statistics_pram), - UCC_GETH_TX_STATISTICS_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_tx_fw_statistics_pram.", - __func__); - return -ENOMEM; - } - ugeth->p_tx_fw_statistics_pram = - (struct ucc_geth_tx_firmware_statistics_pram __iomem *) - qe_muram_addr(ugeth->tx_fw_statistics_pram_offset); - /* Zero out p_tx_fw_statistics_pram */ - memset_io((void __iomem *)ugeth->p_tx_fw_statistics_pram, - 0, sizeof(struct ucc_geth_tx_firmware_statistics_pram)); - } - - /* temoder */ - /* Already has speed set */ - - if (ug_info->numQueuesTx > 1) - temoder |= TEMODER_SCHEDULER_ENABLE; - if (ug_info->ipCheckSumGenerate) - temoder |= TEMODER_IP_CHECKSUM_GENERATE; - temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT); - out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder); - - test = in_be16(&ugeth->p_tx_glbl_pram->temoder); - - /* Function code register value to be used later */ - function_code = UCC_BMR_BO_BE | UCC_BMR_GBL; - /* Required for QE */ - - /* function code register */ - out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24); - - /* Rx global PRAM */ - /* Allocate global rx parameter RAM page */ - ugeth->rx_glbl_pram_offset = - qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram), - UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", - __func__); - return -ENOMEM; - } - ugeth->p_rx_glbl_pram = - (struct ucc_geth_rx_global_pram __iomem *) qe_muram_addr(ugeth-> - rx_glbl_pram_offset); - /* Zero out p_rx_glbl_pram */ - memset_io((void __iomem *)ugeth->p_rx_glbl_pram, 0, sizeof(struct ucc_geth_rx_global_pram)); - - /* Fill global PRAM */ - - /* RQPTR */ - /* Size varies with number of Rx threads */ - ugeth->thread_dat_rx_offset = - qe_muram_alloc(numThreadsRxNumerical * - sizeof(struct ucc_geth_thread_data_rx), - UCC_GETH_THREAD_DATA_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", - __func__); - return -ENOMEM; - } - - ugeth->p_thread_data_rx = - (struct ucc_geth_thread_data_rx __iomem *) qe_muram_addr(ugeth-> - thread_dat_rx_offset); - out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset); - - /* typeorlen */ - out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen); - - /* rxrmonbaseptr (statistics) */ - if (ug_info-> - statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { - ugeth->rx_fw_statistics_pram_offset = - qe_muram_alloc(sizeof - (struct ucc_geth_rx_firmware_statistics_pram), - UCC_GETH_RX_STATISTICS_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_fw_statistics_pram.", __func__); - return -ENOMEM; - } - ugeth->p_rx_fw_statistics_pram = - (struct ucc_geth_rx_firmware_statistics_pram __iomem *) - qe_muram_addr(ugeth->rx_fw_statistics_pram_offset); - /* Zero out p_rx_fw_statistics_pram */ - memset_io((void __iomem *)ugeth->p_rx_fw_statistics_pram, 0, - sizeof(struct ucc_geth_rx_firmware_statistics_pram)); - } - - /* intCoalescingPtr */ - - /* Size varies with number of Rx queues */ - ugeth->rx_irq_coalescing_tbl_offset = - qe_muram_alloc(ug_info->numQueuesRx * - sizeof(struct ucc_geth_rx_interrupt_coalescing_entry) - + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_irq_coalescing_tbl.", __func__); - return -ENOMEM; - } - - ugeth->p_rx_irq_coalescing_tbl = - (struct ucc_geth_rx_interrupt_coalescing_table __iomem *) - qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset); - out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr, - ugeth->rx_irq_coalescing_tbl_offset); - - /* Fill interrupt coalescing table */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. - interruptcoalescingmaxvalue, - ug_info->interruptcoalescingmaxvalue[i]); - out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. - interruptcoalescingcounter, - ug_info->interruptcoalescingmaxvalue[i]); - } - - /* MRBLR */ - init_max_rx_buff_len(uf_info->max_rx_buf_length, - &ugeth->p_rx_glbl_pram->mrblr); - /* MFLR */ - out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength); - /* MINFLR */ - init_min_frame_len(ug_info->minFrameLength, - &ugeth->p_rx_glbl_pram->minflr, - &ugeth->p_rx_glbl_pram->mrblr); - /* MAXD1 */ - out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length); - /* MAXD2 */ - out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length); - - /* l2qt */ - l2qt = 0; - for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) - l2qt |= (ug_info->l2qt[i] << (28 - 4 * i)); - out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt); - - /* l3qt */ - for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) { - l3qt = 0; - for (i = 0; i < 8; i++) - l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i)); - out_be32(&ugeth->p_rx_glbl_pram->l3qt[j/8], l3qt); - } - - /* vlantype */ - out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype); - - /* vlantci */ - out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci); - - /* ecamptr */ - out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr); - - /* RBDQPTR */ - /* Size varies with number of Rx queues */ - ugeth->rx_bd_qs_tbl_offset = - qe_muram_alloc(ug_info->numQueuesRx * - (sizeof(struct ucc_geth_rx_bd_queues_entry) + - sizeof(struct ucc_geth_rx_prefetched_bds)), - UCC_GETH_RX_BD_QUEUES_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", - __func__); - return -ENOMEM; - } - - ugeth->p_rx_bd_qs_tbl = - (struct ucc_geth_rx_bd_queues_entry __iomem *) qe_muram_addr(ugeth-> - rx_bd_qs_tbl_offset); - out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset); - /* Zero out p_rx_bd_qs_tbl */ - memset_io((void __iomem *)ugeth->p_rx_bd_qs_tbl, - 0, - ug_info->numQueuesRx * (sizeof(struct ucc_geth_rx_bd_queues_entry) + - sizeof(struct ucc_geth_rx_prefetched_bds))); - - /* Setup the table */ - /* Assume BD rings are already established */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { - out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, - (u32) virt_to_phys(ugeth->p_rx_bd_ring[i])); - } else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) { - out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, - (u32) immrbar_virt_to_phys(ugeth-> - p_rx_bd_ring[i])); - } - /* rest of fields handled by QE */ - } - - /* remoder */ - /* Already has speed set */ - - if (ugeth->rx_extended_features) - remoder |= REMODER_RX_EXTENDED_FEATURES; - if (ug_info->rxExtendedFiltering) - remoder |= REMODER_RX_EXTENDED_FILTERING; - if (ug_info->dynamicMaxFrameLength) - remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH; - if (ug_info->dynamicMinFrameLength) - remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH; - remoder |= - ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT; - remoder |= - ug_info-> - vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT; - remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT; - remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT); - if (ug_info->ipCheckSumCheck) - remoder |= REMODER_IP_CHECKSUM_CHECK; - if (ug_info->ipAddressAlignment) - remoder |= REMODER_IP_ADDRESS_ALIGNMENT; - out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder); - - /* Note that this function must be called */ - /* ONLY AFTER p_tx_fw_statistics_pram */ - /* andp_UccGethRxFirmwareStatisticsPram are allocated ! */ - init_firmware_statistics_gathering_mode((ug_info-> - statisticsMode & - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX), - (ug_info->statisticsMode & - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX), - &ugeth->p_tx_glbl_pram->txrmonbaseptr, - ugeth->tx_fw_statistics_pram_offset, - &ugeth->p_rx_glbl_pram->rxrmonbaseptr, - ugeth->rx_fw_statistics_pram_offset, - &ugeth->p_tx_glbl_pram->temoder, - &ugeth->p_rx_glbl_pram->remoder); - - /* function code register */ - out_8(&ugeth->p_rx_glbl_pram->rstate, function_code); - - /* initialize extended filtering */ - if (ug_info->rxExtendedFiltering) { - if (!ug_info->extendedFilteringChainPointer) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Null Extended Filtering Chain Pointer.", - __func__); - return -EINVAL; - } - - /* Allocate memory for extended filtering Mode Global - Parameters */ - ugeth->exf_glbl_param_offset = - qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram), - UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_exf_glbl_param.", __func__); - return -ENOMEM; - } - - ugeth->p_exf_glbl_param = - (struct ucc_geth_exf_global_pram __iomem *) qe_muram_addr(ugeth-> - exf_glbl_param_offset); - out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam, - ugeth->exf_glbl_param_offset); - out_be32(&ugeth->p_exf_glbl_param->l2pcdptr, - (u32) ug_info->extendedFilteringChainPointer); - - } else { /* initialize 82xx style address filtering */ - - /* Init individual address recognition registers to disabled */ - - for (j = 0; j < NUM_OF_PADDRS; j++) - ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j); - - p_82xx_addr_filt = - (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth-> - p_rx_glbl_pram->addressfiltering; - - ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, - ENET_ADDR_TYPE_GROUP); - ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, - ENET_ADDR_TYPE_INDIVIDUAL); - } - - /* - * Initialize UCC at QE level - */ - - command = QE_INIT_TX_RX; - - /* Allocate shadow InitEnet command parameter structure. - * This is needed because after the InitEnet command is executed, - * the structure in DPRAM is released, because DPRAM is a premium - * resource. - * This shadow structure keeps a copy of what was done so that the - * allocated resources can be released when the channel is freed. - */ - if (!(ugeth->p_init_enet_param_shadow = - kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate memory for" - " p_UccInitEnetParamShadows.", __func__); - return -ENOMEM; - } - /* Zero out *p_init_enet_param_shadow */ - memset((char *)ugeth->p_init_enet_param_shadow, - 0, sizeof(struct ucc_geth_init_pram)); - - /* Fill shadow InitEnet command parameter structure */ - - ugeth->p_init_enet_param_shadow->resinit1 = - ENET_INIT_PARAM_MAGIC_RES_INIT1; - ugeth->p_init_enet_param_shadow->resinit2 = - ENET_INIT_PARAM_MAGIC_RES_INIT2; - ugeth->p_init_enet_param_shadow->resinit3 = - ENET_INIT_PARAM_MAGIC_RES_INIT3; - ugeth->p_init_enet_param_shadow->resinit4 = - ENET_INIT_PARAM_MAGIC_RES_INIT4; - ugeth->p_init_enet_param_shadow->resinit5 = - ENET_INIT_PARAM_MAGIC_RES_INIT5; - ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= - ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT; - ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= - ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT; - - ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= - ugeth->rx_glbl_pram_offset | ug_info->riscRx; - if ((ug_info->largestexternallookupkeysize != - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) && - (ug_info->largestexternallookupkeysize != - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) && - (ug_info->largestexternallookupkeysize != - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Invalid largest External Lookup Key Size.", - __func__); - return -EINVAL; - } - ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = - ug_info->largestexternallookupkeysize; - size = sizeof(struct ucc_geth_thread_rx_pram); - if (ug_info->rxExtendedFiltering) { - size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; - if (ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; - if (ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; - } - - if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth-> - p_init_enet_param_shadow->rxthread[0]), - (u8) (numThreadsRxNumerical + 1) - /* Rx needs one extra for terminator */ - , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT, - ug_info->riscRx, 1)) != 0) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __func__); - return ret_val; - } - - ugeth->p_init_enet_param_shadow->txglobal = - ugeth->tx_glbl_pram_offset | ug_info->riscTx; - if ((ret_val = - fill_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - txthread[0]), numThreadsTxNumerical, - sizeof(struct ucc_geth_thread_tx_pram), - UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, - ug_info->riscTx, 0)) != 0) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __func__); - return ret_val; - } - - /* Load Rx bds with buffers */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Can not fill Rx bds with buffers.", - __func__); - return ret_val; - } - } - - /* Allocate InitEnet command parameter structure */ - init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4); - if (IS_ERR_VALUE(init_enet_pram_offset)) { - if (netif_msg_ifup(ugeth)) - ugeth_err - ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", - __func__); - return -ENOMEM; - } - p_init_enet_pram = - (struct ucc_geth_init_pram __iomem *) qe_muram_addr(init_enet_pram_offset); - - /* Copy shadow InitEnet command parameter structure into PRAM */ - out_8(&p_init_enet_pram->resinit1, - ugeth->p_init_enet_param_shadow->resinit1); - out_8(&p_init_enet_pram->resinit2, - ugeth->p_init_enet_param_shadow->resinit2); - out_8(&p_init_enet_pram->resinit3, - ugeth->p_init_enet_param_shadow->resinit3); - out_8(&p_init_enet_pram->resinit4, - ugeth->p_init_enet_param_shadow->resinit4); - out_be16(&p_init_enet_pram->resinit5, - ugeth->p_init_enet_param_shadow->resinit5); - out_8(&p_init_enet_pram->largestexternallookupkeysize, - ugeth->p_init_enet_param_shadow->largestexternallookupkeysize); - out_be32(&p_init_enet_pram->rgftgfrxglobal, - ugeth->p_init_enet_param_shadow->rgftgfrxglobal); - for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++) - out_be32(&p_init_enet_pram->rxthread[i], - ugeth->p_init_enet_param_shadow->rxthread[i]); - out_be32(&p_init_enet_pram->txglobal, - ugeth->p_init_enet_param_shadow->txglobal); - for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++) - out_be32(&p_init_enet_pram->txthread[i], - ugeth->p_init_enet_param_shadow->txthread[i]); - - /* Issue QE command */ - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(command, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, - init_enet_pram_offset); - - /* Free InitEnet command parameter */ - qe_muram_free(init_enet_pram_offset); - - return 0; -} - -/* This is called by the kernel when a frame is ready for transmission. */ -/* It is pointed to by the dev->hard_start_xmit function pointer */ -static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); -#ifdef CONFIG_UGETH_TX_ON_DEMAND - struct ucc_fast_private *uccf; -#endif - u8 __iomem *bd; /* BD pointer */ - u32 bd_status; - u8 txQ = 0; - unsigned long flags; - - ugeth_vdbg("%s: IN", __func__); - - spin_lock_irqsave(&ugeth->lock, flags); - - dev->stats.tx_bytes += skb->len; - - /* Start from the next BD that should be filled */ - bd = ugeth->txBd[txQ]; - bd_status = in_be32((u32 __iomem *)bd); - /* Save the skb pointer so we can free it later */ - ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb; - - /* Update the current skb pointer (wrapping if this was the last) */ - ugeth->skb_curtx[txQ] = - (ugeth->skb_curtx[txQ] + - 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); - - /* set up the buffer descriptor */ - out_be32(&((struct qe_bd __iomem *)bd)->buf, - dma_map_single(ugeth->dev, skb->data, - skb->len, DMA_TO_DEVICE)); - - /* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */ - - bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len; - - /* set bd status and length */ - out_be32((u32 __iomem *)bd, bd_status); - - /* Move to next BD in the ring */ - if (!(bd_status & T_W)) - bd += sizeof(struct qe_bd); - else - bd = ugeth->p_tx_bd_ring[txQ]; - - /* If the next BD still needs to be cleaned up, then the bds - are full. We need to tell the kernel to stop sending us stuff. */ - if (bd == ugeth->confBd[txQ]) { - if (!netif_queue_stopped(dev)) - netif_stop_queue(dev); - } - - ugeth->txBd[txQ] = bd; - - skb_tx_timestamp(skb); - - if (ugeth->p_scheduler) { - ugeth->cpucount[txQ]++; - /* Indicate to QE that there are more Tx bds ready for - transmission */ - /* This is done by writing a running counter of the bd - count to the scheduler PRAM. */ - out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]); - } - -#ifdef CONFIG_UGETH_TX_ON_DEMAND - uccf = ugeth->uccf; - out_be16(uccf->p_utodr, UCC_FAST_TOD); -#endif - spin_unlock_irqrestore(&ugeth->lock, flags); - - return NETDEV_TX_OK; -} - -static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit) -{ - struct sk_buff *skb; - u8 __iomem *bd; - u16 length, howmany = 0; - u32 bd_status; - u8 *bdBuffer; - struct net_device *dev; - - ugeth_vdbg("%s: IN", __func__); - - dev = ugeth->ndev; - - /* collect received buffers */ - bd = ugeth->rxBd[rxQ]; - - bd_status = in_be32((u32 __iomem *)bd); - - /* while there are received buffers and BD is full (~R_E) */ - while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) { - bdBuffer = (u8 *) in_be32(&((struct qe_bd __iomem *)bd)->buf); - length = (u16) ((bd_status & BD_LENGTH_MASK) - 4); - skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]]; - - /* determine whether buffer is first, last, first and last - (single buffer frame) or middle (not first and not last) */ - if (!skb || - (!(bd_status & (R_F | R_L))) || - (bd_status & R_ERRORS_FATAL)) { - if (netif_msg_rx_err(ugeth)) - ugeth_err("%s, %d: ERROR!!! skb - 0x%08x", - __func__, __LINE__, (u32) skb); - if (skb) { - skb->data = skb->head + NET_SKB_PAD; - skb->len = 0; - skb_reset_tail_pointer(skb); - __skb_queue_head(&ugeth->rx_recycle, skb); - } - - ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL; - dev->stats.rx_dropped++; - } else { - dev->stats.rx_packets++; - howmany++; - - /* Prep the skb for the packet */ - skb_put(skb, length); - - /* Tell the skb what kind of packet this is */ - skb->protocol = eth_type_trans(skb, ugeth->ndev); - - dev->stats.rx_bytes += length; - /* Send the packet up the stack */ - netif_receive_skb(skb); - } - - skb = get_new_skb(ugeth, bd); - if (!skb) { - if (netif_msg_rx_err(ugeth)) - ugeth_warn("%s: No Rx Data Buffer", __func__); - dev->stats.rx_dropped++; - break; - } - - ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb; - - /* update to point at the next skb */ - ugeth->skb_currx[rxQ] = - (ugeth->skb_currx[rxQ] + - 1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]); - - if (bd_status & R_W) - bd = ugeth->p_rx_bd_ring[rxQ]; - else - bd += sizeof(struct qe_bd); - - bd_status = in_be32((u32 __iomem *)bd); - } - - ugeth->rxBd[rxQ] = bd; - return howmany; -} - -static int ucc_geth_tx(struct net_device *dev, u8 txQ) -{ - /* Start from the next BD that should be filled */ - struct ucc_geth_private *ugeth = netdev_priv(dev); - u8 __iomem *bd; /* BD pointer */ - u32 bd_status; - - bd = ugeth->confBd[txQ]; - bd_status = in_be32((u32 __iomem *)bd); - - /* Normal processing. */ - while ((bd_status & T_R) == 0) { - struct sk_buff *skb; - - /* BD contains already transmitted buffer. */ - /* Handle the transmitted buffer and release */ - /* the BD to be used with the current frame */ - - skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; - if (!skb) - break; - - dev->stats.tx_packets++; - - if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN && - skb_recycle_check(skb, - ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT)) - __skb_queue_head(&ugeth->rx_recycle, skb); - else - dev_kfree_skb(skb); - - ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; - ugeth->skb_dirtytx[txQ] = - (ugeth->skb_dirtytx[txQ] + - 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); - - /* We freed a buffer, so now we can restart transmission */ - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - - /* Advance the confirmation BD pointer */ - if (!(bd_status & T_W)) - bd += sizeof(struct qe_bd); - else - bd = ugeth->p_tx_bd_ring[txQ]; - bd_status = in_be32((u32 __iomem *)bd); - } - ugeth->confBd[txQ] = bd; - return 0; -} - -static int ucc_geth_poll(struct napi_struct *napi, int budget) -{ - struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi); - struct ucc_geth_info *ug_info; - int howmany, i; - - ug_info = ugeth->ug_info; - - /* Tx event processing */ - spin_lock(&ugeth->lock); - for (i = 0; i < ug_info->numQueuesTx; i++) - ucc_geth_tx(ugeth->ndev, i); - spin_unlock(&ugeth->lock); - - howmany = 0; - for (i = 0; i < ug_info->numQueuesRx; i++) - howmany += ucc_geth_rx(ugeth, i, budget - howmany); - - if (howmany < budget) { - napi_complete(napi); - setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS); - } - - return howmany; -} - -static irqreturn_t ucc_geth_irq_handler(int irq, void *info) -{ - struct net_device *dev = info; - struct ucc_geth_private *ugeth = netdev_priv(dev); - struct ucc_fast_private *uccf; - struct ucc_geth_info *ug_info; - register u32 ucce; - register u32 uccm; - - ugeth_vdbg("%s: IN", __func__); - - uccf = ugeth->uccf; - ug_info = ugeth->ug_info; - - /* read and clear events */ - ucce = (u32) in_be32(uccf->p_ucce); - uccm = (u32) in_be32(uccf->p_uccm); - ucce &= uccm; - out_be32(uccf->p_ucce, ucce); - - /* check for receive events that require processing */ - if (ucce & (UCCE_RX_EVENTS | UCCE_TX_EVENTS)) { - if (napi_schedule_prep(&ugeth->napi)) { - uccm &= ~(UCCE_RX_EVENTS | UCCE_TX_EVENTS); - out_be32(uccf->p_uccm, uccm); - __napi_schedule(&ugeth->napi); - } - } - - /* Errors and other events */ - if (ucce & UCCE_OTHER) { - if (ucce & UCC_GETH_UCCE_BSY) - dev->stats.rx_errors++; - if (ucce & UCC_GETH_UCCE_TXE) - dev->stats.tx_errors++; - } - - return IRQ_HANDLED; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void ucc_netpoll(struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - int irq = ugeth->ug_info->uf_info.irq; - - disable_irq(irq); - ucc_geth_irq_handler(irq, dev); - enable_irq(irq); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static int ucc_geth_set_mac_addr(struct net_device *dev, void *p) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * If device is not running, we will set mac addr register - * when opening the device. - */ - if (!netif_running(dev)) - return 0; - - spin_lock_irq(&ugeth->lock); - init_mac_station_addr_regs(dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5], - &ugeth->ug_regs->macstnaddr1, - &ugeth->ug_regs->macstnaddr2); - spin_unlock_irq(&ugeth->lock); - - return 0; -} - -static int ucc_geth_init_mac(struct ucc_geth_private *ugeth) -{ - struct net_device *dev = ugeth->ndev; - int err; - - err = ucc_struct_init(ugeth); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot configure internal struct, " - "aborting.", dev->name); - goto err; - } - - err = ucc_geth_startup(ugeth); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); - goto err; - } - - err = adjust_enet_interface(ugeth); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); - goto err; - } - - /* Set MACSTNADDR1, MACSTNADDR2 */ - /* For more details see the hardware spec. */ - init_mac_station_addr_regs(dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5], - &ugeth->ug_regs->macstnaddr1, - &ugeth->ug_regs->macstnaddr2); - - err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot enable net device, aborting.", dev->name); - goto err; - } - - return 0; -err: - ucc_geth_stop(ugeth); - return err; -} - -/* Called when something needs to use the ethernet device */ -/* Returns 0 for success. */ -static int ucc_geth_open(struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - int err; - - ugeth_vdbg("%s: IN", __func__); - - /* Test station address */ - if (dev->dev_addr[0] & ENET_GROUP_ADDR) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Multicast address used for station " - "address - is this what you wanted?", - __func__); - return -EINVAL; - } - - err = init_phy(dev); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot initialize PHY, aborting.", - dev->name); - return err; - } - - err = ucc_geth_init_mac(ugeth); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot initialize MAC, aborting.", - dev->name); - goto err; - } - - err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, - 0, "UCC Geth", dev); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot get IRQ for net device, aborting.", - dev->name); - goto err; - } - - phy_start(ugeth->phydev); - napi_enable(&ugeth->napi); - netif_start_queue(dev); - - device_set_wakeup_capable(&dev->dev, - qe_alive_during_sleep() || ugeth->phydev->irq); - device_set_wakeup_enable(&dev->dev, ugeth->wol_en); - - return err; - -err: - ucc_geth_stop(ugeth); - return err; -} - -/* Stops the kernel queue, and halts the controller */ -static int ucc_geth_close(struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - - ugeth_vdbg("%s: IN", __func__); - - napi_disable(&ugeth->napi); - - cancel_work_sync(&ugeth->timeout_work); - ucc_geth_stop(ugeth); - phy_disconnect(ugeth->phydev); - ugeth->phydev = NULL; - - free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev); - - netif_stop_queue(dev); - - return 0; -} - -/* Reopen device. This will reset the MAC and PHY. */ -static void ucc_geth_timeout_work(struct work_struct *work) -{ - struct ucc_geth_private *ugeth; - struct net_device *dev; - - ugeth = container_of(work, struct ucc_geth_private, timeout_work); - dev = ugeth->ndev; - - ugeth_vdbg("%s: IN", __func__); - - dev->stats.tx_errors++; - - ugeth_dump_regs(ugeth); - - if (dev->flags & IFF_UP) { - /* - * Must reset MAC *and* PHY. This is done by reopening - * the device. - */ - netif_tx_stop_all_queues(dev); - ucc_geth_stop(ugeth); - ucc_geth_init_mac(ugeth); - /* Must start PHY here */ - phy_start(ugeth->phydev); - netif_tx_start_all_queues(dev); - } - - netif_tx_schedule_all(dev); -} - -/* - * ucc_geth_timeout gets called when a packet has not been - * transmitted after a set amount of time. - */ -static void ucc_geth_timeout(struct net_device *dev) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - - schedule_work(&ugeth->timeout_work); -} - - -#ifdef CONFIG_PM - -static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) -{ - struct net_device *ndev = dev_get_drvdata(&ofdev->dev); - struct ucc_geth_private *ugeth = netdev_priv(ndev); - - if (!netif_running(ndev)) - return 0; - - netif_device_detach(ndev); - napi_disable(&ugeth->napi); - - /* - * Disable the controller, otherwise we'll wakeup on any network - * activity. - */ - ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); - - if (ugeth->wol_en & WAKE_MAGIC) { - setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD); - setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE); - ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX); - } else if (!(ugeth->wol_en & WAKE_PHY)) { - phy_stop(ugeth->phydev); - } - - return 0; -} - -static int ucc_geth_resume(struct platform_device *ofdev) -{ - struct net_device *ndev = dev_get_drvdata(&ofdev->dev); - struct ucc_geth_private *ugeth = netdev_priv(ndev); - int err; - - if (!netif_running(ndev)) - return 0; - - if (qe_alive_during_sleep()) { - if (ugeth->wol_en & WAKE_MAGIC) { - ucc_fast_disable(ugeth->uccf, COMM_DIR_RX_AND_TX); - clrbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE); - clrbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD); - } - ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); - } else { - /* - * Full reinitialization is required if QE shuts down - * during sleep. - */ - ucc_geth_memclean(ugeth); - - err = ucc_geth_init_mac(ugeth); - if (err) { - ugeth_err("%s: Cannot initialize MAC, aborting.", - ndev->name); - return err; - } - } - - ugeth->oldlink = 0; - ugeth->oldspeed = 0; - ugeth->oldduplex = -1; - - phy_stop(ugeth->phydev); - phy_start(ugeth->phydev); - - napi_enable(&ugeth->napi); - netif_device_attach(ndev); - - return 0; -} - -#else -#define ucc_geth_suspend NULL -#define ucc_geth_resume NULL -#endif - -static phy_interface_t to_phy_interface(const char *phy_connection_type) -{ - if (strcasecmp(phy_connection_type, "mii") == 0) - return PHY_INTERFACE_MODE_MII; - if (strcasecmp(phy_connection_type, "gmii") == 0) - return PHY_INTERFACE_MODE_GMII; - if (strcasecmp(phy_connection_type, "tbi") == 0) - return PHY_INTERFACE_MODE_TBI; - if (strcasecmp(phy_connection_type, "rmii") == 0) - return PHY_INTERFACE_MODE_RMII; - if (strcasecmp(phy_connection_type, "rgmii") == 0) - return PHY_INTERFACE_MODE_RGMII; - if (strcasecmp(phy_connection_type, "rgmii-id") == 0) - return PHY_INTERFACE_MODE_RGMII_ID; - if (strcasecmp(phy_connection_type, "rgmii-txid") == 0) - return PHY_INTERFACE_MODE_RGMII_TXID; - if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0) - return PHY_INTERFACE_MODE_RGMII_RXID; - if (strcasecmp(phy_connection_type, "rtbi") == 0) - return PHY_INTERFACE_MODE_RTBI; - if (strcasecmp(phy_connection_type, "sgmii") == 0) - return PHY_INTERFACE_MODE_SGMII; - - return PHY_INTERFACE_MODE_MII; -} - -static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct ucc_geth_private *ugeth = netdev_priv(dev); - - if (!netif_running(dev)) - return -EINVAL; - - if (!ugeth->phydev) - return -ENODEV; - - return phy_mii_ioctl(ugeth->phydev, rq, cmd); -} - -static const struct net_device_ops ucc_geth_netdev_ops = { - .ndo_open = ucc_geth_open, - .ndo_stop = ucc_geth_close, - .ndo_start_xmit = ucc_geth_start_xmit, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = ucc_geth_set_mac_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_rx_mode = ucc_geth_set_multi, - .ndo_tx_timeout = ucc_geth_timeout, - .ndo_do_ioctl = ucc_geth_ioctl, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ucc_netpoll, -#endif -}; - -static int ucc_geth_probe(struct platform_device* ofdev) -{ - struct device *device = &ofdev->dev; - struct device_node *np = ofdev->dev.of_node; - struct net_device *dev = NULL; - struct ucc_geth_private *ugeth = NULL; - struct ucc_geth_info *ug_info; - struct resource res; - int err, ucc_num, max_speed = 0; - const unsigned int *prop; - const char *sprop; - const void *mac_addr; - phy_interface_t phy_interface; - static const int enet_to_speed[] = { - SPEED_10, SPEED_10, SPEED_10, - SPEED_100, SPEED_100, SPEED_100, - SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000, - }; - static const phy_interface_t enet_to_phy_interface[] = { - PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII, - PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII, - PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, - PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, - PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, - PHY_INTERFACE_MODE_SGMII, - }; - - ugeth_vdbg("%s: IN", __func__); - - prop = of_get_property(np, "cell-index", NULL); - if (!prop) { - prop = of_get_property(np, "device-id", NULL); - if (!prop) - return -ENODEV; - } - - ucc_num = *prop - 1; - if ((ucc_num < 0) || (ucc_num > 7)) - return -ENODEV; - - ug_info = &ugeth_info[ucc_num]; - if (ug_info == NULL) { - if (netif_msg_probe(&debug)) - ugeth_err("%s: [%d] Missing additional data!", - __func__, ucc_num); - return -ENODEV; - } - - ug_info->uf_info.ucc_num = ucc_num; - - sprop = of_get_property(np, "rx-clock-name", NULL); - if (sprop) { - ug_info->uf_info.rx_clock = qe_clock_source(sprop); - if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) || - (ug_info->uf_info.rx_clock > QE_CLK24)) { - printk(KERN_ERR - "ucc_geth: invalid rx-clock-name property\n"); - return -EINVAL; - } - } else { - prop = of_get_property(np, "rx-clock", NULL); - if (!prop) { - /* If both rx-clock-name and rx-clock are missing, - we want to tell people to use rx-clock-name. */ - printk(KERN_ERR - "ucc_geth: missing rx-clock-name property\n"); - return -EINVAL; - } - if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) { - printk(KERN_ERR - "ucc_geth: invalid rx-clock propperty\n"); - return -EINVAL; - } - ug_info->uf_info.rx_clock = *prop; - } - - sprop = of_get_property(np, "tx-clock-name", NULL); - if (sprop) { - ug_info->uf_info.tx_clock = qe_clock_source(sprop); - if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) || - (ug_info->uf_info.tx_clock > QE_CLK24)) { - printk(KERN_ERR - "ucc_geth: invalid tx-clock-name property\n"); - return -EINVAL; - } - } else { - prop = of_get_property(np, "tx-clock", NULL); - if (!prop) { - printk(KERN_ERR - "ucc_geth: missing tx-clock-name property\n"); - return -EINVAL; - } - if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) { - printk(KERN_ERR - "ucc_geth: invalid tx-clock property\n"); - return -EINVAL; - } - ug_info->uf_info.tx_clock = *prop; - } - - err = of_address_to_resource(np, 0, &res); - if (err) - return -EINVAL; - - ug_info->uf_info.regs = res.start; - ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); - - ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0); - - /* Find the TBI PHY node. If it's not there, we don't support SGMII */ - ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0); - - /* get the phy interface type, or default to MII */ - prop = of_get_property(np, "phy-connection-type", NULL); - if (!prop) { - /* handle interface property present in old trees */ - prop = of_get_property(ug_info->phy_node, "interface", NULL); - if (prop != NULL) { - phy_interface = enet_to_phy_interface[*prop]; - max_speed = enet_to_speed[*prop]; - } else - phy_interface = PHY_INTERFACE_MODE_MII; - } else { - phy_interface = to_phy_interface((const char *)prop); - } - - /* get speed, or derive from PHY interface */ - if (max_speed == 0) - switch (phy_interface) { - case PHY_INTERFACE_MODE_GMII: - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - case PHY_INTERFACE_MODE_TBI: - case PHY_INTERFACE_MODE_RTBI: - case PHY_INTERFACE_MODE_SGMII: - max_speed = SPEED_1000; - break; - default: - max_speed = SPEED_100; - break; - } - - if (max_speed == SPEED_1000) { - unsigned int snums = qe_get_num_of_snums(); - - /* configure muram FIFOs for gigabit operation */ - ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT; - ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT; - ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT; - ug_info->uf_info.utfs = UCC_GETH_UTFS_GIGA_INIT; - ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT; - ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT; - ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4; - - /* If QE's snum number is 46/76 which means we need to support - * 4 UECs at 1000Base-T simultaneously, we need to allocate - * more Threads to Rx. - */ - if ((snums == 76) || (snums == 46)) - ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6; - else - ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4; - } - - if (netif_msg_probe(&debug)) - printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d)\n", - ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, - ug_info->uf_info.irq); - - /* Create an ethernet device instance */ - dev = alloc_etherdev(sizeof(*ugeth)); - - if (dev == NULL) - return -ENOMEM; - - ugeth = netdev_priv(dev); - spin_lock_init(&ugeth->lock); - - /* Create CQs for hash tables */ - INIT_LIST_HEAD(&ugeth->group_hash_q); - INIT_LIST_HEAD(&ugeth->ind_hash_q); - - dev_set_drvdata(device, dev); - - /* Set the dev->base_addr to the gfar reg region */ - dev->base_addr = (unsigned long)(ug_info->uf_info.regs); - - SET_NETDEV_DEV(dev, device); - - /* Fill in the dev structure */ - uec_set_ethtool_ops(dev); - dev->netdev_ops = &ucc_geth_netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; - INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); - netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64); - dev->mtu = 1500; - - ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); - ugeth->phy_interface = phy_interface; - ugeth->max_speed = max_speed; - - err = register_netdev(dev); - if (err) { - if (netif_msg_probe(ugeth)) - ugeth_err("%s: Cannot register net device, aborting.", - dev->name); - free_netdev(dev); - return err; - } - - mac_addr = of_get_mac_address(np); - if (mac_addr) - memcpy(dev->dev_addr, mac_addr, 6); - - ugeth->ug_info = ug_info; - ugeth->dev = device; - ugeth->ndev = dev; - ugeth->node = np; - - return 0; -} - -static int ucc_geth_remove(struct platform_device* ofdev) -{ - struct device *device = &ofdev->dev; - struct net_device *dev = dev_get_drvdata(device); - struct ucc_geth_private *ugeth = netdev_priv(dev); - - unregister_netdev(dev); - free_netdev(dev); - ucc_geth_memclean(ugeth); - dev_set_drvdata(device, NULL); - - return 0; -} - -static struct of_device_id ucc_geth_match[] = { - { - .type = "network", - .compatible = "ucc_geth", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, ucc_geth_match); - -static struct platform_driver ucc_geth_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - .of_match_table = ucc_geth_match, - }, - .probe = ucc_geth_probe, - .remove = ucc_geth_remove, - .suspend = ucc_geth_suspend, - .resume = ucc_geth_resume, -}; - -static int __init ucc_geth_init(void) -{ - int i, ret; - - if (netif_msg_drv(&debug)) - printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); - for (i = 0; i < 8; i++) - memcpy(&(ugeth_info[i]), &ugeth_primary_info, - sizeof(ugeth_primary_info)); - - ret = platform_driver_register(&ucc_geth_driver); - - return ret; -} - -static void __exit ucc_geth_exit(void) -{ - platform_driver_unregister(&ucc_geth_driver); -} - -module_init(ucc_geth_init); -module_exit(ucc_geth_exit); - -MODULE_AUTHOR("Freescale Semiconductor, Inc"); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_VERSION(DRV_VERSION); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth.h b/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth.h deleted file mode 100644 index f71b3e7b..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth.h +++ /dev/null @@ -1,1240 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006-2009. All rights reserved. - * - * Author: Shlomi Gridish <gridish@freescale.com> - * - * Description: - * Internal header file for UCC Gigabit Ethernet unit routines. - * - * Changelog: - * Jun 28, 2006 Li Yang <LeoLi@freescale.com> - * - Rearrange code and style fixes - * - * 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. - */ -#ifndef __UCC_GETH_H__ -#define __UCC_GETH_H__ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/if_ether.h> - -#include <asm/immap_qe.h> -#include <asm/qe.h> - -#include <asm/ucc.h> -#include <asm/ucc_fast.h> - -#define DRV_DESC "QE UCC Gigabit Ethernet Controller" -#define DRV_NAME "ucc_geth" -#define DRV_VERSION "1.1" - -#define NUM_TX_QUEUES 8 -#define NUM_RX_QUEUES 8 -#define NUM_BDS_IN_PREFETCHED_BDS 4 -#define TX_IP_OFFSET_ENTRY_MAX 8 -#define NUM_OF_PADDRS 4 -#define ENET_INIT_PARAM_MAX_ENTRIES_RX 9 -#define ENET_INIT_PARAM_MAX_ENTRIES_TX 8 - -struct ucc_geth { - struct ucc_fast uccf; - u8 res0[0x100 - sizeof(struct ucc_fast)]; - - u32 maccfg1; /* mac configuration reg. 1 */ - u32 maccfg2; /* mac configuration reg. 2 */ - u32 ipgifg; /* interframe gap reg. */ - u32 hafdup; /* half-duplex reg. */ - u8 res1[0x10]; - u8 miimng[0x18]; /* MII management structure moved to _mii.h */ - u32 ifctl; /* interface control reg */ - u32 ifstat; /* interface statux reg */ - u32 macstnaddr1; /* mac station address part 1 reg */ - u32 macstnaddr2; /* mac station address part 2 reg */ - u8 res2[0x8]; - u32 uempr; /* UCC Ethernet Mac parameter reg */ - u32 utbipar; /* UCC tbi address reg */ - u16 uescr; /* UCC Ethernet statistics control reg */ - u8 res3[0x180 - 0x15A]; - u32 tx64; /* Total number of frames (including bad - frames) transmitted that were exactly of the - minimal length (64 for un tagged, 68 for - tagged, or with length exactly equal to the - parameter MINLength */ - u32 tx127; /* Total number of frames (including bad - frames) transmitted that were between - MINLength (Including FCS length==4) and 127 - octets */ - u32 tx255; /* Total number of frames (including bad - frames) transmitted that were between 128 - (Including FCS length==4) and 255 octets */ - u32 rx64; /* Total number of frames received including - bad frames that were exactly of the mninimal - length (64 bytes) */ - u32 rx127; /* Total number of frames (including bad - frames) received that were between MINLength - (Including FCS length==4) and 127 octets */ - u32 rx255; /* Total number of frames (including bad - frames) received that were between 128 - (Including FCS length==4) and 255 octets */ - u32 txok; /* Total number of octets residing in frames - that where involved in successful - transmission */ - u16 txcf; /* Total number of PAUSE control frames - transmitted by this MAC */ - u8 res4[0x2]; - u32 tmca; /* Total number of frames that were transmitted - successfully with the group address bit set - that are not broadcast frames */ - u32 tbca; /* Total number of frames transmitted - successfully that had destination address - field equal to the broadcast address */ - u32 rxfok; /* Total number of frames received OK */ - u32 rxbok; /* Total number of octets received OK */ - u32 rbyt; /* Total number of octets received including - octets in bad frames. Must be implemented in - HW because it includes octets in frames that - never even reach the UCC */ - u32 rmca; /* Total number of frames that were received - successfully with the group address bit set - that are not broadcast frames */ - u32 rbca; /* Total number of frames received successfully - that had destination address equal to the - broadcast address */ - u32 scar; /* Statistics carry register */ - u32 scam; /* Statistics caryy mask register */ - u8 res5[0x200 - 0x1c4]; -} __packed; - -/* UCC GETH TEMODR Register */ -#define TEMODER_TX_RMON_STATISTICS_ENABLE 0x0100 /* enable Tx statistics - */ -#define TEMODER_SCHEDULER_ENABLE 0x2000 /* enable scheduler */ -#define TEMODER_IP_CHECKSUM_GENERATE 0x0400 /* generate IPv4 - checksums */ -#define TEMODER_PERFORMANCE_OPTIMIZATION_MODE1 0x0200 /* enable performance - optimization - enhancement (mode1) */ -#define TEMODER_RMON_STATISTICS 0x0100 /* enable tx statistics - */ -#define TEMODER_NUM_OF_QUEUES_SHIFT (15-15) /* Number of queues << - shift */ - -/* UCC GETH TEMODR Register */ -#define REMODER_RX_RMON_STATISTICS_ENABLE 0x00001000 /* enable Rx - statistics */ -#define REMODER_RX_EXTENDED_FEATURES 0x80000000 /* enable - extended - features */ -#define REMODER_VLAN_OPERATION_TAGGED_SHIFT (31-9 ) /* vlan operation - tagged << shift */ -#define REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT (31-10) /* vlan operation non - tagged << shift */ -#define REMODER_RX_QOS_MODE_SHIFT (31-15) /* rx QoS mode << shift - */ -#define REMODER_RMON_STATISTICS 0x00001000 /* enable rx - statistics */ -#define REMODER_RX_EXTENDED_FILTERING 0x00000800 /* extended - filtering - vs. - mpc82xx-like - filtering */ -#define REMODER_NUM_OF_QUEUES_SHIFT (31-23) /* Number of queues << - shift */ -#define REMODER_DYNAMIC_MAX_FRAME_LENGTH 0x00000008 /* enable - dynamic max - frame length - */ -#define REMODER_DYNAMIC_MIN_FRAME_LENGTH 0x00000004 /* enable - dynamic min - frame length - */ -#define REMODER_IP_CHECKSUM_CHECK 0x00000002 /* check IPv4 - checksums */ -#define REMODER_IP_ADDRESS_ALIGNMENT 0x00000001 /* align ip - address to - 4-byte - boundary */ - -/* UCC GETH Event Register */ -#define UCCE_TXB (UCC_GETH_UCCE_TXB7 | UCC_GETH_UCCE_TXB6 | \ - UCC_GETH_UCCE_TXB5 | UCC_GETH_UCCE_TXB4 | \ - UCC_GETH_UCCE_TXB3 | UCC_GETH_UCCE_TXB2 | \ - UCC_GETH_UCCE_TXB1 | UCC_GETH_UCCE_TXB0) - -#define UCCE_RXB (UCC_GETH_UCCE_RXB7 | UCC_GETH_UCCE_RXB6 | \ - UCC_GETH_UCCE_RXB5 | UCC_GETH_UCCE_RXB4 | \ - UCC_GETH_UCCE_RXB3 | UCC_GETH_UCCE_RXB2 | \ - UCC_GETH_UCCE_RXB1 | UCC_GETH_UCCE_RXB0) - -#define UCCE_RXF (UCC_GETH_UCCE_RXF7 | UCC_GETH_UCCE_RXF6 | \ - UCC_GETH_UCCE_RXF5 | UCC_GETH_UCCE_RXF4 | \ - UCC_GETH_UCCE_RXF3 | UCC_GETH_UCCE_RXF2 | \ - UCC_GETH_UCCE_RXF1 | UCC_GETH_UCCE_RXF0) - -#define UCCE_OTHER (UCC_GETH_UCCE_SCAR | UCC_GETH_UCCE_GRA | \ - UCC_GETH_UCCE_CBPR | UCC_GETH_UCCE_BSY | \ - UCC_GETH_UCCE_RXC | UCC_GETH_UCCE_TXC | UCC_GETH_UCCE_TXE) - -#define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY) -#define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE) - -/* TBI defines */ -#define ENET_TBI_MII_CR 0x00 /* Control */ -#define ENET_TBI_MII_SR 0x01 /* Status */ -#define ENET_TBI_MII_ANA 0x04 /* AN advertisement */ -#define ENET_TBI_MII_ANLPBPA 0x05 /* AN link partner base page ability */ -#define ENET_TBI_MII_ANEX 0x06 /* AN expansion */ -#define ENET_TBI_MII_ANNPT 0x07 /* AN next page transmit */ -#define ENET_TBI_MII_ANLPANP 0x08 /* AN link partner ability next page */ -#define ENET_TBI_MII_EXST 0x0F /* Extended status */ -#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */ -#define ENET_TBI_MII_TBICON 0x11 /* TBI control */ - -/* TBI MDIO register bit fields*/ -#define TBISR_LSTATUS 0x0004 -#define TBICON_CLK_SELECT 0x0020 -#define TBIANA_ASYMMETRIC_PAUSE 0x0100 -#define TBIANA_SYMMETRIC_PAUSE 0x0080 -#define TBIANA_HALF_DUPLEX 0x0040 -#define TBIANA_FULL_DUPLEX 0x0020 -#define TBICR_PHY_RESET 0x8000 -#define TBICR_ANEG_ENABLE 0x1000 -#define TBICR_RESTART_ANEG 0x0200 -#define TBICR_FULL_DUPLEX 0x0100 -#define TBICR_SPEED1_SET 0x0040 - -#define TBIANA_SETTINGS ( \ - TBIANA_ASYMMETRIC_PAUSE \ - | TBIANA_SYMMETRIC_PAUSE \ - | TBIANA_FULL_DUPLEX \ - ) -#define TBICR_SETTINGS ( \ - TBICR_PHY_RESET \ - | TBICR_ANEG_ENABLE \ - | TBICR_FULL_DUPLEX \ - | TBICR_SPEED1_SET \ - ) - -/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ -#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control - Rx */ -#define MACCFG1_FLOW_TX 0x00000010 /* Flow Control - Tx */ -#define MACCFG1_ENABLE_SYNCHED_RX 0x00000008 /* Rx Enable - synchronized - to Rx stream - */ -#define MACCFG1_ENABLE_RX 0x00000004 /* Enable Rx */ -#define MACCFG1_ENABLE_SYNCHED_TX 0x00000002 /* Tx Enable - synchronized - to Tx stream - */ -#define MACCFG1_ENABLE_TX 0x00000001 /* Enable Tx */ - -/* UCC GETH MACCFG2 (MAC Configuration 2 Register) */ -#define MACCFG2_PREL_SHIFT (31 - 19) /* Preamble - Length << - shift */ -#define MACCFG2_PREL_MASK 0x0000f000 /* Preamble - Length mask */ -#define MACCFG2_SRP 0x00000080 /* Soft Receive - Preamble */ -#define MACCFG2_STP 0x00000040 /* Soft - Transmit - Preamble */ -#define MACCFG2_RESERVED_1 0x00000020 /* Reserved - - must be set - to 1 */ -#define MACCFG2_LC 0x00000010 /* Length Check - */ -#define MACCFG2_MPE 0x00000008 /* Magic packet - detect */ -#define MACCFG2_FDX 0x00000001 /* Full Duplex */ -#define MACCFG2_FDX_MASK 0x00000001 /* Full Duplex - mask */ -#define MACCFG2_PAD_CRC 0x00000004 -#define MACCFG2_CRC_EN 0x00000002 -#define MACCFG2_PAD_AND_CRC_MODE_NONE 0x00000000 /* Neither - Padding - short frames - nor CRC */ -#define MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY 0x00000002 /* Append CRC - only */ -#define MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC 0x00000004 -#define MACCFG2_INTERFACE_MODE_NIBBLE 0x00000100 /* nibble mode - (MII/RMII/RGMII - 10/100bps) */ -#define MACCFG2_INTERFACE_MODE_BYTE 0x00000200 /* byte mode - (GMII/TBI/RTB/RGMII - 1000bps ) */ -#define MACCFG2_INTERFACE_MODE_MASK 0x00000300 /* mask - covering all - relevant - bits */ - -/* UCC GETH IPGIFG (Inter-frame Gap / Inter-Frame Gap Register) */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT (31 - 7) /* Non - back-to-back - inter frame - gap part 1. - << shift */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT (31 - 15) /* Non - back-to-back - inter frame - gap part 2. - << shift */ -#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT (31 - 23) /* Mimimum IFG - Enforcement - << shift */ -#define IPGIFG_BACK_TO_BACK_IFG_SHIFT (31 - 31) /* back-to-back - inter frame - gap << shift - */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX 127 /* Non back-to-back - inter frame gap part - 1. max val */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX 127 /* Non back-to-back - inter frame gap part - 2. max val */ -#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX 255 /* Mimimum IFG - Enforcement max val */ -#define IPGIFG_BACK_TO_BACK_IFG_MAX 127 /* back-to-back inter - frame gap max val */ -#define IPGIFG_NBTB_CS_IPG_MASK 0x7F000000 -#define IPGIFG_NBTB_IPG_MASK 0x007F0000 -#define IPGIFG_MIN_IFG_MASK 0x0000FF00 -#define IPGIFG_BTB_IPG_MASK 0x0000007F - -/* UCC GETH HAFDUP (Half Duplex Register) */ -#define HALFDUP_ALT_BEB_TRUNCATION_SHIFT (31 - 11) /* Alternate - Binary - Exponential - Backoff - Truncation - << shift */ -#define HALFDUP_ALT_BEB_TRUNCATION_MAX 0xf /* Alternate Binary - Exponential Backoff - Truncation max val */ -#define HALFDUP_ALT_BEB 0x00080000 /* Alternate - Binary - Exponential - Backoff */ -#define HALFDUP_BACK_PRESSURE_NO_BACKOFF 0x00040000 /* Back - pressure no - backoff */ -#define HALFDUP_NO_BACKOFF 0x00020000 /* No Backoff */ -#define HALFDUP_EXCESSIVE_DEFER 0x00010000 /* Excessive - Defer */ -#define HALFDUP_MAX_RETRANSMISSION_SHIFT (31 - 19) /* Maximum - Retransmission - << shift */ -#define HALFDUP_MAX_RETRANSMISSION_MAX 0xf /* Maximum - Retransmission max - val */ -#define HALFDUP_COLLISION_WINDOW_SHIFT (31 - 31) /* Collision - Window << - shift */ -#define HALFDUP_COLLISION_WINDOW_MAX 0x3f /* Collision Window max - val */ -#define HALFDUP_ALT_BEB_TR_MASK 0x00F00000 -#define HALFDUP_RETRANS_MASK 0x0000F000 -#define HALFDUP_COL_WINDOW_MASK 0x0000003F - -/* UCC GETH UCCS (Ethernet Status Register) */ -#define UCCS_BPR 0x02 /* Back pressure (in - half duplex mode) */ -#define UCCS_PAU 0x02 /* Pause state (in full - duplex mode) */ -#define UCCS_MPD 0x01 /* Magic Packet - Detected */ - -/* UCC GETH IFSTAT (Interface Status Register) */ -#define IFSTAT_EXCESS_DEFER 0x00000200 /* Excessive - transmission - defer */ - -/* UCC GETH MACSTNADDR1 (Station Address Part 1 Register) */ -#define MACSTNADDR1_OCTET_6_SHIFT (31 - 7) /* Station - address 6th - octet << - shift */ -#define MACSTNADDR1_OCTET_5_SHIFT (31 - 15) /* Station - address 5th - octet << - shift */ -#define MACSTNADDR1_OCTET_4_SHIFT (31 - 23) /* Station - address 4th - octet << - shift */ -#define MACSTNADDR1_OCTET_3_SHIFT (31 - 31) /* Station - address 3rd - octet << - shift */ - -/* UCC GETH MACSTNADDR2 (Station Address Part 2 Register) */ -#define MACSTNADDR2_OCTET_2_SHIFT (31 - 7) /* Station - address 2nd - octet << - shift */ -#define MACSTNADDR2_OCTET_1_SHIFT (31 - 15) /* Station - address 1st - octet << - shift */ - -/* UCC GETH UEMPR (Ethernet Mac Parameter Register) */ -#define UEMPR_PAUSE_TIME_VALUE_SHIFT (31 - 15) /* Pause time - value << - shift */ -#define UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT (31 - 31) /* Extended - pause time - value << - shift */ - -/* UCC GETH UTBIPAR (Ten Bit Interface Physical Address Register) */ -#define UTBIPAR_PHY_ADDRESS_SHIFT (31 - 31) /* Phy address - << shift */ -#define UTBIPAR_PHY_ADDRESS_MASK 0x0000001f /* Phy address - mask */ - -/* UCC GETH UESCR (Ethernet Statistics Control Register) */ -#define UESCR_AUTOZ 0x8000 /* Automatically zero - addressed - statistical counter - values */ -#define UESCR_CLRCNT 0x4000 /* Clear all statistics - counters */ -#define UESCR_MAXCOV_SHIFT (15 - 7) /* Max - Coalescing - Value << - shift */ -#define UESCR_SCOV_SHIFT (15 - 15) /* Status - Coalescing - Value << - shift */ - -/* UCC GETH UDSR (Data Synchronization Register) */ -#define UDSR_MAGIC 0x067E - -struct ucc_geth_thread_data_tx { - u8 res0[104]; -} __packed; - -struct ucc_geth_thread_data_rx { - u8 res0[40]; -} __packed; - -/* Send Queue Queue-Descriptor */ -struct ucc_geth_send_queue_qd { - u32 bd_ring_base; /* pointer to BD ring base address */ - u8 res0[0x8]; - u32 last_bd_completed_address;/* initialize to last entry in BD ring */ - u8 res1[0x30]; -} __packed; - -struct ucc_geth_send_queue_mem_region { - struct ucc_geth_send_queue_qd sqqd[NUM_TX_QUEUES]; -} __packed; - -struct ucc_geth_thread_tx_pram { - u8 res0[64]; -} __packed; - -struct ucc_geth_thread_rx_pram { - u8 res0[128]; -} __packed; - -#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING 64 -#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8 64 -#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16 96 - -struct ucc_geth_scheduler { - u16 cpucount0; /* CPU packet counter */ - u16 cpucount1; /* CPU packet counter */ - u16 cecount0; /* QE packet counter */ - u16 cecount1; /* QE packet counter */ - u16 cpucount2; /* CPU packet counter */ - u16 cpucount3; /* CPU packet counter */ - u16 cecount2; /* QE packet counter */ - u16 cecount3; /* QE packet counter */ - u16 cpucount4; /* CPU packet counter */ - u16 cpucount5; /* CPU packet counter */ - u16 cecount4; /* QE packet counter */ - u16 cecount5; /* QE packet counter */ - u16 cpucount6; /* CPU packet counter */ - u16 cpucount7; /* CPU packet counter */ - u16 cecount6; /* QE packet counter */ - u16 cecount7; /* QE packet counter */ - u32 weightstatus[NUM_TX_QUEUES]; /* accumulated weight factor */ - u32 rtsrshadow; /* temporary variable handled by QE */ - u32 time; /* temporary variable handled by QE */ - u32 ttl; /* temporary variable handled by QE */ - u32 mblinterval; /* max burst length interval */ - u16 nortsrbytetime; /* normalized value of byte time in tsr units */ - u8 fracsiz; /* radix 2 log value of denom. of - NorTSRByteTime */ - u8 res0[1]; - u8 strictpriorityq; /* Strict Priority Mask register */ - u8 txasap; /* Transmit ASAP register */ - u8 extrabw; /* Extra BandWidth register */ - u8 oldwfqmask; /* temporary variable handled by QE */ - u8 weightfactor[NUM_TX_QUEUES]; - /**< weight factor for queues */ - u32 minw; /* temporary variable handled by QE */ - u8 res1[0x70 - 0x64]; -} __packed; - -struct ucc_geth_tx_firmware_statistics_pram { - u32 sicoltx; /* single collision */ - u32 mulcoltx; /* multiple collision */ - u32 latecoltxfr; /* late collision */ - u32 frabortduecol; /* frames aborted due to transmit collision */ - u32 frlostinmactxer; /* frames lost due to internal MAC error - transmission that are not counted on any - other counter */ - u32 carriersenseertx; /* carrier sense error */ - u32 frtxok; /* frames transmitted OK */ - u32 txfrexcessivedefer; /* frames with defferal time greater than - specified threshold */ - u32 txpkts256; /* total packets (including bad) between 256 - and 511 octets */ - u32 txpkts512; /* total packets (including bad) between 512 - and 1023 octets */ - u32 txpkts1024; /* total packets (including bad) between 1024 - and 1518 octets */ - u32 txpktsjumbo; /* total packets (including bad) between 1024 - and MAXLength octets */ -} __packed; - -struct ucc_geth_rx_firmware_statistics_pram { - u32 frrxfcser; /* frames with crc error */ - u32 fraligner; /* frames with alignment error */ - u32 inrangelenrxer; /* in range length error */ - u32 outrangelenrxer; /* out of range length error */ - u32 frtoolong; /* frame too long */ - u32 runt; /* runt */ - u32 verylongevent; /* very long event */ - u32 symbolerror; /* symbol error */ - u32 dropbsy; /* drop because of BD not ready */ - u8 res0[0x8]; - u32 mismatchdrop; /* drop because of MAC filtering (e.g. address - or type mismatch) */ - u32 underpkts; /* total frames less than 64 octets */ - u32 pkts256; /* total frames (including bad) between 256 and - 511 octets */ - u32 pkts512; /* total frames (including bad) between 512 and - 1023 octets */ - u32 pkts1024; /* total frames (including bad) between 1024 - and 1518 octets */ - u32 pktsjumbo; /* total frames (including bad) between 1024 - and MAXLength octets */ - u32 frlossinmacer; /* frames lost because of internal MAC error - that is not counted in any other counter */ - u32 pausefr; /* pause frames */ - u8 res1[0x4]; - u32 removevlan; /* total frames that had their VLAN tag removed - */ - u32 replacevlan; /* total frames that had their VLAN tag - replaced */ - u32 insertvlan; /* total frames that had their VLAN tag - inserted */ -} __packed; - -struct ucc_geth_rx_interrupt_coalescing_entry { - u32 interruptcoalescingmaxvalue; /* interrupt coalescing max - value */ - u32 interruptcoalescingcounter; /* interrupt coalescing counter, - initialize to - interruptcoalescingmaxvalue */ -} __packed; - -struct ucc_geth_rx_interrupt_coalescing_table { - struct ucc_geth_rx_interrupt_coalescing_entry coalescingentry[NUM_RX_QUEUES]; - /**< interrupt coalescing entry */ -} __packed; - -struct ucc_geth_rx_prefetched_bds { - struct qe_bd bd[NUM_BDS_IN_PREFETCHED_BDS]; /* prefetched bd */ -} __packed; - -struct ucc_geth_rx_bd_queues_entry { - u32 bdbaseptr; /* BD base pointer */ - u32 bdptr; /* BD pointer */ - u32 externalbdbaseptr; /* external BD base pointer */ - u32 externalbdptr; /* external BD pointer */ -} __packed; - -struct ucc_geth_tx_global_pram { - u16 temoder; - u8 res0[0x38 - 0x02]; - u32 sqptr; /* a base pointer to send queue memory region */ - u32 schedulerbasepointer; /* a base pointer to scheduler memory - region */ - u32 txrmonbaseptr; /* base pointer to Tx RMON statistics counter */ - u32 tstate; /* tx internal state. High byte contains - function code */ - u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; - u32 vtagtable[0x8]; /* 8 4-byte VLAN tags */ - u32 tqptr; /* a base pointer to the Tx Queues Memory - Region */ - u8 res2[0x80 - 0x74]; -} __packed; - -/* structure representing Extended Filtering Global Parameters in PRAM */ -struct ucc_geth_exf_global_pram { - u32 l2pcdptr; /* individual address filter, high */ - u8 res0[0x10 - 0x04]; -} __packed; - -struct ucc_geth_rx_global_pram { - u32 remoder; /* ethernet mode reg. */ - u32 rqptr; /* base pointer to the Rx Queues Memory Region*/ - u32 res0[0x1]; - u8 res1[0x20 - 0xC]; - u16 typeorlen; /* cutoff point less than which, type/len field - is considered length */ - u8 res2[0x1]; - u8 rxgstpack; /* acknowledgement on GRACEFUL STOP RX command*/ - u32 rxrmonbaseptr; /* base pointer to Rx RMON statistics counter */ - u8 res3[0x30 - 0x28]; - u32 intcoalescingptr; /* Interrupt coalescing table pointer */ - u8 res4[0x36 - 0x34]; - u8 rstate; /* rx internal state. High byte contains - function code */ - u8 res5[0x46 - 0x37]; - u16 mrblr; /* max receive buffer length reg. */ - u32 rbdqptr; /* base pointer to RxBD parameter table - description */ - u16 mflr; /* max frame length reg. */ - u16 minflr; /* min frame length reg. */ - u16 maxd1; /* max dma1 length reg. */ - u16 maxd2; /* max dma2 length reg. */ - u32 ecamptr; /* external CAM address */ - u32 l2qt; /* VLAN priority mapping table. */ - u32 l3qt[0x8]; /* IP priority mapping table. */ - u16 vlantype; /* vlan type */ - u16 vlantci; /* default vlan tci */ - u8 addressfiltering[64]; /* address filtering data structure */ - u32 exfGlobalParam; /* base address for extended filtering global - parameters */ - u8 res6[0x100 - 0xC4]; /* Initialize to zero */ -} __packed; - -#define GRACEFUL_STOP_ACKNOWLEDGE_RX 0x01 - -/* structure representing InitEnet command */ -struct ucc_geth_init_pram { - u8 resinit1; - u8 resinit2; - u8 resinit3; - u8 resinit4; - u16 resinit5; - u8 res1[0x1]; - u8 largestexternallookupkeysize; - u32 rgftgfrxglobal; - u32 rxthread[ENET_INIT_PARAM_MAX_ENTRIES_RX]; /* rx threads */ - u8 res2[0x38 - 0x30]; - u32 txglobal; /* tx global */ - u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX]; /* tx threads */ - u8 res3[0x1]; -} __packed; - -#define ENET_INIT_PARAM_RGF_SHIFT (32 - 4) -#define ENET_INIT_PARAM_TGF_SHIFT (32 - 8) - -#define ENET_INIT_PARAM_RISC_MASK 0x0000003f -#define ENET_INIT_PARAM_PTR_MASK 0x00ffffc0 -#define ENET_INIT_PARAM_SNUM_MASK 0xff000000 -#define ENET_INIT_PARAM_SNUM_SHIFT 24 - -#define ENET_INIT_PARAM_MAGIC_RES_INIT1 0x06 -#define ENET_INIT_PARAM_MAGIC_RES_INIT2 0x30 -#define ENET_INIT_PARAM_MAGIC_RES_INIT3 0xff -#define ENET_INIT_PARAM_MAGIC_RES_INIT4 0x00 -#define ENET_INIT_PARAM_MAGIC_RES_INIT5 0x0400 - -/* structure representing 82xx Address Filtering Enet Address in PRAM */ -struct ucc_geth_82xx_enet_address { - u8 res1[0x2]; - u16 h; /* address (MSB) */ - u16 m; /* address */ - u16 l; /* address (LSB) */ -} __packed; - -/* structure representing 82xx Address Filtering PRAM */ -struct ucc_geth_82xx_address_filtering_pram { - u32 iaddr_h; /* individual address filter, high */ - u32 iaddr_l; /* individual address filter, low */ - u32 gaddr_h; /* group address filter, high */ - u32 gaddr_l; /* group address filter, low */ - struct ucc_geth_82xx_enet_address __iomem taddr; - struct ucc_geth_82xx_enet_address __iomem paddr[NUM_OF_PADDRS]; - u8 res0[0x40 - 0x38]; -} __packed; - -/* GETH Tx firmware statistics structure, used when calling - UCC_GETH_GetStatistics. */ -struct ucc_geth_tx_firmware_statistics { - u32 sicoltx; /* single collision */ - u32 mulcoltx; /* multiple collision */ - u32 latecoltxfr; /* late collision */ - u32 frabortduecol; /* frames aborted due to transmit collision */ - u32 frlostinmactxer; /* frames lost due to internal MAC error - transmission that are not counted on any - other counter */ - u32 carriersenseertx; /* carrier sense error */ - u32 frtxok; /* frames transmitted OK */ - u32 txfrexcessivedefer; /* frames with defferal time greater than - specified threshold */ - u32 txpkts256; /* total packets (including bad) between 256 - and 511 octets */ - u32 txpkts512; /* total packets (including bad) between 512 - and 1023 octets */ - u32 txpkts1024; /* total packets (including bad) between 1024 - and 1518 octets */ - u32 txpktsjumbo; /* total packets (including bad) between 1024 - and MAXLength octets */ -} __packed; - -/* GETH Rx firmware statistics structure, used when calling - UCC_GETH_GetStatistics. */ -struct ucc_geth_rx_firmware_statistics { - u32 frrxfcser; /* frames with crc error */ - u32 fraligner; /* frames with alignment error */ - u32 inrangelenrxer; /* in range length error */ - u32 outrangelenrxer; /* out of range length error */ - u32 frtoolong; /* frame too long */ - u32 runt; /* runt */ - u32 verylongevent; /* very long event */ - u32 symbolerror; /* symbol error */ - u32 dropbsy; /* drop because of BD not ready */ - u8 res0[0x8]; - u32 mismatchdrop; /* drop because of MAC filtering (e.g. address - or type mismatch) */ - u32 underpkts; /* total frames less than 64 octets */ - u32 pkts256; /* total frames (including bad) between 256 and - 511 octets */ - u32 pkts512; /* total frames (including bad) between 512 and - 1023 octets */ - u32 pkts1024; /* total frames (including bad) between 1024 - and 1518 octets */ - u32 pktsjumbo; /* total frames (including bad) between 1024 - and MAXLength octets */ - u32 frlossinmacer; /* frames lost because of internal MAC error - that is not counted in any other counter */ - u32 pausefr; /* pause frames */ - u8 res1[0x4]; - u32 removevlan; /* total frames that had their VLAN tag removed - */ - u32 replacevlan; /* total frames that had their VLAN tag - replaced */ - u32 insertvlan; /* total frames that had their VLAN tag - inserted */ -} __packed; - -/* GETH hardware statistics structure, used when calling - UCC_GETH_GetStatistics. */ -struct ucc_geth_hardware_statistics { - u32 tx64; /* Total number of frames (including bad - frames) transmitted that were exactly of the - minimal length (64 for un tagged, 68 for - tagged, or with length exactly equal to the - parameter MINLength */ - u32 tx127; /* Total number of frames (including bad - frames) transmitted that were between - MINLength (Including FCS length==4) and 127 - octets */ - u32 tx255; /* Total number of frames (including bad - frames) transmitted that were between 128 - (Including FCS length==4) and 255 octets */ - u32 rx64; /* Total number of frames received including - bad frames that were exactly of the mninimal - length (64 bytes) */ - u32 rx127; /* Total number of frames (including bad - frames) received that were between MINLength - (Including FCS length==4) and 127 octets */ - u32 rx255; /* Total number of frames (including bad - frames) received that were between 128 - (Including FCS length==4) and 255 octets */ - u32 txok; /* Total number of octets residing in frames - that where involved in successful - transmission */ - u16 txcf; /* Total number of PAUSE control frames - transmitted by this MAC */ - u32 tmca; /* Total number of frames that were transmitted - successfully with the group address bit set - that are not broadcast frames */ - u32 tbca; /* Total number of frames transmitted - successfully that had destination address - field equal to the broadcast address */ - u32 rxfok; /* Total number of frames received OK */ - u32 rxbok; /* Total number of octets received OK */ - u32 rbyt; /* Total number of octets received including - octets in bad frames. Must be implemented in - HW because it includes octets in frames that - never even reach the UCC */ - u32 rmca; /* Total number of frames that were received - successfully with the group address bit set - that are not broadcast frames */ - u32 rbca; /* Total number of frames received successfully - that had destination address equal to the - broadcast address */ -} __packed; - -/* UCC GETH Tx errors returned via TxConf callback */ -#define TX_ERRORS_DEF 0x0200 -#define TX_ERRORS_EXDEF 0x0100 -#define TX_ERRORS_LC 0x0080 -#define TX_ERRORS_RL 0x0040 -#define TX_ERRORS_RC_MASK 0x003C -#define TX_ERRORS_RC_SHIFT 2 -#define TX_ERRORS_UN 0x0002 -#define TX_ERRORS_CSL 0x0001 - -/* UCC GETH Rx errors returned via RxStore callback */ -#define RX_ERRORS_CMR 0x0200 -#define RX_ERRORS_M 0x0100 -#define RX_ERRORS_BC 0x0080 -#define RX_ERRORS_MC 0x0040 - -/* Transmit BD. These are in addition to values defined in uccf. */ -#define T_VID 0x003c0000 /* insert VLAN id index mask. */ -#define T_DEF (((u32) TX_ERRORS_DEF ) << 16) -#define T_EXDEF (((u32) TX_ERRORS_EXDEF ) << 16) -#define T_LC (((u32) TX_ERRORS_LC ) << 16) -#define T_RL (((u32) TX_ERRORS_RL ) << 16) -#define T_RC_MASK (((u32) TX_ERRORS_RC_MASK ) << 16) -#define T_UN (((u32) TX_ERRORS_UN ) << 16) -#define T_CSL (((u32) TX_ERRORS_CSL ) << 16) -#define T_ERRORS_REPORT (T_DEF | T_EXDEF | T_LC | T_RL | T_RC_MASK \ - | T_UN | T_CSL) /* transmit errors to report */ - -/* Receive BD. These are in addition to values defined in uccf. */ -#define R_LG 0x00200000 /* Frame length violation. */ -#define R_NO 0x00100000 /* Non-octet aligned frame. */ -#define R_SH 0x00080000 /* Short frame. */ -#define R_CR 0x00040000 /* CRC error. */ -#define R_OV 0x00020000 /* Overrun. */ -#define R_IPCH 0x00010000 /* IP checksum check failed. */ -#define R_CMR (((u32) RX_ERRORS_CMR ) << 16) -#define R_M (((u32) RX_ERRORS_M ) << 16) -#define R_BC (((u32) RX_ERRORS_BC ) << 16) -#define R_MC (((u32) RX_ERRORS_MC ) << 16) -#define R_ERRORS_REPORT (R_CMR | R_M | R_BC | R_MC) /* receive errors to - report */ -#define R_ERRORS_FATAL (R_LG | R_NO | R_SH | R_CR | \ - R_OV | R_IPCH) /* receive errors to discard */ - -/* Alignments */ -#define UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT 256 -#define UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT 128 -#define UCC_GETH_THREAD_RX_PRAM_ALIGNMENT 128 -#define UCC_GETH_THREAD_TX_PRAM_ALIGNMENT 64 -#define UCC_GETH_THREAD_DATA_ALIGNMENT 256 /* spec gives values - based on num of - threads, but always - using the maximum is - easier */ -#define UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT 32 -#define UCC_GETH_SCHEDULER_ALIGNMENT 8 /* This is a guess */ -#define UCC_GETH_TX_STATISTICS_ALIGNMENT 4 /* This is a guess */ -#define UCC_GETH_RX_STATISTICS_ALIGNMENT 4 /* This is a guess */ -#define UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT 64 -#define UCC_GETH_RX_BD_QUEUES_ALIGNMENT 8 /* This is a guess */ -#define UCC_GETH_RX_PREFETCHED_BDS_ALIGNMENT 128 /* This is a guess */ -#define UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT 8 /* This - is a - guess - */ -#define UCC_GETH_RX_BD_RING_ALIGNMENT 32 -#define UCC_GETH_TX_BD_RING_ALIGNMENT 32 -#define UCC_GETH_MRBLR_ALIGNMENT 128 -#define UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT 4 -#define UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT 32 -#define UCC_GETH_RX_DATA_BUF_ALIGNMENT 64 - -#define UCC_GETH_TAD_EF 0x80 -#define UCC_GETH_TAD_V 0x40 -#define UCC_GETH_TAD_REJ 0x20 -#define UCC_GETH_TAD_VTAG_OP_RIGHT_SHIFT 2 -#define UCC_GETH_TAD_VTAG_OP_SHIFT 6 -#define UCC_GETH_TAD_V_NON_VTAG_OP 0x20 -#define UCC_GETH_TAD_RQOS_SHIFT 0 -#define UCC_GETH_TAD_V_PRIORITY_SHIFT 5 -#define UCC_GETH_TAD_CFI 0x10 - -#define UCC_GETH_VLAN_PRIORITY_MAX 8 -#define UCC_GETH_IP_PRIORITY_MAX 64 -#define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX 8 -#define UCC_GETH_RX_BD_RING_SIZE_MIN 8 -#define UCC_GETH_TX_BD_RING_SIZE_MIN 2 -#define UCC_GETH_BD_RING_SIZE_MAX 0xffff - -#define UCC_GETH_SIZE_OF_BD QE_SIZEOF_BD - -/* Driver definitions */ -#define TX_BD_RING_LEN 0x10 -#define RX_BD_RING_LEN 0x20 - -#define TX_RING_MOD_MASK(size) (size-1) -#define RX_RING_MOD_MASK(size) (size-1) - -#define ENET_GROUP_ADDR 0x01 /* Group address mask - for ethernet - addresses */ - -#define TX_TIMEOUT (1*HZ) -#define SKB_ALLOC_TIMEOUT 100000 -#define PHY_INIT_TIMEOUT 100000 -#define PHY_CHANGE_TIME 2 - -/* Fast Ethernet (10/100 Mbps) */ -#define UCC_GETH_URFS_INIT 512 /* Rx virtual FIFO size - */ -#define UCC_GETH_URFET_INIT 256 /* 1/2 urfs */ -#define UCC_GETH_URFSET_INIT 384 /* 3/4 urfs */ -#define UCC_GETH_UTFS_INIT 512 /* Tx virtual FIFO size - */ -#define UCC_GETH_UTFET_INIT 256 /* 1/2 utfs */ -#define UCC_GETH_UTFTT_INIT 256 /* 1/2 utfs - due to errata */ -/* Gigabit Ethernet (1000 Mbps) */ -#define UCC_GETH_URFS_GIGA_INIT 4096/*2048*/ /* Rx virtual - FIFO size */ -#define UCC_GETH_URFET_GIGA_INIT 2048/*1024*/ /* 1/2 urfs */ -#define UCC_GETH_URFSET_GIGA_INIT 3072/*1536*/ /* 3/4 urfs */ -#define UCC_GETH_UTFS_GIGA_INIT 4096/*2048*/ /* Tx virtual - FIFO size */ -#define UCC_GETH_UTFET_GIGA_INIT 2048/*1024*/ /* 1/2 utfs */ -#define UCC_GETH_UTFTT_GIGA_INIT 4096/*0x40*/ /* Tx virtual - FIFO size */ - -#define UCC_GETH_REMODER_INIT 0 /* bits that must be - set */ -#define UCC_GETH_TEMODER_INIT 0xC000 /* bits that must */ - -/* Initial value for UPSMR */ -#define UCC_GETH_UPSMR_INIT UCC_GETH_UPSMR_RES1 - -#define UCC_GETH_MACCFG1_INIT 0 -#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1) - -/* Ethernet Address Type. */ -enum enet_addr_type { - ENET_ADDR_TYPE_INDIVIDUAL, - ENET_ADDR_TYPE_GROUP, - ENET_ADDR_TYPE_BROADCAST -}; - -/* UCC GETH 82xx Ethernet Address Recognition Location */ -enum ucc_geth_enet_address_recognition_location { - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station - address */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST, /* additional - station - address - paddr1 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR2, /* additional - station - address - paddr2 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR3, /* additional - station - address - paddr3 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_LAST, /* additional - station - address - paddr4 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH, /* group hash */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual - hash */ -}; - -/* UCC GETH vlan operation tagged */ -enum ucc_geth_vlan_operation_tagged { - UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0, /* Tagged - nop */ - UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG - = 0x1, /* Tagged - replace vid portion of q tag */ - UCC_GETH_VLAN_OPERATION_TAGGED_IF_VID0_REPLACE_VID_WITH_DEFAULT_VALUE - = 0x2, /* Tagged - if vid0 replace vid with default value */ - UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME - = 0x3 /* Tagged - extract q tag from frame */ -}; - -/* UCC GETH vlan operation non-tagged */ -enum ucc_geth_vlan_operation_non_tagged { - UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0, /* Non tagged - nop */ - UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1 /* Non tagged - - q tag insert - */ -}; - -/* UCC GETH Rx Quality of Service Mode */ -enum ucc_geth_qos_mode { - UCC_GETH_QOS_MODE_DEFAULT = 0x0, /* default queue */ - UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1, /* queue - determined - by L2 - criteria */ - UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L3_CRITERIA = 0x2 /* queue - determined - by L3 - criteria */ -}; - -/* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together - for combined functionality */ -enum ucc_geth_statistics_gathering_mode { - UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000, /* No - statistics - gathering */ - UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE = 0x00000001,/* Enable - hardware - statistics - gathering - */ - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX = 0x00000004,/*Enable - firmware - tx - statistics - gathering - */ - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX = 0x00000008/* Enable - firmware - rx - statistics - gathering - */ -}; - -/* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */ -enum ucc_geth_maccfg2_pad_and_crc_mode { - UCC_GETH_PAD_AND_CRC_MODE_NONE - = MACCFG2_PAD_AND_CRC_MODE_NONE, /* Neither Padding - short frames - nor CRC */ - UCC_GETH_PAD_AND_CRC_MODE_CRC_ONLY - = MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY, /* Append - CRC only */ - UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC = - MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC -}; - -/* UCC GETH upsmr Flow Control Mode */ -enum ucc_geth_flow_control_mode { - UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000, /* No automatic - flow control - */ - UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY - = 0x00004000 /* Send pause frame when RxFIFO reaches its - emergency threshold */ -}; - -/* UCC GETH number of threads */ -enum ucc_geth_num_of_threads { - UCC_GETH_NUM_OF_THREADS_1 = 0x1, /* 1 */ - UCC_GETH_NUM_OF_THREADS_2 = 0x2, /* 2 */ - UCC_GETH_NUM_OF_THREADS_4 = 0x0, /* 4 */ - UCC_GETH_NUM_OF_THREADS_6 = 0x3, /* 6 */ - UCC_GETH_NUM_OF_THREADS_8 = 0x4 /* 8 */ -}; - -/* UCC GETH number of station addresses */ -enum ucc_geth_num_of_station_addresses { - UCC_GETH_NUM_OF_STATION_ADDRESSES_1, /* 1 */ - UCC_GETH_NUM_OF_STATION_ADDRESSES_5 /* 5 */ -}; - -/* UCC GETH 82xx Ethernet Address Container */ -struct enet_addr_container { - u8 address[ETH_ALEN]; /* ethernet address */ - enum ucc_geth_enet_address_recognition_location location; /* location in - 82xx address - recognition - hardware */ - struct list_head node; -}; - -#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, struct enet_addr_container, node) - -/* UCC GETH Termination Action Descriptor (TAD) structure. */ -struct ucc_geth_tad_params { - int rx_non_dynamic_extended_features_mode; - int reject_frame; - enum ucc_geth_vlan_operation_tagged vtag_op; - enum ucc_geth_vlan_operation_non_tagged vnontag_op; - enum ucc_geth_qos_mode rqos; - u8 vpri; - u16 vid; -}; - -/* GETH protocol initialization structure */ -struct ucc_geth_info { - struct ucc_fast_info uf_info; - u8 numQueuesTx; - u8 numQueuesRx; - int ipCheckSumCheck; - int ipCheckSumGenerate; - int rxExtendedFiltering; - u32 extendedFilteringChainPointer; - u16 typeorlen; - int dynamicMaxFrameLength; - int dynamicMinFrameLength; - u8 nonBackToBackIfgPart1; - u8 nonBackToBackIfgPart2; - u8 miminumInterFrameGapEnforcement; - u8 backToBackInterFrameGap; - int ipAddressAlignment; - int lengthCheckRx; - u32 mblinterval; - u16 nortsrbytetime; - u8 fracsiz; - u8 strictpriorityq; - u8 txasap; - u8 extrabw; - int miiPreambleSupress; - u8 altBebTruncation; - int altBeb; - int backPressureNoBackoff; - int noBackoff; - int excessDefer; - u8 maxRetransmission; - u8 collisionWindow; - int pro; - int cap; - int rsh; - int rlpb; - int cam; - int bro; - int ecm; - int receiveFlowControl; - int transmitFlowControl; - u8 maxGroupAddrInHash; - u8 maxIndAddrInHash; - u8 prel; - u16 maxFrameLength; - u16 minFrameLength; - u16 maxD1Length; - u16 maxD2Length; - u16 vlantype; - u16 vlantci; - u32 ecamptr; - u32 eventRegMask; - u16 pausePeriod; - u16 extensionField; - struct device_node *phy_node; - struct device_node *tbi_node; - u8 weightfactor[NUM_TX_QUEUES]; - u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; - u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; - u8 l3qt[UCC_GETH_IP_PRIORITY_MAX]; - u32 vtagtable[UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX]; - u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; - u16 bdRingLenTx[NUM_TX_QUEUES]; - u16 bdRingLenRx[NUM_RX_QUEUES]; - enum ucc_geth_num_of_station_addresses numStationAddresses; - enum qe_fltr_largest_external_tbl_lookup_key_size - largestexternallookupkeysize; - enum ucc_geth_statistics_gathering_mode statisticsMode; - enum ucc_geth_vlan_operation_tagged vlanOperationTagged; - enum ucc_geth_vlan_operation_non_tagged vlanOperationNonTagged; - enum ucc_geth_qos_mode rxQoSMode; - enum ucc_geth_flow_control_mode aufc; - enum ucc_geth_maccfg2_pad_and_crc_mode padAndCrc; - enum ucc_geth_num_of_threads numThreadsTx; - enum ucc_geth_num_of_threads numThreadsRx; - unsigned int riscTx; - unsigned int riscRx; -}; - -/* structure representing UCC GETH */ -struct ucc_geth_private { - struct ucc_geth_info *ug_info; - struct ucc_fast_private *uccf; - struct device *dev; - struct net_device *ndev; - struct napi_struct napi; - struct work_struct timeout_work; - struct ucc_geth __iomem *ug_regs; - struct ucc_geth_init_pram *p_init_enet_param_shadow; - struct ucc_geth_exf_global_pram __iomem *p_exf_glbl_param; - u32 exf_glbl_param_offset; - struct ucc_geth_rx_global_pram __iomem *p_rx_glbl_pram; - u32 rx_glbl_pram_offset; - struct ucc_geth_tx_global_pram __iomem *p_tx_glbl_pram; - u32 tx_glbl_pram_offset; - struct ucc_geth_send_queue_mem_region __iomem *p_send_q_mem_reg; - u32 send_q_mem_reg_offset; - struct ucc_geth_thread_data_tx __iomem *p_thread_data_tx; - u32 thread_dat_tx_offset; - struct ucc_geth_thread_data_rx __iomem *p_thread_data_rx; - u32 thread_dat_rx_offset; - struct ucc_geth_scheduler __iomem *p_scheduler; - u32 scheduler_offset; - struct ucc_geth_tx_firmware_statistics_pram __iomem *p_tx_fw_statistics_pram; - u32 tx_fw_statistics_pram_offset; - struct ucc_geth_rx_firmware_statistics_pram __iomem *p_rx_fw_statistics_pram; - u32 rx_fw_statistics_pram_offset; - struct ucc_geth_rx_interrupt_coalescing_table __iomem *p_rx_irq_coalescing_tbl; - u32 rx_irq_coalescing_tbl_offset; - struct ucc_geth_rx_bd_queues_entry __iomem *p_rx_bd_qs_tbl; - u32 rx_bd_qs_tbl_offset; - u8 __iomem *p_tx_bd_ring[NUM_TX_QUEUES]; - u32 tx_bd_ring_offset[NUM_TX_QUEUES]; - u8 __iomem *p_rx_bd_ring[NUM_RX_QUEUES]; - u32 rx_bd_ring_offset[NUM_RX_QUEUES]; - u8 __iomem *confBd[NUM_TX_QUEUES]; - u8 __iomem *txBd[NUM_TX_QUEUES]; - u8 __iomem *rxBd[NUM_RX_QUEUES]; - int badFrame[NUM_RX_QUEUES]; - u16 cpucount[NUM_TX_QUEUES]; - u16 __iomem *p_cpucount[NUM_TX_QUEUES]; - int indAddrRegUsed[NUM_OF_PADDRS]; - u8 paddr[NUM_OF_PADDRS][ETH_ALEN]; /* ethernet address */ - u8 numGroupAddrInHash; - u8 numIndAddrInHash; - u8 numIndAddrInReg; - int rx_extended_features; - int rx_non_dynamic_extended_features; - struct list_head conf_skbs; - struct list_head group_hash_q; - struct list_head ind_hash_q; - u32 saved_uccm; - spinlock_t lock; - /* pointers to arrays of skbuffs for tx and rx */ - struct sk_buff **tx_skbuff[NUM_TX_QUEUES]; - struct sk_buff **rx_skbuff[NUM_RX_QUEUES]; - /* indices pointing to the next free sbk in skb arrays */ - u16 skb_curtx[NUM_TX_QUEUES]; - u16 skb_currx[NUM_RX_QUEUES]; - /* index of the first skb which hasn't been transmitted yet. */ - u16 skb_dirtytx[NUM_TX_QUEUES]; - - struct sk_buff_head rx_recycle; - - struct ugeth_mii_info *mii_info; - struct phy_device *phydev; - phy_interface_t phy_interface; - int max_speed; - uint32_t msg_enable; - int oldspeed; - int oldduplex; - int oldlink; - int wol_en; - - struct device_node *node; -}; - -void uec_set_ethtool_ops(struct net_device *netdev); -int init_flow_control_params(u32 automatic_flow_control_mode, - int rx_flow_control_enable, int tx_flow_control_enable, - u16 pause_period, u16 extension_field, - u32 __iomem *upsmr_register, u32 __iomem *uempr_register, - u32 __iomem *maccfg1_register); - - -#endif /* __UCC_GETH_H__ */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth_ethtool.c deleted file mode 100644 index a97257f9..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/freescale/ucc_geth_ethtool.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 2007 Freescale Semiconductor, Inc. All rights reserved. - * - * Description: QE UCC Gigabit Ethernet Ethtool API Set - * - * Author: Li Yang <leoli@freescale.com> - * - * Limitation: - * Can only get/set settings of the first queue. - * Need to re-open the interface manually after changing some parameters. - * - * 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. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/stddef.h> -#include <linux/interrupt.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#include <linux/phy.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/types.h> - -#include "ucc_geth.h" - -static char hw_stat_gstrings[][ETH_GSTRING_LEN] = { - "tx-64-frames", - "tx-65-127-frames", - "tx-128-255-frames", - "rx-64-frames", - "rx-65-127-frames", - "rx-128-255-frames", - "tx-bytes-ok", - "tx-pause-frames", - "tx-multicast-frames", - "tx-broadcast-frames", - "rx-frames", - "rx-bytes-ok", - "rx-bytes-all", - "rx-multicast-frames", - "rx-broadcast-frames", - "stats-counter-carry", - "stats-counter-mask", - "rx-dropped-frames", -}; - -static char tx_fw_stat_gstrings[][ETH_GSTRING_LEN] = { - "tx-single-collision", - "tx-multiple-collision", - "tx-late-collsion", - "tx-aborted-frames", - "tx-lost-frames", - "tx-carrier-sense-errors", - "tx-frames-ok", - "tx-excessive-differ-frames", - "tx-256-511-frames", - "tx-512-1023-frames", - "tx-1024-1518-frames", - "tx-jumbo-frames", -}; - -static char rx_fw_stat_gstrings[][ETH_GSTRING_LEN] = { - "rx-crc-errors", - "rx-alignment-errors", - "rx-in-range-length-errors", - "rx-out-of-range-length-errors", - "rx-too-long-frames", - "rx-runt", - "rx-very-long-event", - "rx-symbol-errors", - "rx-busy-drop-frames", - "reserved", - "reserved", - "rx-mismatch-drop-frames", - "rx-small-than-64", - "rx-256-511-frames", - "rx-512-1023-frames", - "rx-1024-1518-frames", - "rx-jumbo-frames", - "rx-mac-error-loss", - "rx-pause-frames", - "reserved", - "rx-vlan-removed", - "rx-vlan-replaced", - "rx-vlan-inserted", - "rx-ip-checksum-errors", -}; - -#define UEC_HW_STATS_LEN ARRAY_SIZE(hw_stat_gstrings) -#define UEC_TX_FW_STATS_LEN ARRAY_SIZE(tx_fw_stat_gstrings) -#define UEC_RX_FW_STATS_LEN ARRAY_SIZE(rx_fw_stat_gstrings) - -static int -uec_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - struct phy_device *phydev = ugeth->phydev; - struct ucc_geth_info *ug_info = ugeth->ug_info; - - if (!phydev) - return -ENODEV; - - ecmd->maxtxpkt = 1; - ecmd->maxrxpkt = ug_info->interruptcoalescingmaxvalue[0]; - - return phy_ethtool_gset(phydev, ecmd); -} - -static int -uec_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - struct phy_device *phydev = ugeth->phydev; - - if (!phydev) - return -ENODEV; - - return phy_ethtool_sset(phydev, ecmd); -} - -static void -uec_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - - pause->autoneg = ugeth->phydev->autoneg; - - if (ugeth->ug_info->receiveFlowControl) - pause->rx_pause = 1; - if (ugeth->ug_info->transmitFlowControl) - pause->tx_pause = 1; -} - -static int -uec_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - int ret = 0; - - ugeth->ug_info->receiveFlowControl = pause->rx_pause; - ugeth->ug_info->transmitFlowControl = pause->tx_pause; - - if (ugeth->phydev->autoneg) { - if (netif_running(netdev)) { - /* FIXME: automatically restart */ - printk(KERN_INFO - "Please re-open the interface.\n"); - } - } else { - struct ucc_geth_info *ug_info = ugeth->ug_info; - - ret = init_flow_control_params(ug_info->aufc, - ug_info->receiveFlowControl, - ug_info->transmitFlowControl, - ug_info->pausePeriod, - ug_info->extensionField, - &ugeth->uccf->uf_regs->upsmr, - &ugeth->ug_regs->uempr, - &ugeth->ug_regs->maccfg1); - } - - return ret; -} - -static uint32_t -uec_get_msglevel(struct net_device *netdev) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - return ugeth->msg_enable; -} - -static void -uec_set_msglevel(struct net_device *netdev, uint32_t data) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - ugeth->msg_enable = data; -} - -static int -uec_get_regs_len(struct net_device *netdev) -{ - return sizeof(struct ucc_geth); -} - -static void -uec_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - int i; - struct ucc_geth_private *ugeth = netdev_priv(netdev); - u32 __iomem *ug_regs = (u32 __iomem *)ugeth->ug_regs; - u32 *buff = p; - - for (i = 0; i < sizeof(struct ucc_geth) / sizeof(u32); i++) - buff[i] = in_be32(&ug_regs[i]); -} - -static void -uec_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - struct ucc_geth_info *ug_info = ugeth->ug_info; - int queue = 0; - - ring->rx_max_pending = UCC_GETH_BD_RING_SIZE_MAX; - ring->rx_mini_max_pending = UCC_GETH_BD_RING_SIZE_MAX; - ring->rx_jumbo_max_pending = UCC_GETH_BD_RING_SIZE_MAX; - ring->tx_max_pending = UCC_GETH_BD_RING_SIZE_MAX; - - ring->rx_pending = ug_info->bdRingLenRx[queue]; - ring->rx_mini_pending = ug_info->bdRingLenRx[queue]; - ring->rx_jumbo_pending = ug_info->bdRingLenRx[queue]; - ring->tx_pending = ug_info->bdRingLenTx[queue]; -} - -static int -uec_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - struct ucc_geth_info *ug_info = ugeth->ug_info; - int queue = 0, ret = 0; - - if (ring->rx_pending < UCC_GETH_RX_BD_RING_SIZE_MIN) { - printk("%s: RxBD ring size must be no smaller than %d.\n", - netdev->name, UCC_GETH_RX_BD_RING_SIZE_MIN); - return -EINVAL; - } - if (ring->rx_pending % UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT) { - printk("%s: RxBD ring size must be multiple of %d.\n", - netdev->name, UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT); - return -EINVAL; - } - if (ring->tx_pending < UCC_GETH_TX_BD_RING_SIZE_MIN) { - printk("%s: TxBD ring size must be no smaller than %d.\n", - netdev->name, UCC_GETH_TX_BD_RING_SIZE_MIN); - return -EINVAL; - } - - ug_info->bdRingLenRx[queue] = ring->rx_pending; - ug_info->bdRingLenTx[queue] = ring->tx_pending; - - if (netif_running(netdev)) { - /* FIXME: restart automatically */ - printk(KERN_INFO - "Please re-open the interface.\n"); - } - - return ret; -} - -static int uec_get_sset_count(struct net_device *netdev, int sset) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - u32 stats_mode = ugeth->ug_info->statisticsMode; - int len = 0; - - switch (sset) { - case ETH_SS_STATS: - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) - len += UEC_HW_STATS_LEN; - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) - len += UEC_TX_FW_STATS_LEN; - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) - len += UEC_RX_FW_STATS_LEN; - - return len; - - default: - return -EOPNOTSUPP; - } -} - -static void uec_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - u32 stats_mode = ugeth->ug_info->statisticsMode; - - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { - memcpy(buf, hw_stat_gstrings, UEC_HW_STATS_LEN * - ETH_GSTRING_LEN); - buf += UEC_HW_STATS_LEN * ETH_GSTRING_LEN; - } - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { - memcpy(buf, tx_fw_stat_gstrings, UEC_TX_FW_STATS_LEN * - ETH_GSTRING_LEN); - buf += UEC_TX_FW_STATS_LEN * ETH_GSTRING_LEN; - } - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) - memcpy(buf, rx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN * - ETH_GSTRING_LEN); -} - -static void uec_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - u32 stats_mode = ugeth->ug_info->statisticsMode; - u32 __iomem *base; - int i, j = 0; - - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { - if (ugeth->ug_regs) - base = (u32 __iomem *)&ugeth->ug_regs->tx64; - else - base = NULL; - - for (i = 0; i < UEC_HW_STATS_LEN; i++) - data[j++] = base ? in_be32(&base[i]) : 0; - } - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { - base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; - for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) - data[j++] = base ? in_be32(&base[i]) : 0; - } - if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { - base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; - for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) - data[j++] = base ? in_be32(&base[i]) : 0; - } -} - -static int uec_nway_reset(struct net_device *netdev) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - - return phy_start_aneg(ugeth->phydev); -} - -/* Report driver information */ -static void -uec_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - strncpy(drvinfo->driver, DRV_NAME, 32); - strncpy(drvinfo->version, DRV_VERSION, 32); - strncpy(drvinfo->fw_version, "N/A", 32); - strncpy(drvinfo->bus_info, "QUICC ENGINE", 32); - drvinfo->eedump_len = 0; - drvinfo->regdump_len = uec_get_regs_len(netdev); -} - -#ifdef CONFIG_PM - -static void uec_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - struct phy_device *phydev = ugeth->phydev; - - if (phydev && phydev->irq) - wol->supported |= WAKE_PHY; - if (qe_alive_during_sleep()) - wol->supported |= WAKE_MAGIC; - - wol->wolopts = ugeth->wol_en; -} - -static int uec_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct ucc_geth_private *ugeth = netdev_priv(netdev); - struct phy_device *phydev = ugeth->phydev; - - if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC)) - return -EINVAL; - else if (wol->wolopts & WAKE_PHY && (!phydev || !phydev->irq)) - return -EINVAL; - else if (wol->wolopts & WAKE_MAGIC && !qe_alive_during_sleep()) - return -EINVAL; - - ugeth->wol_en = wol->wolopts; - device_set_wakeup_enable(&netdev->dev, ugeth->wol_en); - - return 0; -} - -#else -#define uec_get_wol NULL -#define uec_set_wol NULL -#endif /* CONFIG_PM */ - -static const struct ethtool_ops uec_ethtool_ops = { - .get_settings = uec_get_settings, - .set_settings = uec_set_settings, - .get_drvinfo = uec_get_drvinfo, - .get_regs_len = uec_get_regs_len, - .get_regs = uec_get_regs, - .get_msglevel = uec_get_msglevel, - .set_msglevel = uec_set_msglevel, - .nway_reset = uec_nway_reset, - .get_link = ethtool_op_get_link, - .get_ringparam = uec_get_ringparam, - .set_ringparam = uec_set_ringparam, - .get_pauseparam = uec_get_pauseparam, - .set_pauseparam = uec_set_pauseparam, - .get_sset_count = uec_get_sset_count, - .get_strings = uec_get_strings, - .get_ethtool_stats = uec_get_ethtool_stats, - .get_wol = uec_get_wol, - .set_wol = uec_set_wol, -}; - -void uec_set_ethtool_ops(struct net_device *netdev) -{ - SET_ETHTOOL_OPS(netdev, &uec_ethtool_ops); -} |