summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/net/ethernet/xilinx
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/net/ethernet/xilinx')
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/Kconfig44
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/Makefile9
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac.h385
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_main.c1189
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_mdio.c122
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet.h506
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_main.c1669
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c238
-rw-r--r--ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_emaclite.c1308
9 files changed, 0 insertions, 5470 deletions
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/Kconfig b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/Kconfig
deleted file mode 100644
index 5778a4ae..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/Kconfig
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Xilink device configuration
-#
-
-config NET_VENDOR_XILINX
- bool "Xilinx devices"
- default y
- depends on PPC || PPC32 || MICROBLAZE
- ---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 Xilinx devices. If you say Y, you will be asked
- for your specific card in the following questions.
-
-if NET_VENDOR_XILINX
-
-config XILINX_EMACLITE
- tristate "Xilinx 10/100 Ethernet Lite support"
- depends on (PPC32 || MICROBLAZE)
- select PHYLIB
- ---help---
- This driver supports the 10/100 Ethernet Lite from Xilinx.
-
-config XILINX_AXI_EMAC
- tristate "Xilinx 10/100/1000 AXI Ethernet support"
- depends on (PPC32 || MICROBLAZE)
- select PHYLIB
- ---help---
- This driver supports the 10/100/1000 Ethernet from Xilinx for the
- AXI bus interface used in Xilinx Virtex FPGAs.
-
-config XILINX_LL_TEMAC
- tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
- depends on (PPC || MICROBLAZE)
- select PHYLIB
- ---help---
- This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
- core used in Xilinx Spartan and Virtex FPGAs
-
-endif # NET_VENDOR_XILINX
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/Makefile b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/Makefile
deleted file mode 100644
index 214205e9..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the Xilink network device drivers.
-#
-
-ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
-obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
-obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
-xilinx_emac-objs := xilinx_axienet_main.o xilinx_axienet_mdio.o
-obj-$(CONFIG_XILINX_AXI_EMAC) += xilinx_emac.o
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac.h b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac.h
deleted file mode 100644
index 522abe2f..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac.h
+++ /dev/null
@@ -1,385 +0,0 @@
-
-#ifndef XILINX_LL_TEMAC_H
-#define XILINX_LL_TEMAC_H
-
-#include <linux/netdevice.h>
-#include <linux/of.h>
-#include <linux/spinlock.h>
-
-#ifdef CONFIG_PPC_DCR
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-#endif
-
-/* packet size info */
-#define XTE_HDR_SIZE 14 /* size of Ethernet header */
-#define XTE_TRL_SIZE 4 /* size of Ethernet trailer (FCS) */
-#define XTE_JUMBO_MTU 9000
-#define XTE_MAX_JUMBO_FRAME_SIZE (XTE_JUMBO_MTU + XTE_HDR_SIZE + XTE_TRL_SIZE)
-
-/* Configuration options */
-
-/* Accept all incoming packets.
- * This option defaults to disabled (cleared) */
-#define XTE_OPTION_PROMISC (1 << 0)
-/* Jumbo frame support for Tx & Rx.
- * This option defaults to disabled (cleared) */
-#define XTE_OPTION_JUMBO (1 << 1)
-/* VLAN Rx & Tx frame support.
- * This option defaults to disabled (cleared) */
-#define XTE_OPTION_VLAN (1 << 2)
-/* Enable recognition of flow control frames on Rx
- * This option defaults to enabled (set) */
-#define XTE_OPTION_FLOW_CONTROL (1 << 4)
-/* Strip FCS and PAD from incoming frames.
- * Note: PAD from VLAN frames is not stripped.
- * This option defaults to disabled (set) */
-#define XTE_OPTION_FCS_STRIP (1 << 5)
-/* Generate FCS field and add PAD automatically for outgoing frames.
- * This option defaults to enabled (set) */
-#define XTE_OPTION_FCS_INSERT (1 << 6)
-/* Enable Length/Type error checking for incoming frames. When this option is
-set, the MAC will filter frames that have a mismatched type/length field
-and if XTE_OPTION_REPORT_RXERR is set, the user is notified when these
-types of frames are encountered. When this option is cleared, the MAC will
-allow these types of frames to be received.
-This option defaults to enabled (set) */
-#define XTE_OPTION_LENTYPE_ERR (1 << 7)
-/* Enable the transmitter.
- * This option defaults to enabled (set) */
-#define XTE_OPTION_TXEN (1 << 11)
-/* Enable the receiver
-* This option defaults to enabled (set) */
-#define XTE_OPTION_RXEN (1 << 12)
-
-/* Default options set when device is initialized or reset */
-#define XTE_OPTION_DEFAULTS \
- (XTE_OPTION_TXEN | \
- XTE_OPTION_FLOW_CONTROL | \
- XTE_OPTION_RXEN)
-
-/* XPS_LL_TEMAC SDMA registers definition */
-
-#define TX_NXTDESC_PTR 0x00 /* r */
-#define TX_CURBUF_ADDR 0x01 /* r */
-#define TX_CURBUF_LENGTH 0x02 /* r */
-#define TX_CURDESC_PTR 0x03 /* rw */
-#define TX_TAILDESC_PTR 0x04 /* rw */
-#define TX_CHNL_CTRL 0x05 /* rw */
-/*
- 0:7 24:31 IRQTimeout
- 8:15 16:23 IRQCount
- 16:20 11:15 Reserved
- 21 10 0
- 22 9 UseIntOnEnd
- 23 8 LdIRQCnt
- 24 7 IRQEn
- 25:28 3:6 Reserved
- 29 2 IrqErrEn
- 30 1 IrqDlyEn
- 31 0 IrqCoalEn
-*/
-#define CHNL_CTRL_IRQ_IOE (1 << 9)
-#define CHNL_CTRL_IRQ_EN (1 << 7)
-#define CHNL_CTRL_IRQ_ERR_EN (1 << 2)
-#define CHNL_CTRL_IRQ_DLY_EN (1 << 1)
-#define CHNL_CTRL_IRQ_COAL_EN (1 << 0)
-#define TX_IRQ_REG 0x06 /* rw */
-/*
- 0:7 24:31 DltTmrValue
- 8:15 16:23 ClscCntrValue
- 16:17 14:15 Reserved
- 18:21 10:13 ClscCnt
- 22:23 8:9 DlyCnt
- 24:28 3::7 Reserved
- 29 2 ErrIrq
- 30 1 DlyIrq
- 31 0 CoalIrq
- */
-#define TX_CHNL_STS 0x07 /* r */
-/*
- 0:9 22:31 Reserved
- 10 21 TailPErr
- 11 20 CmpErr
- 12 19 AddrErr
- 13 18 NxtPErr
- 14 17 CurPErr
- 15 16 BsyWr
- 16:23 8:15 Reserved
- 24 7 Error
- 25 6 IOE
- 26 5 SOE
- 27 4 Cmplt
- 28 3 SOP
- 29 2 EOP
- 30 1 EngBusy
- 31 0 Reserved
-*/
-
-#define RX_NXTDESC_PTR 0x08 /* r */
-#define RX_CURBUF_ADDR 0x09 /* r */
-#define RX_CURBUF_LENGTH 0x0a /* r */
-#define RX_CURDESC_PTR 0x0b /* rw */
-#define RX_TAILDESC_PTR 0x0c /* rw */
-#define RX_CHNL_CTRL 0x0d /* rw */
-/*
- 0:7 24:31 IRQTimeout
- 8:15 16:23 IRQCount
- 16:20 11:15 Reserved
- 21 10 0
- 22 9 UseIntOnEnd
- 23 8 LdIRQCnt
- 24 7 IRQEn
- 25:28 3:6 Reserved
- 29 2 IrqErrEn
- 30 1 IrqDlyEn
- 31 0 IrqCoalEn
- */
-#define RX_IRQ_REG 0x0e /* rw */
-#define IRQ_COAL (1 << 0)
-#define IRQ_DLY (1 << 1)
-#define IRQ_ERR (1 << 2)
-#define IRQ_DMAERR (1 << 7) /* this is not documented ??? */
-/*
- 0:7 24:31 DltTmrValue
- 8:15 16:23 ClscCntrValue
- 16:17 14:15 Reserved
- 18:21 10:13 ClscCnt
- 22:23 8:9 DlyCnt
- 24:28 3::7 Reserved
-*/
-#define RX_CHNL_STS 0x0f /* r */
-#define CHNL_STS_ENGBUSY (1 << 1)
-#define CHNL_STS_EOP (1 << 2)
-#define CHNL_STS_SOP (1 << 3)
-#define CHNL_STS_CMPLT (1 << 4)
-#define CHNL_STS_SOE (1 << 5)
-#define CHNL_STS_IOE (1 << 6)
-#define CHNL_STS_ERR (1 << 7)
-
-#define CHNL_STS_BSYWR (1 << 16)
-#define CHNL_STS_CURPERR (1 << 17)
-#define CHNL_STS_NXTPERR (1 << 18)
-#define CHNL_STS_ADDRERR (1 << 19)
-#define CHNL_STS_CMPERR (1 << 20)
-#define CHNL_STS_TAILERR (1 << 21)
-/*
- 0:9 22:31 Reserved
- 10 21 TailPErr
- 11 20 CmpErr
- 12 19 AddrErr
- 13 18 NxtPErr
- 14 17 CurPErr
- 15 16 BsyWr
- 16:23 8:15 Reserved
- 24 7 Error
- 25 6 IOE
- 26 5 SOE
- 27 4 Cmplt
- 28 3 SOP
- 29 2 EOP
- 30 1 EngBusy
- 31 0 Reserved
-*/
-
-#define DMA_CONTROL_REG 0x10 /* rw */
-#define DMA_CONTROL_RST (1 << 0)
-#define DMA_TAIL_ENABLE (1 << 2)
-
-/* XPS_LL_TEMAC direct registers definition */
-
-#define XTE_RAF0_OFFSET 0x00
-#define RAF0_RST (1 << 0)
-#define RAF0_MCSTREJ (1 << 1)
-#define RAF0_BCSTREJ (1 << 2)
-#define XTE_TPF0_OFFSET 0x04
-#define XTE_IFGP0_OFFSET 0x08
-#define XTE_ISR0_OFFSET 0x0c
-#define ISR0_HARDACSCMPLT (1 << 0)
-#define ISR0_AUTONEG (1 << 1)
-#define ISR0_RXCMPLT (1 << 2)
-#define ISR0_RXREJ (1 << 3)
-#define ISR0_RXFIFOOVR (1 << 4)
-#define ISR0_TXCMPLT (1 << 5)
-#define ISR0_RXDCMLCK (1 << 6)
-
-#define XTE_IPR0_OFFSET 0x10
-#define XTE_IER0_OFFSET 0x14
-
-#define XTE_MSW0_OFFSET 0x20
-#define XTE_LSW0_OFFSET 0x24
-#define XTE_CTL0_OFFSET 0x28
-#define XTE_RDY0_OFFSET 0x2c
-
-#define XTE_RSE_MIIM_RR_MASK 0x0002
-#define XTE_RSE_MIIM_WR_MASK 0x0004
-#define XTE_RSE_CFG_RR_MASK 0x0020
-#define XTE_RSE_CFG_WR_MASK 0x0040
-#define XTE_RDY0_HARD_ACS_RDY_MASK (0x10000)
-
-/* XPS_LL_TEMAC indirect registers offset definition */
-
-#define XTE_RXC0_OFFSET 0x00000200 /* Rx configuration word 0 */
-#define XTE_RXC1_OFFSET 0x00000240 /* Rx configuration word 1 */
-#define XTE_RXC1_RXRST_MASK (1 << 31) /* Receiver reset */
-#define XTE_RXC1_RXJMBO_MASK (1 << 30) /* Jumbo frame enable */
-#define XTE_RXC1_RXFCS_MASK (1 << 29) /* FCS not stripped */
-#define XTE_RXC1_RXEN_MASK (1 << 28) /* Receiver enable */
-#define XTE_RXC1_RXVLAN_MASK (1 << 27) /* VLAN enable */
-#define XTE_RXC1_RXHD_MASK (1 << 26) /* Half duplex */
-#define XTE_RXC1_RXLT_MASK (1 << 25) /* Length/type check disable */
-
-#define XTE_TXC_OFFSET 0x00000280 /* Tx configuration */
-#define XTE_TXC_TXRST_MASK (1 << 31) /* Transmitter reset */
-#define XTE_TXC_TXJMBO_MASK (1 << 30) /* Jumbo frame enable */
-#define XTE_TXC_TXFCS_MASK (1 << 29) /* Generate FCS */
-#define XTE_TXC_TXEN_MASK (1 << 28) /* Transmitter enable */
-#define XTE_TXC_TXVLAN_MASK (1 << 27) /* VLAN enable */
-#define XTE_TXC_TXHD_MASK (1 << 26) /* Half duplex */
-
-#define XTE_FCC_OFFSET 0x000002C0 /* Flow control config */
-#define XTE_FCC_RXFLO_MASK (1 << 29) /* Rx flow control enable */
-#define XTE_FCC_TXFLO_MASK (1 << 30) /* Tx flow control enable */
-
-#define XTE_EMCFG_OFFSET 0x00000300 /* EMAC configuration */
-#define XTE_EMCFG_LINKSPD_MASK 0xC0000000 /* Link speed */
-#define XTE_EMCFG_HOSTEN_MASK (1 << 26) /* Host interface enable */
-#define XTE_EMCFG_LINKSPD_10 0x00000000 /* 10 Mbit LINKSPD_MASK */
-#define XTE_EMCFG_LINKSPD_100 (1 << 30) /* 100 Mbit LINKSPD_MASK */
-#define XTE_EMCFG_LINKSPD_1000 (1 << 31) /* 1000 Mbit LINKSPD_MASK */
-
-#define XTE_GMIC_OFFSET 0x00000320 /* RGMII/SGMII config */
-#define XTE_MC_OFFSET 0x00000340 /* MDIO configuration */
-#define XTE_UAW0_OFFSET 0x00000380 /* Unicast address word 0 */
-#define XTE_UAW1_OFFSET 0x00000384 /* Unicast address word 1 */
-
-#define XTE_MAW0_OFFSET 0x00000388 /* Multicast addr word 0 */
-#define XTE_MAW1_OFFSET 0x0000038C /* Multicast addr word 1 */
-#define XTE_AFM_OFFSET 0x00000390 /* Promiscuous mode */
-#define XTE_AFM_EPPRM_MASK (1 << 31) /* Promiscuous mode enable */
-
-/* Interrupt Request status */
-#define XTE_TIS_OFFSET 0x000003A0
-#define TIS_FRIS (1 << 0)
-#define TIS_MRIS (1 << 1)
-#define TIS_MWIS (1 << 2)
-#define TIS_ARIS (1 << 3)
-#define TIS_AWIS (1 << 4)
-#define TIS_CRIS (1 << 5)
-#define TIS_CWIS (1 << 6)
-
-#define XTE_TIE_OFFSET 0x000003A4 /* Interrupt enable */
-
-/** MII Mamagement Control register (MGTCR) */
-#define XTE_MGTDR_OFFSET 0x000003B0 /* MII data */
-#define XTE_MIIMAI_OFFSET 0x000003B4 /* MII control */
-
-#define CNTLREG_WRITE_ENABLE_MASK 0x8000
-#define CNTLREG_EMAC1SEL_MASK 0x0400
-#define CNTLREG_ADDRESSCODE_MASK 0x03ff
-
-/* CDMAC descriptor status bit definitions */
-
-#define STS_CTRL_APP0_ERR (1 << 31)
-#define STS_CTRL_APP0_IRQONEND (1 << 30)
-/* undoccumented */
-#define STS_CTRL_APP0_STOPONEND (1 << 29)
-#define STS_CTRL_APP0_CMPLT (1 << 28)
-#define STS_CTRL_APP0_SOP (1 << 27)
-#define STS_CTRL_APP0_EOP (1 << 26)
-#define STS_CTRL_APP0_ENGBUSY (1 << 25)
-/* undocumented */
-#define STS_CTRL_APP0_ENGRST (1 << 24)
-
-#define TX_CONTROL_CALC_CSUM_MASK 1
-
-#define MULTICAST_CAM_TABLE_NUM 4
-
-/* TEMAC Synthesis features */
-#define TEMAC_FEATURE_RX_CSUM (1 << 0)
-#define TEMAC_FEATURE_TX_CSUM (1 << 1)
-
-/* TX/RX CURDESC_PTR points to first descriptor */
-/* TX/RX TAILDESC_PTR points to last descriptor in linked list */
-
-/**
- * struct cdmac_bd - LocalLink buffer descriptor format
- *
- * app0 bits:
- * 0 Error
- * 1 IrqOnEnd generate an interrupt at completion of DMA op
- * 2 reserved
- * 3 completed Current descriptor completed
- * 4 SOP TX - marks first desc/ RX marks first desct
- * 5 EOP TX marks last desc/RX marks last desc
- * 6 EngBusy DMA is processing
- * 7 reserved
- * 8:31 application specific
- */
-struct cdmac_bd {
- u32 next; /* Physical address of next buffer descriptor */
- u32 phys;
- u32 len;
- u32 app0;
- u32 app1; /* TX start << 16 | insert */
- u32 app2; /* TX csum */
- u32 app3;
- u32 app4; /* skb for TX length for RX */
-};
-
-struct temac_local {
- struct net_device *ndev;
- struct device *dev;
-
- /* Connection to PHY device */
- struct phy_device *phy_dev; /* Pointer to PHY device */
- struct device_node *phy_node;
-
- /* MDIO bus data */
- struct mii_bus *mii_bus; /* MII bus reference */
- int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */
-
- /* IO registers, dma functions and IRQs */
- void __iomem *regs;
- void __iomem *sdma_regs;
-#ifdef CONFIG_PPC_DCR
- dcr_host_t sdma_dcrs;
-#endif
- u32 (*dma_in)(struct temac_local *, int);
- void (*dma_out)(struct temac_local *, int, u32);
-
- int tx_irq;
- int rx_irq;
- int emac_num;
-
- struct sk_buff **rx_skb;
- spinlock_t rx_lock;
- struct mutex indirect_mutex;
- u32 options; /* Current options word */
- int last_link;
- unsigned int temac_features;
-
- /* Buffer descriptors */
- struct cdmac_bd *tx_bd_v;
- dma_addr_t tx_bd_p;
- struct cdmac_bd *rx_bd_v;
- dma_addr_t rx_bd_p;
- int tx_bd_ci;
- int tx_bd_next;
- int tx_bd_tail;
- int rx_bd_ci;
-};
-
-/* xilinx_temac.c */
-u32 temac_ior(struct temac_local *lp, int offset);
-void temac_iow(struct temac_local *lp, int offset, u32 value);
-int temac_indirect_busywait(struct temac_local *lp);
-u32 temac_indirect_in32(struct temac_local *lp, int reg);
-void temac_indirect_out32(struct temac_local *lp, int reg, u32 value);
-
-
-/* xilinx_temac_mdio.c */
-int temac_mdio_setup(struct temac_local *lp, struct device_node *np);
-void temac_mdio_teardown(struct temac_local *lp);
-
-#endif /* XILINX_LL_TEMAC_H */
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_main.c b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_main.c
deleted file mode 100644
index d21591a2..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ /dev/null
@@ -1,1189 +0,0 @@
-/*
- * Driver for Xilinx TEMAC Ethernet device
- *
- * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi
- * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. <dhlii@dlasys.net>
- * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
- *
- * This is a driver for the Xilinx ll_temac ipcore which is often used
- * in the Virtex and Spartan series of chips.
- *
- * Notes:
- * - The ll_temac hardware uses indirect access for many of the TEMAC
- * registers, include the MDIO bus. However, indirect access to MDIO
- * registers take considerably more clock cycles than to TEMAC registers.
- * MDIO accesses are long, so threads doing them should probably sleep
- * rather than busywait. However, since only one indirect access can be
- * in progress at any given time, that means that *all* indirect accesses
- * could end up sleeping (to wait for an MDIO access to complete).
- * Fortunately none of the indirect accesses are on the 'hot' path for tx
- * or rx, so this should be okay.
- *
- * TODO:
- * - Factor out locallink DMA code into separate driver
- * - Fix multicast assignment.
- * - Fix support for hardware checksumming.
- * - Testing. Lots and lots of testing.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/netdevice.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_mdio.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/tcp.h> /* needed for sizeof(tcphdr) */
-#include <linux/udp.h> /* needed for sizeof(udphdr) */
-#include <linux/phy.h>
-#include <linux/in.h>
-#include <linux/io.h>
-#include <linux/ip.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-
-#include "ll_temac.h"
-
-#define TX_BD_NUM 64
-#define RX_BD_NUM 128
-
-/* ---------------------------------------------------------------------
- * Low level register access functions
- */
-
-u32 temac_ior(struct temac_local *lp, int offset)
-{
- return in_be32((u32 *)(lp->regs + offset));
-}
-
-void temac_iow(struct temac_local *lp, int offset, u32 value)
-{
- out_be32((u32 *) (lp->regs + offset), value);
-}
-
-int temac_indirect_busywait(struct temac_local *lp)
-{
- long end = jiffies + 2;
-
- while (!(temac_ior(lp, XTE_RDY0_OFFSET) & XTE_RDY0_HARD_ACS_RDY_MASK)) {
- if (end - jiffies <= 0) {
- WARN_ON(1);
- return -ETIMEDOUT;
- }
- msleep(1);
- }
- return 0;
-}
-
-/**
- * temac_indirect_in32
- *
- * lp->indirect_mutex must be held when calling this function
- */
-u32 temac_indirect_in32(struct temac_local *lp, int reg)
-{
- u32 val;
-
- if (temac_indirect_busywait(lp))
- return -ETIMEDOUT;
- temac_iow(lp, XTE_CTL0_OFFSET, reg);
- if (temac_indirect_busywait(lp))
- return -ETIMEDOUT;
- val = temac_ior(lp, XTE_LSW0_OFFSET);
-
- return val;
-}
-
-/**
- * temac_indirect_out32
- *
- * lp->indirect_mutex must be held when calling this function
- */
-void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
-{
- if (temac_indirect_busywait(lp))
- return;
- temac_iow(lp, XTE_LSW0_OFFSET, value);
- temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
- temac_indirect_busywait(lp);
-}
-
-/**
- * temac_dma_in32 - Memory mapped DMA read, this function expects a
- * register input that is based on DCR word addresses which
- * are then converted to memory mapped byte addresses
- */
-static u32 temac_dma_in32(struct temac_local *lp, int reg)
-{
- return in_be32((u32 *)(lp->sdma_regs + (reg << 2)));
-}
-
-/**
- * temac_dma_out32 - Memory mapped DMA read, this function expects a
- * register input that is based on DCR word addresses which
- * are then converted to memory mapped byte addresses
- */
-static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
-{
- out_be32((u32 *)(lp->sdma_regs + (reg << 2)), value);
-}
-
-/* DMA register access functions can be DCR based or memory mapped.
- * The PowerPC 440 is DCR based, the PowerPC 405 and MicroBlaze are both
- * memory mapped.
- */
-#ifdef CONFIG_PPC_DCR
-
-/**
- * temac_dma_dcr_in32 - DCR based DMA read
- */
-static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
-{
- return dcr_read(lp->sdma_dcrs, reg);
-}
-
-/**
- * temac_dma_dcr_out32 - DCR based DMA write
- */
-static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
-{
- dcr_write(lp->sdma_dcrs, reg, value);
-}
-
-/**
- * temac_dcr_setup - If the DMA is DCR based, then setup the address and
- * I/O functions
- */
-static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op,
- struct device_node *np)
-{
- unsigned int dcrs;
-
- /* setup the dcr address mapping if it's in the device tree */
-
- dcrs = dcr_resource_start(np, 0);
- if (dcrs != 0) {
- lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
- lp->dma_in = temac_dma_dcr_in;
- lp->dma_out = temac_dma_dcr_out;
- dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
- return 0;
- }
- /* no DCR in the device tree, indicate a failure */
- return -1;
-}
-
-#else
-
-/*
- * temac_dcr_setup - This is a stub for when DCR is not supported,
- * such as with MicroBlaze
- */
-static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op,
- struct device_node *np)
-{
- return -1;
-}
-
-#endif
-
-/**
- * * temac_dma_bd_release - Release buffer descriptor rings
- */
-static void temac_dma_bd_release(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- int i;
-
- /* Reset Local Link (DMA) */
- lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
-
- for (i = 0; i < RX_BD_NUM; i++) {
- if (!lp->rx_skb[i])
- break;
- else {
- dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
- XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
- dev_kfree_skb(lp->rx_skb[i]);
- }
- }
- if (lp->rx_bd_v)
- dma_free_coherent(ndev->dev.parent,
- sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- lp->rx_bd_v, lp->rx_bd_p);
- if (lp->tx_bd_v)
- dma_free_coherent(ndev->dev.parent,
- sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- lp->tx_bd_v, lp->tx_bd_p);
- if (lp->rx_skb)
- kfree(lp->rx_skb);
-}
-
-/**
- * temac_dma_bd_init - Setup buffer descriptor rings
- */
-static int temac_dma_bd_init(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- struct sk_buff *skb;
- int i;
-
- lp->rx_skb = kcalloc(RX_BD_NUM, sizeof(*lp->rx_skb), GFP_KERNEL);
- if (!lp->rx_skb) {
- dev_err(&ndev->dev,
- "can't allocate memory for DMA RX buffer\n");
- goto out;
- }
- /* allocate the tx and rx ring buffer descriptors. */
- /* returns a virtual address and a physical address. */
- lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
- sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- &lp->tx_bd_p, GFP_KERNEL);
- if (!lp->tx_bd_v) {
- dev_err(&ndev->dev,
- "unable to allocate DMA TX buffer descriptors");
- goto out;
- }
- lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
- sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- &lp->rx_bd_p, GFP_KERNEL);
- if (!lp->rx_bd_v) {
- dev_err(&ndev->dev,
- "unable to allocate DMA RX buffer descriptors");
- goto out;
- }
-
- memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
- for (i = 0; i < TX_BD_NUM; i++) {
- lp->tx_bd_v[i].next = lp->tx_bd_p +
- sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM);
- }
-
- memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
- for (i = 0; i < RX_BD_NUM; i++) {
- lp->rx_bd_v[i].next = lp->rx_bd_p +
- sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
-
- skb = netdev_alloc_skb_ip_align(ndev,
- XTE_MAX_JUMBO_FRAME_SIZE);
-
- if (skb == 0) {
- dev_err(&ndev->dev, "alloc_skb error %d\n", i);
- goto out;
- }
- lp->rx_skb[i] = skb;
- /* returns physical address of skb->data */
- lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
- skb->data,
- XTE_MAX_JUMBO_FRAME_SIZE,
- DMA_FROM_DEVICE);
- lp->rx_bd_v[i].len = XTE_MAX_JUMBO_FRAME_SIZE;
- lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
- }
-
- lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
- CHNL_CTRL_IRQ_EN |
- CHNL_CTRL_IRQ_DLY_EN |
- CHNL_CTRL_IRQ_COAL_EN);
- /* 0x10220483 */
- /* 0x00100483 */
- lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 |
- CHNL_CTRL_IRQ_EN |
- CHNL_CTRL_IRQ_DLY_EN |
- CHNL_CTRL_IRQ_COAL_EN |
- CHNL_CTRL_IRQ_IOE);
- /* 0xff010283 */
-
- lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p);
- lp->dma_out(lp, RX_TAILDESC_PTR,
- lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
- lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
-
- return 0;
-
-out:
- temac_dma_bd_release(ndev);
- return -ENOMEM;
-}
-
-/* ---------------------------------------------------------------------
- * net_device_ops
- */
-
-static int temac_set_mac_address(struct net_device *ndev, void *address)
-{
- struct temac_local *lp = netdev_priv(ndev);
-
- if (address)
- memcpy(ndev->dev_addr, address, ETH_ALEN);
-
- if (!is_valid_ether_addr(ndev->dev_addr))
- eth_hw_addr_random(ndev);
- else
- ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
-
- /* set up unicast MAC address filter set its mac address */
- mutex_lock(&lp->indirect_mutex);
- temac_indirect_out32(lp, XTE_UAW0_OFFSET,
- (ndev->dev_addr[0]) |
- (ndev->dev_addr[1] << 8) |
- (ndev->dev_addr[2] << 16) |
- (ndev->dev_addr[3] << 24));
- /* There are reserved bits in EUAW1
- * so don't affect them Set MAC bits [47:32] in EUAW1 */
- temac_indirect_out32(lp, XTE_UAW1_OFFSET,
- (ndev->dev_addr[4] & 0x000000ff) |
- (ndev->dev_addr[5] << 8));
- mutex_unlock(&lp->indirect_mutex);
-
- return 0;
-}
-
-static int netdev_set_mac_address(struct net_device *ndev, void *p)
-{
- struct sockaddr *addr = p;
-
- return temac_set_mac_address(ndev, addr->sa_data);
-}
-
-static void temac_set_multicast_list(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- u32 multi_addr_msw, multi_addr_lsw, val;
- int i;
-
- mutex_lock(&lp->indirect_mutex);
- if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
- netdev_mc_count(ndev) > MULTICAST_CAM_TABLE_NUM) {
- /*
- * We must make the kernel realise we had to move
- * into promisc mode or we start all out war on
- * the cable. If it was a promisc request the
- * flag is already set. If not we assert it.
- */
- ndev->flags |= IFF_PROMISC;
- temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK);
- dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
- } else if (!netdev_mc_empty(ndev)) {
- struct netdev_hw_addr *ha;
-
- i = 0;
- netdev_for_each_mc_addr(ha, ndev) {
- if (i >= MULTICAST_CAM_TABLE_NUM)
- break;
- multi_addr_msw = ((ha->addr[3] << 24) |
- (ha->addr[2] << 16) |
- (ha->addr[1] << 8) |
- (ha->addr[0]));
- temac_indirect_out32(lp, XTE_MAW0_OFFSET,
- multi_addr_msw);
- multi_addr_lsw = ((ha->addr[5] << 8) |
- (ha->addr[4]) | (i << 16));
- temac_indirect_out32(lp, XTE_MAW1_OFFSET,
- multi_addr_lsw);
- i++;
- }
- } else {
- val = temac_indirect_in32(lp, XTE_AFM_OFFSET);
- temac_indirect_out32(lp, XTE_AFM_OFFSET,
- val & ~XTE_AFM_EPPRM_MASK);
- temac_indirect_out32(lp, XTE_MAW0_OFFSET, 0);
- temac_indirect_out32(lp, XTE_MAW1_OFFSET, 0);
- dev_info(&ndev->dev, "Promiscuous mode disabled.\n");
- }
- mutex_unlock(&lp->indirect_mutex);
-}
-
-struct temac_option {
- int flg;
- u32 opt;
- u32 reg;
- u32 m_or;
- u32 m_and;
-} temac_options[] = {
- /* Turn on jumbo packet support for both Rx and Tx */
- {
- .opt = XTE_OPTION_JUMBO,
- .reg = XTE_TXC_OFFSET,
- .m_or = XTE_TXC_TXJMBO_MASK,
- },
- {
- .opt = XTE_OPTION_JUMBO,
- .reg = XTE_RXC1_OFFSET,
- .m_or =XTE_RXC1_RXJMBO_MASK,
- },
- /* Turn on VLAN packet support for both Rx and Tx */
- {
- .opt = XTE_OPTION_VLAN,
- .reg = XTE_TXC_OFFSET,
- .m_or =XTE_TXC_TXVLAN_MASK,
- },
- {
- .opt = XTE_OPTION_VLAN,
- .reg = XTE_RXC1_OFFSET,
- .m_or =XTE_RXC1_RXVLAN_MASK,
- },
- /* Turn on FCS stripping on receive packets */
- {
- .opt = XTE_OPTION_FCS_STRIP,
- .reg = XTE_RXC1_OFFSET,
- .m_or =XTE_RXC1_RXFCS_MASK,
- },
- /* Turn on FCS insertion on transmit packets */
- {
- .opt = XTE_OPTION_FCS_INSERT,
- .reg = XTE_TXC_OFFSET,
- .m_or =XTE_TXC_TXFCS_MASK,
- },
- /* Turn on length/type field checking on receive packets */
- {
- .opt = XTE_OPTION_LENTYPE_ERR,
- .reg = XTE_RXC1_OFFSET,
- .m_or =XTE_RXC1_RXLT_MASK,
- },
- /* Turn on flow control */
- {
- .opt = XTE_OPTION_FLOW_CONTROL,
- .reg = XTE_FCC_OFFSET,
- .m_or =XTE_FCC_RXFLO_MASK,
- },
- /* Turn on flow control */
- {
- .opt = XTE_OPTION_FLOW_CONTROL,
- .reg = XTE_FCC_OFFSET,
- .m_or =XTE_FCC_TXFLO_MASK,
- },
- /* Turn on promiscuous frame filtering (all frames are received ) */
- {
- .opt = XTE_OPTION_PROMISC,
- .reg = XTE_AFM_OFFSET,
- .m_or =XTE_AFM_EPPRM_MASK,
- },
- /* Enable transmitter if not already enabled */
- {
- .opt = XTE_OPTION_TXEN,
- .reg = XTE_TXC_OFFSET,
- .m_or =XTE_TXC_TXEN_MASK,
- },
- /* Enable receiver? */
- {
- .opt = XTE_OPTION_RXEN,
- .reg = XTE_RXC1_OFFSET,
- .m_or =XTE_RXC1_RXEN_MASK,
- },
- {}
-};
-
-/**
- * temac_setoptions
- */
-static u32 temac_setoptions(struct net_device *ndev, u32 options)
-{
- struct temac_local *lp = netdev_priv(ndev);
- struct temac_option *tp = &temac_options[0];
- int reg;
-
- mutex_lock(&lp->indirect_mutex);
- while (tp->opt) {
- reg = temac_indirect_in32(lp, tp->reg) & ~tp->m_or;
- if (options & tp->opt)
- reg |= tp->m_or;
- temac_indirect_out32(lp, tp->reg, reg);
- tp++;
- }
- lp->options |= options;
- mutex_unlock(&lp->indirect_mutex);
-
- return 0;
-}
-
-/* Initialize temac */
-static void temac_device_reset(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- u32 timeout;
- u32 val;
-
- /* Perform a software reset */
-
- /* 0x300 host enable bit ? */
- /* reset PHY through control register ?:1 */
-
- dev_dbg(&ndev->dev, "%s()\n", __func__);
-
- mutex_lock(&lp->indirect_mutex);
- /* Reset the receiver and wait for it to finish reset */
- temac_indirect_out32(lp, XTE_RXC1_OFFSET, XTE_RXC1_RXRST_MASK);
- timeout = 1000;
- while (temac_indirect_in32(lp, XTE_RXC1_OFFSET) & XTE_RXC1_RXRST_MASK) {
- udelay(1);
- if (--timeout == 0) {
- dev_err(&ndev->dev,
- "temac_device_reset RX reset timeout!!\n");
- break;
- }
- }
-
- /* Reset the transmitter and wait for it to finish reset */
- temac_indirect_out32(lp, XTE_TXC_OFFSET, XTE_TXC_TXRST_MASK);
- timeout = 1000;
- while (temac_indirect_in32(lp, XTE_TXC_OFFSET) & XTE_TXC_TXRST_MASK) {
- udelay(1);
- if (--timeout == 0) {
- dev_err(&ndev->dev,
- "temac_device_reset TX reset timeout!!\n");
- break;
- }
- }
-
- /* Disable the receiver */
- val = temac_indirect_in32(lp, XTE_RXC1_OFFSET);
- temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
-
- /* Reset Local Link (DMA) */
- lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
- timeout = 1000;
- while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
- udelay(1);
- if (--timeout == 0) {
- dev_err(&ndev->dev,
- "temac_device_reset DMA reset timeout!!\n");
- break;
- }
- }
- lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
-
- if (temac_dma_bd_init(ndev)) {
- dev_err(&ndev->dev,
- "temac_device_reset descriptor allocation failed\n");
- }
-
- temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0);
- temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0);
- temac_indirect_out32(lp, XTE_TXC_OFFSET, 0);
- temac_indirect_out32(lp, XTE_FCC_OFFSET, XTE_FCC_RXFLO_MASK);
-
- mutex_unlock(&lp->indirect_mutex);
-
- /* Sync default options with HW
- * but leave receiver and transmitter disabled. */
- temac_setoptions(ndev,
- lp->options & ~(XTE_OPTION_TXEN | XTE_OPTION_RXEN));
-
- temac_set_mac_address(ndev, NULL);
-
- /* Set address filter table */
- temac_set_multicast_list(ndev);
- if (temac_setoptions(ndev, lp->options))
- dev_err(&ndev->dev, "Error setting TEMAC options\n");
-
- /* Init Driver variable */
- ndev->trans_start = jiffies; /* prevent tx timeout */
-}
-
-void temac_adjust_link(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- struct phy_device *phy = lp->phy_dev;
- u32 mii_speed;
- int link_state;
-
- /* hash together the state values to decide if something has changed */
- link_state = phy->speed | (phy->duplex << 1) | phy->link;
-
- mutex_lock(&lp->indirect_mutex);
- if (lp->last_link != link_state) {
- mii_speed = temac_indirect_in32(lp, XTE_EMCFG_OFFSET);
- mii_speed &= ~XTE_EMCFG_LINKSPD_MASK;
-
- switch (phy->speed) {
- case SPEED_1000: mii_speed |= XTE_EMCFG_LINKSPD_1000; break;
- case SPEED_100: mii_speed |= XTE_EMCFG_LINKSPD_100; break;
- case SPEED_10: mii_speed |= XTE_EMCFG_LINKSPD_10; break;
- }
-
- /* Write new speed setting out to TEMAC */
- temac_indirect_out32(lp, XTE_EMCFG_OFFSET, mii_speed);
- lp->last_link = link_state;
- phy_print_status(phy);
- }
- mutex_unlock(&lp->indirect_mutex);
-}
-
-static void temac_start_xmit_done(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- struct cdmac_bd *cur_p;
- unsigned int stat = 0;
-
- cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
- stat = cur_p->app0;
-
- while (stat & STS_CTRL_APP0_CMPLT) {
- dma_unmap_single(ndev->dev.parent, cur_p->phys, cur_p->len,
- DMA_TO_DEVICE);
- if (cur_p->app4)
- dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
- cur_p->app0 = 0;
- cur_p->app1 = 0;
- cur_p->app2 = 0;
- cur_p->app3 = 0;
- cur_p->app4 = 0;
-
- ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += cur_p->len;
-
- lp->tx_bd_ci++;
- if (lp->tx_bd_ci >= TX_BD_NUM)
- lp->tx_bd_ci = 0;
-
- cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
- stat = cur_p->app0;
- }
-
- netif_wake_queue(ndev);
-}
-
-static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag)
-{
- struct cdmac_bd *cur_p;
- int tail;
-
- tail = lp->tx_bd_tail;
- cur_p = &lp->tx_bd_v[tail];
-
- do {
- if (cur_p->app0)
- return NETDEV_TX_BUSY;
-
- tail++;
- if (tail >= TX_BD_NUM)
- tail = 0;
-
- cur_p = &lp->tx_bd_v[tail];
- num_frag--;
- } while (num_frag >= 0);
-
- return 0;
-}
-
-static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- struct cdmac_bd *cur_p;
- dma_addr_t start_p, tail_p;
- int ii;
- unsigned long num_frag;
- skb_frag_t *frag;
-
- num_frag = skb_shinfo(skb)->nr_frags;
- frag = &skb_shinfo(skb)->frags[0];
- start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
- cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
-
- if (temac_check_tx_bd_space(lp, num_frag)) {
- if (!netif_queue_stopped(ndev)) {
- netif_stop_queue(ndev);
- return NETDEV_TX_BUSY;
- }
- return NETDEV_TX_BUSY;
- }
-
- cur_p->app0 = 0;
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- unsigned int csum_start_off = skb_checksum_start_offset(skb);
- unsigned int csum_index_off = csum_start_off + skb->csum_offset;
-
- cur_p->app0 |= 1; /* TX Checksum Enabled */
- cur_p->app1 = (csum_start_off << 16) | csum_index_off;
- cur_p->app2 = 0; /* initial checksum seed */
- }
-
- cur_p->app0 |= STS_CTRL_APP0_SOP;
- cur_p->len = skb_headlen(skb);
- cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len,
- DMA_TO_DEVICE);
- cur_p->app4 = (unsigned long)skb;
-
- for (ii = 0; ii < num_frag; ii++) {
- lp->tx_bd_tail++;
- if (lp->tx_bd_tail >= TX_BD_NUM)
- lp->tx_bd_tail = 0;
-
- cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
- cur_p->phys = dma_map_single(ndev->dev.parent,
- skb_frag_address(frag),
- skb_frag_size(frag), DMA_TO_DEVICE);
- cur_p->len = skb_frag_size(frag);
- cur_p->app0 = 0;
- frag++;
- }
- cur_p->app0 |= STS_CTRL_APP0_EOP;
-
- tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
- lp->tx_bd_tail++;
- if (lp->tx_bd_tail >= TX_BD_NUM)
- lp->tx_bd_tail = 0;
-
- skb_tx_timestamp(skb);
-
- /* Kick off the transfer */
- lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
-
- return NETDEV_TX_OK;
-}
-
-
-static void ll_temac_recv(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- struct sk_buff *skb, *new_skb;
- unsigned int bdstat;
- struct cdmac_bd *cur_p;
- dma_addr_t tail_p;
- int length;
- unsigned long flags;
-
- spin_lock_irqsave(&lp->rx_lock, flags);
-
- tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
- cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-
- bdstat = cur_p->app0;
- while ((bdstat & STS_CTRL_APP0_CMPLT)) {
-
- skb = lp->rx_skb[lp->rx_bd_ci];
- length = cur_p->app4 & 0x3FFF;
-
- dma_unmap_single(ndev->dev.parent, cur_p->phys, length,
- DMA_FROM_DEVICE);
-
- skb_put(skb, length);
- skb->dev = ndev;
- skb->protocol = eth_type_trans(skb, ndev);
- skb_checksum_none_assert(skb);
-
- /* if we're doing rx csum offload, set it up */
- if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) &&
- (skb->protocol == __constant_htons(ETH_P_IP)) &&
- (skb->len > 64)) {
-
- skb->csum = cur_p->app3 & 0xFFFF;
- skb->ip_summed = CHECKSUM_COMPLETE;
- }
-
- if (!skb_defer_rx_timestamp(skb))
- netif_rx(skb);
-
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += length;
-
- new_skb = netdev_alloc_skb_ip_align(ndev,
- XTE_MAX_JUMBO_FRAME_SIZE);
-
- if (new_skb == 0) {
- dev_err(&ndev->dev, "no memory for new sk_buff\n");
- spin_unlock_irqrestore(&lp->rx_lock, flags);
- return;
- }
-
- cur_p->app0 = STS_CTRL_APP0_IRQONEND;
- cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
- XTE_MAX_JUMBO_FRAME_SIZE,
- DMA_FROM_DEVICE);
- cur_p->len = XTE_MAX_JUMBO_FRAME_SIZE;
- lp->rx_skb[lp->rx_bd_ci] = new_skb;
-
- lp->rx_bd_ci++;
- if (lp->rx_bd_ci >= RX_BD_NUM)
- lp->rx_bd_ci = 0;
-
- cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
- bdstat = cur_p->app0;
- }
- lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
-
- spin_unlock_irqrestore(&lp->rx_lock, flags);
-}
-
-static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
-{
- struct net_device *ndev = _ndev;
- struct temac_local *lp = netdev_priv(ndev);
- unsigned int status;
-
- status = lp->dma_in(lp, TX_IRQ_REG);
- lp->dma_out(lp, TX_IRQ_REG, status);
-
- if (status & (IRQ_COAL | IRQ_DLY))
- temac_start_xmit_done(lp->ndev);
- if (status & 0x080)
- dev_err(&ndev->dev, "DMA error 0x%x\n", status);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
-{
- struct net_device *ndev = _ndev;
- struct temac_local *lp = netdev_priv(ndev);
- unsigned int status;
-
- /* Read and clear the status registers */
- status = lp->dma_in(lp, RX_IRQ_REG);
- lp->dma_out(lp, RX_IRQ_REG, status);
-
- if (status & (IRQ_COAL | IRQ_DLY))
- ll_temac_recv(lp->ndev);
-
- return IRQ_HANDLED;
-}
-
-static int temac_open(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- int rc;
-
- dev_dbg(&ndev->dev, "temac_open()\n");
-
- if (lp->phy_node) {
- lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
- temac_adjust_link, 0, 0);
- if (!lp->phy_dev) {
- dev_err(lp->dev, "of_phy_connect() failed\n");
- return -ENODEV;
- }
-
- phy_start(lp->phy_dev);
- }
-
- temac_device_reset(ndev);
-
- rc = request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->name, ndev);
- if (rc)
- goto err_tx_irq;
- rc = request_irq(lp->rx_irq, ll_temac_rx_irq, 0, ndev->name, ndev);
- if (rc)
- goto err_rx_irq;
-
- return 0;
-
- err_rx_irq:
- free_irq(lp->tx_irq, ndev);
- err_tx_irq:
- if (lp->phy_dev)
- phy_disconnect(lp->phy_dev);
- lp->phy_dev = NULL;
- dev_err(lp->dev, "request_irq() failed\n");
- return rc;
-}
-
-static int temac_stop(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
-
- dev_dbg(&ndev->dev, "temac_close()\n");
-
- free_irq(lp->tx_irq, ndev);
- free_irq(lp->rx_irq, ndev);
-
- if (lp->phy_dev)
- phy_disconnect(lp->phy_dev);
- lp->phy_dev = NULL;
-
- temac_dma_bd_release(ndev);
-
- return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void
-temac_poll_controller(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
-
- disable_irq(lp->tx_irq);
- disable_irq(lp->rx_irq);
-
- ll_temac_rx_irq(lp->tx_irq, ndev);
- ll_temac_tx_irq(lp->rx_irq, ndev);
-
- enable_irq(lp->tx_irq);
- enable_irq(lp->rx_irq);
-}
-#endif
-
-static int temac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
-{
- struct temac_local *lp = netdev_priv(ndev);
-
- if (!netif_running(ndev))
- return -EINVAL;
-
- if (!lp->phy_dev)
- return -EINVAL;
-
- return phy_mii_ioctl(lp->phy_dev, rq, cmd);
-}
-
-static const struct net_device_ops temac_netdev_ops = {
- .ndo_open = temac_open,
- .ndo_stop = temac_stop,
- .ndo_start_xmit = temac_start_xmit,
- .ndo_set_mac_address = netdev_set_mac_address,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_do_ioctl = temac_ioctl,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = temac_poll_controller,
-#endif
-};
-
-/* ---------------------------------------------------------------------
- * SYSFS device attributes
- */
-static ssize_t temac_show_llink_regs(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct net_device *ndev = dev_get_drvdata(dev);
- struct temac_local *lp = netdev_priv(ndev);
- int i, len = 0;
-
- for (i = 0; i < 0x11; i++)
- len += sprintf(buf + len, "%.8x%s", lp->dma_in(lp, i),
- (i % 8) == 7 ? "\n" : " ");
- len += sprintf(buf + len, "\n");
-
- return len;
-}
-
-static DEVICE_ATTR(llink_regs, 0440, temac_show_llink_regs, NULL);
-
-static struct attribute *temac_device_attrs[] = {
- &dev_attr_llink_regs.attr,
- NULL,
-};
-
-static const struct attribute_group temac_attr_group = {
- .attrs = temac_device_attrs,
-};
-
-/* ethtool support */
-static int temac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
- struct temac_local *lp = netdev_priv(ndev);
- return phy_ethtool_gset(lp->phy_dev, cmd);
-}
-
-static int temac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
- struct temac_local *lp = netdev_priv(ndev);
- return phy_ethtool_sset(lp->phy_dev, cmd);
-}
-
-static int temac_nway_reset(struct net_device *ndev)
-{
- struct temac_local *lp = netdev_priv(ndev);
- return phy_start_aneg(lp->phy_dev);
-}
-
-static const struct ethtool_ops temac_ethtool_ops = {
- .get_settings = temac_get_settings,
- .set_settings = temac_set_settings,
- .nway_reset = temac_nway_reset,
- .get_link = ethtool_op_get_link,
-};
-
-static int __devinit temac_of_probe(struct platform_device *op)
-{
- struct device_node *np;
- struct temac_local *lp;
- struct net_device *ndev;
- const void *addr;
- __be32 *p;
- int size, rc = 0;
-
- /* Init network device structure */
- ndev = alloc_etherdev(sizeof(*lp));
- if (!ndev)
- return -ENOMEM;
-
- ether_setup(ndev);
- dev_set_drvdata(&op->dev, ndev);
- SET_NETDEV_DEV(ndev, &op->dev);
- ndev->flags &= ~IFF_MULTICAST; /* clear multicast */
- ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
- ndev->netdev_ops = &temac_netdev_ops;
- ndev->ethtool_ops = &temac_ethtool_ops;
-#if 0
- ndev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4. */
- ndev->features |= NETIF_F_HW_CSUM; /* Can checksum all the packets. */
- ndev->features |= NETIF_F_IPV6_CSUM; /* Can checksum IPV6 TCP/UDP */
- ndev->features |= NETIF_F_HIGHDMA; /* Can DMA to high memory. */
- ndev->features |= NETIF_F_HW_VLAN_TX; /* Transmit VLAN hw accel */
- ndev->features |= NETIF_F_HW_VLAN_RX; /* Receive VLAN hw acceleration */
- ndev->features |= NETIF_F_HW_VLAN_FILTER; /* Receive VLAN filtering */
- ndev->features |= NETIF_F_VLAN_CHALLENGED; /* cannot handle VLAN pkts */
- ndev->features |= NETIF_F_GSO; /* Enable software GSO. */
- ndev->features |= NETIF_F_MULTI_QUEUE; /* Has multiple TX/RX queues */
- ndev->features |= NETIF_F_LRO; /* large receive offload */
-#endif
-
- /* setup temac private info structure */
- lp = netdev_priv(ndev);
- lp->ndev = ndev;
- lp->dev = &op->dev;
- lp->options = XTE_OPTION_DEFAULTS;
- spin_lock_init(&lp->rx_lock);
- mutex_init(&lp->indirect_mutex);
-
- /* map device registers */
- lp->regs = of_iomap(op->dev.of_node, 0);
- if (!lp->regs) {
- dev_err(&op->dev, "could not map temac regs.\n");
- goto nodev;
- }
-
- /* Setup checksum offload, but default to off if not specified */
- lp->temac_features = 0;
- p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
- if (p && be32_to_cpu(*p)) {
- lp->temac_features |= TEMAC_FEATURE_TX_CSUM;
- /* Can checksum TCP/UDP over IPv4. */
- ndev->features |= NETIF_F_IP_CSUM;
- }
- p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
- if (p && be32_to_cpu(*p))
- lp->temac_features |= TEMAC_FEATURE_RX_CSUM;
-
- /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
- np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);
- if (!np) {
- dev_err(&op->dev, "could not find DMA node\n");
- goto err_iounmap;
- }
-
- /* Setup the DMA register accesses, could be DCR or memory mapped */
- if (temac_dcr_setup(lp, op, np)) {
-
- /* no DCR in the device tree, try non-DCR */
- lp->sdma_regs = of_iomap(np, 0);
- if (lp->sdma_regs) {
- lp->dma_in = temac_dma_in32;
- lp->dma_out = temac_dma_out32;
- dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
- } else {
- dev_err(&op->dev, "unable to map DMA registers\n");
- of_node_put(np);
- goto err_iounmap;
- }
- }
-
- lp->rx_irq = irq_of_parse_and_map(np, 0);
- lp->tx_irq = irq_of_parse_and_map(np, 1);
-
- of_node_put(np); /* Finished with the DMA node; drop the reference */
-
- if (!lp->rx_irq || !lp->tx_irq) {
- dev_err(&op->dev, "could not determine irqs\n");
- rc = -ENOMEM;
- goto err_iounmap_2;
- }
-
-
- /* Retrieve the MAC address */
- addr = of_get_property(op->dev.of_node, "local-mac-address", &size);
- if ((!addr) || (size != 6)) {
- dev_err(&op->dev, "could not find MAC address\n");
- rc = -ENODEV;
- goto err_iounmap_2;
- }
- temac_set_mac_address(ndev, (void *)addr);
-
- rc = temac_mdio_setup(lp, op->dev.of_node);
- if (rc)
- dev_warn(&op->dev, "error registering MDIO bus\n");
-
- lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0);
- if (lp->phy_node)
- dev_dbg(lp->dev, "using PHY node %s (%p)\n", np->full_name, np);
-
- /* Add the device attributes */
- rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group);
- if (rc) {
- dev_err(lp->dev, "Error creating sysfs files\n");
- goto err_iounmap_2;
- }
-
- rc = register_netdev(lp->ndev);
- if (rc) {
- dev_err(lp->dev, "register_netdev() error (%i)\n", rc);
- goto err_register_ndev;
- }
-
- return 0;
-
- err_register_ndev:
- sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
- err_iounmap_2:
- if (lp->sdma_regs)
- iounmap(lp->sdma_regs);
- err_iounmap:
- iounmap(lp->regs);
- nodev:
- free_netdev(ndev);
- ndev = NULL;
- return rc;
-}
-
-static int __devexit temac_of_remove(struct platform_device *op)
-{
- struct net_device *ndev = dev_get_drvdata(&op->dev);
- struct temac_local *lp = netdev_priv(ndev);
-
- temac_mdio_teardown(lp);
- unregister_netdev(ndev);
- sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
- if (lp->phy_node)
- of_node_put(lp->phy_node);
- lp->phy_node = NULL;
- dev_set_drvdata(&op->dev, NULL);
- iounmap(lp->regs);
- if (lp->sdma_regs)
- iounmap(lp->sdma_regs);
- free_netdev(ndev);
- return 0;
-}
-
-static struct of_device_id temac_of_match[] __devinitdata = {
- { .compatible = "xlnx,xps-ll-temac-1.01.b", },
- { .compatible = "xlnx,xps-ll-temac-2.00.a", },
- { .compatible = "xlnx,xps-ll-temac-2.02.a", },
- { .compatible = "xlnx,xps-ll-temac-2.03.a", },
- {},
-};
-MODULE_DEVICE_TABLE(of, temac_of_match);
-
-static struct platform_driver temac_of_driver = {
- .probe = temac_of_probe,
- .remove = __devexit_p(temac_of_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "xilinx_temac",
- .of_match_table = temac_of_match,
- },
-};
-
-module_platform_driver(temac_of_driver);
-
-MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver");
-MODULE_AUTHOR("Yoshio Kashiwagi");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_mdio.c b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_mdio.c
deleted file mode 100644
index 8cf9d4f5..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/ll_temac_mdio.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * MDIO bus driver for the Xilinx TEMAC device
- *
- * Copyright (c) 2009 Secret Lab Technologies, Ltd.
- */
-
-#include <linux/io.h>
-#include <linux/netdevice.h>
-#include <linux/mutex.h>
-#include <linux/phy.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/of_mdio.h>
-
-#include "ll_temac.h"
-
-/* ---------------------------------------------------------------------
- * MDIO Bus functions
- */
-static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
-{
- struct temac_local *lp = bus->priv;
- u32 rc;
-
- /* Write the PHY address to the MIIM Access Initiator register.
- * When the transfer completes, the PHY register value will appear
- * in the LSW0 register */
- mutex_lock(&lp->indirect_mutex);
- temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg);
- rc = temac_indirect_in32(lp, XTE_MIIMAI_OFFSET);
- mutex_unlock(&lp->indirect_mutex);
-
- dev_dbg(lp->dev, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
- phy_id, reg, rc);
-
- return rc;
-}
-
-static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
-{
- struct temac_local *lp = bus->priv;
-
- dev_dbg(lp->dev, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
- phy_id, reg, val);
-
- /* First write the desired value into the write data register
- * and then write the address into the access initiator register
- */
- mutex_lock(&lp->indirect_mutex);
- temac_indirect_out32(lp, XTE_MGTDR_OFFSET, val);
- temac_indirect_out32(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) | reg);
- mutex_unlock(&lp->indirect_mutex);
-
- return 0;
-}
-
-int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
-{
- struct mii_bus *bus;
- const u32 *bus_hz;
- int clk_div;
- int rc, size;
- struct resource res;
-
- /* Calculate a reasonable divisor for the clock rate */
- clk_div = 0x3f; /* worst-case default setting */
- bus_hz = of_get_property(np, "clock-frequency", &size);
- if (bus_hz && size >= sizeof(*bus_hz)) {
- clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1;
- if (clk_div < 1)
- clk_div = 1;
- if (clk_div > 0x3f)
- clk_div = 0x3f;
- }
-
- /* Enable the MDIO bus by asserting the enable bit and writing
- * in the clock config */
- mutex_lock(&lp->indirect_mutex);
- temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
- mutex_unlock(&lp->indirect_mutex);
-
- bus = mdiobus_alloc();
- if (!bus)
- return -ENOMEM;
-
- of_address_to_resource(np, 0, &res);
- snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
- (unsigned long long)res.start);
- bus->priv = lp;
- bus->name = "Xilinx TEMAC MDIO";
- bus->read = temac_mdio_read;
- bus->write = temac_mdio_write;
- bus->parent = lp->dev;
- bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
-
- lp->mii_bus = bus;
-
- rc = of_mdiobus_register(bus, np);
- if (rc)
- goto err_register;
-
- mutex_lock(&lp->indirect_mutex);
- dev_dbg(lp->dev, "MDIO bus registered; MC:%x\n",
- temac_indirect_in32(lp, XTE_MC_OFFSET));
- mutex_unlock(&lp->indirect_mutex);
- return 0;
-
- err_register:
- mdiobus_free(bus);
- return rc;
-}
-
-void temac_mdio_teardown(struct temac_local *lp)
-{
- mdiobus_unregister(lp->mii_bus);
- kfree(lp->mii_bus->irq);
- mdiobus_free(lp->mii_bus);
- lp->mii_bus = NULL;
-}
-
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet.h b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet.h
deleted file mode 100644
index 44b8d2ba..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Definitions for Xilinx Axi Ethernet device driver.
- *
- * Copyright (c) 2009 Secret Lab Technologies, Ltd.
- * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
- */
-
-#ifndef XILINX_AXIENET_H
-#define XILINX_AXIENET_H
-
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-
-/* Packet size info */
-#define XAE_HDR_SIZE 14 /* Size of Ethernet header */
-#define XAE_HDR_VLAN_SIZE 18 /* Size of an Ethernet hdr + VLAN */
-#define XAE_TRL_SIZE 4 /* Size of Ethernet trailer (FCS) */
-#define XAE_MTU 1500 /* Max MTU of an Ethernet frame */
-#define XAE_JUMBO_MTU 9000 /* Max MTU of a jumbo Eth. frame */
-
-#define XAE_MAX_FRAME_SIZE (XAE_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE)
-#define XAE_MAX_VLAN_FRAME_SIZE (XAE_MTU + XAE_HDR_VLAN_SIZE + XAE_TRL_SIZE)
-#define XAE_MAX_JUMBO_FRAME_SIZE (XAE_JUMBO_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE)
-
-/* Configuration options */
-
-/* Accept all incoming packets. Default: disabled (cleared) */
-#define XAE_OPTION_PROMISC (1 << 0)
-
-/* Jumbo frame support for Tx & Rx. Default: disabled (cleared) */
-#define XAE_OPTION_JUMBO (1 << 1)
-
-/* VLAN Rx & Tx frame support. Default: disabled (cleared) */
-#define XAE_OPTION_VLAN (1 << 2)
-
-/* Enable recognition of flow control frames on Rx. Default: enabled (set) */
-#define XAE_OPTION_FLOW_CONTROL (1 << 4)
-
-/* Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not
- * stripped. Default: disabled (set) */
-#define XAE_OPTION_FCS_STRIP (1 << 5)
-
-/* Generate FCS field and add PAD automatically for outgoing frames.
- * Default: enabled (set) */
-#define XAE_OPTION_FCS_INSERT (1 << 6)
-
-/* Enable Length/Type error checking for incoming frames. When this option is
- * set, the MAC will filter frames that have a mismatched type/length field
- * and if XAE_OPTION_REPORT_RXERR is set, the user is notified when these
- * types of frames are encountered. When this option is cleared, the MAC will
- * allow these types of frames to be received. Default: enabled (set) */
-#define XAE_OPTION_LENTYPE_ERR (1 << 7)
-
-/* Enable the transmitter. Default: enabled (set) */
-#define XAE_OPTION_TXEN (1 << 11)
-
-/* Enable the receiver. Default: enabled (set) */
-#define XAE_OPTION_RXEN (1 << 12)
-
-/* Default options set when device is initialized or reset */
-#define XAE_OPTION_DEFAULTS \
- (XAE_OPTION_TXEN | \
- XAE_OPTION_FLOW_CONTROL | \
- XAE_OPTION_RXEN)
-
-/* Axi DMA Register definitions */
-
-#define XAXIDMA_TX_CR_OFFSET 0x00000000 /* Channel control */
-#define XAXIDMA_TX_SR_OFFSET 0x00000004 /* Status */
-#define XAXIDMA_TX_CDESC_OFFSET 0x00000008 /* Current descriptor pointer */
-#define XAXIDMA_TX_TDESC_OFFSET 0x00000010 /* Tail descriptor pointer */
-
-#define XAXIDMA_RX_CR_OFFSET 0x00000030 /* Channel control */
-#define XAXIDMA_RX_SR_OFFSET 0x00000034 /* Status */
-#define XAXIDMA_RX_CDESC_OFFSET 0x00000038 /* Current descriptor pointer */
-#define XAXIDMA_RX_TDESC_OFFSET 0x00000040 /* Tail descriptor pointer */
-
-#define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /* Start/stop DMA channel */
-#define XAXIDMA_CR_RESET_MASK 0x00000004 /* Reset DMA engine */
-
-#define XAXIDMA_BD_NDESC_OFFSET 0x00 /* Next descriptor pointer */
-#define XAXIDMA_BD_BUFA_OFFSET 0x08 /* Buffer address */
-#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /* Control/buffer length */
-#define XAXIDMA_BD_STS_OFFSET 0x1C /* Status */
-#define XAXIDMA_BD_USR0_OFFSET 0x20 /* User IP specific word0 */
-#define XAXIDMA_BD_USR1_OFFSET 0x24 /* User IP specific word1 */
-#define XAXIDMA_BD_USR2_OFFSET 0x28 /* User IP specific word2 */
-#define XAXIDMA_BD_USR3_OFFSET 0x2C /* User IP specific word3 */
-#define XAXIDMA_BD_USR4_OFFSET 0x30 /* User IP specific word4 */
-#define XAXIDMA_BD_ID_OFFSET 0x34 /* Sw ID */
-#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET 0x38 /* Whether has stscntrl strm */
-#define XAXIDMA_BD_HAS_DRE_OFFSET 0x3C /* Whether has DRE */
-
-#define XAXIDMA_BD_HAS_DRE_SHIFT 8 /* Whether has DRE shift */
-#define XAXIDMA_BD_HAS_DRE_MASK 0xF00 /* Whether has DRE mask */
-#define XAXIDMA_BD_WORDLEN_MASK 0xFF /* Whether has DRE mask */
-
-#define XAXIDMA_BD_CTRL_LENGTH_MASK 0x007FFFFF /* Requested len */
-#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */
-#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */
-#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /* All control bits */
-
-#define XAXIDMA_DELAY_MASK 0xFF000000 /* Delay timeout counter */
-#define XAXIDMA_COALESCE_MASK 0x00FF0000 /* Coalesce counter */
-
-#define XAXIDMA_DELAY_SHIFT 24
-#define XAXIDMA_COALESCE_SHIFT 16
-
-#define XAXIDMA_IRQ_IOC_MASK 0x00001000 /* Completion intr */
-#define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /* Delay interrupt */
-#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */
-#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */
-
-/* Default TX/RX Threshold and waitbound values for SGDMA mode */
-#define XAXIDMA_DFT_TX_THRESHOLD 24
-#define XAXIDMA_DFT_TX_WAITBOUND 254
-#define XAXIDMA_DFT_RX_THRESHOLD 24
-#define XAXIDMA_DFT_RX_WAITBOUND 254
-
-#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */
-#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */
-#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /* All control bits */
-
-#define XAXIDMA_BD_STS_ACTUAL_LEN_MASK 0x007FFFFF /* Actual len */
-#define XAXIDMA_BD_STS_COMPLETE_MASK 0x80000000 /* Completed */
-#define XAXIDMA_BD_STS_DEC_ERR_MASK 0x40000000 /* Decode error */
-#define XAXIDMA_BD_STS_SLV_ERR_MASK 0x20000000 /* Slave error */
-#define XAXIDMA_BD_STS_INT_ERR_MASK 0x10000000 /* Internal err */
-#define XAXIDMA_BD_STS_ALL_ERR_MASK 0x70000000 /* All errors */
-#define XAXIDMA_BD_STS_RXSOF_MASK 0x08000000 /* First rx pkt */
-#define XAXIDMA_BD_STS_RXEOF_MASK 0x04000000 /* Last rx pkt */
-#define XAXIDMA_BD_STS_ALL_MASK 0xFC000000 /* All status bits */
-
-#define XAXIDMA_BD_MINIMUM_ALIGNMENT 0x40
-
-/* Axi Ethernet registers definition */
-#define XAE_RAF_OFFSET 0x00000000 /* Reset and Address filter */
-#define XAE_TPF_OFFSET 0x00000004 /* Tx Pause Frame */
-#define XAE_IFGP_OFFSET 0x00000008 /* Tx Inter-frame gap adjustment*/
-#define XAE_IS_OFFSET 0x0000000C /* Interrupt status */
-#define XAE_IP_OFFSET 0x00000010 /* Interrupt pending */
-#define XAE_IE_OFFSET 0x00000014 /* Interrupt enable */
-#define XAE_TTAG_OFFSET 0x00000018 /* Tx VLAN TAG */
-#define XAE_RTAG_OFFSET 0x0000001C /* Rx VLAN TAG */
-#define XAE_UAWL_OFFSET 0x00000020 /* Unicast address word lower */
-#define XAE_UAWU_OFFSET 0x00000024 /* Unicast address word upper */
-#define XAE_TPID0_OFFSET 0x00000028 /* VLAN TPID0 register */
-#define XAE_TPID1_OFFSET 0x0000002C /* VLAN TPID1 register */
-#define XAE_PPST_OFFSET 0x00000030 /* PCS PMA Soft Temac Status Reg */
-#define XAE_RCW0_OFFSET 0x00000400 /* Rx Configuration Word 0 */
-#define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */
-#define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */
-#define XAE_FCC_OFFSET 0x0000040C /* Flow Control Configuration */
-#define XAE_EMMC_OFFSET 0x00000410 /* EMAC mode configuration */
-#define XAE_PHYC_OFFSET 0x00000414 /* RGMII/SGMII configuration */
-#define XAE_MDIO_MC_OFFSET 0x00000500 /* MII Management Config */
-#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MII Management Control */
-#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MII Management Write Data */
-#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MII Management Read Data */
-#define XAE_MDIO_MIS_OFFSET 0x00000600 /* MII Management Interrupt Status */
-#define XAE_MDIO_MIP_OFFSET 0x00000620 /* MII Mgmt Interrupt Pending
- * register offset */
-#define XAE_MDIO_MIE_OFFSET 0x00000640 /* MII Management Interrupt Enable
- * register offset */
-#define XAE_MDIO_MIC_OFFSET 0x00000660 /* MII Management Interrupt Clear
- * register offset. */
-#define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */
-#define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */
-#define XAE_FMI_OFFSET 0x00000708 /* Filter Mask Index */
-#define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */
-#define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */
-
-#define XAE_TX_VLAN_DATA_OFFSET 0x00004000 /* TX VLAN data table address */
-#define XAE_RX_VLAN_DATA_OFFSET 0x00008000 /* RX VLAN data table address */
-#define XAE_MCAST_TABLE_OFFSET 0x00020000 /* Multicast table address */
-
-/* Bit Masks for Axi Ethernet RAF register */
-#define XAE_RAF_MCSTREJ_MASK 0x00000002 /* Reject receive multicast
- * destination address */
-#define XAE_RAF_BCSTREJ_MASK 0x00000004 /* Reject receive broadcast
- * destination address */
-#define XAE_RAF_TXVTAGMODE_MASK 0x00000018 /* Tx VLAN TAG mode */
-#define XAE_RAF_RXVTAGMODE_MASK 0x00000060 /* Rx VLAN TAG mode */
-#define XAE_RAF_TXVSTRPMODE_MASK 0x00000180 /* Tx VLAN STRIP mode */
-#define XAE_RAF_RXVSTRPMODE_MASK 0x00000600 /* Rx VLAN STRIP mode */
-#define XAE_RAF_NEWFNCENBL_MASK 0x00000800 /* New function mode */
-#define XAE_RAF_EMULTIFLTRENBL_MASK 0x00001000 /* Exteneded Multicast
- * Filtering mode
- */
-#define XAE_RAF_STATSRST_MASK 0x00002000 /* Stats. Counter Reset */
-#define XAE_RAF_RXBADFRMEN_MASK 0x00004000 /* Recv Bad Frame Enable */
-#define XAE_RAF_TXVTAGMODE_SHIFT 3 /* Tx Tag mode shift bits */
-#define XAE_RAF_RXVTAGMODE_SHIFT 5 /* Rx Tag mode shift bits */
-#define XAE_RAF_TXVSTRPMODE_SHIFT 7 /* Tx strip mode shift bits*/
-#define XAE_RAF_RXVSTRPMODE_SHIFT 9 /* Rx Strip mode shift bits*/
-
-/* Bit Masks for Axi Ethernet TPF and IFGP registers */
-#define XAE_TPF_TPFV_MASK 0x0000FFFF /* Tx pause frame value */
-#define XAE_IFGP0_IFGP_MASK 0x0000007F /* Transmit inter-frame
- * gap adjustment value */
-
-/* Bit Masks for Axi Ethernet IS, IE and IP registers, Same masks apply
- * for all 3 registers. */
-#define XAE_INT_HARDACSCMPLT_MASK 0x00000001 /* Hard register access
- * complete */
-#define XAE_INT_AUTONEG_MASK 0x00000002 /* Auto negotiation
- * complete */
-#define XAE_INT_RXCMPIT_MASK 0x00000004 /* Rx complete */
-#define XAE_INT_RXRJECT_MASK 0x00000008 /* Rx frame rejected */
-#define XAE_INT_RXFIFOOVR_MASK 0x00000010 /* Rx fifo overrun */
-#define XAE_INT_TXCMPIT_MASK 0x00000020 /* Tx complete */
-#define XAE_INT_RXDCMLOCK_MASK 0x00000040 /* Rx Dcm Lock */
-#define XAE_INT_MGTRDY_MASK 0x00000080 /* MGT clock Lock */
-#define XAE_INT_PHYRSTCMPLT_MASK 0x00000100 /* Phy Reset complete */
-#define XAE_INT_ALL_MASK 0x0000003F /* All the ints */
-
-#define XAE_INT_RECV_ERROR_MASK \
- (XAE_INT_RXRJECT_MASK | XAE_INT_RXFIFOOVR_MASK) /* INT bits that
- * indicate receive
- * errors */
-
-/* Bit masks for Axi Ethernet VLAN TPID Word 0 register */
-#define XAE_TPID_0_MASK 0x0000FFFF /* TPID 0 */
-#define XAE_TPID_1_MASK 0xFFFF0000 /* TPID 1 */
-
-/* Bit masks for Axi Ethernet VLAN TPID Word 1 register */
-#define XAE_TPID_2_MASK 0x0000FFFF /* TPID 0 */
-#define XAE_TPID_3_MASK 0xFFFF0000 /* TPID 1 */
-
-/* Bit masks for Axi Ethernet RCW1 register */
-#define XAE_RCW1_RST_MASK 0x80000000 /* Reset */
-#define XAE_RCW1_JUM_MASK 0x40000000 /* Jumbo frame enable */
-#define XAE_RCW1_FCS_MASK 0x20000000 /* In-Band FCS enable
- * (FCS not stripped) */
-#define XAE_RCW1_RX_MASK 0x10000000 /* Receiver enable */
-#define XAE_RCW1_VLAN_MASK 0x08000000 /* VLAN frame enable */
-#define XAE_RCW1_LT_DIS_MASK 0x02000000 /* Length/type field valid check
- * disable */
-#define XAE_RCW1_CL_DIS_MASK 0x01000000 /* Control frame Length check
- * disable */
-#define XAE_RCW1_PAUSEADDR_MASK 0x0000FFFF /* Pause frame source address
- * bits [47:32]. Bits [31:0] are
- * stored in register RCW0 */
-
-/* Bit masks for Axi Ethernet TC register */
-#define XAE_TC_RST_MASK 0x80000000 /* Reset */
-#define XAE_TC_JUM_MASK 0x40000000 /* Jumbo frame enable */
-#define XAE_TC_FCS_MASK 0x20000000 /* In-Band FCS enable
- * (FCS not generated) */
-#define XAE_TC_TX_MASK 0x10000000 /* Transmitter enable */
-#define XAE_TC_VLAN_MASK 0x08000000 /* VLAN frame enable */
-#define XAE_TC_IFG_MASK 0x02000000 /* Inter-frame gap adjustment
- * enable */
-
-/* Bit masks for Axi Ethernet FCC register */
-#define XAE_FCC_FCRX_MASK 0x20000000 /* Rx flow control enable */
-#define XAE_FCC_FCTX_MASK 0x40000000 /* Tx flow control enable */
-
-/* Bit masks for Axi Ethernet EMMC register */
-#define XAE_EMMC_LINKSPEED_MASK 0xC0000000 /* Link speed */
-#define XAE_EMMC_RGMII_MASK 0x20000000 /* RGMII mode enable */
-#define XAE_EMMC_SGMII_MASK 0x10000000 /* SGMII mode enable */
-#define XAE_EMMC_GPCS_MASK 0x08000000 /* 1000BaseX mode enable */
-#define XAE_EMMC_HOST_MASK 0x04000000 /* Host interface enable */
-#define XAE_EMMC_TX16BIT 0x02000000 /* 16 bit Tx client enable */
-#define XAE_EMMC_RX16BIT 0x01000000 /* 16 bit Rx client enable */
-#define XAE_EMMC_LINKSPD_10 0x00000000 /* Link Speed mask for 10 Mbit */
-#define XAE_EMMC_LINKSPD_100 0x40000000 /* Link Speed mask for 100 Mbit */
-#define XAE_EMMC_LINKSPD_1000 0x80000000 /* Link Speed mask for 1000 Mbit */
-
-/* Bit masks for Axi Ethernet PHYC register */
-#define XAE_PHYC_SGMIILINKSPEED_MASK 0xC0000000 /* SGMII link speed mask*/
-#define XAE_PHYC_RGMIILINKSPEED_MASK 0x0000000C /* RGMII link speed */
-#define XAE_PHYC_RGMIIHD_MASK 0x00000002 /* RGMII Half-duplex */
-#define XAE_PHYC_RGMIILINK_MASK 0x00000001 /* RGMII link status */
-#define XAE_PHYC_RGLINKSPD_10 0x00000000 /* RGMII link 10 Mbit */
-#define XAE_PHYC_RGLINKSPD_100 0x00000004 /* RGMII link 100 Mbit */
-#define XAE_PHYC_RGLINKSPD_1000 0x00000008 /* RGMII link 1000 Mbit */
-#define XAE_PHYC_SGLINKSPD_10 0x00000000 /* SGMII link 10 Mbit */
-#define XAE_PHYC_SGLINKSPD_100 0x40000000 /* SGMII link 100 Mbit */
-#define XAE_PHYC_SGLINKSPD_1000 0x80000000 /* SGMII link 1000 Mbit */
-
-/* Bit masks for Axi Ethernet MDIO interface MC register */
-#define XAE_MDIO_MC_MDIOEN_MASK 0x00000040 /* MII management enable */
-#define XAE_MDIO_MC_CLOCK_DIVIDE_MAX 0x3F /* Maximum MDIO divisor */
-
-/* Bit masks for Axi Ethernet MDIO interface MCR register */
-#define XAE_MDIO_MCR_PHYAD_MASK 0x1F000000 /* Phy Address Mask */
-#define XAE_MDIO_MCR_PHYAD_SHIFT 24 /* Phy Address Shift */
-#define XAE_MDIO_MCR_REGAD_MASK 0x001F0000 /* Reg Address Mask */
-#define XAE_MDIO_MCR_REGAD_SHIFT 16 /* Reg Address Shift */
-#define XAE_MDIO_MCR_OP_MASK 0x0000C000 /* Operation Code Mask */
-#define XAE_MDIO_MCR_OP_SHIFT 13 /* Operation Code Shift */
-#define XAE_MDIO_MCR_OP_READ_MASK 0x00008000 /* Op Code Read Mask */
-#define XAE_MDIO_MCR_OP_WRITE_MASK 0x00004000 /* Op Code Write Mask */
-#define XAE_MDIO_MCR_INITIATE_MASK 0x00000800 /* Ready Mask */
-#define XAE_MDIO_MCR_READY_MASK 0x00000080 /* Ready Mask */
-
-/* Bit masks for Axi Ethernet MDIO interface MIS, MIP, MIE, MIC registers */
-#define XAE_MDIO_INT_MIIM_RDY_MASK 0x00000001 /* MIIM Interrupt */
-
-/* Bit masks for Axi Ethernet UAW1 register */
-#define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF /* Station address bits
- * [47:32]; Station address
- * bits [31:0] are stored in
- * register UAW0 */
-
-/* Bit masks for Axi Ethernet FMI register */
-#define XAE_FMI_PM_MASK 0x80000000 /* Promis. mode enable */
-#define XAE_FMI_IND_MASK 0x00000003 /* Index Mask */
-
-#define XAE_MDIO_DIV_DFT 29 /* Default MDIO clock divisor */
-
-/* Defines for different options for C_PHY_TYPE parameter in Axi Ethernet IP */
-#define XAE_PHY_TYPE_MII 0
-#define XAE_PHY_TYPE_GMII 1
-#define XAE_PHY_TYPE_RGMII_1_3 2
-#define XAE_PHY_TYPE_RGMII_2_0 3
-#define XAE_PHY_TYPE_SGMII 4
-#define XAE_PHY_TYPE_1000BASE_X 5
-
-#define XAE_MULTICAST_CAM_TABLE_NUM 4 /* Total number of entries in the
- * hardware multicast table. */
-
-/* Axi Ethernet Synthesis features */
-#define XAE_FEATURE_PARTIAL_RX_CSUM (1 << 0)
-#define XAE_FEATURE_PARTIAL_TX_CSUM (1 << 1)
-#define XAE_FEATURE_FULL_RX_CSUM (1 << 2)
-#define XAE_FEATURE_FULL_TX_CSUM (1 << 3)
-
-#define XAE_NO_CSUM_OFFLOAD 0
-
-#define XAE_FULL_CSUM_STATUS_MASK 0x00000038
-#define XAE_IP_UDP_CSUM_VALIDATED 0x00000003
-#define XAE_IP_TCP_CSUM_VALIDATED 0x00000002
-
-#define DELAY_OF_ONE_MILLISEC 1000
-
-/**
- * struct axidma_bd - Axi Dma buffer descriptor layout
- * @next: MM2S/S2MM Next Descriptor Pointer
- * @reserved1: Reserved and not used
- * @phys: MM2S/S2MM Buffer Address
- * @reserved2: Reserved and not used
- * @reserved3: Reserved and not used
- * @reserved4: Reserved and not used
- * @cntrl: MM2S/S2MM Control value
- * @status: MM2S/S2MM Status value
- * @app0: MM2S/S2MM User Application Field 0.
- * @app1: MM2S/S2MM User Application Field 1.
- * @app2: MM2S/S2MM User Application Field 2.
- * @app3: MM2S/S2MM User Application Field 3.
- * @app4: MM2S/S2MM User Application Field 4.
- * @sw_id_offset: MM2S/S2MM Sw ID
- * @reserved5: Reserved and not used
- * @reserved6: Reserved and not used
- */
-struct axidma_bd {
- u32 next; /* Physical address of next buffer descriptor */
- u32 reserved1;
- u32 phys;
- u32 reserved2;
- u32 reserved3;
- u32 reserved4;
- u32 cntrl;
- u32 status;
- u32 app0;
- u32 app1; /* TX start << 16 | insert */
- u32 app2; /* TX csum seed */
- u32 app3;
- u32 app4;
- u32 sw_id_offset;
- u32 reserved5;
- u32 reserved6;
-};
-
-/**
- * struct axienet_local - axienet private per device data
- * @ndev: Pointer for net_device to which it will be attached.
- * @dev: Pointer to device structure
- * @phy_dev: Pointer to PHY device structure attached to the axienet_local
- * @phy_node: Pointer to device node structure
- * @mii_bus: Pointer to MII bus structure
- * @mdio_irqs: IRQs table for MDIO bus required in mii_bus structure
- * @regs: Base address for the axienet_local device address space
- * @dma_regs: Base address for the axidma device address space
- * @dma_err_tasklet: Tasklet structure to process Axi DMA errors
- * @tx_irq: Axidma TX IRQ number
- * @rx_irq: Axidma RX IRQ number
- * @temac_type: axienet type to identify between soft and hard temac
- * @phy_type: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X
- * @options: AxiEthernet option word
- * @last_link: Phy link state in which the PHY was negotiated earlier
- * @features: Stores the extended features supported by the axienet hw
- * @tx_bd_v: Virtual address of the TX buffer descriptor ring
- * @tx_bd_p: Physical address(start address) of the TX buffer descr. ring
- * @rx_bd_v: Virtual address of the RX buffer descriptor ring
- * @rx_bd_p: Physical address(start address) of the RX buffer descr. ring
- * @tx_bd_ci: Stores the index of the Tx buffer descriptor in the ring being
- * accessed currently. Used while alloc. BDs before a TX starts
- * @tx_bd_tail: Stores the index of the Tx buffer descriptor in the ring being
- * accessed currently. Used while processing BDs after the TX
- * completed.
- * @rx_bd_ci: Stores the index of the Rx buffer descriptor in the ring being
- * accessed currently.
- * @max_frm_size: Stores the maximum size of the frame that can be that
- * Txed/Rxed in the existing hardware. If jumbo option is
- * supported, the maximum frame size would be 9k. Else it is
- * 1522 bytes (assuming support for basic VLAN)
- * @jumbo_support: Stores hardware configuration for jumbo support. If hardware
- * can handle jumbo packets, this entry will be 1, else 0.
- */
-struct axienet_local {
- struct net_device *ndev;
- struct device *dev;
-
- /* Connection to PHY device */
- struct phy_device *phy_dev; /* Pointer to PHY device */
- struct device_node *phy_node;
-
- /* MDIO bus data */
- struct mii_bus *mii_bus; /* MII bus reference */
- int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */
-
- /* IO registers, dma functions and IRQs */
- void __iomem *regs;
- void __iomem *dma_regs;
-
- struct tasklet_struct dma_err_tasklet;
-
- int tx_irq;
- int rx_irq;
- u32 temac_type;
- u32 phy_type;
-
- u32 options; /* Current options word */
- u32 last_link;
- u32 features;
-
- /* Buffer descriptors */
- struct axidma_bd *tx_bd_v;
- dma_addr_t tx_bd_p;
- struct axidma_bd *rx_bd_v;
- dma_addr_t rx_bd_p;
- u32 tx_bd_ci;
- u32 tx_bd_tail;
- u32 rx_bd_ci;
-
- u32 max_frm_size;
- u32 jumbo_support;
-
- int csum_offload_on_tx_path;
- int csum_offload_on_rx_path;
-
- u32 coalesce_count_rx;
- u32 coalesce_count_tx;
-};
-
-/**
- * struct axiethernet_option - Used to set axi ethernet hardware options
- * @opt: Option to be set.
- * @reg: Register offset to be written for setting the option
- * @m_or: Mask to be ORed for setting the option in the register
- */
-struct axienet_option {
- u32 opt;
- u32 reg;
- u32 m_or;
-};
-
-/**
- * axienet_ior - Memory mapped Axi Ethernet register read
- * @lp: Pointer to axienet local structure
- * @offset: Address offset from the base address of Axi Ethernet core
- *
- * returns: The contents of the Axi Ethernet register
- *
- * This function returns the contents of the corresponding register.
- */
-static inline u32 axienet_ior(struct axienet_local *lp, off_t offset)
-{
- return in_be32(lp->regs + offset);
-}
-
-/**
- * axienet_iow - Memory mapped Axi Ethernet register write
- * @lp: Pointer to axienet local structure
- * @offset: Address offset from the base address of Axi Ethernet core
- * @value: Value to be written into the Axi Ethernet register
- *
- * This function writes the desired value into the corresponding Axi Ethernet
- * register.
- */
-static inline void axienet_iow(struct axienet_local *lp, off_t offset,
- u32 value)
-{
- out_be32((lp->regs + offset), value);
-}
-
-/* Function prototypes visible in xilinx_axienet_mdio.c for other files */
-int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np);
-int axienet_mdio_wait_until_ready(struct axienet_local *lp);
-void axienet_mdio_teardown(struct axienet_local *lp);
-
-#endif /* XILINX_AXI_ENET_H */
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
deleted file mode 100644
index 9c365e19..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ /dev/null
@@ -1,1669 +0,0 @@
-/*
- * Xilinx Axi Ethernet device driver
- *
- * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi
- * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. <dhlii@dlasys.net>
- * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
- * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
- * Copyright (c) 2010 - 2011 PetaLogix
- * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
- *
- * This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6
- * and Spartan6.
- *
- * TODO:
- * - Add Axi Fifo support.
- * - Factor out Axi DMA code into separate driver.
- * - Test and fix basic multicast filtering.
- * - Add support for extended multicast filtering.
- * - Test basic VLAN support.
- * - Add support for extended VLAN support.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/of_mdio.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/phy.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-
-#include "xilinx_axienet.h"
-
-/* Descriptors defines for Tx and Rx DMA - 2^n for the best performance */
-#define TX_BD_NUM 64
-#define RX_BD_NUM 128
-
-/* Must be shorter than length of ethtool_drvinfo.driver field to fit */
-#define DRIVER_NAME "xaxienet"
-#define DRIVER_DESCRIPTION "Xilinx Axi Ethernet driver"
-#define DRIVER_VERSION "1.00a"
-
-#define AXIENET_REGS_N 32
-
-/* Match table for of_platform binding */
-static struct of_device_id axienet_of_match[] __devinitdata = {
- { .compatible = "xlnx,axi-ethernet-1.00.a", },
- { .compatible = "xlnx,axi-ethernet-1.01.a", },
- { .compatible = "xlnx,axi-ethernet-2.01.a", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, axienet_of_match);
-
-/* Option table for setting up Axi Ethernet hardware options */
-static struct axienet_option axienet_options[] = {
- /* Turn on jumbo packet support for both Rx and Tx */
- {
- .opt = XAE_OPTION_JUMBO,
- .reg = XAE_TC_OFFSET,
- .m_or = XAE_TC_JUM_MASK,
- }, {
- .opt = XAE_OPTION_JUMBO,
- .reg = XAE_RCW1_OFFSET,
- .m_or = XAE_RCW1_JUM_MASK,
- }, { /* Turn on VLAN packet support for both Rx and Tx */
- .opt = XAE_OPTION_VLAN,
- .reg = XAE_TC_OFFSET,
- .m_or = XAE_TC_VLAN_MASK,
- }, {
- .opt = XAE_OPTION_VLAN,
- .reg = XAE_RCW1_OFFSET,
- .m_or = XAE_RCW1_VLAN_MASK,
- }, { /* Turn on FCS stripping on receive packets */
- .opt = XAE_OPTION_FCS_STRIP,
- .reg = XAE_RCW1_OFFSET,
- .m_or = XAE_RCW1_FCS_MASK,
- }, { /* Turn on FCS insertion on transmit packets */
- .opt = XAE_OPTION_FCS_INSERT,
- .reg = XAE_TC_OFFSET,
- .m_or = XAE_TC_FCS_MASK,
- }, { /* Turn off length/type field checking on receive packets */
- .opt = XAE_OPTION_LENTYPE_ERR,
- .reg = XAE_RCW1_OFFSET,
- .m_or = XAE_RCW1_LT_DIS_MASK,
- }, { /* Turn on Rx flow control */
- .opt = XAE_OPTION_FLOW_CONTROL,
- .reg = XAE_FCC_OFFSET,
- .m_or = XAE_FCC_FCRX_MASK,
- }, { /* Turn on Tx flow control */
- .opt = XAE_OPTION_FLOW_CONTROL,
- .reg = XAE_FCC_OFFSET,
- .m_or = XAE_FCC_FCTX_MASK,
- }, { /* Turn on promiscuous frame filtering */
- .opt = XAE_OPTION_PROMISC,
- .reg = XAE_FMI_OFFSET,
- .m_or = XAE_FMI_PM_MASK,
- }, { /* Enable transmitter */
- .opt = XAE_OPTION_TXEN,
- .reg = XAE_TC_OFFSET,
- .m_or = XAE_TC_TX_MASK,
- }, { /* Enable receiver */
- .opt = XAE_OPTION_RXEN,
- .reg = XAE_RCW1_OFFSET,
- .m_or = XAE_RCW1_RX_MASK,
- },
- {}
-};
-
-/**
- * axienet_dma_in32 - Memory mapped Axi DMA register read
- * @lp: Pointer to axienet local structure
- * @reg: Address offset from the base address of the Axi DMA core
- *
- * returns: The contents of the Axi DMA register
- *
- * This function returns the contents of the corresponding Axi DMA register.
- */
-static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg)
-{
- return in_be32(lp->dma_regs + reg);
-}
-
-/**
- * axienet_dma_out32 - Memory mapped Axi DMA register write.
- * @lp: Pointer to axienet local structure
- * @reg: Address offset from the base address of the Axi DMA core
- * @value: Value to be written into the Axi DMA register
- *
- * This function writes the desired value into the corresponding Axi DMA
- * register.
- */
-static inline void axienet_dma_out32(struct axienet_local *lp,
- off_t reg, u32 value)
-{
- out_be32((lp->dma_regs + reg), value);
-}
-
-/**
- * axienet_dma_bd_release - Release buffer descriptor rings
- * @ndev: Pointer to the net_device structure
- *
- * This function is used to release the descriptors allocated in
- * axienet_dma_bd_init. axienet_dma_bd_release is called when Axi Ethernet
- * driver stop api is called.
- */
-static void axienet_dma_bd_release(struct net_device *ndev)
-{
- int i;
- struct axienet_local *lp = netdev_priv(ndev);
-
- for (i = 0; i < RX_BD_NUM; i++) {
- dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
- lp->max_frm_size, DMA_FROM_DEVICE);
- dev_kfree_skb((struct sk_buff *)
- (lp->rx_bd_v[i].sw_id_offset));
- }
-
- if (lp->rx_bd_v) {
- dma_free_coherent(ndev->dev.parent,
- sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- lp->rx_bd_v,
- lp->rx_bd_p);
- }
- if (lp->tx_bd_v) {
- dma_free_coherent(ndev->dev.parent,
- sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- lp->tx_bd_v,
- lp->tx_bd_p);
- }
-}
-
-/**
- * axienet_dma_bd_init - Setup buffer descriptor rings for Axi DMA
- * @ndev: Pointer to the net_device structure
- *
- * returns: 0, on success
- * -ENOMEM, on failure
- *
- * This function is called to initialize the Rx and Tx DMA descriptor
- * rings. This initializes the descriptors with required default values
- * and is called when Axi Ethernet driver reset is called.
- */
-static int axienet_dma_bd_init(struct net_device *ndev)
-{
- u32 cr;
- int i;
- struct sk_buff *skb;
- struct axienet_local *lp = netdev_priv(ndev);
-
- /* Reset the indexes which are used for accessing the BDs */
- lp->tx_bd_ci = 0;
- lp->tx_bd_tail = 0;
- lp->rx_bd_ci = 0;
-
- /*
- * Allocate the Tx and Rx buffer descriptors.
- */
- lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
- sizeof(*lp->tx_bd_v) * TX_BD_NUM,
- &lp->tx_bd_p,
- GFP_KERNEL);
- if (!lp->tx_bd_v) {
- dev_err(&ndev->dev, "unable to allocate DMA Tx buffer "
- "descriptors");
- goto out;
- }
-
- lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
- sizeof(*lp->rx_bd_v) * RX_BD_NUM,
- &lp->rx_bd_p,
- GFP_KERNEL);
- if (!lp->rx_bd_v) {
- dev_err(&ndev->dev, "unable to allocate DMA Rx buffer "
- "descriptors");
- goto out;
- }
-
- memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
- for (i = 0; i < TX_BD_NUM; i++) {
- lp->tx_bd_v[i].next = lp->tx_bd_p +
- sizeof(*lp->tx_bd_v) *
- ((i + 1) % TX_BD_NUM);
- }
-
- memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
- for (i = 0; i < RX_BD_NUM; i++) {
- lp->rx_bd_v[i].next = lp->rx_bd_p +
- sizeof(*lp->rx_bd_v) *
- ((i + 1) % RX_BD_NUM);
-
- skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
- if (!skb) {
- dev_err(&ndev->dev, "alloc_skb error %d\n", i);
- goto out;
- }
-
- lp->rx_bd_v[i].sw_id_offset = (u32) skb;
- lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
- skb->data,
- lp->max_frm_size,
- DMA_FROM_DEVICE);
- lp->rx_bd_v[i].cntrl = lp->max_frm_size;
- }
-
- /* Start updating the Rx channel control register */
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- /* Update the interrupt coalesce count */
- cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
- ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT));
- /* Update the delay timer count */
- cr = ((cr & ~XAXIDMA_DELAY_MASK) |
- (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
- /* Enable coalesce, delay timer and error interrupts */
- cr |= XAXIDMA_IRQ_ALL_MASK;
- /* Write to the Rx channel control register */
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
- /* Start updating the Tx channel control register */
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- /* Update the interrupt coalesce count */
- cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
- ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT));
- /* Update the delay timer count */
- cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
- (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
- /* Enable coalesce, delay timer and error interrupts */
- cr |= XAXIDMA_IRQ_ALL_MASK;
- /* Write to the Tx channel control register */
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
- /* Populate the tail pointer and bring the Rx Axi DMA engine out of
- * halted state. This will make the Rx side ready for reception.*/
- axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
- cr | XAXIDMA_CR_RUNSTOP_MASK);
- axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
- (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
-
- /* Write to the RS (Run-stop) bit in the Tx channel control register.
- * Tx channel is now ready to run. But only after we write to the
- * tail pointer register that the Tx channel will start transmitting */
- axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
- cr | XAXIDMA_CR_RUNSTOP_MASK);
-
- return 0;
-out:
- axienet_dma_bd_release(ndev);
- return -ENOMEM;
-}
-
-/**
- * axienet_set_mac_address - Write the MAC address
- * @ndev: Pointer to the net_device structure
- * @address: 6 byte Address to be written as MAC address
- *
- * This function is called to initialize the MAC address of the Axi Ethernet
- * core. It writes to the UAW0 and UAW1 registers of the core.
- */
-static void axienet_set_mac_address(struct net_device *ndev, void *address)
-{
- struct axienet_local *lp = netdev_priv(ndev);
-
- if (address)
- memcpy(ndev->dev_addr, address, ETH_ALEN);
- if (!is_valid_ether_addr(ndev->dev_addr))
- random_ether_addr(ndev->dev_addr);
-
- /* Set up unicast MAC address filter set its mac address */
- axienet_iow(lp, XAE_UAW0_OFFSET,
- (ndev->dev_addr[0]) |
- (ndev->dev_addr[1] << 8) |
- (ndev->dev_addr[2] << 16) |
- (ndev->dev_addr[3] << 24));
- axienet_iow(lp, XAE_UAW1_OFFSET,
- (((axienet_ior(lp, XAE_UAW1_OFFSET)) &
- ~XAE_UAW1_UNICASTADDR_MASK) |
- (ndev->dev_addr[4] |
- (ndev->dev_addr[5] << 8))));
-}
-
-/**
- * netdev_set_mac_address - Write the MAC address (from outside the driver)
- * @ndev: Pointer to the net_device structure
- * @p: 6 byte Address to be written as MAC address
- *
- * returns: 0 for all conditions. Presently, there is no failure case.
- *
- * This function is called to initialize the MAC address of the Axi Ethernet
- * core. It calls the core specific axienet_set_mac_address. This is the
- * function that goes into net_device_ops structure entry ndo_set_mac_address.
- */
-static int netdev_set_mac_address(struct net_device *ndev, void *p)
-{
- struct sockaddr *addr = p;
- axienet_set_mac_address(ndev, addr->sa_data);
- return 0;
-}
-
-/**
- * axienet_set_multicast_list - Prepare the multicast table
- * @ndev: Pointer to the net_device structure
- *
- * This function is called to initialize the multicast table during
- * initialization. The Axi Ethernet basic multicast support has a four-entry
- * multicast table which is initialized here. Additionally this function
- * goes into the net_device_ops structure entry ndo_set_multicast_list. This
- * means whenever the multicast table entries need to be updated this
- * function gets called.
- */
-static void axienet_set_multicast_list(struct net_device *ndev)
-{
- int i;
- u32 reg, af0reg, af1reg;
- struct axienet_local *lp = netdev_priv(ndev);
-
- if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
- netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
- /* We must make the kernel realize we had to move into
- * promiscuous mode. If it was a promiscuous mode request
- * the flag is already set. If not we set it. */
- ndev->flags |= IFF_PROMISC;
- reg = axienet_ior(lp, XAE_FMI_OFFSET);
- reg |= XAE_FMI_PM_MASK;
- axienet_iow(lp, XAE_FMI_OFFSET, reg);
- dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
- } else if (!netdev_mc_empty(ndev)) {
- struct netdev_hw_addr *ha;
-
- i = 0;
- netdev_for_each_mc_addr(ha, ndev) {
- if (i >= XAE_MULTICAST_CAM_TABLE_NUM)
- break;
-
- af0reg = (ha->addr[0]);
- af0reg |= (ha->addr[1] << 8);
- af0reg |= (ha->addr[2] << 16);
- af0reg |= (ha->addr[3] << 24);
-
- af1reg = (ha->addr[4]);
- af1reg |= (ha->addr[5] << 8);
-
- reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
- reg |= i;
-
- axienet_iow(lp, XAE_FMI_OFFSET, reg);
- axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
- axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
- i++;
- }
- } else {
- reg = axienet_ior(lp, XAE_FMI_OFFSET);
- reg &= ~XAE_FMI_PM_MASK;
-
- axienet_iow(lp, XAE_FMI_OFFSET, reg);
-
- for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
- reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
- reg |= i;
-
- axienet_iow(lp, XAE_FMI_OFFSET, reg);
- axienet_iow(lp, XAE_AF0_OFFSET, 0);
- axienet_iow(lp, XAE_AF1_OFFSET, 0);
- }
-
- dev_info(&ndev->dev, "Promiscuous mode disabled.\n");
- }
-}
-
-/**
- * axienet_setoptions - Set an Axi Ethernet option
- * @ndev: Pointer to the net_device structure
- * @options: Option to be enabled/disabled
- *
- * The Axi Ethernet core has multiple features which can be selectively turned
- * on or off. The typical options could be jumbo frame option, basic VLAN
- * option, promiscuous mode option etc. This function is used to set or clear
- * these options in the Axi Ethernet hardware. This is done through
- * axienet_option structure .
- */
-static void axienet_setoptions(struct net_device *ndev, u32 options)
-{
- int reg;
- struct axienet_local *lp = netdev_priv(ndev);
- struct axienet_option *tp = &axienet_options[0];
-
- while (tp->opt) {
- reg = ((axienet_ior(lp, tp->reg)) & ~(tp->m_or));
- if (options & tp->opt)
- reg |= tp->m_or;
- axienet_iow(lp, tp->reg, reg);
- tp++;
- }
-
- lp->options |= options;
-}
-
-static void __axienet_device_reset(struct axienet_local *lp,
- struct device *dev, off_t offset)
-{
- u32 timeout;
- /* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset
- * process of Axi DMA takes a while to complete as all pending
- * commands/transfers will be flushed or completed during this
- * reset process. */
- axienet_dma_out32(lp, offset, XAXIDMA_CR_RESET_MASK);
- timeout = DELAY_OF_ONE_MILLISEC;
- while (axienet_dma_in32(lp, offset) & XAXIDMA_CR_RESET_MASK) {
- udelay(1);
- if (--timeout == 0) {
- dev_err(dev, "axienet_device_reset DMA "
- "reset timeout!\n");
- break;
- }
- }
-}
-
-/**
- * axienet_device_reset - Reset and initialize the Axi Ethernet hardware.
- * @ndev: Pointer to the net_device structure
- *
- * This function is called to reset and initialize the Axi Ethernet core. This
- * is typically called during initialization. It does a reset of the Axi DMA
- * Rx/Tx channels and initializes the Axi DMA BDs. Since Axi DMA reset lines
- * areconnected to Axi Ethernet reset lines, this in turn resets the Axi
- * Ethernet core. No separate hardware reset is done for the Axi Ethernet
- * core.
- */
-static void axienet_device_reset(struct net_device *ndev)
-{
- u32 axienet_status;
- struct axienet_local *lp = netdev_priv(ndev);
-
- __axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET);
- __axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET);
-
- lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE;
- lp->options &= (~XAE_OPTION_JUMBO);
-
- if ((ndev->mtu > XAE_MTU) &&
- (ndev->mtu <= XAE_JUMBO_MTU) &&
- (lp->jumbo_support)) {
- lp->max_frm_size = ndev->mtu + XAE_HDR_VLAN_SIZE +
- XAE_TRL_SIZE;
- lp->options |= XAE_OPTION_JUMBO;
- }
-
- if (axienet_dma_bd_init(ndev)) {
- dev_err(&ndev->dev, "axienet_device_reset descriptor "
- "allocation failed\n");
- }
-
- axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
- axienet_status &= ~XAE_RCW1_RX_MASK;
- axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
-
- axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
- if (axienet_status & XAE_INT_RXRJECT_MASK)
- axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
-
- axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
-
- /* Sync default options with HW but leave receiver and
- * transmitter disabled.*/
- axienet_setoptions(ndev, lp->options &
- ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
- axienet_set_mac_address(ndev, NULL);
- axienet_set_multicast_list(ndev);
- axienet_setoptions(ndev, lp->options);
-
- ndev->trans_start = jiffies;
-}
-
-/**
- * axienet_adjust_link - Adjust the PHY link speed/duplex.
- * @ndev: Pointer to the net_device structure
- *
- * This function is called to change the speed and duplex setting after
- * auto negotiation is done by the PHY. This is the function that gets
- * registered with the PHY interface through the "of_phy_connect" call.
- */
-static void axienet_adjust_link(struct net_device *ndev)
-{
- u32 emmc_reg;
- u32 link_state;
- u32 setspeed = 1;
- struct axienet_local *lp = netdev_priv(ndev);
- struct phy_device *phy = lp->phy_dev;
-
- link_state = phy->speed | (phy->duplex << 1) | phy->link;
- if (lp->last_link != link_state) {
- if ((phy->speed == SPEED_10) || (phy->speed == SPEED_100)) {
- if (lp->phy_type == XAE_PHY_TYPE_1000BASE_X)
- setspeed = 0;
- } else {
- if ((phy->speed == SPEED_1000) &&
- (lp->phy_type == XAE_PHY_TYPE_MII))
- setspeed = 0;
- }
-
- if (setspeed == 1) {
- emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
- emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
-
- switch (phy->speed) {
- case SPEED_1000:
- emmc_reg |= XAE_EMMC_LINKSPD_1000;
- break;
- case SPEED_100:
- emmc_reg |= XAE_EMMC_LINKSPD_100;
- break;
- case SPEED_10:
- emmc_reg |= XAE_EMMC_LINKSPD_10;
- break;
- default:
- dev_err(&ndev->dev, "Speed other than 10, 100 "
- "or 1Gbps is not supported\n");
- break;
- }
-
- axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
- lp->last_link = link_state;
- phy_print_status(phy);
- } else {
- dev_err(&ndev->dev, "Error setting Axi Ethernet "
- "mac speed\n");
- }
- }
-}
-
-/**
- * axienet_start_xmit_done - Invoked once a transmit is completed by the
- * Axi DMA Tx channel.
- * @ndev: Pointer to the net_device structure
- *
- * This function is invoked from the Axi DMA Tx isr to notify the completion
- * of transmit operation. It clears fields in the corresponding Tx BDs and
- * unmaps the corresponding buffer so that CPU can regain ownership of the
- * buffer. It finally invokes "netif_wake_queue" to restart transmission if
- * required.
- */
-static void axienet_start_xmit_done(struct net_device *ndev)
-{
- u32 size = 0;
- u32 packets = 0;
- struct axienet_local *lp = netdev_priv(ndev);
- struct axidma_bd *cur_p;
- unsigned int status = 0;
-
- cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
- status = cur_p->status;
- while (status & XAXIDMA_BD_STS_COMPLETE_MASK) {
- dma_unmap_single(ndev->dev.parent, cur_p->phys,
- (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
- DMA_TO_DEVICE);
- if (cur_p->app4)
- dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
- /*cur_p->phys = 0;*/
- cur_p->app0 = 0;
- cur_p->app1 = 0;
- cur_p->app2 = 0;
- cur_p->app4 = 0;
- cur_p->status = 0;
-
- size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
- packets++;
-
- lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM;
- cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
- status = cur_p->status;
- }
-
- ndev->stats.tx_packets += packets;
- ndev->stats.tx_bytes += size;
- netif_wake_queue(ndev);
-}
-
-/**
- * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy
- * @lp: Pointer to the axienet_local structure
- * @num_frag: The number of BDs to check for
- *
- * returns: 0, on success
- * NETDEV_TX_BUSY, if any of the descriptors are not free
- *
- * This function is invoked before BDs are allocated and transmission starts.
- * This function returns 0 if a BD or group of BDs can be allocated for
- * transmission. If the BD or any of the BDs are not free the function
- * returns a busy status. This is invoked from axienet_start_xmit.
- */
-static inline int axienet_check_tx_bd_space(struct axienet_local *lp,
- int num_frag)
-{
- struct axidma_bd *cur_p;
- cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % TX_BD_NUM];
- if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK)
- return NETDEV_TX_BUSY;
- return 0;
-}
-
-/**
- * axienet_start_xmit - Starts the transmission.
- * @skb: sk_buff pointer that contains data to be Txed.
- * @ndev: Pointer to net_device structure.
- *
- * returns: NETDEV_TX_OK, on success
- * NETDEV_TX_BUSY, if any of the descriptors are not free
- *
- * This function is invoked from upper layers to initiate transmission. The
- * function uses the next available free BDs and populates their fields to
- * start the transmission. Additionally if checksum offloading is supported,
- * it populates AXI Stream Control fields with appropriate values.
- */
-static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
- u32 ii;
- u32 num_frag;
- u32 csum_start_off;
- u32 csum_index_off;
- skb_frag_t *frag;
- dma_addr_t tail_p;
- struct axienet_local *lp = netdev_priv(ndev);
- struct axidma_bd *cur_p;
-
- num_frag = skb_shinfo(skb)->nr_frags;
- cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
-
- if (axienet_check_tx_bd_space(lp, num_frag)) {
- if (!netif_queue_stopped(ndev))
- netif_stop_queue(ndev);
- return NETDEV_TX_BUSY;
- }
-
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (lp->features & XAE_FEATURE_FULL_TX_CSUM) {
- /* Tx Full Checksum Offload Enabled */
- cur_p->app0 |= 2;
- } else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) {
- csum_start_off = skb_transport_offset(skb);
- csum_index_off = csum_start_off + skb->csum_offset;
- /* Tx Partial Checksum Offload Enabled */
- cur_p->app0 |= 1;
- cur_p->app1 = (csum_start_off << 16) | csum_index_off;
- }
- } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */
- }
-
- cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK;
- cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
-
- for (ii = 0; ii < num_frag; ii++) {
- lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
- cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
- frag = &skb_shinfo(skb)->frags[ii];
- cur_p->phys = dma_map_single(ndev->dev.parent,
- skb_frag_address(frag),
- skb_frag_size(frag),
- DMA_TO_DEVICE);
- cur_p->cntrl = skb_frag_size(frag);
- }
-
- cur_p->cntrl |= XAXIDMA_BD_CTRL_TXEOF_MASK;
- cur_p->app4 = (unsigned long)skb;
-
- tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
- /* Start the transfer */
- axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
- lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
-
- return NETDEV_TX_OK;
-}
-
-/**
- * axienet_recv - Is called from Axi DMA Rx Isr to complete the received
- * BD processing.
- * @ndev: Pointer to net_device structure.
- *
- * This function is invoked from the Axi DMA Rx isr to process the Rx BDs. It
- * does minimal processing and invokes "netif_rx" to complete further
- * processing.
- */
-static void axienet_recv(struct net_device *ndev)
-{
- u32 length;
- u32 csumstatus;
- u32 size = 0;
- u32 packets = 0;
- dma_addr_t tail_p;
- struct axienet_local *lp = netdev_priv(ndev);
- struct sk_buff *skb, *new_skb;
- struct axidma_bd *cur_p;
-
- tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
- cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-
- while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
- skb = (struct sk_buff *) (cur_p->sw_id_offset);
- length = cur_p->app4 & 0x0000FFFF;
-
- dma_unmap_single(ndev->dev.parent, cur_p->phys,
- lp->max_frm_size,
- DMA_FROM_DEVICE);
-
- skb_put(skb, length);
- skb->protocol = eth_type_trans(skb, ndev);
- /*skb_checksum_none_assert(skb);*/
- skb->ip_summed = CHECKSUM_NONE;
-
- /* if we're doing Rx csum offload, set it up */
- if (lp->features & XAE_FEATURE_FULL_RX_CSUM) {
- csumstatus = (cur_p->app2 &
- XAE_FULL_CSUM_STATUS_MASK) >> 3;
- if ((csumstatus == XAE_IP_TCP_CSUM_VALIDATED) ||
- (csumstatus == XAE_IP_UDP_CSUM_VALIDATED)) {
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- }
- } else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 &&
- skb->protocol == __constant_htons(ETH_P_IP) &&
- skb->len > 64) {
- skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF);
- skb->ip_summed = CHECKSUM_COMPLETE;
- }
-
- netif_rx(skb);
-
- size += length;
- packets++;
-
- new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
- if (!new_skb) {
- dev_err(&ndev->dev, "no memory for new sk_buff\n");
- return;
- }
- cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
- lp->max_frm_size,
- DMA_FROM_DEVICE);
- cur_p->cntrl = lp->max_frm_size;
- cur_p->status = 0;
- cur_p->sw_id_offset = (u32) new_skb;
-
- lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM;
- cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
- }
-
- ndev->stats.rx_packets += packets;
- ndev->stats.rx_bytes += size;
-
- axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
-}
-
-/**
- * axienet_tx_irq - Tx Done Isr.
- * @irq: irq number
- * @_ndev: net_device pointer
- *
- * returns: IRQ_HANDLED for all cases.
- *
- * This is the Axi DMA Tx done Isr. It invokes "axienet_start_xmit_done"
- * to complete the BD processing.
- */
-static irqreturn_t axienet_tx_irq(int irq, void *_ndev)
-{
- u32 cr;
- unsigned int status;
- struct net_device *ndev = _ndev;
- struct axienet_local *lp = netdev_priv(ndev);
-
- status = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
- if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
- axienet_start_xmit_done(lp->ndev);
- goto out;
- }
- if (!(status & XAXIDMA_IRQ_ALL_MASK))
- dev_err(&ndev->dev, "No interrupts asserted in Tx path");
- if (status & XAXIDMA_IRQ_ERROR_MASK) {
- dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
- dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
- (lp->tx_bd_v[lp->tx_bd_ci]).phys);
-
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- /* Disable coalesce, delay timer and error interrupts */
- cr &= (~XAXIDMA_IRQ_ALL_MASK);
- /* Write to the Tx channel control register */
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- /* Disable coalesce, delay timer and error interrupts */
- cr &= (~XAXIDMA_IRQ_ALL_MASK);
- /* Write to the Rx channel control register */
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
- tasklet_schedule(&lp->dma_err_tasklet);
- }
-out:
- axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET, status);
- return IRQ_HANDLED;
-}
-
-/**
- * axienet_rx_irq - Rx Isr.
- * @irq: irq number
- * @_ndev: net_device pointer
- *
- * returns: IRQ_HANDLED for all cases.
- *
- * This is the Axi DMA Rx Isr. It invokes "axienet_recv" to complete the BD
- * processing.
- */
-static irqreturn_t axienet_rx_irq(int irq, void *_ndev)
-{
- u32 cr;
- unsigned int status;
- struct net_device *ndev = _ndev;
- struct axienet_local *lp = netdev_priv(ndev);
-
- status = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
- if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
- axienet_recv(lp->ndev);
- goto out;
- }
- if (!(status & XAXIDMA_IRQ_ALL_MASK))
- dev_err(&ndev->dev, "No interrupts asserted in Rx path");
- if (status & XAXIDMA_IRQ_ERROR_MASK) {
- dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
- dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
- (lp->rx_bd_v[lp->rx_bd_ci]).phys);
-
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- /* Disable coalesce, delay timer and error interrupts */
- cr &= (~XAXIDMA_IRQ_ALL_MASK);
- /* Finally write to the Tx channel control register */
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- /* Disable coalesce, delay timer and error interrupts */
- cr &= (~XAXIDMA_IRQ_ALL_MASK);
- /* write to the Rx channel control register */
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
- tasklet_schedule(&lp->dma_err_tasklet);
- }
-out:
- axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET, status);
- return IRQ_HANDLED;
-}
-
-/**
- * axienet_open - Driver open routine.
- * @ndev: Pointer to net_device structure
- *
- * returns: 0, on success.
- * -ENODEV, if PHY cannot be connected to
- * non-zero error value on failure
- *
- * This is the driver open routine. It calls phy_start to start the PHY device.
- * It also allocates interrupt service routines, enables the interrupt lines
- * and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer
- * descriptors are initialized.
- */
-static int axienet_open(struct net_device *ndev)
-{
- int ret, mdio_mcreg;
- struct axienet_local *lp = netdev_priv(ndev);
-
- dev_dbg(&ndev->dev, "axienet_open()\n");
-
- mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
- /* Disable the MDIO interface till Axi Ethernet Reset is completed.
- * When we do an Axi Ethernet reset, it resets the complete core
- * including the MDIO. If MDIO is not disabled when the reset
- * process is started, MDIO will be broken afterwards. */
- axienet_iow(lp, XAE_MDIO_MC_OFFSET,
- (mdio_mcreg & (~XAE_MDIO_MC_MDIOEN_MASK)));
- axienet_device_reset(ndev);
- /* Enable the MDIO */
- axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg);
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
-
- if (lp->phy_node) {
- lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
- axienet_adjust_link, 0,
- PHY_INTERFACE_MODE_GMII);
- if (!lp->phy_dev) {
- dev_err(lp->dev, "of_phy_connect() failed\n");
- return -ENODEV;
- }
- phy_start(lp->phy_dev);
- }
-
- /* Enable interrupts for Axi DMA Tx */
- ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
- if (ret)
- goto err_tx_irq;
- /* Enable interrupts for Axi DMA Rx */
- ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
- if (ret)
- goto err_rx_irq;
- /* Enable tasklets for Axi DMA error handling */
- tasklet_enable(&lp->dma_err_tasklet);
- return 0;
-
-err_rx_irq:
- free_irq(lp->tx_irq, ndev);
-err_tx_irq:
- if (lp->phy_dev)
- phy_disconnect(lp->phy_dev);
- lp->phy_dev = NULL;
- dev_err(lp->dev, "request_irq() failed\n");
- return ret;
-}
-
-/**
- * axienet_stop - Driver stop routine.
- * @ndev: Pointer to net_device structure
- *
- * returns: 0, on success.
- *
- * This is the driver stop routine. It calls phy_disconnect to stop the PHY
- * device. It also removes the interrupt handlers and disables the interrupts.
- * The Axi DMA Tx/Rx BDs are released.
- */
-static int axienet_stop(struct net_device *ndev)
-{
- u32 cr;
- struct axienet_local *lp = netdev_priv(ndev);
-
- dev_dbg(&ndev->dev, "axienet_close()\n");
-
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
- cr & (~XAXIDMA_CR_RUNSTOP_MASK));
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
- cr & (~XAXIDMA_CR_RUNSTOP_MASK));
- axienet_setoptions(ndev, lp->options &
- ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
-
- tasklet_disable(&lp->dma_err_tasklet);
-
- free_irq(lp->tx_irq, ndev);
- free_irq(lp->rx_irq, ndev);
-
- if (lp->phy_dev)
- phy_disconnect(lp->phy_dev);
- lp->phy_dev = NULL;
-
- axienet_dma_bd_release(ndev);
- return 0;
-}
-
-/**
- * axienet_change_mtu - Driver change mtu routine.
- * @ndev: Pointer to net_device structure
- * @new_mtu: New mtu value to be applied
- *
- * returns: Always returns 0 (success).
- *
- * This is the change mtu driver routine. It checks if the Axi Ethernet
- * hardware supports jumbo frames before changing the mtu. This can be
- * called only when the device is not up.
- */
-static int axienet_change_mtu(struct net_device *ndev, int new_mtu)
-{
- struct axienet_local *lp = netdev_priv(ndev);
-
- if (netif_running(ndev))
- return -EBUSY;
- if (lp->jumbo_support) {
- if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64))
- return -EINVAL;
- ndev->mtu = new_mtu;
- } else {
- if ((new_mtu > XAE_MTU) || (new_mtu < 64))
- return -EINVAL;
- ndev->mtu = new_mtu;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * axienet_poll_controller - Axi Ethernet poll mechanism.
- * @ndev: Pointer to net_device structure
- *
- * This implements Rx/Tx ISR poll mechanisms. The interrupts are disabled prior
- * to polling the ISRs and are enabled back after the polling is done.
- */
-static void axienet_poll_controller(struct net_device *ndev)
-{
- struct axienet_local *lp = netdev_priv(ndev);
- disable_irq(lp->tx_irq);
- disable_irq(lp->rx_irq);
- axienet_rx_irq(lp->tx_irq, ndev);
- axienet_tx_irq(lp->rx_irq, ndev);
- enable_irq(lp->tx_irq);
- enable_irq(lp->rx_irq);
-}
-#endif
-
-static const struct net_device_ops axienet_netdev_ops = {
- .ndo_open = axienet_open,
- .ndo_stop = axienet_stop,
- .ndo_start_xmit = axienet_start_xmit,
- .ndo_change_mtu = axienet_change_mtu,
- .ndo_set_mac_address = netdev_set_mac_address,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_rx_mode = axienet_set_multicast_list,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = axienet_poll_controller,
-#endif
-};
-
-/**
- * axienet_ethtools_get_settings - Get Axi Ethernet settings related to PHY.
- * @ndev: Pointer to net_device structure
- * @ecmd: Pointer to ethtool_cmd structure
- *
- * This implements ethtool command for getting PHY settings. If PHY could
- * not be found, the function returns -ENODEV. This function calls the
- * relevant PHY ethtool API to get the PHY settings.
- * Issue "ethtool ethX" under linux prompt to execute this function.
- */
-static int axienet_ethtools_get_settings(struct net_device *ndev,
- struct ethtool_cmd *ecmd)
-{
- struct axienet_local *lp = netdev_priv(ndev);
- struct phy_device *phydev = lp->phy_dev;
- if (!phydev)
- return -ENODEV;
- return phy_ethtool_gset(phydev, ecmd);
-}
-
-/**
- * axienet_ethtools_set_settings - Set PHY settings as passed in the argument.
- * @ndev: Pointer to net_device structure
- * @ecmd: Pointer to ethtool_cmd structure
- *
- * This implements ethtool command for setting various PHY settings. If PHY
- * could not be found, the function returns -ENODEV. This function calls the
- * relevant PHY ethtool API to set the PHY.
- * Issue e.g. "ethtool -s ethX speed 1000" under linux prompt to execute this
- * function.
- */
-static int axienet_ethtools_set_settings(struct net_device *ndev,
- struct ethtool_cmd *ecmd)
-{
- struct axienet_local *lp = netdev_priv(ndev);
- struct phy_device *phydev = lp->phy_dev;
- if (!phydev)
- return -ENODEV;
- return phy_ethtool_sset(phydev, ecmd);
-}
-
-/**
- * axienet_ethtools_get_drvinfo - Get various Axi Ethernet driver information.
- * @ndev: Pointer to net_device structure
- * @ed: Pointer to ethtool_drvinfo structure
- *
- * This implements ethtool command for getting the driver information.
- * Issue "ethtool -i ethX" under linux prompt to execute this function.
- */
-static void axienet_ethtools_get_drvinfo(struct net_device *ndev,
- struct ethtool_drvinfo *ed)
-{
- memset(ed, 0, sizeof(struct ethtool_drvinfo));
- strcpy(ed->driver, DRIVER_NAME);
- strcpy(ed->version, DRIVER_VERSION);
- ed->regdump_len = sizeof(u32) * AXIENET_REGS_N;
-}
-
-/**
- * axienet_ethtools_get_regs_len - Get the total regs length present in the
- * AxiEthernet core.
- * @ndev: Pointer to net_device structure
- *
- * This implements ethtool command for getting the total register length
- * information.
- */
-static int axienet_ethtools_get_regs_len(struct net_device *ndev)
-{
- return sizeof(u32) * AXIENET_REGS_N;
-}
-
-/**
- * axienet_ethtools_get_regs - Dump the contents of all registers present
- * in AxiEthernet core.
- * @ndev: Pointer to net_device structure
- * @regs: Pointer to ethtool_regs structure
- * @ret: Void pointer used to return the contents of the registers.
- *
- * This implements ethtool command for getting the Axi Ethernet register dump.
- * Issue "ethtool -d ethX" to execute this function.
- */
-static void axienet_ethtools_get_regs(struct net_device *ndev,
- struct ethtool_regs *regs, void *ret)
-{
- u32 *data = (u32 *) ret;
- size_t len = sizeof(u32) * AXIENET_REGS_N;
- struct axienet_local *lp = netdev_priv(ndev);
-
- regs->version = 0;
- regs->len = len;
-
- memset(data, 0, len);
- data[0] = axienet_ior(lp, XAE_RAF_OFFSET);
- data[1] = axienet_ior(lp, XAE_TPF_OFFSET);
- data[2] = axienet_ior(lp, XAE_IFGP_OFFSET);
- data[3] = axienet_ior(lp, XAE_IS_OFFSET);
- data[4] = axienet_ior(lp, XAE_IP_OFFSET);
- data[5] = axienet_ior(lp, XAE_IE_OFFSET);
- data[6] = axienet_ior(lp, XAE_TTAG_OFFSET);
- data[7] = axienet_ior(lp, XAE_RTAG_OFFSET);
- data[8] = axienet_ior(lp, XAE_UAWL_OFFSET);
- data[9] = axienet_ior(lp, XAE_UAWU_OFFSET);
- data[10] = axienet_ior(lp, XAE_TPID0_OFFSET);
- data[11] = axienet_ior(lp, XAE_TPID1_OFFSET);
- data[12] = axienet_ior(lp, XAE_PPST_OFFSET);
- data[13] = axienet_ior(lp, XAE_RCW0_OFFSET);
- data[14] = axienet_ior(lp, XAE_RCW1_OFFSET);
- data[15] = axienet_ior(lp, XAE_TC_OFFSET);
- data[16] = axienet_ior(lp, XAE_FCC_OFFSET);
- data[17] = axienet_ior(lp, XAE_EMMC_OFFSET);
- data[18] = axienet_ior(lp, XAE_PHYC_OFFSET);
- data[19] = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
- data[20] = axienet_ior(lp, XAE_MDIO_MCR_OFFSET);
- data[21] = axienet_ior(lp, XAE_MDIO_MWD_OFFSET);
- data[22] = axienet_ior(lp, XAE_MDIO_MRD_OFFSET);
- data[23] = axienet_ior(lp, XAE_MDIO_MIS_OFFSET);
- data[24] = axienet_ior(lp, XAE_MDIO_MIP_OFFSET);
- data[25] = axienet_ior(lp, XAE_MDIO_MIE_OFFSET);
- data[26] = axienet_ior(lp, XAE_MDIO_MIC_OFFSET);
- data[27] = axienet_ior(lp, XAE_UAW0_OFFSET);
- data[28] = axienet_ior(lp, XAE_UAW1_OFFSET);
- data[29] = axienet_ior(lp, XAE_FMI_OFFSET);
- data[30] = axienet_ior(lp, XAE_AF0_OFFSET);
- data[31] = axienet_ior(lp, XAE_AF1_OFFSET);
-}
-
-/**
- * axienet_ethtools_get_pauseparam - Get the pause parameter setting for
- * Tx and Rx paths.
- * @ndev: Pointer to net_device structure
- * @epauseparm: Pointer to ethtool_pauseparam structure.
- *
- * This implements ethtool command for getting axi ethernet pause frame
- * setting. Issue "ethtool -a ethX" to execute this function.
- */
-static void
-axienet_ethtools_get_pauseparam(struct net_device *ndev,
- struct ethtool_pauseparam *epauseparm)
-{
- u32 regval;
- struct axienet_local *lp = netdev_priv(ndev);
- epauseparm->autoneg = 0;
- regval = axienet_ior(lp, XAE_FCC_OFFSET);
- epauseparm->tx_pause = regval & XAE_FCC_FCTX_MASK;
- epauseparm->rx_pause = regval & XAE_FCC_FCRX_MASK;
-}
-
-/**
- * axienet_ethtools_set_pauseparam - Set device pause parameter(flow control)
- * settings.
- * @ndev: Pointer to net_device structure
- * @epauseparam:Pointer to ethtool_pauseparam structure
- *
- * This implements ethtool command for enabling flow control on Rx and Tx
- * paths. Issue "ethtool -A ethX tx on|off" under linux prompt to execute this
- * function.
- */
-static int
-axienet_ethtools_set_pauseparam(struct net_device *ndev,
- struct ethtool_pauseparam *epauseparm)
-{
- u32 regval = 0;
- struct axienet_local *lp = netdev_priv(ndev);
-
- if (netif_running(ndev)) {
- printk(KERN_ERR "%s: Please stop netif before applying "
- "configruation\n", ndev->name);
- return -EFAULT;
- }
-
- regval = axienet_ior(lp, XAE_FCC_OFFSET);
- if (epauseparm->tx_pause)
- regval |= XAE_FCC_FCTX_MASK;
- else
- regval &= ~XAE_FCC_FCTX_MASK;
- if (epauseparm->rx_pause)
- regval |= XAE_FCC_FCRX_MASK;
- else
- regval &= ~XAE_FCC_FCRX_MASK;
- axienet_iow(lp, XAE_FCC_OFFSET, regval);
-
- return 0;
-}
-
-/**
- * axienet_ethtools_get_coalesce - Get DMA interrupt coalescing count.
- * @ndev: Pointer to net_device structure
- * @ecoalesce: Pointer to ethtool_coalesce structure
- *
- * This implements ethtool command for getting the DMA interrupt coalescing
- * count on Tx and Rx paths. Issue "ethtool -c ethX" under linux prompt to
- * execute this function.
- */
-static int axienet_ethtools_get_coalesce(struct net_device *ndev,
- struct ethtool_coalesce *ecoalesce)
-{
- u32 regval = 0;
- struct axienet_local *lp = netdev_priv(ndev);
- regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
- >> XAXIDMA_COALESCE_SHIFT;
- regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
- >> XAXIDMA_COALESCE_SHIFT;
- return 0;
-}
-
-/**
- * axienet_ethtools_set_coalesce - Set DMA interrupt coalescing count.
- * @ndev: Pointer to net_device structure
- * @ecoalesce: Pointer to ethtool_coalesce structure
- *
- * This implements ethtool command for setting the DMA interrupt coalescing
- * count on Tx and Rx paths. Issue "ethtool -C ethX rx-frames 5" under linux
- * prompt to execute this function.
- */
-static int axienet_ethtools_set_coalesce(struct net_device *ndev,
- struct ethtool_coalesce *ecoalesce)
-{
- struct axienet_local *lp = netdev_priv(ndev);
-
- if (netif_running(ndev)) {
- printk(KERN_ERR "%s: Please stop netif before applying "
- "configruation\n", ndev->name);
- return -EFAULT;
- }
-
- if ((ecoalesce->rx_coalesce_usecs) ||
- (ecoalesce->rx_coalesce_usecs_irq) ||
- (ecoalesce->rx_max_coalesced_frames_irq) ||
- (ecoalesce->tx_coalesce_usecs) ||
- (ecoalesce->tx_coalesce_usecs_irq) ||
- (ecoalesce->tx_max_coalesced_frames_irq) ||
- (ecoalesce->stats_block_coalesce_usecs) ||
- (ecoalesce->use_adaptive_rx_coalesce) ||
- (ecoalesce->use_adaptive_tx_coalesce) ||
- (ecoalesce->pkt_rate_low) ||
- (ecoalesce->rx_coalesce_usecs_low) ||
- (ecoalesce->rx_max_coalesced_frames_low) ||
- (ecoalesce->tx_coalesce_usecs_low) ||
- (ecoalesce->tx_max_coalesced_frames_low) ||
- (ecoalesce->pkt_rate_high) ||
- (ecoalesce->rx_coalesce_usecs_high) ||
- (ecoalesce->rx_max_coalesced_frames_high) ||
- (ecoalesce->tx_coalesce_usecs_high) ||
- (ecoalesce->tx_max_coalesced_frames_high) ||
- (ecoalesce->rate_sample_interval))
- return -EOPNOTSUPP;
- if (ecoalesce->rx_max_coalesced_frames)
- lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames;
- if (ecoalesce->tx_max_coalesced_frames)
- lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames;
-
- return 0;
-}
-
-static struct ethtool_ops axienet_ethtool_ops = {
- .get_settings = axienet_ethtools_get_settings,
- .set_settings = axienet_ethtools_set_settings,
- .get_drvinfo = axienet_ethtools_get_drvinfo,
- .get_regs_len = axienet_ethtools_get_regs_len,
- .get_regs = axienet_ethtools_get_regs,
- .get_link = ethtool_op_get_link,
- .get_pauseparam = axienet_ethtools_get_pauseparam,
- .set_pauseparam = axienet_ethtools_set_pauseparam,
- .get_coalesce = axienet_ethtools_get_coalesce,
- .set_coalesce = axienet_ethtools_set_coalesce,
-};
-
-/**
- * axienet_dma_err_handler - Tasklet handler for Axi DMA Error
- * @data: Data passed
- *
- * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the
- * Tx/Rx BDs.
- */
-static void axienet_dma_err_handler(unsigned long data)
-{
- u32 axienet_status;
- u32 cr, i;
- int mdio_mcreg;
- struct axienet_local *lp = (struct axienet_local *) data;
- struct net_device *ndev = lp->ndev;
- struct axidma_bd *cur_p;
-
- axienet_setoptions(ndev, lp->options &
- ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
- mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
- axienet_mdio_wait_until_ready(lp);
- /* Disable the MDIO interface till Axi Ethernet Reset is completed.
- * When we do an Axi Ethernet reset, it resets the complete core
- * including the MDIO. So if MDIO is not disabled when the reset
- * process is started, MDIO will be broken afterwards. */
- axienet_iow(lp, XAE_MDIO_MC_OFFSET, (mdio_mcreg &
- ~XAE_MDIO_MC_MDIOEN_MASK));
-
- __axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET);
- __axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET);
-
- axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg);
- axienet_mdio_wait_until_ready(lp);
-
- for (i = 0; i < TX_BD_NUM; i++) {
- cur_p = &lp->tx_bd_v[i];
- if (cur_p->phys)
- dma_unmap_single(ndev->dev.parent, cur_p->phys,
- (cur_p->cntrl &
- XAXIDMA_BD_CTRL_LENGTH_MASK),
- DMA_TO_DEVICE);
- if (cur_p->app4)
- dev_kfree_skb_irq((struct sk_buff *) cur_p->app4);
- cur_p->phys = 0;
- cur_p->cntrl = 0;
- cur_p->status = 0;
- cur_p->app0 = 0;
- cur_p->app1 = 0;
- cur_p->app2 = 0;
- cur_p->app3 = 0;
- cur_p->app4 = 0;
- cur_p->sw_id_offset = 0;
- }
-
- for (i = 0; i < RX_BD_NUM; i++) {
- cur_p = &lp->rx_bd_v[i];
- cur_p->status = 0;
- cur_p->app0 = 0;
- cur_p->app1 = 0;
- cur_p->app2 = 0;
- cur_p->app3 = 0;
- cur_p->app4 = 0;
- }
-
- lp->tx_bd_ci = 0;
- lp->tx_bd_tail = 0;
- lp->rx_bd_ci = 0;
-
- /* Start updating the Rx channel control register */
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- /* Update the interrupt coalesce count */
- cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
- (XAXIDMA_DFT_RX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
- /* Update the delay timer count */
- cr = ((cr & ~XAXIDMA_DELAY_MASK) |
- (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
- /* Enable coalesce, delay timer and error interrupts */
- cr |= XAXIDMA_IRQ_ALL_MASK;
- /* Finally write to the Rx channel control register */
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
- /* Start updating the Tx channel control register */
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- /* Update the interrupt coalesce count */
- cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
- (XAXIDMA_DFT_TX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
- /* Update the delay timer count */
- cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
- (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
- /* Enable coalesce, delay timer and error interrupts */
- cr |= XAXIDMA_IRQ_ALL_MASK;
- /* Finally write to the Tx channel control register */
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
- /* Populate the tail pointer and bring the Rx Axi DMA engine out of
- * halted state. This will make the Rx side ready for reception.*/
- axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
- cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
- cr | XAXIDMA_CR_RUNSTOP_MASK);
- axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
- (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
-
- /* Write to the RS (Run-stop) bit in the Tx channel control register.
- * Tx channel is now ready to run. But only after we write to the
- * tail pointer register that the Tx channel will start transmitting */
- axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
- cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
- cr | XAXIDMA_CR_RUNSTOP_MASK);
-
- axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
- axienet_status &= ~XAE_RCW1_RX_MASK;
- axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
-
- axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
- if (axienet_status & XAE_INT_RXRJECT_MASK)
- axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
- axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
-
- /* Sync default options with HW but leave receiver and
- * transmitter disabled.*/
- axienet_setoptions(ndev, lp->options &
- ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
- axienet_set_mac_address(ndev, NULL);
- axienet_set_multicast_list(ndev);
- axienet_setoptions(ndev, lp->options);
-}
-
-/**
- * axienet_of_probe - Axi Ethernet probe function.
- * @op: Pointer to platform device structure.
- * @match: Pointer to device id structure
- *
- * returns: 0, on success
- * Non-zero error value on failure.
- *
- * This is the probe routine for Axi Ethernet driver. This is called before
- * any other driver routines are invoked. It allocates and sets up the Ethernet
- * device. Parses through device tree and populates fields of
- * axienet_local. It registers the Ethernet device.
- */
-static int __devinit axienet_of_probe(struct platform_device *op)
-{
- __be32 *p;
- int size, ret = 0;
- struct device_node *np;
- struct axienet_local *lp;
- struct net_device *ndev;
- const void *addr;
-
- ndev = alloc_etherdev(sizeof(*lp));
- if (!ndev)
- return -ENOMEM;
-
- ether_setup(ndev);
- dev_set_drvdata(&op->dev, ndev);
-
- SET_NETDEV_DEV(ndev, &op->dev);
- ndev->flags &= ~IFF_MULTICAST; /* clear multicast */
- ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
- ndev->netdev_ops = &axienet_netdev_ops;
- ndev->ethtool_ops = &axienet_ethtool_ops;
-
- lp = netdev_priv(ndev);
- lp->ndev = ndev;
- lp->dev = &op->dev;
- lp->options = XAE_OPTION_DEFAULTS;
- /* Map device registers */
- lp->regs = of_iomap(op->dev.of_node, 0);
- if (!lp->regs) {
- dev_err(&op->dev, "could not map Axi Ethernet regs.\n");
- goto nodev;
- }
- /* Setup checksum offload, but default to off if not specified */
- lp->features = 0;
-
- p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
- if (p) {
- switch (be32_to_cpup(p)) {
- case 1:
- lp->csum_offload_on_tx_path =
- XAE_FEATURE_PARTIAL_TX_CSUM;
- lp->features |= XAE_FEATURE_PARTIAL_TX_CSUM;
- /* Can checksum TCP/UDP over IPv4. */
- ndev->features |= NETIF_F_IP_CSUM;
- break;
- case 2:
- lp->csum_offload_on_tx_path =
- XAE_FEATURE_FULL_TX_CSUM;
- lp->features |= XAE_FEATURE_FULL_TX_CSUM;
- /* Can checksum TCP/UDP over IPv4. */
- ndev->features |= NETIF_F_IP_CSUM;
- break;
- default:
- lp->csum_offload_on_tx_path = XAE_NO_CSUM_OFFLOAD;
- }
- }
- p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
- if (p) {
- switch (be32_to_cpup(p)) {
- case 1:
- lp->csum_offload_on_rx_path =
- XAE_FEATURE_PARTIAL_RX_CSUM;
- lp->features |= XAE_FEATURE_PARTIAL_RX_CSUM;
- break;
- case 2:
- lp->csum_offload_on_rx_path =
- XAE_FEATURE_FULL_RX_CSUM;
- lp->features |= XAE_FEATURE_FULL_RX_CSUM;
- break;
- default:
- lp->csum_offload_on_rx_path = XAE_NO_CSUM_OFFLOAD;
- }
- }
- /* For supporting jumbo frames, the Axi Ethernet hardware must have
- * a larger Rx/Tx Memory. Typically, the size must be more than or
- * equal to 16384 bytes, so that we can enable jumbo option and start
- * supporting jumbo frames. Here we check for memory allocated for
- * Rx/Tx in the hardware from the device-tree and accordingly set
- * flags. */
- p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxmem", NULL);
- if (p) {
- if ((be32_to_cpup(p)) >= 0x4000)
- lp->jumbo_support = 1;
- }
- p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,temac-type",
- NULL);
- if (p)
- lp->temac_type = be32_to_cpup(p);
- p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,phy-type", NULL);
- if (p)
- lp->phy_type = be32_to_cpup(p);
-
- /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
- np = of_parse_phandle(op->dev.of_node, "axistream-connected", 0);
- if (!np) {
- dev_err(&op->dev, "could not find DMA node\n");
- goto err_iounmap;
- }
- lp->dma_regs = of_iomap(np, 0);
- if (lp->dma_regs) {
- dev_dbg(&op->dev, "MEM base: %p\n", lp->dma_regs);
- } else {
- dev_err(&op->dev, "unable to map DMA registers\n");
- of_node_put(np);
- }
- lp->rx_irq = irq_of_parse_and_map(np, 1);
- lp->tx_irq = irq_of_parse_and_map(np, 0);
- of_node_put(np);
- if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
- dev_err(&op->dev, "could not determine irqs\n");
- ret = -ENOMEM;
- goto err_iounmap_2;
- }
-
- /* Retrieve the MAC address */
- addr = of_get_property(op->dev.of_node, "local-mac-address", &size);
- if ((!addr) || (size != 6)) {
- dev_err(&op->dev, "could not find MAC address\n");
- ret = -ENODEV;
- goto err_iounmap_2;
- }
- axienet_set_mac_address(ndev, (void *) addr);
-
- lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
- lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
-
- lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0);
- ret = axienet_mdio_setup(lp, op->dev.of_node);
- if (ret)
- dev_warn(&op->dev, "error registering MDIO bus\n");
-
- ret = register_netdev(lp->ndev);
- if (ret) {
- dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
- goto err_iounmap_2;
- }
-
- tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
- (unsigned long) lp);
- tasklet_disable(&lp->dma_err_tasklet);
-
- return 0;
-
-err_iounmap_2:
- if (lp->dma_regs)
- iounmap(lp->dma_regs);
-err_iounmap:
- iounmap(lp->regs);
-nodev:
- free_netdev(ndev);
- ndev = NULL;
- return ret;
-}
-
-static int __devexit axienet_of_remove(struct platform_device *op)
-{
- struct net_device *ndev = dev_get_drvdata(&op->dev);
- struct axienet_local *lp = netdev_priv(ndev);
-
- axienet_mdio_teardown(lp);
- unregister_netdev(ndev);
-
- if (lp->phy_node)
- of_node_put(lp->phy_node);
- lp->phy_node = NULL;
-
- dev_set_drvdata(&op->dev, NULL);
-
- iounmap(lp->regs);
- if (lp->dma_regs)
- iounmap(lp->dma_regs);
- free_netdev(ndev);
-
- return 0;
-}
-
-static struct platform_driver axienet_of_driver = {
- .probe = axienet_of_probe,
- .remove = __devexit_p(axienet_of_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "xilinx_axienet",
- .of_match_table = axienet_of_match,
- },
-};
-
-module_platform_driver(axienet_of_driver);
-
-MODULE_DESCRIPTION("Xilinx Axi Ethernet driver");
-MODULE_AUTHOR("Xilinx");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
deleted file mode 100644
index e90e1f46..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * MDIO bus driver for the Xilinx Axi Ethernet device
- *
- * Copyright (c) 2009 Secret Lab Technologies, Ltd.
- * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
- * Copyright (c) 2010 - 2011 PetaLogix
- * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
- */
-
-#include <linux/of_address.h>
-#include <linux/of_mdio.h>
-#include <linux/jiffies.h>
-
-#include "xilinx_axienet.h"
-
-#define MAX_MDIO_FREQ 2500000 /* 2.5 MHz */
-#define DEFAULT_CLOCK_DIVISOR XAE_MDIO_DIV_DFT
-
-/* Wait till MDIO interface is ready to accept a new transaction.*/
-int axienet_mdio_wait_until_ready(struct axienet_local *lp)
-{
- long end = jiffies + 2;
- while (!(axienet_ior(lp, XAE_MDIO_MCR_OFFSET) &
- XAE_MDIO_MCR_READY_MASK)) {
- if (end - jiffies <= 0) {
- WARN_ON(1);
- return -ETIMEDOUT;
- }
- udelay(1);
- }
- return 0;
-}
-
-/**
- * axienet_mdio_read - MDIO interface read function
- * @bus: Pointer to mii bus structure
- * @phy_id: Address of the PHY device
- * @reg: PHY register to read
- *
- * returns: The register contents on success, -ETIMEDOUT on a timeout
- *
- * Reads the contents of the requested register from the requested PHY
- * address by first writing the details into MCR register. After a while
- * the register MRD is read to obtain the PHY register content.
- */
-static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
-{
- u32 rc;
- int ret;
- struct axienet_local *lp = bus->priv;
-
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
-
- axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
- (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
- XAE_MDIO_MCR_PHYAD_MASK) |
- ((reg << XAE_MDIO_MCR_REGAD_SHIFT) &
- XAE_MDIO_MCR_REGAD_MASK) |
- XAE_MDIO_MCR_INITIATE_MASK |
- XAE_MDIO_MCR_OP_READ_MASK));
-
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
-
- rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF;
-
- dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n",
- phy_id, reg, rc);
-
- return rc;
-}
-
-/**
- * axienet_mdio_write - MDIO interface write function
- * @bus: Pointer to mii bus structure
- * @phy_id: Address of the PHY device
- * @reg: PHY register to write to
- * @val: Value to be written into the register
- *
- * returns: 0 on success, -ETIMEDOUT on a timeout
- *
- * Writes the value to the requested register by first writing the value
- * into MWD register. The the MCR register is then appropriately setup
- * to finish the write operation.
- */
-static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
- u16 val)
-{
- int ret;
- struct axienet_local *lp = bus->priv;
-
- dev_dbg(lp->dev, "axienet_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
- phy_id, reg, val);
-
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
-
- axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val);
- axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
- (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
- XAE_MDIO_MCR_PHYAD_MASK) |
- ((reg << XAE_MDIO_MCR_REGAD_SHIFT) &
- XAE_MDIO_MCR_REGAD_MASK) |
- XAE_MDIO_MCR_INITIATE_MASK |
- XAE_MDIO_MCR_OP_WRITE_MASK));
-
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-/**
- * axienet_mdio_setup - MDIO setup function
- * @lp: Pointer to axienet local data structure.
- * @np: Pointer to device node
- *
- * returns: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
- * mdiobus_alloc (to allocate memory for mii bus structure) fails.
- *
- * Sets up the MDIO interface by initializing the MDIO clock and enabling the
- * MDIO interface in hardware. Register the MDIO interface.
- **/
-int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
-{
- int ret;
- u32 clk_div, host_clock;
- u32 *property_p;
- struct mii_bus *bus;
- struct resource res;
- struct device_node *np1;
-
- /* clk_div can be calculated by deriving it from the equation:
- * fMDIO = fHOST / ((1 + clk_div) * 2)
- *
- * Where fMDIO <= 2500000, so we get:
- * fHOST / ((1 + clk_div) * 2) <= 2500000
- *
- * Then we get:
- * 1 / ((1 + clk_div) * 2) <= (2500000 / fHOST)
- *
- * Then we get:
- * 1 / (1 + clk_div) <= ((2500000 * 2) / fHOST)
- *
- * Then we get:
- * 1 / (1 + clk_div) <= (5000000 / fHOST)
- *
- * So:
- * (1 + clk_div) >= (fHOST / 5000000)
- *
- * And finally:
- * clk_div >= (fHOST / 5000000) - 1
- *
- * fHOST can be read from the flattened device tree as property
- * "clock-frequency" from the CPU
- */
-
- np1 = of_find_node_by_name(NULL, "cpu");
- if (!np1) {
- printk(KERN_WARNING "%s(): Could not find CPU device node.",
- __func__);
- printk(KERN_WARNING "Setting MDIO clock divisor to "
- "default %d\n", DEFAULT_CLOCK_DIVISOR);
- clk_div = DEFAULT_CLOCK_DIVISOR;
- goto issue;
- }
- property_p = (u32 *) of_get_property(np1, "clock-frequency", NULL);
- if (!property_p) {
- printk(KERN_WARNING "%s(): Could not find CPU property: "
- "clock-frequency.", __func__);
- printk(KERN_WARNING "Setting MDIO clock divisor to "
- "default %d\n", DEFAULT_CLOCK_DIVISOR);
- clk_div = DEFAULT_CLOCK_DIVISOR;
- goto issue;
- }
-
- host_clock = be32_to_cpup(property_p);
- clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
- /* If there is any remainder from the division of
- * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
- * 1 to the clock divisor or we will surely be above 2.5 MHz */
- if (host_clock % (MAX_MDIO_FREQ * 2))
- clk_div++;
-
- printk(KERN_DEBUG "%s(): Setting MDIO clock divisor to %u based "
- "on %u Hz host clock.\n", __func__, clk_div, host_clock);
-
- of_node_put(np1);
-issue:
- axienet_iow(lp, XAE_MDIO_MC_OFFSET,
- (((u32) clk_div) | XAE_MDIO_MC_MDIOEN_MASK));
-
- ret = axienet_mdio_wait_until_ready(lp);
- if (ret < 0)
- return ret;
-
- bus = mdiobus_alloc();
- if (!bus)
- return -ENOMEM;
-
- np1 = of_get_parent(lp->phy_node);
- of_address_to_resource(np1, 0, &res);
- snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
- (unsigned long long) res.start);
-
- bus->priv = lp;
- bus->name = "Xilinx Axi Ethernet MDIO";
- bus->read = axienet_mdio_read;
- bus->write = axienet_mdio_write;
- bus->parent = lp->dev;
- bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
- lp->mii_bus = bus;
-
- ret = of_mdiobus_register(bus, np1);
- if (ret) {
- mdiobus_free(bus);
- return ret;
- }
- return 0;
-}
-
-/**
- * axienet_mdio_teardown - MDIO remove function
- * @lp: Pointer to axienet local data structure.
- *
- * Unregisters the MDIO and frees any associate memory for mii bus.
- */
-void axienet_mdio_teardown(struct axienet_local *lp)
-{
- mdiobus_unregister(lp->mii_bus);
- kfree(lp->mii_bus->irq);
- mdiobus_free(lp->mii_bus);
- lp->mii_bus = NULL;
-}
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_emaclite.c
deleted file mode 100644
index 77cfe511..00000000
--- a/ANDROID_3.4.5/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ /dev/null
@@ -1,1308 +0,0 @@
-/*
- * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device.
- *
- * This is a new flat driver which is based on the original emac_lite
- * driver from John Williams <john.williams@petalogix.com>.
- *
- * 2007-2009 (c) Xilinx, 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.
- */
-
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_mdio.h>
-#include <linux/of_net.h>
-#include <linux/phy.h>
-#include <linux/interrupt.h>
-
-#define DRIVER_NAME "xilinx_emaclite"
-
-/* Register offsets for the EmacLite Core */
-#define XEL_TXBUFF_OFFSET 0x0 /* Transmit Buffer */
-#define XEL_MDIOADDR_OFFSET 0x07E4 /* MDIO Address Register */
-#define XEL_MDIOWR_OFFSET 0x07E8 /* MDIO Write Data Register */
-#define XEL_MDIORD_OFFSET 0x07EC /* MDIO Read Data Register */
-#define XEL_MDIOCTRL_OFFSET 0x07F0 /* MDIO Control Register */
-#define XEL_GIER_OFFSET 0x07F8 /* GIE Register */
-#define XEL_TSR_OFFSET 0x07FC /* Tx status */
-#define XEL_TPLR_OFFSET 0x07F4 /* Tx packet length */
-
-#define XEL_RXBUFF_OFFSET 0x1000 /* Receive Buffer */
-#define XEL_RPLR_OFFSET 0x100C /* Rx packet length */
-#define XEL_RSR_OFFSET 0x17FC /* Rx status */
-
-#define XEL_BUFFER_OFFSET 0x0800 /* Next Tx/Rx buffer's offset */
-
-/* MDIO Address Register Bit Masks */
-#define XEL_MDIOADDR_REGADR_MASK 0x0000001F /* Register Address */
-#define XEL_MDIOADDR_PHYADR_MASK 0x000003E0 /* PHY Address */
-#define XEL_MDIOADDR_PHYADR_SHIFT 5
-#define XEL_MDIOADDR_OP_MASK 0x00000400 /* RD/WR Operation */
-
-/* MDIO Write Data Register Bit Masks */
-#define XEL_MDIOWR_WRDATA_MASK 0x0000FFFF /* Data to be Written */
-
-/* MDIO Read Data Register Bit Masks */
-#define XEL_MDIORD_RDDATA_MASK 0x0000FFFF /* Data to be Read */
-
-/* MDIO Control Register Bit Masks */
-#define XEL_MDIOCTRL_MDIOSTS_MASK 0x00000001 /* MDIO Status Mask */
-#define XEL_MDIOCTRL_MDIOEN_MASK 0x00000008 /* MDIO Enable */
-
-/* Global Interrupt Enable Register (GIER) Bit Masks */
-#define XEL_GIER_GIE_MASK 0x80000000 /* Global Enable */
-
-/* Transmit Status Register (TSR) Bit Masks */
-#define XEL_TSR_XMIT_BUSY_MASK 0x00000001 /* Tx complete */
-#define XEL_TSR_PROGRAM_MASK 0x00000002 /* Program the MAC address */
-#define XEL_TSR_XMIT_IE_MASK 0x00000008 /* Tx interrupt enable bit */
-#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000 /* Buffer is active, SW bit
- * only. This is not documented
- * in the HW spec */
-
-/* Define for programming the MAC address into the EmacLite */
-#define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
-
-/* Receive Status Register (RSR) */
-#define XEL_RSR_RECV_DONE_MASK 0x00000001 /* Rx complete */
-#define XEL_RSR_RECV_IE_MASK 0x00000008 /* Rx interrupt enable bit */
-
-/* Transmit Packet Length Register (TPLR) */
-#define XEL_TPLR_LENGTH_MASK 0x0000FFFF /* Tx packet length */
-
-/* Receive Packet Length Register (RPLR) */
-#define XEL_RPLR_LENGTH_MASK 0x0000FFFF /* Rx packet length */
-
-#define XEL_HEADER_OFFSET 12 /* Offset to length field */
-#define XEL_HEADER_SHIFT 16 /* Shift value for length */
-
-/* General Ethernet Definitions */
-#define XEL_ARP_PACKET_SIZE 28 /* Max ARP packet size */
-#define XEL_HEADER_IP_LENGTH_OFFSET 16 /* IP Length Offset */
-
-
-
-#define TX_TIMEOUT (60*HZ) /* Tx timeout is 60 seconds. */
-#define ALIGNMENT 4
-
-/* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
-#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
-
-/**
- * struct net_local - Our private per device data
- * @ndev: instance of the network device
- * @tx_ping_pong: indicates whether Tx Pong buffer is configured in HW
- * @rx_ping_pong: indicates whether Rx Pong buffer is configured in HW
- * @next_tx_buf_to_use: next Tx buffer to write to
- * @next_rx_buf_to_use: next Rx buffer to read from
- * @base_addr: base address of the Emaclite device
- * @reset_lock: lock used for synchronization
- * @deferred_skb: holds an skb (for transmission at a later time) when the
- * Tx buffer is not free
- * @phy_dev: pointer to the PHY device
- * @phy_node: pointer to the PHY device node
- * @mii_bus: pointer to the MII bus
- * @mdio_irqs: IRQs table for MDIO bus
- * @last_link: last link status
- * @has_mdio: indicates whether MDIO is included in the HW
- */
-struct net_local {
-
- struct net_device *ndev;
-
- bool tx_ping_pong;
- bool rx_ping_pong;
- u32 next_tx_buf_to_use;
- u32 next_rx_buf_to_use;
- void __iomem *base_addr;
-
- spinlock_t reset_lock;
- struct sk_buff *deferred_skb;
-
- struct phy_device *phy_dev;
- struct device_node *phy_node;
-
- struct mii_bus *mii_bus;
- int mdio_irqs[PHY_MAX_ADDR];
-
- int last_link;
- bool has_mdio;
-};
-
-
-/*************************/
-/* EmacLite driver calls */
-/*************************/
-
-/**
- * xemaclite_enable_interrupts - Enable the interrupts for the EmacLite device
- * @drvdata: Pointer to the Emaclite device private data
- *
- * This function enables the Tx and Rx interrupts for the Emaclite device along
- * with the Global Interrupt Enable.
- */
-static void xemaclite_enable_interrupts(struct net_local *drvdata)
-{
- u32 reg_data;
-
- /* Enable the Tx interrupts for the first Buffer */
- reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
- out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
- reg_data | XEL_TSR_XMIT_IE_MASK);
-
- /* Enable the Tx interrupts for the second Buffer if
- * configured in HW */
- if (drvdata->tx_ping_pong != 0) {
- reg_data = in_be32(drvdata->base_addr +
- XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
- out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
- XEL_TSR_OFFSET,
- reg_data | XEL_TSR_XMIT_IE_MASK);
- }
-
- /* Enable the Rx interrupts for the first buffer */
- out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
- XEL_RSR_RECV_IE_MASK);
-
- /* Enable the Rx interrupts for the second Buffer if
- * configured in HW */
- if (drvdata->rx_ping_pong != 0) {
- out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
- XEL_RSR_OFFSET,
- XEL_RSR_RECV_IE_MASK);
- }
-
- /* Enable the Global Interrupt Enable */
- out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
-}
-
-/**
- * xemaclite_disable_interrupts - Disable the interrupts for the EmacLite device
- * @drvdata: Pointer to the Emaclite device private data
- *
- * This function disables the Tx and Rx interrupts for the Emaclite device,
- * along with the Global Interrupt Enable.
- */
-static void xemaclite_disable_interrupts(struct net_local *drvdata)
-{
- u32 reg_data;
-
- /* Disable the Global Interrupt Enable */
- out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
-
- /* Disable the Tx interrupts for the first buffer */
- reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
- out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
- reg_data & (~XEL_TSR_XMIT_IE_MASK));
-
- /* Disable the Tx interrupts for the second Buffer
- * if configured in HW */
- if (drvdata->tx_ping_pong != 0) {
- reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
- XEL_TSR_OFFSET);
- out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
- XEL_TSR_OFFSET,
- reg_data & (~XEL_TSR_XMIT_IE_MASK));
- }
-
- /* Disable the Rx interrupts for the first buffer */
- reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
- out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
- reg_data & (~XEL_RSR_RECV_IE_MASK));
-
- /* Disable the Rx interrupts for the second buffer
- * if configured in HW */
- if (drvdata->rx_ping_pong != 0) {
-
- reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
- XEL_RSR_OFFSET);
- out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
- XEL_RSR_OFFSET,
- reg_data & (~XEL_RSR_RECV_IE_MASK));
- }
-}
-
-/**
- * xemaclite_aligned_write - Write from 16-bit aligned to 32-bit aligned address
- * @src_ptr: Void pointer to the 16-bit aligned source address
- * @dest_ptr: Pointer to the 32-bit aligned destination address
- * @length: Number bytes to write from source to destination
- *
- * This function writes data from a 16-bit aligned buffer to a 32-bit aligned
- * address in the EmacLite device.
- */
-static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
- unsigned length)
-{
- u32 align_buffer;
- u32 *to_u32_ptr;
- u16 *from_u16_ptr, *to_u16_ptr;
-
- to_u32_ptr = dest_ptr;
- from_u16_ptr = src_ptr;
- align_buffer = 0;
-
- for (; length > 3; length -= 4) {
- to_u16_ptr = (u16 *)&align_buffer;
- *to_u16_ptr++ = *from_u16_ptr++;
- *to_u16_ptr++ = *from_u16_ptr++;
-
- /* Output a word */
- *to_u32_ptr++ = align_buffer;
- }
- if (length) {
- u8 *from_u8_ptr, *to_u8_ptr;
-
- /* Set up to output the remaining data */
- align_buffer = 0;
- to_u8_ptr = (u8 *) &align_buffer;
- from_u8_ptr = (u8 *) from_u16_ptr;
-
- /* Output the remaining data */
- for (; length > 0; length--)
- *to_u8_ptr++ = *from_u8_ptr++;
-
- *to_u32_ptr = align_buffer;
- }
-}
-
-/**
- * xemaclite_aligned_read - Read from 32-bit aligned to 16-bit aligned buffer
- * @src_ptr: Pointer to the 32-bit aligned source address
- * @dest_ptr: Pointer to the 16-bit aligned destination address
- * @length: Number bytes to read from source to destination
- *
- * This function reads data from a 32-bit aligned address in the EmacLite device
- * to a 16-bit aligned buffer.
- */
-static void xemaclite_aligned_read(u32 *src_ptr, u8 *dest_ptr,
- unsigned length)
-{
- u16 *to_u16_ptr, *from_u16_ptr;
- u32 *from_u32_ptr;
- u32 align_buffer;
-
- from_u32_ptr = src_ptr;
- to_u16_ptr = (u16 *) dest_ptr;
-
- for (; length > 3; length -= 4) {
- /* Copy each word into the temporary buffer */
- align_buffer = *from_u32_ptr++;
- from_u16_ptr = (u16 *)&align_buffer;
-
- /* Read data from source */
- *to_u16_ptr++ = *from_u16_ptr++;
- *to_u16_ptr++ = *from_u16_ptr++;
- }
-
- if (length) {
- u8 *to_u8_ptr, *from_u8_ptr;
-
- /* Set up to read the remaining data */
- to_u8_ptr = (u8 *) to_u16_ptr;
- align_buffer = *from_u32_ptr++;
- from_u8_ptr = (u8 *) &align_buffer;
-
- /* Read the remaining data */
- for (; length > 0; length--)
- *to_u8_ptr = *from_u8_ptr;
- }
-}
-
-/**
- * xemaclite_send_data - Send an Ethernet frame
- * @drvdata: Pointer to the Emaclite device private data
- * @data: Pointer to the data to be sent
- * @byte_count: Total frame size, including header
- *
- * This function checks if the Tx buffer of the Emaclite device is free to send
- * data. If so, it fills the Tx buffer with data for transmission. Otherwise, it
- * returns an error.
- *
- * Return: 0 upon success or -1 if the buffer(s) are full.
- *
- * Note: The maximum Tx packet size can not be more than Ethernet header
- * (14 Bytes) + Maximum MTU (1500 bytes). This is excluding FCS.
- */
-static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
- unsigned int byte_count)
-{
- u32 reg_data;
- void __iomem *addr;
-
- /* Determine the expected Tx buffer address */
- addr = drvdata->base_addr + drvdata->next_tx_buf_to_use;
-
- /* If the length is too large, truncate it */
- if (byte_count > ETH_FRAME_LEN)
- byte_count = ETH_FRAME_LEN;
-
- /* Check if the expected buffer is available */
- reg_data = in_be32(addr + XEL_TSR_OFFSET);
- if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
- XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
-
- /* Switch to next buffer if configured */
- if (drvdata->tx_ping_pong != 0)
- drvdata->next_tx_buf_to_use ^= XEL_BUFFER_OFFSET;
- } else if (drvdata->tx_ping_pong != 0) {
- /* If the expected buffer is full, try the other buffer,
- * if it is configured in HW */
-
- addr = (void __iomem __force *)((u32 __force)addr ^
- XEL_BUFFER_OFFSET);
- reg_data = in_be32(addr + XEL_TSR_OFFSET);
-
- if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
- XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
- return -1; /* Buffers were full, return failure */
- } else
- return -1; /* Buffer was full, return failure */
-
- /* Write the frame to the buffer */
- xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
-
- out_be32(addr + XEL_TPLR_OFFSET, (byte_count & XEL_TPLR_LENGTH_MASK));
-
- /* Update the Tx Status Register to indicate that there is a
- * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
- * is used by the interrupt handler to check whether a frame
- * has been transmitted */
- reg_data = in_be32(addr + XEL_TSR_OFFSET);
- reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
- out_be32(addr + XEL_TSR_OFFSET, reg_data);
-
- return 0;
-}
-
-/**
- * xemaclite_recv_data - Receive a frame
- * @drvdata: Pointer to the Emaclite device private data
- * @data: Address where the data is to be received
- *
- * This function is intended to be called from the interrupt context or
- * with a wrapper which waits for the receive frame to be available.
- *
- * Return: Total number of bytes received
- */
-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
-{
- void __iomem *addr;
- u16 length, proto_type;
- u32 reg_data;
-
- /* Determine the expected buffer address */
- addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
-
- /* Verify which buffer has valid data */
- reg_data = in_be32(addr + XEL_RSR_OFFSET);
-
- if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
- if (drvdata->rx_ping_pong != 0)
- drvdata->next_rx_buf_to_use ^= XEL_BUFFER_OFFSET;
- } else {
- /* The instance is out of sync, try other buffer if other
- * buffer is configured, return 0 otherwise. If the instance is
- * out of sync, do not update the 'next_rx_buf_to_use' since it
- * will correct on subsequent calls */
- if (drvdata->rx_ping_pong != 0)
- addr = (void __iomem __force *)((u32 __force)addr ^
- XEL_BUFFER_OFFSET);
- else
- return 0; /* No data was available */
-
- /* Verify that buffer has valid data */
- reg_data = in_be32(addr + XEL_RSR_OFFSET);
- if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
- XEL_RSR_RECV_DONE_MASK)
- return 0; /* No data was available */
- }
-
- /* Get the protocol type of the ethernet frame that arrived */
- proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET +
- XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
- XEL_RPLR_LENGTH_MASK);
-
- /* Check if received ethernet frame is a raw ethernet frame
- * or an IP packet or an ARP packet */
- if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
-
- if (proto_type == ETH_P_IP) {
- length = ((ntohl(in_be32(addr +
- XEL_HEADER_IP_LENGTH_OFFSET +
- XEL_RXBUFF_OFFSET)) >>
- XEL_HEADER_SHIFT) &
- XEL_RPLR_LENGTH_MASK);
- length += ETH_HLEN + ETH_FCS_LEN;
-
- } else if (proto_type == ETH_P_ARP)
- length = XEL_ARP_PACKET_SIZE + ETH_HLEN + ETH_FCS_LEN;
- else
- /* Field contains type other than IP or ARP, use max
- * frame size and let user parse it */
- length = ETH_FRAME_LEN + ETH_FCS_LEN;
- } else
- /* Use the length in the frame, plus the header and trailer */
- length = proto_type + ETH_HLEN + ETH_FCS_LEN;
-
- /* Read from the EmacLite device */
- xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
- data, length);
-
- /* Acknowledge the frame */
- reg_data = in_be32(addr + XEL_RSR_OFFSET);
- reg_data &= ~XEL_RSR_RECV_DONE_MASK;
- out_be32(addr + XEL_RSR_OFFSET, reg_data);
-
- return length;
-}
-
-/**
- * xemaclite_update_address - Update the MAC address in the device
- * @drvdata: Pointer to the Emaclite device private data
- * @address_ptr:Pointer to the MAC address (MAC address is a 48-bit value)
- *
- * Tx must be idle and Rx should be idle for deterministic results.
- * It is recommended that this function should be called after the
- * initialization and before transmission of any packets from the device.
- * The MAC address can be programmed using any of the two transmit
- * buffers (if configured).
- */
-static void xemaclite_update_address(struct net_local *drvdata,
- u8 *address_ptr)
-{
- void __iomem *addr;
- u32 reg_data;
-
- /* Determine the expected Tx buffer address */
- addr = drvdata->base_addr + drvdata->next_tx_buf_to_use;
-
- xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
-
- out_be32(addr + XEL_TPLR_OFFSET, ETH_ALEN);
-
- /* Update the MAC address in the EmacLite */
- reg_data = in_be32(addr + XEL_TSR_OFFSET);
- out_be32(addr + XEL_TSR_OFFSET, reg_data | XEL_TSR_PROG_MAC_ADDR);
-
- /* Wait for EmacLite to finish with the MAC address update */
- while ((in_be32(addr + XEL_TSR_OFFSET) &
- XEL_TSR_PROG_MAC_ADDR) != 0)
- ;
-}
-
-/**
- * xemaclite_set_mac_address - Set the MAC address for this device
- * @dev: Pointer to the network device instance
- * @addr: Void pointer to the sockaddr structure
- *
- * This function copies the HW address from the sockaddr strucutre to the
- * net_device structure and updates the address in HW.
- *
- * Return: Error if the net device is busy or 0 if the addr is set
- * successfully
- */
-static int xemaclite_set_mac_address(struct net_device *dev, void *address)
-{
- struct net_local *lp = netdev_priv(dev);
- struct sockaddr *addr = address;
-
- if (netif_running(dev))
- return -EBUSY;
-
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- xemaclite_update_address(lp, dev->dev_addr);
- return 0;
-}
-
-/**
- * xemaclite_tx_timeout - Callback for Tx Timeout
- * @dev: Pointer to the network device
- *
- * This function is called when Tx time out occurs for Emaclite device.
- */
-static void xemaclite_tx_timeout(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
-
- dev_err(&lp->ndev->dev, "Exceeded transmit timeout of %lu ms\n",
- TX_TIMEOUT * 1000UL / HZ);
-
- dev->stats.tx_errors++;
-
- /* Reset the device */
- spin_lock_irqsave(&lp->reset_lock, flags);
-
- /* Shouldn't really be necessary, but shouldn't hurt */
- netif_stop_queue(dev);
-
- xemaclite_disable_interrupts(lp);
- xemaclite_enable_interrupts(lp);
-
- if (lp->deferred_skb) {
- dev_kfree_skb(lp->deferred_skb);
- lp->deferred_skb = NULL;
- dev->stats.tx_errors++;
- }
-
- /* To exclude tx timeout */
- dev->trans_start = jiffies; /* prevent tx timeout */
-
- /* We're all ready to go. Start the queue */
- netif_wake_queue(dev);
- spin_unlock_irqrestore(&lp->reset_lock, flags);
-}
-
-/**********************/
-/* Interrupt Handlers */
-/**********************/
-
-/**
- * xemaclite_tx_handler - Interrupt handler for frames sent
- * @dev: Pointer to the network device
- *
- * This function updates the number of packets transmitted and handles the
- * deferred skb, if there is one.
- */
-static void xemaclite_tx_handler(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- dev->stats.tx_packets++;
- if (lp->deferred_skb) {
- if (xemaclite_send_data(lp,
- (u8 *) lp->deferred_skb->data,
- lp->deferred_skb->len) != 0)
- return;
- else {
- dev->stats.tx_bytes += lp->deferred_skb->len;
- dev_kfree_skb_irq(lp->deferred_skb);
- lp->deferred_skb = NULL;
- dev->trans_start = jiffies; /* prevent tx timeout */
- netif_wake_queue(dev);
- }
- }
-}
-
-/**
- * xemaclite_rx_handler- Interrupt handler for frames received
- * @dev: Pointer to the network device
- *
- * This function allocates memory for a socket buffer, fills it with data
- * received and hands it over to the TCP/IP stack.
- */
-static void xemaclite_rx_handler(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- struct sk_buff *skb;
- unsigned int align;
- u32 len;
-
- len = ETH_FRAME_LEN + ETH_FCS_LEN;
- skb = netdev_alloc_skb(dev, len + ALIGNMENT);
- if (!skb) {
- /* Couldn't get memory. */
- dev->stats.rx_dropped++;
- dev_err(&lp->ndev->dev, "Could not allocate receive buffer\n");
- return;
- }
-
- /*
- * A new skb should have the data halfword aligned, but this code is
- * here just in case that isn't true. Calculate how many
- * bytes we should reserve to get the data to start on a word
- * boundary */
- align = BUFFER_ALIGN(skb->data);
- if (align)
- skb_reserve(skb, align);
-
- skb_reserve(skb, 2);
-
- len = xemaclite_recv_data(lp, (u8 *) skb->data);
-
- if (!len) {
- dev->stats.rx_errors++;
- dev_kfree_skb_irq(skb);
- return;
- }
-
- skb_put(skb, len); /* Tell the skb how much data we got */
-
- skb->protocol = eth_type_trans(skb, dev);
- skb_checksum_none_assert(skb);
-
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += len;
-
- if (!skb_defer_rx_timestamp(skb))
- netif_rx(skb); /* Send the packet upstream */
-}
-
-/**
- * xemaclite_interrupt - Interrupt handler for this driver
- * @irq: Irq of the Emaclite device
- * @dev_id: Void pointer to the network device instance used as callback
- * reference
- *
- * This function handles the Tx and Rx interrupts of the EmacLite device.
- */
-static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
-{
- bool tx_complete = false;
- struct net_device *dev = dev_id;
- struct net_local *lp = netdev_priv(dev);
- void __iomem *base_addr = lp->base_addr;
- u32 tx_status;
-
- /* Check if there is Rx Data available */
- if ((in_be32(base_addr + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK) ||
- (in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
- & XEL_RSR_RECV_DONE_MASK))
-
- xemaclite_rx_handler(dev);
-
- /* Check if the Transmission for the first buffer is completed */
- tx_status = in_be32(base_addr + XEL_TSR_OFFSET);
- if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
- (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
-
- tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
- out_be32(base_addr + XEL_TSR_OFFSET, tx_status);
-
- tx_complete = true;
- }
-
- /* Check if the Transmission for the second buffer is completed */
- tx_status = in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
- if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
- (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
-
- tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
- out_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET,
- tx_status);
-
- tx_complete = true;
- }
-
- /* If there was a Tx interrupt, call the Tx Handler */
- if (tx_complete != 0)
- xemaclite_tx_handler(dev);
-
- return IRQ_HANDLED;
-}
-
-/**********************/
-/* MDIO Bus functions */
-/**********************/
-
-/**
- * xemaclite_mdio_wait - Wait for the MDIO to be ready to use
- * @lp: Pointer to the Emaclite device private data
- *
- * This function waits till the device is ready to accept a new MDIO
- * request.
- *
- * Return: 0 for success or ETIMEDOUT for a timeout
- */
-
-static int xemaclite_mdio_wait(struct net_local *lp)
-{
- long end = jiffies + 2;
-
- /* wait for the MDIO interface to not be busy or timeout
- after some time.
- */
- while (in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
- XEL_MDIOCTRL_MDIOSTS_MASK) {
- if (end - jiffies <= 0) {
- WARN_ON(1);
- return -ETIMEDOUT;
- }
- msleep(1);
- }
- return 0;
-}
-
-/**
- * xemaclite_mdio_read - Read from a given MII management register
- * @bus: the mii_bus struct
- * @phy_id: the phy address
- * @reg: register number to read from
- *
- * This function waits till the device is ready to accept a new MDIO
- * request and then writes the phy address to the MDIO Address register
- * and reads data from MDIO Read Data register, when its available.
- *
- * Return: Value read from the MII management register
- */
-static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
-{
- struct net_local *lp = bus->priv;
- u32 ctrl_reg;
- u32 rc;
-
- if (xemaclite_mdio_wait(lp))
- return -ETIMEDOUT;
-
- /* Write the PHY address, register number and set the OP bit in the
- * MDIO Address register. Set the Status bit in the MDIO Control
- * register to start a MDIO read transaction.
- */
- ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
- out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
- XEL_MDIOADDR_OP_MASK |
- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
- out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
- ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
-
- if (xemaclite_mdio_wait(lp))
- return -ETIMEDOUT;
-
- rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET);
-
- dev_dbg(&lp->ndev->dev,
- "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
- phy_id, reg, rc);
-
- return rc;
-}
-
-/**
- * xemaclite_mdio_write - Write to a given MII management register
- * @bus: the mii_bus struct
- * @phy_id: the phy address
- * @reg: register number to write to
- * @val: value to write to the register number specified by reg
- *
- * This function waits till the device is ready to accept a new MDIO
- * request and then writes the val to the MDIO Write Data register.
- */
-static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
- u16 val)
-{
- struct net_local *lp = bus->priv;
- u32 ctrl_reg;
-
- dev_dbg(&lp->ndev->dev,
- "xemaclite_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
- phy_id, reg, val);
-
- if (xemaclite_mdio_wait(lp))
- return -ETIMEDOUT;
-
- /* Write the PHY address, register number and clear the OP bit in the
- * MDIO Address register and then write the value into the MDIO Write
- * Data register. Finally, set the Status bit in the MDIO Control
- * register to start a MDIO write transaction.
- */
- ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
- out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
- ~XEL_MDIOADDR_OP_MASK &
- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
- out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val);
- out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
- ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
-
- return 0;
-}
-
-/**
- * xemaclite_mdio_reset - Reset the mdio bus.
- * @bus: Pointer to the MII bus
- *
- * This function is required(?) as per Documentation/networking/phy.txt.
- * There is no reset in this device; this function always returns 0.
- */
-static int xemaclite_mdio_reset(struct mii_bus *bus)
-{
- return 0;
-}
-
-/**
- * xemaclite_mdio_setup - Register mii_bus for the Emaclite device
- * @lp: Pointer to the Emaclite device private data
- * @ofdev: Pointer to OF device structure
- *
- * This function enables MDIO bus in the Emaclite device and registers a
- * mii_bus.
- *
- * Return: 0 upon success or a negative error upon failure
- */
-static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
-{
- struct mii_bus *bus;
- int rc;
- struct resource res;
- struct device_node *np = of_get_parent(lp->phy_node);
-
- /* Don't register the MDIO bus if the phy_node or its parent node
- * can't be found.
- */
- if (!np)
- return -ENODEV;
-
- /* Enable the MDIO bus by asserting the enable bit in MDIO Control
- * register.
- */
- out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
- XEL_MDIOCTRL_MDIOEN_MASK);
-
- bus = mdiobus_alloc();
- if (!bus)
- return -ENOMEM;
-
- of_address_to_resource(np, 0, &res);
- snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
- (unsigned long long)res.start);
- bus->priv = lp;
- bus->name = "Xilinx Emaclite MDIO";
- bus->read = xemaclite_mdio_read;
- bus->write = xemaclite_mdio_write;
- bus->reset = xemaclite_mdio_reset;
- bus->parent = dev;
- bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
-
- lp->mii_bus = bus;
-
- rc = of_mdiobus_register(bus, np);
- if (rc)
- goto err_register;
-
- return 0;
-
-err_register:
- mdiobus_free(bus);
- return rc;
-}
-
-/**
- * xemaclite_adjust_link - Link state callback for the Emaclite device
- * @ndev: pointer to net_device struct
- *
- * There's nothing in the Emaclite device to be configured when the link
- * state changes. We just print the status.
- */
-void xemaclite_adjust_link(struct net_device *ndev)
-{
- struct net_local *lp = netdev_priv(ndev);
- struct phy_device *phy = lp->phy_dev;
- int link_state;
-
- /* hash together the state values to decide if something has changed */
- link_state = phy->speed | (phy->duplex << 1) | phy->link;
-
- if (lp->last_link != link_state) {
- lp->last_link = link_state;
- phy_print_status(phy);
- }
-}
-
-/**
- * xemaclite_open - Open the network device
- * @dev: Pointer to the network device
- *
- * This function sets the MAC address, requests an IRQ and enables interrupts
- * for the Emaclite device and starts the Tx queue.
- * It also connects to the phy device, if MDIO is included in Emaclite device.
- */
-static int xemaclite_open(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- int retval;
-
- /* Just to be safe, stop the device first */
- xemaclite_disable_interrupts(lp);
-
- if (lp->phy_node) {
- u32 bmcr;
-
- lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
- xemaclite_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
- if (!lp->phy_dev) {
- dev_err(&lp->ndev->dev, "of_phy_connect() failed\n");
- return -ENODEV;
- }
-
- /* EmacLite doesn't support giga-bit speeds */
- lp->phy_dev->supported &= (PHY_BASIC_FEATURES);
- lp->phy_dev->advertising = lp->phy_dev->supported;
-
- /* Don't advertise 1000BASE-T Full/Half duplex speeds */
- phy_write(lp->phy_dev, MII_CTRL1000, 0);
-
- /* Advertise only 10 and 100mbps full/half duplex speeds */
- phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL);
-
- /* Restart auto negotiation */
- bmcr = phy_read(lp->phy_dev, MII_BMCR);
- bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(lp->phy_dev, MII_BMCR, bmcr);
-
- phy_start(lp->phy_dev);
- }
-
- /* Set the MAC address each time opened */
- xemaclite_update_address(lp, dev->dev_addr);
-
- /* Grab the IRQ */
- retval = request_irq(dev->irq, xemaclite_interrupt, 0, dev->name, dev);
- if (retval) {
- dev_err(&lp->ndev->dev, "Could not allocate interrupt %d\n",
- dev->irq);
- if (lp->phy_dev)
- phy_disconnect(lp->phy_dev);
- lp->phy_dev = NULL;
-
- return retval;
- }
-
- /* Enable Interrupts */
- xemaclite_enable_interrupts(lp);
-
- /* We're ready to go */
- netif_start_queue(dev);
-
- return 0;
-}
-
-/**
- * xemaclite_close - Close the network device
- * @dev: Pointer to the network device
- *
- * This function stops the Tx queue, disables interrupts and frees the IRQ for
- * the Emaclite device.
- * It also disconnects the phy device associated with the Emaclite device.
- */
-static int xemaclite_close(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- netif_stop_queue(dev);
- xemaclite_disable_interrupts(lp);
- free_irq(dev->irq, dev);
-
- if (lp->phy_dev)
- phy_disconnect(lp->phy_dev);
- lp->phy_dev = NULL;
-
- return 0;
-}
-
-/**
- * xemaclite_send - Transmit a frame
- * @orig_skb: Pointer to the socket buffer to be transmitted
- * @dev: Pointer to the network device
- *
- * This function checks if the Tx buffer of the Emaclite device is free to send
- * data. If so, it fills the Tx buffer with data from socket buffer data,
- * updates the stats and frees the socket buffer. The Tx completion is signaled
- * by an interrupt. If the Tx buffer isn't free, then the socket buffer is
- * deferred and the Tx queue is stopped so that the deferred socket buffer can
- * be transmitted when the Emaclite device is free to transmit data.
- *
- * Return: 0, always.
- */
-static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- struct sk_buff *new_skb;
- unsigned int len;
- unsigned long flags;
-
- len = orig_skb->len;
-
- new_skb = orig_skb;
-
- spin_lock_irqsave(&lp->reset_lock, flags);
- if (xemaclite_send_data(lp, (u8 *) new_skb->data, len) != 0) {
- /* If the Emaclite Tx buffer is busy, stop the Tx queue and
- * defer the skb for transmission during the ISR, after the
- * current transmission is complete */
- netif_stop_queue(dev);
- lp->deferred_skb = new_skb;
- /* Take the time stamp now, since we can't do this in an ISR. */
- skb_tx_timestamp(new_skb);
- spin_unlock_irqrestore(&lp->reset_lock, flags);
- return 0;
- }
- spin_unlock_irqrestore(&lp->reset_lock, flags);
-
- skb_tx_timestamp(new_skb);
-
- dev->stats.tx_bytes += len;
- dev_kfree_skb(new_skb);
-
- return 0;
-}
-
-/**
- * xemaclite_remove_ndev - Free the network device
- * @ndev: Pointer to the network device to be freed
- *
- * This function un maps the IO region of the Emaclite device and frees the net
- * device.
- */
-static void xemaclite_remove_ndev(struct net_device *ndev)
-{
- if (ndev) {
- struct net_local *lp = netdev_priv(ndev);
-
- if (lp->base_addr)
- iounmap((void __iomem __force *) (lp->base_addr));
- free_netdev(ndev);
- }
-}
-
-/**
- * get_bool - Get a parameter from the OF device
- * @ofdev: Pointer to OF device structure
- * @s: Property to be retrieved
- *
- * This function looks for a property in the device node and returns the value
- * of the property if its found or 0 if the property is not found.
- *
- * Return: Value of the parameter if the parameter is found, or 0 otherwise
- */
-static bool get_bool(struct platform_device *ofdev, const char *s)
-{
- u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL);
-
- if (p) {
- return (bool)*p;
- } else {
- dev_warn(&ofdev->dev, "Parameter %s not found,"
- "defaulting to false\n", s);
- return 0;
- }
-}
-
-static struct net_device_ops xemaclite_netdev_ops;
-
-/**
- * xemaclite_of_probe - Probe method for the Emaclite device.
- * @ofdev: Pointer to OF device structure
- * @match: Pointer to the structure used for matching a device
- *
- * This function probes for the Emaclite device in the device tree.
- * It initializes the driver data structure and the hardware, sets the MAC
- * address and registers the network device.
- * It also registers a mii_bus for the Emaclite device, if MDIO is included
- * in the device.
- *
- * Return: 0, if the driver is bound to the Emaclite device, or
- * a negative error if there is failure.
- */
-static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
-{
- struct resource r_irq; /* Interrupt resources */
- struct resource r_mem; /* IO mem resources */
- struct net_device *ndev = NULL;
- struct net_local *lp = NULL;
- struct device *dev = &ofdev->dev;
- const void *mac_address;
-
- int rc = 0;
-
- dev_info(dev, "Device Tree Probing\n");
-
- /* Get iospace for the device */
- rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem);
- if (rc) {
- dev_err(dev, "invalid address\n");
- return rc;
- }
-
- /* Get IRQ for the device */
- rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
- if (!rc) {
- dev_err(dev, "no IRQ found\n");
- return rc;
- }
-
- /* Create an ethernet device instance */
- ndev = alloc_etherdev(sizeof(struct net_local));
- if (!ndev)
- return -ENOMEM;
-
- dev_set_drvdata(dev, ndev);
- SET_NETDEV_DEV(ndev, &ofdev->dev);
-
- ndev->irq = r_irq.start;
- ndev->mem_start = r_mem.start;
- ndev->mem_end = r_mem.end;
-
- lp = netdev_priv(ndev);
- lp->ndev = ndev;
-
- if (!request_mem_region(ndev->mem_start,
- ndev->mem_end - ndev->mem_start + 1,
- DRIVER_NAME)) {
- dev_err(dev, "Couldn't lock memory region at %p\n",
- (void *)ndev->mem_start);
- rc = -EBUSY;
- goto error2;
- }
-
- /* Get the virtual base address for the device */
- lp->base_addr = ioremap(r_mem.start, resource_size(&r_mem));
- if (NULL == lp->base_addr) {
- dev_err(dev, "EmacLite: Could not allocate iomem\n");
- rc = -EIO;
- goto error1;
- }
-
- spin_lock_init(&lp->reset_lock);
- lp->next_tx_buf_to_use = 0x0;
- lp->next_rx_buf_to_use = 0x0;
- lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong");
- lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong");
- mac_address = of_get_mac_address(ofdev->dev.of_node);
-
- if (mac_address)
- /* Set the MAC address. */
- memcpy(ndev->dev_addr, mac_address, 6);
- else
- dev_warn(dev, "No MAC address found\n");
-
- /* Clear the Tx CSR's in case this is a restart */
- out_be32(lp->base_addr + XEL_TSR_OFFSET, 0);
- out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
-
- /* Set the MAC address in the EmacLite device */
- xemaclite_update_address(lp, ndev->dev_addr);
-
- lp->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
- rc = xemaclite_mdio_setup(lp, &ofdev->dev);
- if (rc)
- dev_warn(&ofdev->dev, "error registering MDIO bus\n");
-
- dev_info(dev, "MAC address is now %pM\n", ndev->dev_addr);
-
- ndev->netdev_ops = &xemaclite_netdev_ops;
- ndev->flags &= ~IFF_MULTICAST;
- ndev->watchdog_timeo = TX_TIMEOUT;
-
- /* Finally, register the device */
- rc = register_netdev(ndev);
- if (rc) {
- dev_err(dev,
- "Cannot register network device, aborting\n");
- goto error1;
- }
-
- dev_info(dev,
- "Xilinx EmacLite at 0x%08X mapped to 0x%08X, irq=%d\n",
- (unsigned int __force)ndev->mem_start,
- (unsigned int __force)lp->base_addr, ndev->irq);
- return 0;
-
-error1:
- release_mem_region(ndev->mem_start, resource_size(&r_mem));
-
-error2:
- xemaclite_remove_ndev(ndev);
- return rc;
-}
-
-/**
- * xemaclite_of_remove - Unbind the driver from the Emaclite device.
- * @of_dev: Pointer to OF device structure
- *
- * This function is called if a device is physically removed from the system or
- * if the driver module is being unloaded. It frees any resources allocated to
- * the device.
- *
- * Return: 0, always.
- */
-static int __devexit xemaclite_of_remove(struct platform_device *of_dev)
-{
- struct device *dev = &of_dev->dev;
- struct net_device *ndev = dev_get_drvdata(dev);
-
- struct net_local *lp = netdev_priv(ndev);
-
- /* Un-register the mii_bus, if configured */
- if (lp->has_mdio) {
- mdiobus_unregister(lp->mii_bus);
- kfree(lp->mii_bus->irq);
- mdiobus_free(lp->mii_bus);
- lp->mii_bus = NULL;
- }
-
- unregister_netdev(ndev);
-
- if (lp->phy_node)
- of_node_put(lp->phy_node);
- lp->phy_node = NULL;
-
- release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1);
-
- xemaclite_remove_ndev(ndev);
- dev_set_drvdata(dev, NULL);
-
- return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void
-xemaclite_poll_controller(struct net_device *ndev)
-{
- disable_irq(ndev->irq);
- xemaclite_interrupt(ndev->irq, ndev);
- enable_irq(ndev->irq);
-}
-#endif
-
-static struct net_device_ops xemaclite_netdev_ops = {
- .ndo_open = xemaclite_open,
- .ndo_stop = xemaclite_close,
- .ndo_start_xmit = xemaclite_send,
- .ndo_set_mac_address = xemaclite_set_mac_address,
- .ndo_tx_timeout = xemaclite_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = xemaclite_poll_controller,
-#endif
-};
-
-/* Match table for OF platform binding */
-static struct of_device_id xemaclite_of_match[] __devinitdata = {
- { .compatible = "xlnx,opb-ethernetlite-1.01.a", },
- { .compatible = "xlnx,opb-ethernetlite-1.01.b", },
- { .compatible = "xlnx,xps-ethernetlite-1.00.a", },
- { .compatible = "xlnx,xps-ethernetlite-2.00.a", },
- { .compatible = "xlnx,xps-ethernetlite-2.01.a", },
- { .compatible = "xlnx,xps-ethernetlite-3.00.a", },
- { /* end of list */ },
-};
-MODULE_DEVICE_TABLE(of, xemaclite_of_match);
-
-static struct platform_driver xemaclite_of_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = xemaclite_of_match,
- },
- .probe = xemaclite_of_probe,
- .remove = __devexit_p(xemaclite_of_remove),
-};
-
-module_platform_driver(xemaclite_of_driver);
-
-MODULE_AUTHOR("Xilinx, Inc.");
-MODULE_DESCRIPTION("Xilinx Ethernet MAC Lite driver");
-MODULE_LICENSE("GPL");