aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/arm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/arm')
-rw-r--r--drivers/net/arm/Kconfig74
-rw-r--r--drivers/net/arm/Makefile14
-rw-r--r--drivers/net/arm/am79c961a.c770
-rw-r--r--drivers/net/arm/am79c961a.h145
-rw-r--r--drivers/net/arm/at91_ether.c1254
-rw-r--r--drivers/net/arm/at91_ether.h109
-rw-r--r--drivers/net/arm/ep93xx_eth.c904
-rw-r--r--drivers/net/arm/ether1.c1094
-rw-r--r--drivers/net/arm/ether1.h280
-rw-r--r--drivers/net/arm/ether3.c918
-rw-r--r--drivers/net/arm/ether3.h176
-rw-r--r--drivers/net/arm/etherh.c866
-rw-r--r--drivers/net/arm/ixp4xx_eth.c1489
-rw-r--r--drivers/net/arm/ks8695net.c1656
-rw-r--r--drivers/net/arm/ks8695net.h107
-rw-r--r--drivers/net/arm/w90p910_ether.c1123
16 files changed, 0 insertions, 10979 deletions
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
deleted file mode 100644
index 39e1c0d39476..000000000000
--- a/drivers/net/arm/Kconfig
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Acorn Network device configuration
-# These are for Acorn's Expansion card network interfaces
-#
-config ARM_AM79C961A
- bool "ARM EBSA110 AM79C961A support"
- depends on ARM && ARCH_EBSA110
- select CRC32
- help
- If you wish to compile a kernel for the EBSA-110, then you should
- always answer Y to this.
-
-config ARM_ETHER1
- tristate "Acorn Ether1 support"
- depends on ARM && ARCH_ACORN
- help
- If you have an Acorn system with one of these (AKA25) network cards,
- you should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHER3
- tristate "Acorn/ANT Ether3 support"
- depends on ARM && ARCH_ACORN
- help
- If you have an Acorn system with one of these network cards, you
- should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHERH
- tristate "I-cubed EtherH/ANT EtherM support"
- depends on ARM && ARCH_ACORN
- select CRC32
- help
- If you have an Acorn system with one of these network cards, you
- should say Y to this option if you wish to use it with Linux.
-
-config ARM_AT91_ETHER
- tristate "AT91RM9200 Ethernet support"
- depends on ARM && ARCH_AT91RM9200
- select MII
- help
- If you wish to compile a kernel for the AT91RM9200 and enable
- ethernet support, then you should always answer Y to this.
-
-config ARM_KS8695_ETHER
- tristate "KS8695 Ethernet support"
- depends on ARM && ARCH_KS8695
- select MII
- help
- If you wish to compile a kernel for the KS8695 and want to
- use the internal ethernet then you should answer Y to this.
-
-config EP93XX_ETH
- tristate "EP93xx Ethernet support"
- depends on ARM && ARCH_EP93XX
- select MII
- help
- This is a driver for the ethernet hardware included in EP93xx CPUs.
- Say Y if you are building a kernel for EP93xx based devices.
-
-config IXP4XX_ETH
- tristate "Intel IXP4xx Ethernet support"
- depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
- select PHYLIB
- help
- Say Y here if you want to use built-in Ethernet ports
- on IXP4xx processor.
-
-config W90P910_ETH
- tristate "Nuvoton w90p910 Ethernet support"
- depends on ARM && ARCH_W90X900
- select PHYLIB
- select MII
- help
- Say Y here if you want to use built-in Ethernet ports
- on w90p910 processor.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
deleted file mode 100644
index 303171f589e6..000000000000
--- a/drivers/net/arm/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# File: drivers/net/arm/Makefile
-#
-# Makefile for the ARM network device drivers
-#
-
-obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
-obj-$(CONFIG_ARM_ETHERH) += etherh.o
-obj-$(CONFIG_ARM_ETHER3) += ether3.o
-obj-$(CONFIG_ARM_ETHER1) += ether1.o
-obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
-obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
-obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
-obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
-obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
deleted file mode 100644
index 3b1416e3d217..000000000000
--- a/drivers/net/arm/am79c961a.c
+++ /dev/null
@@ -1,770 +0,0 @@
-/*
- * linux/drivers/net/am79c961.c
- *
- * by Russell King <rmk@arm.linux.org.uk> 1995-2001.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Derived from various things including skeleton.c
- *
- * This is a special driver for the am79c961A Lance chip used in the
- * Intel (formally Digital Equipment Corp) EBSA110 platform. Please
- * note that this can not be built as a module (it doesn't make sense).
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/system.h>
-
-#define TX_BUFFERS 15
-#define RX_BUFFERS 25
-
-#include "am79c961a.h"
-
-static irqreturn_t
-am79c961_interrupt (int irq, void *dev_id);
-
-static unsigned int net_debug = NET_DEBUG;
-
-static const char version[] =
- "am79c961 ethernet driver (C) 1995-2001 Russell King v0.04\n";
-
-/* --------------------------------------------------------------------------- */
-
-#ifdef __arm__
-static void write_rreg(u_long base, u_int reg, u_int val)
-{
- asm volatile(
- "str%?h %1, [%2] @ NET_RAP\n\t"
- "str%?h %0, [%2, #-4] @ NET_RDP"
- :
- : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-}
-
-static inline unsigned short read_rreg(u_long base_addr, u_int reg)
-{
- unsigned short v;
- asm volatile(
- "str%?h %1, [%2] @ NET_RAP\n\t"
- "ldr%?h %0, [%2, #-4] @ NET_RDP"
- : "=r" (v)
- : "r" (reg), "r" (ISAIO_BASE + 0x0464));
- return v;
-}
-
-static inline void write_ireg(u_long base, u_int reg, u_int val)
-{
- asm volatile(
- "str%?h %1, [%2] @ NET_RAP\n\t"
- "str%?h %0, [%2, #8] @ NET_IDP"
- :
- : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-}
-
-static inline unsigned short read_ireg(u_long base_addr, u_int reg)
-{
- u_short v;
- asm volatile(
- "str%?h %1, [%2] @ NAT_RAP\n\t"
- "ldr%?h %0, [%2, #8] @ NET_IDP\n\t"
- : "=r" (v)
- : "r" (reg), "r" (ISAIO_BASE + 0x0464));
- return v;
-}
-
-#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
-#define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1))
-
-static void
-am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
-{
- offset = ISAMEM_BASE + (offset << 1);
- length = (length + 1) & ~1;
- if ((int)buf & 2) {
- asm volatile("str%?h %2, [%0], #4"
- : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
- buf += 2;
- length -= 2;
- }
- while (length > 8) {
- register unsigned int tmp asm("r2"), tmp2 asm("r3");
- asm volatile(
- "ldm%?ia %0!, {%1, %2}"
- : "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
- length -= 8;
- asm volatile(
- "str%?h %1, [%0], #4\n\t"
- "mov%? %1, %1, lsr #16\n\t"
- "str%?h %1, [%0], #4\n\t"
- "str%?h %2, [%0], #4\n\t"
- "mov%? %2, %2, lsr #16\n\t"
- "str%?h %2, [%0], #4"
- : "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
- }
- while (length > 0) {
- asm volatile("str%?h %2, [%0], #4"
- : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
- buf += 2;
- length -= 2;
- }
-}
-
-static void
-am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
-{
- offset = ISAMEM_BASE + (offset << 1);
- length = (length + 1) & ~1;
- if ((int)buf & 2) {
- unsigned int tmp;
- asm volatile(
- "ldr%?h %2, [%0], #4\n\t"
- "str%?b %2, [%1], #1\n\t"
- "mov%? %2, %2, lsr #8\n\t"
- "str%?b %2, [%1], #1"
- : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
- length -= 2;
- }
- while (length > 8) {
- register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
- asm volatile(
- "ldr%?h %2, [%0], #4\n\t"
- "ldr%?h %4, [%0], #4\n\t"
- "ldr%?h %3, [%0], #4\n\t"
- "orr%? %2, %2, %4, lsl #16\n\t"
- "ldr%?h %4, [%0], #4\n\t"
- "orr%? %3, %3, %4, lsl #16\n\t"
- "stm%?ia %1!, {%2, %3}"
- : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
- : "0" (offset), "1" (buf));
- length -= 8;
- }
- while (length > 0) {
- unsigned int tmp;
- asm volatile(
- "ldr%?h %2, [%0], #4\n\t"
- "str%?b %2, [%1], #1\n\t"
- "mov%? %2, %2, lsr #8\n\t"
- "str%?b %2, [%1], #1"
- : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
- length -= 2;
- }
-}
-#else
-#error Not compatible
-#endif
-
-static int
-am79c961_ramtest(struct net_device *dev, unsigned int val)
-{
- unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
- int i, error = 0, errorcount = 0;
-
- if (!buffer)
- return 0;
- memset (buffer, val, 65536);
- am_writebuffer(dev, 0, buffer, 65536);
- memset (buffer, val ^ 255, 65536);
- am_readbuffer(dev, 0, buffer, 65536);
- for (i = 0; i < 65536; i++) {
- if (buffer[i] != val && !error) {
- printk ("%s: buffer error (%02X %02X) %05X - ", dev->name, val, buffer[i], i);
- error = 1;
- errorcount ++;
- } else if (error && buffer[i] == val) {
- printk ("%05X\n", i);
- error = 0;
- }
- }
- if (error)
- printk ("10000\n");
- kfree (buffer);
- return errorcount;
-}
-
-static void am79c961_mc_hash(char *addr, u16 *hash)
-{
- int idx, bit;
- u32 crc;
-
- crc = ether_crc_le(ETH_ALEN, addr);
-
- idx = crc >> 30;
- bit = (crc >> 26) & 15;
-
- hash[idx] |= 1 << bit;
-}
-
-static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
-{
- unsigned int mode = MODE_PORT_10BT;
-
- if (dev->flags & IFF_PROMISC) {
- mode |= MODE_PROMISC;
- memset(hash, 0xff, 4 * sizeof(*hash));
- } else if (dev->flags & IFF_ALLMULTI) {
- memset(hash, 0xff, 4 * sizeof(*hash));
- } else {
- struct netdev_hw_addr *ha;
-
- memset(hash, 0, 4 * sizeof(*hash));
-
- netdev_for_each_mc_addr(ha, dev)
- am79c961_mc_hash(ha->addr, hash);
- }
-
- return mode;
-}
-
-static void
-am79c961_init_for_open(struct net_device *dev)
-{
- struct dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
- unsigned char *p;
- u_int hdr_addr, first_free_addr;
- u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
- int i;
-
- /*
- * Stop the chip.
- */
- spin_lock_irqsave(&priv->chip_lock, flags);
- write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP);
- spin_unlock_irqrestore(&priv->chip_lock, flags);
-
- write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */
- write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */
- write_ireg (dev->base_addr, 7, 0x0090); /* XMIT LED */
- write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */
-
- for (i = LADRL; i <= LADRH; i++)
- write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);
-
- for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
- write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
-
- write_rreg (dev->base_addr, MODE, mode);
- write_rreg (dev->base_addr, POLLINT, 0);
- write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
- write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
-
- first_free_addr = RX_BUFFERS * 8 + TX_BUFFERS * 8 + 16;
- hdr_addr = 0;
-
- priv->rxhead = 0;
- priv->rxtail = 0;
- priv->rxhdr = hdr_addr;
-
- for (i = 0; i < RX_BUFFERS; i++) {
- priv->rxbuffer[i] = first_free_addr;
- am_writeword (dev, hdr_addr, first_free_addr);
- am_writeword (dev, hdr_addr + 2, RMD_OWN);
- am_writeword (dev, hdr_addr + 4, (-1600));
- am_writeword (dev, hdr_addr + 6, 0);
- first_free_addr += 1600;
- hdr_addr += 8;
- }
- priv->txhead = 0;
- priv->txtail = 0;
- priv->txhdr = hdr_addr;
- for (i = 0; i < TX_BUFFERS; i++) {
- priv->txbuffer[i] = first_free_addr;
- am_writeword (dev, hdr_addr, first_free_addr);
- am_writeword (dev, hdr_addr + 2, TMD_STP|TMD_ENP);
- am_writeword (dev, hdr_addr + 4, 0xf000);
- am_writeword (dev, hdr_addr + 6, 0);
- first_free_addr += 1600;
- hdr_addr += 8;
- }
-
- write_rreg (dev->base_addr, BASERXL, priv->rxhdr);
- write_rreg (dev->base_addr, BASERXH, 0);
- write_rreg (dev->base_addr, BASETXL, priv->txhdr);
- write_rreg (dev->base_addr, BASERXH, 0);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
- write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
- write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
-}
-
-static void am79c961_timer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- struct dev_priv *priv = netdev_priv(dev);
- unsigned int lnkstat, carrier;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->chip_lock, flags);
- lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
- spin_unlock_irqrestore(&priv->chip_lock, flags);
- carrier = netif_carrier_ok(dev);
-
- if (lnkstat && !carrier) {
- netif_carrier_on(dev);
- printk("%s: link up\n", dev->name);
- } else if (!lnkstat && carrier) {
- netif_carrier_off(dev);
- printk("%s: link down\n", dev->name);
- }
-
- mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
-}
-
-/*
- * Open/initialize the board.
- */
-static int
-am79c961_open(struct net_device *dev)
-{
- struct dev_priv *priv = netdev_priv(dev);
- int ret;
-
- ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev);
- if (ret)
- return ret;
-
- am79c961_init_for_open(dev);
-
- netif_carrier_off(dev);
-
- priv->timer.expires = jiffies;
- add_timer(&priv->timer);
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-/*
- * The inverse routine to am79c961_open().
- */
-static int
-am79c961_close(struct net_device *dev)
-{
- struct dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
-
- del_timer_sync(&priv->timer);
-
- netif_stop_queue(dev);
- netif_carrier_off(dev);
-
- spin_lock_irqsave(&priv->chip_lock, flags);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
- spin_unlock_irqrestore(&priv->chip_lock, flags);
-
- free_irq (dev->irq, dev);
-
- return 0;
-}
-
-/*
- * Set or clear promiscuous/multicast mode filter for this adapter.
- */
-static void am79c961_setmulticastlist (struct net_device *dev)
-{
- struct dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
- u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
- int i, stopped;
-
- spin_lock_irqsave(&priv->chip_lock, flags);
-
- stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
-
- if (!stopped) {
- /*
- * Put the chip into suspend mode
- */
- write_rreg(dev->base_addr, CTRL1, CTRL1_SPND);
-
- /*
- * Spin waiting for chip to report suspend mode
- */
- while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
- spin_unlock_irqrestore(&priv->chip_lock, flags);
- nop();
- spin_lock_irqsave(&priv->chip_lock, flags);
- }
- }
-
- /*
- * Update the multicast hash table
- */
- for (i = 0; i < ARRAY_SIZE(multi_hash); i++)
- write_rreg(dev->base_addr, i + LADRL, multi_hash[i]);
-
- /*
- * Write the mode register
- */
- write_rreg(dev->base_addr, MODE, mode);
-
- if (!stopped) {
- /*
- * Put the chip back into running mode
- */
- write_rreg(dev->base_addr, CTRL1, 0);
- }
-
- spin_unlock_irqrestore(&priv->chip_lock, flags);
-}
-
-static void am79c961_timeout(struct net_device *dev)
-{
- printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n",
- dev->name);
-
- /*
- * ought to do some setup of the tx side here
- */
-
- netif_wake_queue(dev);
-}
-
-/*
- * Transmit a packet
- */
-static int
-am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
-{
- struct dev_priv *priv = netdev_priv(dev);
- unsigned int hdraddr, bufaddr;
- unsigned int head;
- unsigned long flags;
-
- head = priv->txhead;
- hdraddr = priv->txhdr + (head << 3);
- bufaddr = priv->txbuffer[head];
- head += 1;
- if (head >= TX_BUFFERS)
- head = 0;
-
- am_writebuffer (dev, bufaddr, skb->data, skb->len);
- am_writeword (dev, hdraddr + 4, -skb->len);
- am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
- priv->txhead = head;
-
- spin_lock_irqsave(&priv->chip_lock, flags);
- write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
- spin_unlock_irqrestore(&priv->chip_lock, flags);
-
- /*
- * If the next packet is owned by the ethernet device,
- * then the tx ring is full and we can't add another
- * packet.
- */
- if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
- netif_stop_queue(dev);
-
- dev_kfree_skb(skb);
-
- return NETDEV_TX_OK;
-}
-
-/*
- * If we have a good packet(s), get it/them out of the buffers.
- */
-static void
-am79c961_rx(struct net_device *dev, struct dev_priv *priv)
-{
- do {
- struct sk_buff *skb;
- u_int hdraddr;
- u_int pktaddr;
- u_int status;
- int len;
-
- hdraddr = priv->rxhdr + (priv->rxtail << 3);
- pktaddr = priv->rxbuffer[priv->rxtail];
-
- status = am_readword (dev, hdraddr + 2);
- if (status & RMD_OWN) /* do we own it? */
- break;
-
- priv->rxtail ++;
- if (priv->rxtail >= RX_BUFFERS)
- priv->rxtail = 0;
-
- if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
- am_writeword (dev, hdraddr + 2, RMD_OWN);
- dev->stats.rx_errors++;
- if (status & RMD_ERR) {
- if (status & RMD_FRAM)
- dev->stats.rx_frame_errors++;
- if (status & RMD_CRC)
- dev->stats.rx_crc_errors++;
- } else if (status & RMD_STP)
- dev->stats.rx_length_errors++;
- continue;
- }
-
- len = am_readword(dev, hdraddr + 6);
- skb = dev_alloc_skb(len + 2);
-
- if (skb) {
- skb_reserve(skb, 2);
-
- am_readbuffer(dev, pktaddr, skb_put(skb, len), len);
- am_writeword(dev, hdraddr + 2, RMD_OWN);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->stats.rx_bytes += len;
- dev->stats.rx_packets++;
- } else {
- am_writeword (dev, hdraddr + 2, RMD_OWN);
- printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
- dev->stats.rx_dropped++;
- break;
- }
- } while (1);
-}
-
-/*
- * Update stats for the transmitted packet
- */
-static void
-am79c961_tx(struct net_device *dev, struct dev_priv *priv)
-{
- do {
- short len;
- u_int hdraddr;
- u_int status;
-
- hdraddr = priv->txhdr + (priv->txtail << 3);
- status = am_readword (dev, hdraddr + 2);
- if (status & TMD_OWN)
- break;
-
- priv->txtail ++;
- if (priv->txtail >= TX_BUFFERS)
- priv->txtail = 0;
-
- if (status & TMD_ERR) {
- u_int status2;
-
- dev->stats.tx_errors++;
-
- status2 = am_readword (dev, hdraddr + 6);
-
- /*
- * Clear the error byte
- */
- am_writeword (dev, hdraddr + 6, 0);
-
- if (status2 & TST_RTRY)
- dev->stats.collisions += 16;
- if (status2 & TST_LCOL)
- dev->stats.tx_window_errors++;
- if (status2 & TST_LCAR)
- dev->stats.tx_carrier_errors++;
- if (status2 & TST_UFLO)
- dev->stats.tx_fifo_errors++;
- continue;
- }
- dev->stats.tx_packets++;
- len = am_readword (dev, hdraddr + 4);
- dev->stats.tx_bytes += -len;
- } while (priv->txtail != priv->txhead);
-
- netif_wake_queue(dev);
-}
-
-static irqreturn_t
-am79c961_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- struct dev_priv *priv = netdev_priv(dev);
- u_int status, n = 100;
- int handled = 0;
-
- do {
- status = read_rreg(dev->base_addr, CSR0);
- write_rreg(dev->base_addr, CSR0, status &
- (CSR0_IENA|CSR0_TINT|CSR0_RINT|
- CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
-
- if (status & CSR0_RINT) {
- handled = 1;
- am79c961_rx(dev, priv);
- }
- if (status & CSR0_TINT) {
- handled = 1;
- am79c961_tx(dev, priv);
- }
- if (status & CSR0_MISS) {
- handled = 1;
- dev->stats.rx_dropped++;
- }
- if (status & CSR0_CERR) {
- handled = 1;
- mod_timer(&priv->timer, jiffies);
- }
- } while (--n && status & (CSR0_RINT | CSR0_TINT));
-
- return IRQ_RETVAL(handled);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void am79c961_poll_controller(struct net_device *dev)
-{
- unsigned long flags;
- local_irq_save(flags);
- am79c961_interrupt(dev->irq, dev);
- local_irq_restore(flags);
-}
-#endif
-
-/*
- * Initialise the chip. Note that we always expect
- * to be entered with interrupts enabled.
- */
-static int
-am79c961_hw_init(struct net_device *dev)
-{
- struct dev_priv *priv = netdev_priv(dev);
-
- spin_lock_irq(&priv->chip_lock);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
- spin_unlock_irq(&priv->chip_lock);
-
- am79c961_ramtest(dev, 0x66);
- am79c961_ramtest(dev, 0x99);
-
- return 0;
-}
-
-static void __init am79c961_banner(void)
-{
- static unsigned version_printed;
-
- if (net_debug && version_printed++ == 0)
- printk(KERN_INFO "%s", version);
-}
-static const struct net_device_ops am79c961_netdev_ops = {
- .ndo_open = am79c961_open,
- .ndo_stop = am79c961_close,
- .ndo_start_xmit = am79c961_sendpacket,
- .ndo_set_multicast_list = am79c961_setmulticastlist,
- .ndo_tx_timeout = am79c961_timeout,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = am79c961_poll_controller,
-#endif
-};
-
-static int __devinit am79c961_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct net_device *dev;
- struct dev_priv *priv;
- int i, ret;
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!res)
- return -ENODEV;
-
- dev = alloc_etherdev(sizeof(struct dev_priv));
- ret = -ENOMEM;
- if (!dev)
- goto out;
-
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- priv = netdev_priv(dev);
-
- /*
- * Fixed address and IRQ lines here.
- * The PNP initialisation should have been
- * done by the ether bootp loader.
- */
- dev->base_addr = res->start;
- ret = platform_get_irq(pdev, 0);
-
- if (ret < 0) {
- ret = -ENODEV;
- goto nodev;
- }
- dev->irq = ret;
-
- ret = -ENODEV;
- if (!request_region(dev->base_addr, 0x18, dev->name))
- goto nodev;
-
- /*
- * Reset the device.
- */
- inb(dev->base_addr + NET_RESET);
- udelay(5);
-
- /*
- * Check the manufacturer part of the
- * ether address.
- */
- if (inb(dev->base_addr) != 0x08 ||
- inb(dev->base_addr + 2) != 0x00 ||
- inb(dev->base_addr + 4) != 0x2b)
- goto release;
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
-
- am79c961_banner();
-
- spin_lock_init(&priv->chip_lock);
- init_timer(&priv->timer);
- priv->timer.data = (unsigned long)dev;
- priv->timer.function = am79c961_timer;
-
- if (am79c961_hw_init(dev))
- goto release;
-
- dev->netdev_ops = &am79c961_netdev_ops;
-
- ret = register_netdev(dev);
- if (ret == 0) {
- printk(KERN_INFO "%s: ether address %pM\n",
- dev->name, dev->dev_addr);
- return 0;
- }
-
-release:
- release_region(dev->base_addr, 0x18);
-nodev:
- free_netdev(dev);
-out:
- return ret;
-}
-
-static struct platform_driver am79c961_driver = {
- .probe = am79c961_probe,
- .driver = {
- .name = "am79c961",
- },
-};
-
-static int __init am79c961_init(void)
-{
- return platform_driver_register(&am79c961_driver);
-}
-
-__initcall(am79c961_init);
diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h
deleted file mode 100644
index fd634d32756b..000000000000
--- a/drivers/net/arm/am79c961a.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * linux/drivers/net/arm/am79c961a.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _LINUX_am79c961a_H
-#define _LINUX_am79c961a_H
-
-/* use 0 for production, 1 for verification, >2 for debug. debug flags: */
-#define DEBUG_TX 2
-#define DEBUG_RX 4
-#define DEBUG_INT 8
-#define DEBUG_IC 16
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-
-#define NET_UID 0
-#define NET_RDP 0x10
-#define NET_RAP 0x12
-#define NET_RESET 0x14
-#define NET_IDP 0x16
-
-/*
- * RAP registers
- */
-#define CSR0 0
-#define CSR0_INIT 0x0001
-#define CSR0_STRT 0x0002
-#define CSR0_STOP 0x0004
-#define CSR0_TDMD 0x0008
-#define CSR0_TXON 0x0010
-#define CSR0_RXON 0x0020
-#define CSR0_IENA 0x0040
-#define CSR0_INTR 0x0080
-#define CSR0_IDON 0x0100
-#define CSR0_TINT 0x0200
-#define CSR0_RINT 0x0400
-#define CSR0_MERR 0x0800
-#define CSR0_MISS 0x1000
-#define CSR0_CERR 0x2000
-#define CSR0_BABL 0x4000
-#define CSR0_ERR 0x8000
-
-#define CSR3 3
-#define CSR3_EMBA 0x0008
-#define CSR3_DXMT2PD 0x0010
-#define CSR3_LAPPEN 0x0020
-#define CSR3_DXSUFLO 0x0040
-#define CSR3_IDONM 0x0100
-#define CSR3_TINTM 0x0200
-#define CSR3_RINTM 0x0400
-#define CSR3_MERRM 0x0800
-#define CSR3_MISSM 0x1000
-#define CSR3_BABLM 0x4000
-#define CSR3_MASKALL 0x5F00
-
-#define CSR4 4
-#define CSR4_JABM 0x0001
-#define CSR4_JAB 0x0002
-#define CSR4_TXSTRTM 0x0004
-#define CSR4_TXSTRT 0x0008
-#define CSR4_RCVCCOM 0x0010
-#define CSR4_RCVCCO 0x0020
-#define CSR4_MFCOM 0x0100
-#define CSR4_MFCO 0x0200
-#define CSR4_ASTRP_RCV 0x0400
-#define CSR4_APAD_XMIT 0x0800
-
-#define CTRL1 5
-#define CTRL1_SPND 0x0001
-
-#define LADRL 8
-#define LADRM1 9
-#define LADRM2 10
-#define LADRH 11
-#define PADRL 12
-#define PADRM 13
-#define PADRH 14
-
-#define MODE 15
-#define MODE_DISRX 0x0001
-#define MODE_DISTX 0x0002
-#define MODE_LOOP 0x0004
-#define MODE_DTCRC 0x0008
-#define MODE_COLL 0x0010
-#define MODE_DRETRY 0x0020
-#define MODE_INTLOOP 0x0040
-#define MODE_PORT_AUI 0x0000
-#define MODE_PORT_10BT 0x0080
-#define MODE_DRXPA 0x2000
-#define MODE_DRXBA 0x4000
-#define MODE_PROMISC 0x8000
-
-#define BASERXL 24
-#define BASERXH 25
-#define BASETXL 30
-#define BASETXH 31
-
-#define POLLINT 47
-
-#define SIZERXR 76
-#define SIZETXR 78
-
-#define CSR_MFC 112
-
-#define RMD_ENP 0x0100
-#define RMD_STP 0x0200
-#define RMD_CRC 0x0800
-#define RMD_FRAM 0x2000
-#define RMD_ERR 0x4000
-#define RMD_OWN 0x8000
-
-#define TMD_ENP 0x0100
-#define TMD_STP 0x0200
-#define TMD_MORE 0x1000
-#define TMD_ERR 0x4000
-#define TMD_OWN 0x8000
-
-#define TST_RTRY 0x0400
-#define TST_LCAR 0x0800
-#define TST_LCOL 0x1000
-#define TST_UFLO 0x4000
-#define TST_BUFF 0x8000
-
-#define ISALED0 0x0004
-#define ISALED0_LNKST 0x8000
-
-struct dev_priv {
- unsigned long rxbuffer[RX_BUFFERS];
- unsigned long txbuffer[TX_BUFFERS];
- unsigned char txhead;
- unsigned char txtail;
- unsigned char rxhead;
- unsigned char rxtail;
- unsigned long rxhdr;
- unsigned long txhdr;
- spinlock_t chip_lock;
- struct timer_list timer;
-};
-
-#endif
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
deleted file mode 100644
index 29dc43523cec..000000000000
--- a/drivers/net/arm/at91_ether.c
+++ /dev/null
@@ -1,1254 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- * Copyright (C) 2003 SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson 01/11/2003
- *
- * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
- * (Polaroid Corporation)
- *
- * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru>
- *
- * 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <linux/ethtool.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <mach/at91rm9200_emac.h>
-#include <mach/gpio.h>
-#include <mach/board.h>
-
-#include "at91_ether.h"
-
-#define DRV_NAME "at91_ether"
-#define DRV_VERSION "1.0"
-
-#define LINK_POLL_INTERVAL (HZ)
-
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(unsigned int reg)
-{
- void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
- return __raw_readl(emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(unsigned int reg, unsigned long value)
-{
- void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
- __raw_writel(value, emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * When not called from an interrupt-handler, access to the PHY must be
- * protected by a spinlock.
- */
-static void enable_mdi(void)
-{
- unsigned long ctl;
-
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(void)
-{
- unsigned long ctl;
-
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(void) {
- unsigned long timeout = jiffies + 2;
-
- while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
- if (time_after(jiffies, timeout)) {
- printk("at91_ether: MIO timeout\n");
- break;
- }
- cpu_relax();
- }
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value)
-{
- at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
- | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
- /* Wait until IDLE bit in Network Status register is cleared */
- at91_phy_wait();
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value)
-{
- at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
- | ((phy_addr & 0x1f) << 23) | (address << 18));
-
- /* Wait until IDLE bit in Network Status register is cleared */
- at91_phy_wait();
-
- *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct net_device *dev, int silent)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int bmsr, bmcr, lpa, mac_cfg;
- unsigned int speed, duplex;
-
- if (!mii_link_ok(&lp->mii)) { /* no link */
- netif_carrier_off(dev);
- if (!silent)
- printk(KERN_INFO "%s: Link down.\n", dev->name);
- return;
- }
-
- /* Link up, or auto-negotiation still in progress */
- read_phy(lp->phy_address, MII_BMSR, &bmsr);
- read_phy(lp->phy_address, MII_BMCR, &bmcr);
- if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
- if (!(bmsr & BMSR_ANEGCOMPLETE))
- return; /* Do nothing - another interrupt generated when negotiation complete */
-
- read_phy(lp->phy_address, MII_LPA, &lpa);
- if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
- else speed = SPEED_10;
- if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
- else duplex = DUPLEX_HALF;
- } else {
- speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
- duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
- }
-
- /* Update the MAC */
- mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
- if (speed == SPEED_100) {
- if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
- mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
- else /* 100 Half Duplex */
- mac_cfg |= AT91_EMAC_SPD;
- } else {
- if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
- mac_cfg |= AT91_EMAC_FD;
- else {} /* 10 Half Duplex */
- }
- at91_emac_write(AT91_EMAC_CFG, mac_cfg);
-
- if (!silent)
- printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
- netif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
- unsigned int phy;
-
- /*
- * This hander is triggered on both edges, but the PHY chips expect
- * level-triggering. We therefore have to check if the PHY actually has
- * an IRQ pending.
- */
- enable_mdi();
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
- read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
- if (!(phy & (1 << 0)))
- goto done;
- }
- else if (lp->phy_type == MII_LXT971A_ID) {
- read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
- if (!(phy & (1 << 2)))
- goto done;
- }
- else if (lp->phy_type == MII_BCM5221_ID) {
- read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
- if (!(phy & (1 << 0)))
- goto done;
- }
- else if (lp->phy_type == MII_KS8721_ID) {
- read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
- if (!(phy & ((1 << 2) | 1)))
- goto done;
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */
- read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy);
- if (!(phy & ((1 << 2) | 1)))
- goto done;
- }
- else if (lp->phy_type == MII_DP83848_ID) {
- read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */
- if (!(phy & (1 << 7)))
- goto done;
- }
-
- update_linkspeed(dev, 0);
-
-done:
- disable_mdi();
-
- return IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int dsintr, irq_number;
- int status;
-
- irq_number = lp->board_data.phy_irq_pin;
- if (!irq_number) {
- /*
- * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
- * or board does not have it connected.
- */
- mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
- return;
- }
-
- status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
- if (status) {
- printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
- return;
- }
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
- read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
- dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
- write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
- read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
- dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
- write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
- }
- else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
- dsintr = (1 << 15) | ( 1 << 14);
- write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
- dsintr = (1 << 10) | ( 1 << 8);
- write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
- read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
- dsintr = dsintr | 0x500; /* set bits 8, 10 */
- write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
- }
- else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
- read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
- dsintr = dsintr | 0x3c; /* set bits 2..5 */
- write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
- read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
- dsintr = dsintr | 0x3; /* set bits 0,1 */
- write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
- }
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-}
-
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int dsintr;
- unsigned int irq_number;
-
- irq_number = lp->board_data.phy_irq_pin;
- if (!irq_number) {
- del_timer_sync(&lp->check_timer);
- return;
- }
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
- read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
- dsintr = dsintr | 0xf00; /* set bits 8..11 */
- write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
- read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
- dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
- write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
- }
- else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
- read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
- dsintr = ~(1 << 14);
- write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
- read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
- dsintr = ~((1 << 10) | (1 << 8));
- write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
- read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
- dsintr = dsintr & ~0x500; /* clear bits 8, 10 */
- write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
- }
- else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
- read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
- dsintr = dsintr & ~0x3; /* clear bits 0, 1 */
- write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
- read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
- dsintr = dsintr & ~0x3c; /* clear bits 2..5 */
- write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
- }
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- free_irq(irq_number, dev); /* Free interrupt handler */
-}
-
-/*
- * Perform a software reset of the PHY.
- */
-#if 0
-static void reset_phy(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned int bmcr;
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
-
- /* Perform PHY reset */
- write_phy(lp->phy_address, MII_BMCR, BMCR_RESET);
-
- /* Wait until PHY reset is complete */
- do {
- read_phy(lp->phy_address, MII_BMCR, &bmcr);
- } while (!(bmcr & BMCR_RESET));
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-}
-#endif
-
-static void at91ether_check_link(unsigned long dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
-
- enable_mdi();
- update_linkspeed(dev, 1);
- disable_mdi();
-
- mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
-
-/* ......................... ADDRESS MANAGEMENT ........................ */
-
-/*
- * NOTE: Your bootloader must always set the MAC address correctly before
- * booting into Linux.
- *
- * - It must always set the MAC address after reset, even if it doesn't
- * happen to access the Ethernet while it's booting. Some versions of
- * U-Boot on the AT91RM9200-DK do not do this.
- *
- * - Likewise it must store the addresses in the correct byte order.
- * MicroMonitor (uMon) on the CSB337 does this incorrectly (and
- * continues to do so, for bug-compatibility).
- */
-
-static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
-{
- char addr[6];
-
- if (machine_is_csb337()) {
- addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */
- addr[4] = (lo & 0xff00) >> 8;
- addr[3] = (lo & 0xff0000) >> 16;
- addr[2] = (lo & 0xff000000) >> 24;
- addr[1] = (hi & 0xff);
- addr[0] = (hi & 0xff00) >> 8;
- }
- else {
- addr[0] = (lo & 0xff);
- addr[1] = (lo & 0xff00) >> 8;
- addr[2] = (lo & 0xff0000) >> 16;
- addr[3] = (lo & 0xff000000) >> 24;
- addr[4] = (hi & 0xff);
- addr[5] = (hi & 0xff00) >> 8;
- }
-
- if (is_valid_ether_addr(addr)) {
- memcpy(dev->dev_addr, &addr, 6);
- return 1;
- }
- return 0;
-}
-
-/*
- * Set the ethernet MAC address in dev->dev_addr
- */
-static void __init get_mac_address(struct net_device *dev)
-{
- /* Check Specific-Address 1 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L)))
- return;
- /* Check Specific-Address 2 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L)))
- return;
- /* Check Specific-Address 3 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L)))
- return;
- /* Check Specific-Address 4 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L)))
- return;
-
- printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static void update_mac_address(struct net_device *dev)
-{
- at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
- at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-
- at91_emac_write(AT91_EMAC_SA2L, 0);
- at91_emac_write(AT91_EMAC_SA2H, 0);
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-static int set_mac_address(struct net_device *dev, void* addr)
-{
- struct sockaddr *address = addr;
-
- if (!is_valid_ether_addr(address->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
- update_mac_address(dev);
-
- printk("%s: Setting MAC address to %pM\n", dev->name,
- dev->dev_addr);
-
- return 0;
-}
-
-static int inline hash_bit_value(int bitnr, __u8 *addr)
-{
- if (addr[bitnr / 8] & (1 << (bitnr % 8)))
- return 1;
- return 0;
-}
-
-/*
- * The hash address register is 64 bits long and takes up two locations in the memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network configuration
- * register enable the reception of hash matched frames. The destination address is
- * reduced to a 6 bit index into the 64 bit hash register using the following hash function.
- * The hash function is an exclusive or of every sixth bit of the destination address.
- * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
- * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
- * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
- * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
- * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
- * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that is, the multicast/
- * unicast indicator, and da[47] represents the most significant bit of the last byte
- * received.
- * If the hash index points to a bit that is set in the hash register then the frame will be
- * matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
- * the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
- * hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all ones and the
- * multicast hash enable bit should be set in the network configuration register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-static int hash_get_index(__u8 *addr)
-{
- int i, j, bitval;
- int hash_index = 0;
-
- for (j = 0; j < 6; j++) {
- for (i = 0, bitval = 0; i < 8; i++)
- bitval ^= hash_bit_value(i*6 + j, addr);
-
- hash_index |= (bitval << j);
- }
-
- return hash_index;
-}
-
-/*
- * Add multicast addresses to the internal multicast-hash table.
- */
-static void at91ether_sethashtable(struct net_device *dev)
-{
- struct netdev_hw_addr *ha;
- unsigned long mc_filter[2];
- unsigned int bitnr;
-
- mc_filter[0] = mc_filter[1] = 0;
-
- netdev_for_each_mc_addr(ha, dev) {
- bitnr = hash_get_index(ha->addr);
- mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
- }
-
- at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
- at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
-}
-
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-static void at91ether_set_multicast_list(struct net_device *dev)
-{
- unsigned long cfg;
-
- cfg = at91_emac_read(AT91_EMAC_CFG);
-
- if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
- cfg |= AT91_EMAC_CAF;
- else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */
- cfg &= ~AT91_EMAC_CAF;
-
- if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
- at91_emac_write(AT91_EMAC_HSH, -1);
- at91_emac_write(AT91_EMAC_HSL, -1);
- cfg |= AT91_EMAC_MTI;
- } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
- at91ether_sethashtable(dev);
- cfg |= AT91_EMAC_MTI;
- } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
- at91_emac_write(AT91_EMAC_HSH, 0);
- at91_emac_write(AT91_EMAC_HSL, 0);
- cfg &= ~AT91_EMAC_MTI;
- }
-
- at91_emac_write(AT91_EMAC_CFG, cfg);
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
- unsigned int value;
-
- read_phy(phy_id, location, &value);
- return value;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
- write_phy(phy_id, location, value);
-}
-
-static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
-
- ret = mii_ethtool_gset(&lp->mii, cmd);
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
- cmd->supported = SUPPORTED_FIBRE;
- cmd->port = PORT_FIBRE;
- }
-
- return ret;
-}
-
-static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
-
- ret = mii_ethtool_sset(&lp->mii, cmd);
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- return ret;
-}
-
-static int at91ether_nwayreset(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
-
- ret = mii_nway_restart(&lp->mii);
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- return ret;
-}
-
-static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
- strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops at91ether_ethtool_ops = {
- .get_settings = at91ether_get_settings,
- .set_settings = at91ether_set_settings,
- .get_drvinfo = at91ether_get_drvinfo,
- .nway_reset = at91ether_nwayreset,
- .get_link = ethtool_op_get_link,
-};
-
-static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct at91_private *lp = netdev_priv(dev);
- int res;
-
- if (!netif_running(dev))
- return -EINVAL;
-
- spin_lock_irq(&lp->lock);
- enable_mdi();
- res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- return res;
-}
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- struct recv_desc_bufs *dlist, *dlist_phys;
- int i;
- unsigned long ctl;
-
- dlist = lp->dlist;
- dlist_phys = lp->dlist_phys;
-
- for (i = 0; i < MAX_RX_DESCR; i++) {
- dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
- dlist->descriptors[i].size = 0;
- }
-
- /* Set the Wrap bit on the last descriptor */
- dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
-
- /* Reset buffer index */
- lp->rxBuffIndex = 0;
-
- /* Program address of descriptor list in Rx Buffer Queue register */
- at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
-
- /* Enable Receive and Transmit */
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
-}
-
-/*
- * Open the ethernet interface
- */
-static int at91ether_open(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned long ctl;
-
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EADDRNOTAVAIL;
-
- clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */
-
- /* Clear internal statistics */
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
-
- /* Update the MAC address (incase user has changed it) */
- update_mac_address(dev);
-
- /* Enable PHY interrupt */
- enable_phyirq(dev);
-
- /* Enable MAC interrupts */
- at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
- | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
- | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
- /* Determine current link speed */
- spin_lock_irq(&lp->lock);
- enable_mdi();
- update_linkspeed(dev, 0);
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- at91ether_start(dev);
- netif_start_queue(dev);
- return 0;
-}
-
-/*
- * Close the interface
- */
-static int at91ether_close(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- unsigned long ctl;
-
- /* Disable Receiver and Transmitter */
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
- /* Disable PHY interrupt */
- disable_phyirq(dev);
-
- /* Disable MAC interrupts */
- at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
- | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
- | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
- netif_stop_queue(dev);
-
- clk_disable(lp->ether_clk); /* Disable Peripheral clock */
-
- return 0;
-}
-
-/*
- * Transmit packet.
- */
-static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
-
- if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
- netif_stop_queue(dev);
-
- /* Store packet information (to free when Tx completed) */
- lp->skb = skb;
- lp->skb_length = skb->len;
- lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
- dev->stats.tx_bytes += skb->len;
-
- /* Set address of the data in the Transmit Address register */
- at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
- /* Set length of the packet in the Transmit Control register */
- at91_emac_write(AT91_EMAC_TCR, skb->len);
-
- } else {
- printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
- return NETDEV_TX_BUSY; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
- on this skb, he also reports -ENETDOWN and printk's, so either
- we free and return(0) or don't free and return 1 */
- }
-
- return NETDEV_TX_OK;
-}
-
-/*
- * Update the current statistics from the internal statistics registers.
- */
-static struct net_device_stats *at91ether_stats(struct net_device *dev)
-{
- int ale, lenerr, seqe, lcol, ecol;
-
- if (netif_running(dev)) {
- dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
- ale = at91_emac_read(AT91_EMAC_ALE);
- dev->stats.rx_frame_errors += ale; /* Alignment errors */
- lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
- dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
- seqe = at91_emac_read(AT91_EMAC_SEQE);
- dev->stats.rx_crc_errors += seqe; /* CRC error */
- dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
- dev->stats.rx_errors += (ale + lenerr + seqe
- + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
-
- dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
- dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
- dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
- dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
-
- lcol = at91_emac_read(AT91_EMAC_LCOL);
- ecol = at91_emac_read(AT91_EMAC_ECOL);
- dev->stats.tx_window_errors += lcol; /* Late collisions */
- dev->stats.tx_aborted_errors += ecol; /* 16 collisions */
-
- dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
- }
- return &dev->stats;
-}
-
-/*
- * Extract received frame from buffer descriptors and sent to upper layers.
- * (Called from interrupt context)
- */
-static void at91ether_rx(struct net_device *dev)
-{
- struct at91_private *lp = netdev_priv(dev);
- struct recv_desc_bufs *dlist;
- unsigned char *p_recv;
- struct sk_buff *skb;
- unsigned int pktlen;
-
- dlist = lp->dlist;
- while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
- p_recv = dlist->recv_buf[lp->rxBuffIndex];
- pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
- skb = dev_alloc_skb(pktlen + 2);
- if (skb != NULL) {
- skb_reserve(skb, 2);
- memcpy(skb_put(skb, pktlen), p_recv, pktlen);
-
- skb->protocol = eth_type_trans(skb, dev);
- dev->stats.rx_bytes += pktlen;
- netif_rx(skb);
- }
- else {
- dev->stats.rx_dropped += 1;
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- }
-
- if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
- dev->stats.multicast++;
-
- dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
- if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
- lp->rxBuffIndex = 0;
- else
- lp->rxBuffIndex++;
- }
-}
-
-/*
- * MAC interrupt handler
- */
-static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
- unsigned long intstatus, ctl;
-
- /* MAC Interrupt Status register indicates what interrupts are pending.
- It is automatically cleared once read. */
- intstatus = at91_emac_read(AT91_EMAC_ISR);
-
- if (intstatus & AT91_EMAC_RCOM) /* Receive complete */
- at91ether_rx(dev);
-
- if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
- /* The TCOM bit is set even if the transmission failed. */
- if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
- dev->stats.tx_errors += 1;
-
- if (lp->skb) {
- dev_kfree_skb_irq(lp->skb);
- lp->skb = NULL;
- dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
- }
- netif_wake_queue(dev);
- }
-
- /* Work-around for Errata #11 */
- if (intstatus & AT91_EMAC_RBNA) {
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
- }
-
- if (intstatus & AT91_EMAC_ROVR)
- printk("%s: ROVR error\n", dev->name);
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void at91ether_poll_controller(struct net_device *dev)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- at91ether_interrupt(dev->irq, dev);
- local_irq_restore(flags);
-}
-#endif
-
-static const struct net_device_ops at91ether_netdev_ops = {
- .ndo_open = at91ether_open,
- .ndo_stop = at91ether_close,
- .ndo_start_xmit = at91ether_start_xmit,
- .ndo_get_stats = at91ether_stats,
- .ndo_set_multicast_list = at91ether_set_multicast_list,
- .ndo_set_mac_address = set_mac_address,
- .ndo_do_ioctl = at91ether_ioctl,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = at91ether_poll_controller,
-#endif
-};
-
-/*
- * Initialize the ethernet interface
- */
-static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
- struct platform_device *pdev, struct clk *ether_clk)
-{
- struct at91_eth_data *board_data = pdev->dev.platform_data;
- struct net_device *dev;
- struct at91_private *lp;
- unsigned int val;
- int res;
-
- dev = alloc_etherdev(sizeof(struct at91_private));
- if (!dev)
- return -ENOMEM;
-
- dev->base_addr = AT91_VA_BASE_EMAC;
- dev->irq = AT91RM9200_ID_EMAC;
-
- /* Install the interrupt handler */
- if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
- free_netdev(dev);
- return -EBUSY;
- }
-
- /* Allocate memory for DMA Receive descriptors */
- lp = netdev_priv(dev);
- lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
- if (lp->dlist == NULL) {
- free_irq(dev->irq, dev);
- free_netdev(dev);
- return -ENOMEM;
- }
- lp->board_data = *board_data;
- lp->ether_clk = ether_clk;
- platform_set_drvdata(pdev, dev);
-
- spin_lock_init(&lp->lock);
-
- ether_setup(dev);
- dev->netdev_ops = &at91ether_netdev_ops;
- dev->ethtool_ops = &at91ether_ethtool_ops;
-
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
- update_mac_address(dev); /* Program ethernet address into MAC */
-
- at91_emac_write(AT91_EMAC_CTL, 0);
-
- if (lp->board_data.is_rmii)
- at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
- else
- at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-
- /* Perform PHY-specific initialization */
- spin_lock_irq(&lp->lock);
- enable_mdi();
- if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
- read_phy(phy_address, MII_DSCR_REG, &val);
- if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
- lp->phy_media = PORT_FIBRE;
- } else if (machine_is_csb337()) {
- /* mix link activity status into LED2 link state */
- write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
- } else if (machine_is_ecbat91())
- write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
-
- disable_mdi();
- spin_unlock_irq(&lp->lock);
-
- lp->mii.dev = dev; /* Support for ethtool */
- lp->mii.mdio_read = mdio_read;
- lp->mii.mdio_write = mdio_write;
- lp->mii.phy_id = phy_address;
- lp->mii.phy_id_mask = 0x1f;
- lp->mii.reg_num_mask = 0x1f;
-
- lp->phy_type = phy_type; /* Type of PHY connected */
- lp->phy_address = phy_address; /* MDI address of PHY */
-
- /* Register the network interface */
- res = register_netdev(dev);
- if (res) {
- free_irq(dev->irq, dev);
- free_netdev(dev);
- dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
- return res;
- }
-
- /* Determine current link speed */
- spin_lock_irq(&lp->lock);
- enable_mdi();
- update_linkspeed(dev, 0);
- disable_mdi();
- spin_unlock_irq(&lp->lock);
- netif_carrier_off(dev); /* will be enabled in open() */
-
- /* If board has no PHY IRQ, use a timer to poll the PHY */
- if (!lp->board_data.phy_irq_pin) {
- init_timer(&lp->check_timer);
- lp->check_timer.data = (unsigned long)dev;
- lp->check_timer.function = at91ether_check_link;
- } else if (lp->board_data.phy_irq_pin >= 32)
- gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy");
-
- /* Display ethernet banner */
- printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
- dev->name, (uint) dev->base_addr, dev->irq,
- at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
- at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
- dev->dev_addr);
- if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
- printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
- else if (phy_type == MII_LXT971A_ID)
- printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
- else if (phy_type == MII_RTL8201_ID)
- printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
- else if (phy_type == MII_BCM5221_ID)
- printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
- else if (phy_type == MII_DP83847_ID)
- printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
- else if (phy_type == MII_DP83848_ID)
- printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
- else if (phy_type == MII_AC101L_ID)
- printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
- else if (phy_type == MII_KS8721_ID)
- printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
- else if (phy_type == MII_T78Q21x3_ID)
- printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
- else if (phy_type == MII_LAN83C185_ID)
- printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
- return 0;
-}
-
-/*
- * Detect MAC and PHY and perform initialization
- */
-static int __init at91ether_probe(struct platform_device *pdev)
-{
- unsigned int phyid1, phyid2;
- int detected = -1;
- unsigned long phy_id;
- unsigned short phy_address = 0;
- struct clk *ether_clk;
-
- ether_clk = clk_get(&pdev->dev, "ether_clk");
- if (IS_ERR(ether_clk)) {
- printk(KERN_ERR "at91_ether: no clock defined\n");
- return -ENODEV;
- }
- clk_enable(ether_clk); /* Enable Peripheral clock */
-
- while ((detected != 0) && (phy_address < 32)) {
- /* Read the PHY ID registers */
- enable_mdi();
- read_phy(phy_address, MII_PHYSID1, &phyid1);
- read_phy(phy_address, MII_PHYSID2, &phyid2);
- disable_mdi();
-
- phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
- switch (phy_id) {
- case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
- case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
- case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
- case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
- case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
- case MII_DP83847_ID: /* National Semiconductor DP83847: */
- case MII_DP83848_ID: /* National Semiconductor DP83848: */
- case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
- case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
- case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
- case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
- detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
- break;
- }
-
- phy_address++;
- }
-
- clk_disable(ether_clk); /* Disable Peripheral clock */
-
- return detected;
-}
-
-static int __devexit at91ether_remove(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(dev);
-
- if (lp->board_data.phy_irq_pin >= 32)
- gpio_free(lp->board_data.phy_irq_pin);
-
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
- clk_put(lp->ether_clk);
-
- platform_set_drvdata(pdev, NULL);
- free_netdev(dev);
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
- struct net_device *net_dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(net_dev);
- int phy_irq = lp->board_data.phy_irq_pin;
-
- if (netif_running(net_dev)) {
- if (phy_irq)
- disable_irq(phy_irq);
-
- netif_stop_queue(net_dev);
- netif_device_detach(net_dev);
-
- clk_disable(lp->ether_clk);
- }
- return 0;
-}
-
-static int at91ether_resume(struct platform_device *pdev)
-{
- struct net_device *net_dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(net_dev);
- int phy_irq = lp->board_data.phy_irq_pin;
-
- if (netif_running(net_dev)) {
- clk_enable(lp->ether_clk);
-
- netif_device_attach(net_dev);
- netif_start_queue(net_dev);
-
- if (phy_irq)
- enable_irq(phy_irq);
- }
- return 0;
-}
-
-#else
-#define at91ether_suspend NULL
-#define at91ether_resume NULL
-#endif
-
-static struct platform_driver at91ether_driver = {
- .remove = __devexit_p(at91ether_remove),
- .suspend = at91ether_suspend,
- .resume = at91ether_resume,
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init at91ether_init(void)
-{
- return platform_driver_probe(&at91ether_driver, at91ether_probe);
-}
-
-static void __exit at91ether_exit(void)
-{
- platform_driver_unregister(&at91ether_driver);
-}
-
-module_init(at91ether_init)
-module_exit(at91ether_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
-MODULE_AUTHOR("Andrew Victor");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h
deleted file mode 100644
index 353f4dab62be..000000000000
--- a/drivers/net/arm/at91_ether.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- * Copyright (C) SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef AT91_ETHERNET
-#define AT91_ETHERNET
-
-
-/* Davicom 9161 PHY */
-#define MII_DM9161_ID 0x0181b880
-#define MII_DM9161A_ID 0x0181b8a0
-#define MII_DSCR_REG 16
-#define MII_DSCSR_REG 17
-#define MII_DSINTR_REG 21
-
-/* Intel LXT971A PHY */
-#define MII_LXT971A_ID 0x001378E0
-#define MII_ISINTE_REG 18
-#define MII_ISINTS_REG 19
-#define MII_LEDCTRL_REG 20
-
-/* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID 0x00008200
-
-/* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID 0x004061e0
-#define MII_BCMINTR_REG 26
-
-/* National Semiconductor DP83847 */
-#define MII_DP83847_ID 0x20005c30
-
-/* National Semiconductor DP83848 */
-#define MII_DP83848_ID 0x20005c90
-#define MII_DPPHYSTS_REG 16
-#define MII_DPMICR_REG 17
-#define MII_DPMISR_REG 18
-
-/* Altima AC101L PHY */
-#define MII_AC101L_ID 0x00225520
-
-/* Micrel KS8721 PHY */
-#define MII_KS8721_ID 0x00221610
-
-/* Teridian 78Q2123/78Q2133 */
-#define MII_T78Q21x3_ID 0x000e7230
-#define MII_T78Q21INT_REG 17
-
-/* SMSC LAN83C185 */
-#define MII_LAN83C185_ID 0x0007C0A0
-
-/* ........................................................................ */
-
-#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
-#define MAX_RX_DESCR 9 /* max number of receive buffers */
-
-#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
-#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
-
-#define EMAC_BROADCAST 0x80000000 /* broadcast address */
-#define EMAC_MULTICAST 0x40000000 /* multicast address */
-#define EMAC_UNICAST 0x20000000 /* unicast address */
-
-struct rbf_t
-{
- unsigned int addr;
- unsigned long size;
-};
-
-struct recv_desc_bufs
-{
- struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
- char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
-};
-
-struct at91_private
-{
- struct mii_if_info mii; /* ethtool support */
- struct at91_eth_data board_data; /* board-specific configuration */
- struct clk *ether_clk; /* clock */
-
- /* PHY */
- unsigned long phy_type; /* type of PHY (PHY_ID) */
- spinlock_t lock; /* lock for MDI interface */
- short phy_media; /* media interface type */
- unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */
- struct timer_list check_timer; /* Poll link status */
-
- /* Transmit */
- struct sk_buff *skb; /* holds skb until xmit interrupt completes */
- dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
- int skb_length; /* saved skb length for pci_unmap_single */
-
- /* Receive */
- int rxBuffIndex; /* index into receive descriptor list */
- struct recv_desc_bufs *dlist; /* descriptor list address */
- struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
-};
-
-#endif
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
deleted file mode 100644
index 4317af8d2f0a..000000000000
--- a/drivers/net/arm/ep93xx_eth.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/*
- * EP93xx ethernet network device driver
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/mii.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <mach/hardware.h>
-
-#define DRV_MODULE_NAME "ep93xx-eth"
-#define DRV_MODULE_VERSION "0.1"
-
-#define RX_QUEUE_ENTRIES 64
-#define TX_QUEUE_ENTRIES 8
-
-#define MAX_PKT_SIZE 2044
-#define PKT_BUF_SIZE 2048
-
-#define REG_RXCTL 0x0000
-#define REG_RXCTL_DEFAULT 0x00073800
-#define REG_TXCTL 0x0004
-#define REG_TXCTL_ENABLE 0x00000001
-#define REG_MIICMD 0x0010
-#define REG_MIICMD_READ 0x00008000
-#define REG_MIICMD_WRITE 0x00004000
-#define REG_MIIDATA 0x0014
-#define REG_MIISTS 0x0018
-#define REG_MIISTS_BUSY 0x00000001
-#define REG_SELFCTL 0x0020
-#define REG_SELFCTL_RESET 0x00000001
-#define REG_INTEN 0x0024
-#define REG_INTEN_TX 0x00000008
-#define REG_INTEN_RX 0x00000007
-#define REG_INTSTSP 0x0028
-#define REG_INTSTS_TX 0x00000008
-#define REG_INTSTS_RX 0x00000004
-#define REG_INTSTSC 0x002c
-#define REG_AFP 0x004c
-#define REG_INDAD0 0x0050
-#define REG_INDAD1 0x0051
-#define REG_INDAD2 0x0052
-#define REG_INDAD3 0x0053
-#define REG_INDAD4 0x0054
-#define REG_INDAD5 0x0055
-#define REG_GIINTMSK 0x0064
-#define REG_GIINTMSK_ENABLE 0x00008000
-#define REG_BMCTL 0x0080
-#define REG_BMCTL_ENABLE_TX 0x00000100
-#define REG_BMCTL_ENABLE_RX 0x00000001
-#define REG_BMSTS 0x0084
-#define REG_BMSTS_RX_ACTIVE 0x00000008
-#define REG_RXDQBADD 0x0090
-#define REG_RXDQBLEN 0x0094
-#define REG_RXDCURADD 0x0098
-#define REG_RXDENQ 0x009c
-#define REG_RXSTSQBADD 0x00a0
-#define REG_RXSTSQBLEN 0x00a4
-#define REG_RXSTSQCURADD 0x00a8
-#define REG_RXSTSENQ 0x00ac
-#define REG_TXDQBADD 0x00b0
-#define REG_TXDQBLEN 0x00b4
-#define REG_TXDQCURADD 0x00b8
-#define REG_TXDENQ 0x00bc
-#define REG_TXSTSQBADD 0x00c0
-#define REG_TXSTSQBLEN 0x00c4
-#define REG_TXSTSQCURADD 0x00c8
-#define REG_MAXFRMLEN 0x00e8
-
-struct ep93xx_rdesc
-{
- u32 buf_addr;
- u32 rdesc1;
-};
-
-#define RDESC1_NSOF 0x80000000
-#define RDESC1_BUFFER_INDEX 0x7fff0000
-#define RDESC1_BUFFER_LENGTH 0x0000ffff
-
-struct ep93xx_rstat
-{
- u32 rstat0;
- u32 rstat1;
-};
-
-#define RSTAT0_RFP 0x80000000
-#define RSTAT0_RWE 0x40000000
-#define RSTAT0_EOF 0x20000000
-#define RSTAT0_EOB 0x10000000
-#define RSTAT0_AM 0x00c00000
-#define RSTAT0_RX_ERR 0x00200000
-#define RSTAT0_OE 0x00100000
-#define RSTAT0_FE 0x00080000
-#define RSTAT0_RUNT 0x00040000
-#define RSTAT0_EDATA 0x00020000
-#define RSTAT0_CRCE 0x00010000
-#define RSTAT0_CRCI 0x00008000
-#define RSTAT0_HTI 0x00003f00
-#define RSTAT1_RFP 0x80000000
-#define RSTAT1_BUFFER_INDEX 0x7fff0000
-#define RSTAT1_FRAME_LENGTH 0x0000ffff
-
-struct ep93xx_tdesc
-{
- u32 buf_addr;
- u32 tdesc1;
-};
-
-#define TDESC1_EOF 0x80000000
-#define TDESC1_BUFFER_INDEX 0x7fff0000
-#define TDESC1_BUFFER_ABORT 0x00008000
-#define TDESC1_BUFFER_LENGTH 0x00000fff
-
-struct ep93xx_tstat
-{
- u32 tstat0;
-};
-
-#define TSTAT0_TXFP 0x80000000
-#define TSTAT0_TXWE 0x40000000
-#define TSTAT0_FA 0x20000000
-#define TSTAT0_LCRS 0x10000000
-#define TSTAT0_OW 0x04000000
-#define TSTAT0_TXU 0x02000000
-#define TSTAT0_ECOLL 0x01000000
-#define TSTAT0_NCOLL 0x001f0000
-#define TSTAT0_BUFFER_INDEX 0x00007fff
-
-struct ep93xx_descs
-{
- struct ep93xx_rdesc rdesc[RX_QUEUE_ENTRIES];
- struct ep93xx_tdesc tdesc[TX_QUEUE_ENTRIES];
- struct ep93xx_rstat rstat[RX_QUEUE_ENTRIES];
- struct ep93xx_tstat tstat[TX_QUEUE_ENTRIES];
-};
-
-struct ep93xx_priv
-{
- struct resource *res;
- void __iomem *base_addr;
- int irq;
-
- struct ep93xx_descs *descs;
- dma_addr_t descs_dma_addr;
-
- void *rx_buf[RX_QUEUE_ENTRIES];
- void *tx_buf[TX_QUEUE_ENTRIES];
-
- spinlock_t rx_lock;
- unsigned int rx_pointer;
- unsigned int tx_clean_pointer;
- unsigned int tx_pointer;
- spinlock_t tx_pending_lock;
- unsigned int tx_pending;
-
- struct net_device *dev;
- struct napi_struct napi;
-
- struct mii_if_info mii;
- u8 mdc_divisor;
-};
-
-#define rdb(ep, off) __raw_readb((ep)->base_addr + (off))
-#define rdw(ep, off) __raw_readw((ep)->base_addr + (off))
-#define rdl(ep, off) __raw_readl((ep)->base_addr + (off))
-#define wrb(ep, off, val) __raw_writeb((val), (ep)->base_addr + (off))
-#define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off))
-#define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off))
-
-static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- int data;
- int i;
-
- wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg);
-
- for (i = 0; i < 10; i++) {
- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
- break;
- msleep(1);
- }
-
- if (i == 10) {
- pr_info("mdio read timed out\n");
- data = 0xffff;
- } else {
- data = rdl(ep, REG_MIIDATA);
- }
-
- return data;
-}
-
-static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- int i;
-
- wrl(ep, REG_MIIDATA, data);
- wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg);
-
- for (i = 0; i < 10; i++) {
- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
- break;
- msleep(1);
- }
-
- if (i == 10)
- pr_info("mdio write timed out\n");
-}
-
-static int ep93xx_rx(struct net_device *dev, int processed, int budget)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
-
- while (processed < budget) {
- int entry;
- struct ep93xx_rstat *rstat;
- u32 rstat0;
- u32 rstat1;
- int length;
- struct sk_buff *skb;
-
- entry = ep->rx_pointer;
- rstat = ep->descs->rstat + entry;
-
- rstat0 = rstat->rstat0;
- rstat1 = rstat->rstat1;
- if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP))
- break;
-
- rstat->rstat0 = 0;
- rstat->rstat1 = 0;
-
- if (!(rstat0 & RSTAT0_EOF))
- pr_crit("not end-of-frame %.8x %.8x\n", rstat0, rstat1);
- if (!(rstat0 & RSTAT0_EOB))
- pr_crit("not end-of-buffer %.8x %.8x\n", rstat0, rstat1);
- if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry)
- pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1);
-
- if (!(rstat0 & RSTAT0_RWE)) {
- dev->stats.rx_errors++;
- if (rstat0 & RSTAT0_OE)
- dev->stats.rx_fifo_errors++;
- if (rstat0 & RSTAT0_FE)
- dev->stats.rx_frame_errors++;
- if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA))
- dev->stats.rx_length_errors++;
- if (rstat0 & RSTAT0_CRCE)
- dev->stats.rx_crc_errors++;
- goto err;
- }
-
- length = rstat1 & RSTAT1_FRAME_LENGTH;
- if (length > MAX_PKT_SIZE) {
- pr_notice("invalid length %.8x %.8x\n", rstat0, rstat1);
- goto err;
- }
-
- /* Strip FCS. */
- if (rstat0 & RSTAT0_CRCI)
- length -= 4;
-
- skb = dev_alloc_skb(length + 2);
- if (likely(skb != NULL)) {
- struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry];
- skb_reserve(skb, 2);
- dma_sync_single_for_cpu(dev->dev.parent, rxd->buf_addr,
- length, DMA_FROM_DEVICE);
- skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
- dma_sync_single_for_device(dev->dev.parent,
- rxd->buf_addr, length,
- DMA_FROM_DEVICE);
- skb_put(skb, length);
- skb->protocol = eth_type_trans(skb, dev);
-
- netif_receive_skb(skb);
-
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += length;
- } else {
- dev->stats.rx_dropped++;
- }
-
-err:
- ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1);
- processed++;
- }
-
- return processed;
-}
-
-static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
-{
- struct ep93xx_rstat *rstat = ep->descs->rstat + ep->rx_pointer;
- return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP));
-}
-
-static int ep93xx_poll(struct napi_struct *napi, int budget)
-{
- struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi);
- struct net_device *dev = ep->dev;
- int rx = 0;
-
-poll_some_more:
- rx = ep93xx_rx(dev, rx, budget);
- if (rx < budget) {
- int more = 0;
-
- spin_lock_irq(&ep->rx_lock);
- __napi_complete(napi);
- wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
- if (ep93xx_have_more_rx(ep)) {
- wrl(ep, REG_INTEN, REG_INTEN_TX);
- wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
- more = 1;
- }
- spin_unlock_irq(&ep->rx_lock);
-
- if (more && napi_reschedule(napi))
- goto poll_some_more;
- }
-
- if (rx) {
- wrw(ep, REG_RXDENQ, rx);
- wrw(ep, REG_RXSTSENQ, rx);
- }
-
- return rx;
-}
-
-static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- struct ep93xx_tdesc *txd;
- int entry;
-
- if (unlikely(skb->len > MAX_PKT_SIZE)) {
- dev->stats.tx_dropped++;
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
- entry = ep->tx_pointer;
- ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1);
-
- txd = &ep->descs->tdesc[entry];
-
- txd->tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff);
- dma_sync_single_for_cpu(dev->dev.parent, txd->buf_addr, skb->len,
- DMA_TO_DEVICE);
- skb_copy_and_csum_dev(skb, ep->tx_buf[entry]);
- dma_sync_single_for_device(dev->dev.parent, txd->buf_addr, skb->len,
- DMA_TO_DEVICE);
- dev_kfree_skb(skb);
-
- spin_lock_irq(&ep->tx_pending_lock);
- ep->tx_pending++;
- if (ep->tx_pending == TX_QUEUE_ENTRIES)
- netif_stop_queue(dev);
- spin_unlock_irq(&ep->tx_pending_lock);
-
- wrl(ep, REG_TXDENQ, 1);
-
- return NETDEV_TX_OK;
-}
-
-static void ep93xx_tx_complete(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- int wake;
-
- wake = 0;
-
- spin_lock(&ep->tx_pending_lock);
- while (1) {
- int entry;
- struct ep93xx_tstat *tstat;
- u32 tstat0;
-
- entry = ep->tx_clean_pointer;
- tstat = ep->descs->tstat + entry;
-
- tstat0 = tstat->tstat0;
- if (!(tstat0 & TSTAT0_TXFP))
- break;
-
- tstat->tstat0 = 0;
-
- if (tstat0 & TSTAT0_FA)
- pr_crit("frame aborted %.8x\n", tstat0);
- if ((tstat0 & TSTAT0_BUFFER_INDEX) != entry)
- pr_crit("entry mismatch %.8x\n", tstat0);
-
- if (tstat0 & TSTAT0_TXWE) {
- int length = ep->descs->tdesc[entry].tdesc1 & 0xfff;
-
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += length;
- } else {
- dev->stats.tx_errors++;
- }
-
- if (tstat0 & TSTAT0_OW)
- dev->stats.tx_window_errors++;
- if (tstat0 & TSTAT0_TXU)
- dev->stats.tx_fifo_errors++;
- dev->stats.collisions += (tstat0 >> 16) & 0x1f;
-
- ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1);
- if (ep->tx_pending == TX_QUEUE_ENTRIES)
- wake = 1;
- ep->tx_pending--;
- }
- spin_unlock(&ep->tx_pending_lock);
-
- if (wake)
- netif_wake_queue(dev);
-}
-
-static irqreturn_t ep93xx_irq(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct ep93xx_priv *ep = netdev_priv(dev);
- u32 status;
-
- status = rdl(ep, REG_INTSTSC);
- if (status == 0)
- return IRQ_NONE;
-
- if (status & REG_INTSTS_RX) {
- spin_lock(&ep->rx_lock);
- if (likely(napi_schedule_prep(&ep->napi))) {
- wrl(ep, REG_INTEN, REG_INTEN_TX);
- __napi_schedule(&ep->napi);
- }
- spin_unlock(&ep->rx_lock);
- }
-
- if (status & REG_INTSTS_TX)
- ep93xx_tx_complete(dev);
-
- return IRQ_HANDLED;
-}
-
-static void ep93xx_free_buffers(struct ep93xx_priv *ep)
-{
- struct device *dev = ep->dev->dev.parent;
- int i;
-
- for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
- dma_addr_t d;
-
- d = ep->descs->rdesc[i].buf_addr;
- if (d)
- dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_FROM_DEVICE);
-
- if (ep->rx_buf[i] != NULL)
- kfree(ep->rx_buf[i]);
- }
-
- for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
- dma_addr_t d;
-
- d = ep->descs->tdesc[i].buf_addr;
- if (d)
- dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_TO_DEVICE);
-
- if (ep->tx_buf[i] != NULL)
- kfree(ep->tx_buf[i]);
- }
-
- dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs,
- ep->descs_dma_addr);
-}
-
-static int ep93xx_alloc_buffers(struct ep93xx_priv *ep)
-{
- struct device *dev = ep->dev->dev.parent;
- int i;
-
- ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs),
- &ep->descs_dma_addr, GFP_KERNEL);
- if (ep->descs == NULL)
- return 1;
-
- for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
- void *buf;
- dma_addr_t d;
-
- buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL);
- if (buf == NULL)
- goto err;
-
- d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, d)) {
- kfree(buf);
- goto err;
- }
-
- ep->rx_buf[i] = buf;
- ep->descs->rdesc[i].buf_addr = d;
- ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE;
- }
-
- for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
- void *buf;
- dma_addr_t d;
-
- buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL);
- if (buf == NULL)
- goto err;
-
- d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_TO_DEVICE);
- if (dma_mapping_error(dev, d)) {
- kfree(buf);
- goto err;
- }
-
- ep->tx_buf[i] = buf;
- ep->descs->tdesc[i].buf_addr = d;
- }
-
- return 0;
-
-err:
- ep93xx_free_buffers(ep);
- return 1;
-}
-
-static int ep93xx_start_hw(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- unsigned long addr;
- int i;
-
- wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET);
- for (i = 0; i < 10; i++) {
- if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0)
- break;
- msleep(1);
- }
-
- if (i == 10) {
- pr_crit("hw failed to reset\n");
- return 1;
- }
-
- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
-
- /* Does the PHY support preamble suppress? */
- if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
-
- /* Receive descriptor ring. */
- addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
- wrl(ep, REG_RXDQBADD, addr);
- wrl(ep, REG_RXDCURADD, addr);
- wrw(ep, REG_RXDQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rdesc));
-
- /* Receive status ring. */
- addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rstat);
- wrl(ep, REG_RXSTSQBADD, addr);
- wrl(ep, REG_RXSTSQCURADD, addr);
- wrw(ep, REG_RXSTSQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rstat));
-
- /* Transmit descriptor ring. */
- addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tdesc);
- wrl(ep, REG_TXDQBADD, addr);
- wrl(ep, REG_TXDQCURADD, addr);
- wrw(ep, REG_TXDQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tdesc));
-
- /* Transmit status ring. */
- addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tstat);
- wrl(ep, REG_TXSTSQBADD, addr);
- wrl(ep, REG_TXSTSQCURADD, addr);
- wrw(ep, REG_TXSTSQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tstat));
-
- wrl(ep, REG_BMCTL, REG_BMCTL_ENABLE_TX | REG_BMCTL_ENABLE_RX);
- wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
- wrl(ep, REG_GIINTMSK, 0);
-
- for (i = 0; i < 10; i++) {
- if ((rdl(ep, REG_BMSTS) & REG_BMSTS_RX_ACTIVE) != 0)
- break;
- msleep(1);
- }
-
- if (i == 10) {
- pr_crit("hw failed to start\n");
- return 1;
- }
-
- wrl(ep, REG_RXDENQ, RX_QUEUE_ENTRIES);
- wrl(ep, REG_RXSTSENQ, RX_QUEUE_ENTRIES);
-
- wrb(ep, REG_INDAD0, dev->dev_addr[0]);
- wrb(ep, REG_INDAD1, dev->dev_addr[1]);
- wrb(ep, REG_INDAD2, dev->dev_addr[2]);
- wrb(ep, REG_INDAD3, dev->dev_addr[3]);
- wrb(ep, REG_INDAD4, dev->dev_addr[4]);
- wrb(ep, REG_INDAD5, dev->dev_addr[5]);
- wrl(ep, REG_AFP, 0);
-
- wrl(ep, REG_MAXFRMLEN, (MAX_PKT_SIZE << 16) | MAX_PKT_SIZE);
-
- wrl(ep, REG_RXCTL, REG_RXCTL_DEFAULT);
- wrl(ep, REG_TXCTL, REG_TXCTL_ENABLE);
-
- return 0;
-}
-
-static void ep93xx_stop_hw(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- int i;
-
- wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET);
- for (i = 0; i < 10; i++) {
- if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0)
- break;
- msleep(1);
- }
-
- if (i == 10)
- pr_crit("hw failed to reset\n");
-}
-
-static int ep93xx_open(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- int err;
-
- if (ep93xx_alloc_buffers(ep))
- return -ENOMEM;
-
- napi_enable(&ep->napi);
-
- if (ep93xx_start_hw(dev)) {
- napi_disable(&ep->napi);
- ep93xx_free_buffers(ep);
- return -EIO;
- }
-
- spin_lock_init(&ep->rx_lock);
- ep->rx_pointer = 0;
- ep->tx_clean_pointer = 0;
- ep->tx_pointer = 0;
- spin_lock_init(&ep->tx_pending_lock);
- ep->tx_pending = 0;
-
- err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev);
- if (err) {
- napi_disable(&ep->napi);
- ep93xx_stop_hw(dev);
- ep93xx_free_buffers(ep);
- return err;
- }
-
- wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE);
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-static int ep93xx_close(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
-
- napi_disable(&ep->napi);
- netif_stop_queue(dev);
-
- wrl(ep, REG_GIINTMSK, 0);
- free_irq(ep->irq, dev);
- ep93xx_stop_hw(dev);
- ep93xx_free_buffers(ep);
-
- return 0;
-}
-
-static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- struct mii_ioctl_data *data = if_mii(ifr);
-
- return generic_mii_ioctl(&ep->mii, data, cmd, NULL);
-}
-
-static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, DRV_MODULE_NAME);
- strcpy(info->version, DRV_MODULE_VERSION);
-}
-
-static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- return mii_ethtool_gset(&ep->mii, cmd);
-}
-
-static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- return mii_ethtool_sset(&ep->mii, cmd);
-}
-
-static int ep93xx_nway_reset(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- return mii_nway_restart(&ep->mii);
-}
-
-static u32 ep93xx_get_link(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- return mii_link_ok(&ep->mii);
-}
-
-static const struct ethtool_ops ep93xx_ethtool_ops = {
- .get_drvinfo = ep93xx_get_drvinfo,
- .get_settings = ep93xx_get_settings,
- .set_settings = ep93xx_set_settings,
- .nway_reset = ep93xx_nway_reset,
- .get_link = ep93xx_get_link,
-};
-
-static const struct net_device_ops ep93xx_netdev_ops = {
- .ndo_open = ep93xx_open,
- .ndo_stop = ep93xx_close,
- .ndo_start_xmit = ep93xx_xmit,
- .ndo_do_ioctl = ep93xx_ioctl,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
-};
-
-static struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
-{
- struct net_device *dev;
-
- dev = alloc_etherdev(sizeof(struct ep93xx_priv));
- if (dev == NULL)
- return NULL;
-
- memcpy(dev->dev_addr, data->dev_addr, ETH_ALEN);
-
- dev->ethtool_ops = &ep93xx_ethtool_ops;
- dev->netdev_ops = &ep93xx_netdev_ops;
-
- dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
-
- return dev;
-}
-
-
-static int ep93xx_eth_remove(struct platform_device *pdev)
-{
- struct net_device *dev;
- struct ep93xx_priv *ep;
-
- dev = platform_get_drvdata(pdev);
- if (dev == NULL)
- return 0;
- platform_set_drvdata(pdev, NULL);
-
- ep = netdev_priv(dev);
-
- /* @@@ Force down. */
- unregister_netdev(dev);
- ep93xx_free_buffers(ep);
-
- if (ep->base_addr != NULL)
- iounmap(ep->base_addr);
-
- if (ep->res != NULL) {
- release_resource(ep->res);
- kfree(ep->res);
- }
-
- free_netdev(dev);
-
- return 0;
-}
-
-static int ep93xx_eth_probe(struct platform_device *pdev)
-{
- struct ep93xx_eth_data *data;
- struct net_device *dev;
- struct ep93xx_priv *ep;
- struct resource *mem;
- int irq;
- int err;
-
- if (pdev == NULL)
- return -ENODEV;
- data = pdev->dev.platform_data;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (!mem || irq < 0)
- return -ENXIO;
-
- dev = ep93xx_dev_alloc(data);
- if (dev == NULL) {
- err = -ENOMEM;
- goto err_out;
- }
- ep = netdev_priv(dev);
- ep->dev = dev;
- SET_NETDEV_DEV(dev, &pdev->dev);
- netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);
-
- platform_set_drvdata(pdev, dev);
-
- ep->res = request_mem_region(mem->start, resource_size(mem),
- dev_name(&pdev->dev));
- if (ep->res == NULL) {
- dev_err(&pdev->dev, "Could not reserve memory region\n");
- err = -ENOMEM;
- goto err_out;
- }
-
- ep->base_addr = ioremap(mem->start, resource_size(mem));
- if (ep->base_addr == NULL) {
- dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
- err = -EIO;
- goto err_out;
- }
- ep->irq = irq;
-
- ep->mii.phy_id = data->phy_id;
- ep->mii.phy_id_mask = 0x1f;
- ep->mii.reg_num_mask = 0x1f;
- ep->mii.dev = dev;
- ep->mii.mdio_read = ep93xx_mdio_read;
- ep->mii.mdio_write = ep93xx_mdio_write;
- ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */
-
- if (is_zero_ether_addr(dev->dev_addr))
- random_ether_addr(dev->dev_addr);
-
- err = register_netdev(dev);
- if (err) {
- dev_err(&pdev->dev, "Failed to register netdev\n");
- goto err_out;
- }
-
- printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n",
- dev->name, ep->irq, dev->dev_addr);
-
- return 0;
-
-err_out:
- ep93xx_eth_remove(pdev);
- return err;
-}
-
-
-static struct platform_driver ep93xx_eth_driver = {
- .probe = ep93xx_eth_probe,
- .remove = ep93xx_eth_remove,
- .driver = {
- .name = "ep93xx-eth",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init ep93xx_eth_init_module(void)
-{
- printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
- return platform_driver_register(&ep93xx_eth_driver);
-}
-
-static void __exit ep93xx_eth_cleanup_module(void)
-{
- platform_driver_unregister(&ep93xx_eth_driver);
-}
-
-module_init(ep93xx_eth_init_module);
-module_exit(ep93xx_eth_cleanup_module);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ep93xx-eth");
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
deleted file mode 100644
index b00781c02d5d..000000000000
--- a/drivers/net/arm/ether1.c
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*
- * linux/drivers/acorn/net/ether1.c
- *
- * Copyright (C) 1996-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Acorn ether1 driver (82586 chip) for Acorn machines
- *
- * We basically keep two queues in the cards memory - one for transmit
- * and one for receive. Each has a head and a tail. The head is where
- * we/the chip adds packets to be transmitted/received, and the tail
- * is where the transmitter has got to/where the receiver will stop.
- * Both of these queues are circular, and since the chip is running
- * all the time, we have to be careful when we modify the pointers etc
- * so that the buffer memory contents is valid all the time.
- *
- * Change log:
- * 1.00 RMK Released
- * 1.01 RMK 19/03/1996 Transfers the last odd byte onto/off of the card now.
- * 1.02 RMK 25/05/1997 Added code to restart RU if it goes not ready
- * 1.03 RMK 14/09/1997 Cleaned up the handling of a reset during the TX interrupt.
- * Should prevent lockup.
- * 1.04 RMK 17/09/1997 Added more info when initialsation of chip goes wrong.
- * TDR now only reports failure when chip reports non-zero
- * TDR time-distance.
- * 1.05 RMK 31/12/1997 Removed calls to dev_tint for 2.1
- * 1.06 RMK 10/02/2000 Updated for 2.3.43
- * 1.07 RMK 13/05/2000 Updated for 2.3.99-pre8
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/ecard.h>
-
-#define __ETHER1_C
-#include "ether1.h"
-
-static unsigned int net_debug = NET_DEBUG;
-
-#define BUFFER_SIZE 0x10000
-#define TX_AREA_START 0x00100
-#define TX_AREA_END 0x05000
-#define RX_AREA_START 0x05000
-#define RX_AREA_END 0x0fc00
-
-static int ether1_open(struct net_device *dev);
-static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ether1_interrupt(int irq, void *dev_id);
-static int ether1_close(struct net_device *dev);
-static void ether1_setmulticastlist(struct net_device *dev);
-static void ether1_timeout(struct net_device *dev);
-
-/* ------------------------------------------------------------------------- */
-
-static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
-
-#define BUS_16 16
-#define BUS_8 8
-
-/* ------------------------------------------------------------------------- */
-
-#define DISABLEIRQS 1
-#define NORMALIRQS 0
-
-#define ether1_readw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
-#define ether1_writew(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
-
-static inline unsigned short
-ether1_inw_p (struct net_device *dev, int addr, int svflgs)
-{
- unsigned long flags;
- unsigned short ret;
-
- if (svflgs)
- local_irq_save (flags);
-
- writeb(addr >> 12, REG_PAGE);
- ret = readw(ETHER1_RAM + ((addr & 4095) << 1));
- if (svflgs)
- local_irq_restore (flags);
- return ret;
-}
-
-static inline void
-ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs)
-{
- unsigned long flags;
-
- if (svflgs)
- local_irq_save (flags);
-
- writeb(addr >> 12, REG_PAGE);
- writew(val, ETHER1_RAM + ((addr & 4095) << 1));
- if (svflgs)
- local_irq_restore (flags);
-}
-
-/*
- * Some inline assembler to allow fast transfers on to/off of the card.
- * Since this driver depends on some features presented by the ARM
- * specific architecture, and that you can't configure this driver
- * without specifiing ARM mode, this is not a problem.
- *
- * This routine is essentially an optimised memcpy from the card's
- * onboard RAM to kernel memory.
- */
-static void
-ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
-{
- unsigned int page, thislen, offset;
- void __iomem *addr;
-
- offset = start & 4095;
- page = start >> 12;
- addr = ETHER1_RAM + (offset << 1);
-
- if (offset + length > 4096)
- thislen = 4096 - offset;
- else
- thislen = length;
-
- do {
- int used;
-
- writeb(page, REG_PAGE);
- length -= thislen;
-
- __asm__ __volatile__(
- "subs %3, %3, #2\n\
- bmi 2f\n\
-1: ldr %0, [%1], #2\n\
- mov %0, %0, lsl #16\n\
- orr %0, %0, %0, lsr #16\n\
- str %0, [%2], #4\n\
- subs %3, %3, #2\n\
- bmi 2f\n\
- ldr %0, [%1], #2\n\
- mov %0, %0, lsl #16\n\
- orr %0, %0, %0, lsr #16\n\
- str %0, [%2], #4\n\
- subs %3, %3, #2\n\
- bmi 2f\n\
- ldr %0, [%1], #2\n\
- mov %0, %0, lsl #16\n\
- orr %0, %0, %0, lsr #16\n\
- str %0, [%2], #4\n\
- subs %3, %3, #2\n\
- bmi 2f\n\
- ldr %0, [%1], #2\n\
- mov %0, %0, lsl #16\n\
- orr %0, %0, %0, lsr #16\n\
- str %0, [%2], #4\n\
- subs %3, %3, #2\n\
- bpl 1b\n\
-2: adds %3, %3, #1\n\
- ldreqb %0, [%1]\n\
- streqb %0, [%2]"
- : "=&r" (used), "=&r" (data)
- : "r" (addr), "r" (thislen), "1" (data));
-
- addr = ETHER1_RAM;
-
- thislen = length;
- if (thislen > 4096)
- thislen = 4096;
- page++;
- } while (thislen);
-}
-
-static void
-ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
-{
- unsigned int page, thislen, offset;
- void __iomem *addr;
-
- offset = start & 4095;
- page = start >> 12;
- addr = ETHER1_RAM + (offset << 1);
-
- if (offset + length > 4096)
- thislen = 4096 - offset;
- else
- thislen = length;
-
- do {
- int used;
-
- writeb(page, REG_PAGE);
- length -= thislen;
-
- __asm__ __volatile__(
- "subs %3, %3, #2\n\
- bmi 2f\n\
-1: ldr %0, [%2], #4\n\
- strb %0, [%1], #1\n\
- mov %0, %0, lsr #8\n\
- strb %0, [%1], #1\n\
- subs %3, %3, #2\n\
- bmi 2f\n\
- ldr %0, [%2], #4\n\
- strb %0, [%1], #1\n\
- mov %0, %0, lsr #8\n\
- strb %0, [%1], #1\n\
- subs %3, %3, #2\n\
- bmi 2f\n\
- ldr %0, [%2], #4\n\
- strb %0, [%1], #1\n\
- mov %0, %0, lsr #8\n\
- strb %0, [%1], #1\n\
- subs %3, %3, #2\n\
- bmi 2f\n\
- ldr %0, [%2], #4\n\
- strb %0, [%1], #1\n\
- mov %0, %0, lsr #8\n\
- strb %0, [%1], #1\n\
- subs %3, %3, #2\n\
- bpl 1b\n\
-2: adds %3, %3, #1\n\
- ldreqb %0, [%2]\n\
- streqb %0, [%1]"
- : "=&r" (used), "=&r" (data)
- : "r" (addr), "r" (thislen), "1" (data));
-
- addr = ETHER1_RAM;
-
- thislen = length;
- if (thislen > 4096)
- thislen = 4096;
- page++;
- } while (thislen);
-}
-
-static int __devinit
-ether1_ramtest(struct net_device *dev, unsigned char byte)
-{
- unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
- int i, ret = BUFFER_SIZE;
- int max_errors = 15;
- int bad = -1;
- int bad_start = 0;
-
- if (!buffer)
- return 1;
-
- memset (buffer, byte, BUFFER_SIZE);
- ether1_writebuffer (dev, buffer, 0, BUFFER_SIZE);
- memset (buffer, byte ^ 0xff, BUFFER_SIZE);
- ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE);
-
- for (i = 0; i < BUFFER_SIZE; i++) {
- if (buffer[i] != byte) {
- if (max_errors >= 0 && bad != buffer[i]) {
- if (bad != -1)
- printk ("\n");
- printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X",
- dev->name, buffer[i], byte, i);
- ret = -ENODEV;
- max_errors --;
- bad = buffer[i];
- bad_start = i;
- }
- } else {
- if (bad != -1) {
- if (bad_start == i - 1)
- printk ("\n");
- else
- printk (" - 0x%04X\n", i - 1);
- bad = -1;
- }
- }
- }
-
- if (bad != -1)
- printk (" - 0x%04X\n", BUFFER_SIZE);
- kfree (buffer);
-
- return ret;
-}
-
-static int
-ether1_reset (struct net_device *dev)
-{
- writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
- return BUS_16;
-}
-
-static int __devinit
-ether1_init_2(struct net_device *dev)
-{
- int i;
- dev->mem_start = 0;
-
- i = ether1_ramtest (dev, 0x5a);
-
- if (i > 0)
- i = ether1_ramtest (dev, 0x1e);
-
- if (i <= 0)
- return -ENODEV;
-
- dev->mem_end = i;
- return 0;
-}
-
-/*
- * These are the structures that are loaded into the ether RAM card to
- * initialise the 82586
- */
-
-/* at 0x0100 */
-#define NOP_ADDR (TX_AREA_START)
-#define NOP_SIZE (0x06)
-static nop_t init_nop = {
- 0,
- CMD_NOP,
- NOP_ADDR
-};
-
-/* at 0x003a */
-#define TDR_ADDR (0x003a)
-#define TDR_SIZE (0x08)
-static tdr_t init_tdr = {
- 0,
- CMD_TDR | CMD_INTR,
- NOP_ADDR,
- 0
-};
-
-/* at 0x002e */
-#define MC_ADDR (0x002e)
-#define MC_SIZE (0x0c)
-static mc_t init_mc = {
- 0,
- CMD_SETMULTICAST,
- TDR_ADDR,
- 0,
- { { 0, } }
-};
-
-/* at 0x0022 */
-#define SA_ADDR (0x0022)
-#define SA_SIZE (0x0c)
-static sa_t init_sa = {
- 0,
- CMD_SETADDRESS,
- MC_ADDR,
- { 0, }
-};
-
-/* at 0x0010 */
-#define CFG_ADDR (0x0010)
-#define CFG_SIZE (0x12)
-static cfg_t init_cfg = {
- 0,
- CMD_CONFIG,
- SA_ADDR,
- 8,
- 8,
- CFG8_SRDY,
- CFG9_PREAMB8 | CFG9_ADDRLENBUF | CFG9_ADDRLEN(6),
- 0,
- 0x60,
- 0,
- CFG13_RETRY(15) | CFG13_SLOTH(2),
- 0,
-};
-
-/* at 0x0000 */
-#define SCB_ADDR (0x0000)
-#define SCB_SIZE (0x10)
-static scb_t init_scb = {
- 0,
- SCB_CMDACKRNR | SCB_CMDACKCNA | SCB_CMDACKFR | SCB_CMDACKCX,
- CFG_ADDR,
- RX_AREA_START,
- 0,
- 0,
- 0,
- 0
-};
-
-/* at 0xffee */
-#define ISCP_ADDR (0xffee)
-#define ISCP_SIZE (0x08)
-static iscp_t init_iscp = {
- 1,
- SCB_ADDR,
- 0x0000,
- 0x0000
-};
-
-/* at 0xfff6 */
-#define SCP_ADDR (0xfff6)
-#define SCP_SIZE (0x0a)
-static scp_t init_scp = {
- SCP_SY_16BBUS,
- { 0, 0 },
- ISCP_ADDR,
- 0
-};
-
-#define RFD_SIZE (0x16)
-static rfd_t init_rfd = {
- 0,
- 0,
- 0,
- 0,
- { 0, },
- { 0, },
- 0
-};
-
-#define RBD_SIZE (0x0a)
-static rbd_t init_rbd = {
- 0,
- 0,
- 0,
- 0,
- ETH_FRAME_LEN + 8
-};
-
-#define TX_SIZE (0x08)
-#define TBD_SIZE (0x08)
-
-static int
-ether1_init_for_open (struct net_device *dev)
-{
- int i, status, addr, next, next2;
- int failures = 0;
- unsigned long timeout;
-
- writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
-
- for (i = 0; i < 6; i++)
- init_sa.sa_addr[i] = dev->dev_addr[i];
-
- /* load data structures into ether1 RAM */
- ether1_writebuffer (dev, &init_scp, SCP_ADDR, SCP_SIZE);
- ether1_writebuffer (dev, &init_iscp, ISCP_ADDR, ISCP_SIZE);
- ether1_writebuffer (dev, &init_scb, SCB_ADDR, SCB_SIZE);
- ether1_writebuffer (dev, &init_cfg, CFG_ADDR, CFG_SIZE);
- ether1_writebuffer (dev, &init_sa, SA_ADDR, SA_SIZE);
- ether1_writebuffer (dev, &init_mc, MC_ADDR, MC_SIZE);
- ether1_writebuffer (dev, &init_tdr, TDR_ADDR, TDR_SIZE);
- ether1_writebuffer (dev, &init_nop, NOP_ADDR, NOP_SIZE);
-
- if (ether1_readw(dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
- printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n",
- dev->name);
- return 1;
- }
-
- /*
- * setup circularly linked list of { rfd, rbd, buffer }, with
- * all rfds circularly linked, rbds circularly linked.
- * First rfd is linked to scp, first rbd is linked to first
- * rfd. Last rbd has a suspend command.
- */
- addr = RX_AREA_START;
- do {
- next = addr + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
- next2 = next + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
-
- if (next2 >= RX_AREA_END) {
- next = RX_AREA_START;
- init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND;
- priv(dev)->rx_tail = addr;
- } else
- init_rfd.rfd_command = 0;
- if (addr == RX_AREA_START)
- init_rfd.rfd_rbdoffset = addr + RFD_SIZE;
- else
- init_rfd.rfd_rbdoffset = 0;
- init_rfd.rfd_link = next;
- init_rbd.rbd_link = next + RFD_SIZE;
- init_rbd.rbd_bufl = addr + RFD_SIZE + RBD_SIZE;
-
- ether1_writebuffer (dev, &init_rfd, addr, RFD_SIZE);
- ether1_writebuffer (dev, &init_rbd, addr + RFD_SIZE, RBD_SIZE);
- addr = next;
- } while (next2 < RX_AREA_END);
-
- priv(dev)->tx_link = NOP_ADDR;
- priv(dev)->tx_head = NOP_ADDR + NOP_SIZE;
- priv(dev)->tx_tail = TDR_ADDR;
- priv(dev)->rx_head = RX_AREA_START;
-
- /* release reset & give 586 a prod */
- priv(dev)->resetting = 1;
- priv(dev)->initialising = 1;
- writeb(CTRL_RST, REG_CONTROL);
- writeb(0, REG_CONTROL);
- writeb(CTRL_CA, REG_CONTROL);
-
- /* 586 should now unset iscp.busy */
- timeout = jiffies + HZ/2;
- while (ether1_readw(dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
- if (time_after(jiffies, timeout)) {
- printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
- return 1;
- }
- }
-
- /* check status of commands that we issued */
- timeout += HZ/10;
- while (((status = ether1_readw(dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
- & STAT_COMPLETE) == 0) {
- if (time_after(jiffies, timeout))
- break;
- }
-
- if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
- printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status);
- printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
- failures += 1;
- }
-
- timeout += HZ/10;
- while (((status = ether1_readw(dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
- & STAT_COMPLETE) == 0) {
- if (time_after(jiffies, timeout))
- break;
- }
-
- if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
- printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status);
- printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
- failures += 1;
- }
-
- timeout += HZ/10;
- while (((status = ether1_readw(dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
- & STAT_COMPLETE) == 0) {
- if (time_after(jiffies, timeout))
- break;
- }
-
- if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
- printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status);
- printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
- failures += 1;
- }
-
- timeout += HZ;
- while (((status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
- & STAT_COMPLETE) == 0) {
- if (time_after(jiffies, timeout))
- break;
- }
-
- if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
- printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name);
- printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
- } else {
- status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
- if (status & TDR_XCVRPROB)
- printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name);
- else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) {
-#ifdef FANCY
- printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d.%d us away\n", dev->name,
- status & TDR_SHORT ? "short" : "open", (status & TDR_TIME) / 10,
- (status & TDR_TIME) % 10);
-#else
- printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d clks away\n", dev->name,
- status & TDR_SHORT ? "short" : "open", (status & TDR_TIME));
-#endif
- }
- }
-
- if (failures)
- ether1_reset (dev);
- return failures ? 1 : 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int
-ether1_txalloc (struct net_device *dev, int size)
-{
- int start, tail;
-
- size = (size + 1) & ~1;
- tail = priv(dev)->tx_tail;
-
- if (priv(dev)->tx_head + size > TX_AREA_END) {
- if (tail > priv(dev)->tx_head)
- return -1;
- start = TX_AREA_START;
- if (start + size > tail)
- return -1;
- priv(dev)->tx_head = start + size;
- } else {
- if (priv(dev)->tx_head < tail && (priv(dev)->tx_head + size) > tail)
- return -1;
- start = priv(dev)->tx_head;
- priv(dev)->tx_head += size;
- }
-
- return start;
-}
-
-static int
-ether1_open (struct net_device *dev)
-{
- if (!is_valid_ether_addr(dev->dev_addr)) {
- printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
- dev->name);
- return -EINVAL;
- }
-
- if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
- return -EAGAIN;
-
- if (ether1_init_for_open (dev)) {
- free_irq (dev->irq, dev);
- return -EAGAIN;
- }
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-static void
-ether1_timeout(struct net_device *dev)
-{
- printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n",
- dev->name);
- printk(KERN_WARNING "%s: resetting device\n", dev->name);
-
- ether1_reset (dev);
-
- if (ether1_init_for_open (dev))
- printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
-
- dev->stats.tx_errors++;
- netif_wake_queue(dev);
-}
-
-static int
-ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
-{
- int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
- unsigned long flags;
- tx_t tx;
- tbd_t tbd;
- nop_t nop;
-
- if (priv(dev)->restart) {
- printk(KERN_WARNING "%s: resetting device\n", dev->name);
-
- ether1_reset(dev);
-
- if (ether1_init_for_open(dev))
- printk(KERN_ERR "%s: unable to restart interface\n", dev->name);
- else
- priv(dev)->restart = 0;
- }
-
- if (skb->len < ETH_ZLEN) {
- if (skb_padto(skb, ETH_ZLEN))
- goto out;
- }
-
- /*
- * insert packet followed by a nop
- */
- txaddr = ether1_txalloc (dev, TX_SIZE);
- tbdaddr = ether1_txalloc (dev, TBD_SIZE);
- dataddr = ether1_txalloc (dev, skb->len);
- nopaddr = ether1_txalloc (dev, NOP_SIZE);
-
- tx.tx_status = 0;
- tx.tx_command = CMD_TX | CMD_INTR;
- tx.tx_link = nopaddr;
- tx.tx_tbdoffset = tbdaddr;
- tbd.tbd_opts = TBD_EOL | skb->len;
- tbd.tbd_link = I82586_NULL;
- tbd.tbd_bufl = dataddr;
- tbd.tbd_bufh = 0;
- nop.nop_status = 0;
- nop.nop_command = CMD_NOP;
- nop.nop_link = nopaddr;
-
- local_irq_save(flags);
- ether1_writebuffer (dev, &tx, txaddr, TX_SIZE);
- ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
- ether1_writebuffer (dev, skb->data, dataddr, skb->len);
- ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
- tmp = priv(dev)->tx_link;
- priv(dev)->tx_link = nopaddr;
-
- /* now reset the previous nop pointer */
- ether1_writew(dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
-
- local_irq_restore(flags);
-
- /* handle transmit */
-
- /* check to see if we have room for a full sized ether frame */
- tmp = priv(dev)->tx_head;
- tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
- priv(dev)->tx_head = tmp;
- dev_kfree_skb (skb);
-
- if (tst == -1)
- netif_stop_queue(dev);
-
- out:
- return NETDEV_TX_OK;
-}
-
-static void
-ether1_xmit_done (struct net_device *dev)
-{
- nop_t nop;
- int caddr, tst;
-
- caddr = priv(dev)->tx_tail;
-
-again:
- ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
-
- switch (nop.nop_command & CMD_MASK) {
- case CMD_TDR:
- /* special case */
- if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
- != (unsigned short)I82586_NULL) {
- ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
- scb_command, NORMALIRQS);
- writeb(CTRL_CA, REG_CONTROL);
- }
- priv(dev)->tx_tail = NOP_ADDR;
- return;
-
- case CMD_NOP:
- if (nop.nop_link == caddr) {
- if (priv(dev)->initialising == 0)
- printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
- else
- priv(dev)->initialising = 0;
- return;
- }
- if (caddr == nop.nop_link)
- return;
- caddr = nop.nop_link;
- goto again;
-
- case CMD_TX:
- if (nop.nop_status & STAT_COMPLETE)
- break;
- printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
- priv(dev)->restart = 1;
- return;
-
- default:
- printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
- nop.nop_command & CMD_MASK, caddr);
- priv(dev)->restart = 1;
- return;
- }
-
- while (nop.nop_status & STAT_COMPLETE) {
- if (nop.nop_status & STAT_OK) {
- dev->stats.tx_packets++;
- dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
- } else {
- dev->stats.tx_errors++;
-
- if (nop.nop_status & STAT_COLLAFTERTX)
- dev->stats.collisions++;
- if (nop.nop_status & STAT_NOCARRIER)
- dev->stats.tx_carrier_errors++;
- if (nop.nop_status & STAT_TXLOSTCTS)
- printk (KERN_WARNING "%s: cts lost\n", dev->name);
- if (nop.nop_status & STAT_TXSLOWDMA)
- dev->stats.tx_fifo_errors++;
- if (nop.nop_status & STAT_COLLEXCESSIVE)
- dev->stats.collisions += 16;
- }
-
- if (nop.nop_link == caddr) {
- printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name);
- break;
- }
-
- caddr = nop.nop_link;
- ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
- if ((nop.nop_command & CMD_MASK) != CMD_NOP) {
- printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name);
- break;
- }
-
- if (caddr == nop.nop_link)
- break;
-
- caddr = nop.nop_link;
- ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
- if ((nop.nop_command & CMD_MASK) != CMD_TX) {
- printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name);
- break;
- }
- }
- priv(dev)->tx_tail = caddr;
-
- caddr = priv(dev)->tx_head;
- tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
- priv(dev)->tx_head = caddr;
- if (tst != -1)
- netif_wake_queue(dev);
-}
-
-static void
-ether1_recv_done (struct net_device *dev)
-{
- int status;
- int nexttail, rbdaddr;
- rbd_t rbd;
-
- do {
- status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS);
- if ((status & RFD_COMPLETE) == 0)
- break;
-
- rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
- ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
-
- if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
- int length = rbd.rbd_status & RBD_ACNT;
- struct sk_buff *skb;
-
- length = (length + 1) & ~1;
- skb = dev_alloc_skb (length + 2);
-
- if (skb) {
- skb_reserve (skb, 2);
-
- ether1_readbuffer (dev, skb_put (skb, length), rbd.rbd_bufl, length);
-
- skb->protocol = eth_type_trans (skb, dev);
- netif_rx (skb);
- dev->stats.rx_packets++;
- } else
- dev->stats.rx_dropped++;
- } else {
- printk(KERN_WARNING "%s: %s\n", dev->name,
- (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
- dev->stats.rx_dropped++;
- }
-
- nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
- /* nexttail should be rx_head */
- if (nexttail != priv(dev)->rx_head)
- printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
- dev->name, nexttail, priv(dev)->rx_head);
- ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
- ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS);
- ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS);
- ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
-
- priv(dev)->rx_tail = nexttail;
- priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS);
- } while (1);
-}
-
-static irqreturn_t
-ether1_interrupt (int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- int status;
-
- status = ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
-
- if (status) {
- ether1_writew(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
- SCB_ADDR, scb_t, scb_command, NORMALIRQS);
- writeb(CTRL_CA | CTRL_ACK, REG_CONTROL);
- if (status & SCB_STCX) {
- ether1_xmit_done (dev);
- }
- if (status & SCB_STCNA) {
- if (priv(dev)->resetting == 0)
- printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name);
- else
- priv(dev)->resetting += 1;
- if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
- != (unsigned short)I82586_NULL) {
- ether1_writew(dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
- writeb(CTRL_CA, REG_CONTROL);
- }
- if (priv(dev)->resetting == 2)
- priv(dev)->resetting = 0;
- }
- if (status & SCB_STFR) {
- ether1_recv_done (dev);
- }
- if (status & SCB_STRNR) {
- if (ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
- printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
- ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
- writeb(CTRL_CA, REG_CONTROL);
- dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */
- } else
- printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
- ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
- printk (KERN_WARNING "RU ptr = %04X\n", ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset,
- NORMALIRQS));
- }
- } else
- writeb(CTRL_ACK, REG_CONTROL);
-
- return IRQ_HANDLED;
-}
-
-static int
-ether1_close (struct net_device *dev)
-{
- ether1_reset (dev);
-
- free_irq(dev->irq, dev);
-
- return 0;
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- * num_addrs == -1 Promiscuous mode, receive all packets.
- * num_addrs == 0 Normal mode, clear multicast list.
- * num_addrs > 0 Multicast mode, receive normal and MC packets, and do
- * best-effort filtering.
- */
-static void
-ether1_setmulticastlist (struct net_device *dev)
-{
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void __devinit ether1_banner(void)
-{
- static unsigned int version_printed = 0;
-
- if (net_debug && version_printed++ == 0)
- printk(KERN_INFO "%s", version);
-}
-
-static const struct net_device_ops ether1_netdev_ops = {
- .ndo_open = ether1_open,
- .ndo_stop = ether1_close,
- .ndo_start_xmit = ether1_sendpacket,
- .ndo_set_multicast_list = ether1_setmulticastlist,
- .ndo_tx_timeout = ether1_timeout,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
-};
-
-static int __devinit
-ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
- struct net_device *dev;
- int i, ret = 0;
-
- ether1_banner();
-
- ret = ecard_request_resources(ec);
- if (ret)
- goto out;
-
- dev = alloc_etherdev(sizeof(struct ether1_priv));
- if (!dev) {
- ret = -ENOMEM;
- goto release;
- }
-
- SET_NETDEV_DEV(dev, &ec->dev);
-
- dev->irq = ec->irq;
- priv(dev)->base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
- if (!priv(dev)->base) {
- ret = -ENOMEM;
- goto free;
- }
-
- if ((priv(dev)->bus_type = ether1_reset(dev)) == 0) {
- ret = -ENODEV;
- goto free;
- }
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = readb(IDPROM_ADDRESS + (i << 2));
-
- if (ether1_init_2(dev)) {
- ret = -ENODEV;
- goto free;
- }
-
- dev->netdev_ops = &ether1_netdev_ops;
- dev->watchdog_timeo = 5 * HZ / 100;
-
- ret = register_netdev(dev);
- if (ret)
- goto free;
-
- printk(KERN_INFO "%s: ether1 in slot %d, %pM\n",
- dev->name, ec->slot_no, dev->dev_addr);
-
- ecard_set_drvdata(ec, dev);
- return 0;
-
- free:
- free_netdev(dev);
- release:
- ecard_release_resources(ec);
- out:
- return ret;
-}
-
-static void __devexit ether1_remove(struct expansion_card *ec)
-{
- struct net_device *dev = ecard_get_drvdata(ec);
-
- ecard_set_drvdata(ec, NULL);
-
- unregister_netdev(dev);
- free_netdev(dev);
- ecard_release_resources(ec);
-}
-
-static const struct ecard_id ether1_ids[] = {
- { MANU_ACORN, PROD_ACORN_ETHER1 },
- { 0xffff, 0xffff }
-};
-
-static struct ecard_driver ether1_driver = {
- .probe = ether1_probe,
- .remove = __devexit_p(ether1_remove),
- .id_table = ether1_ids,
- .drv = {
- .name = "ether1",
- },
-};
-
-static int __init ether1_init(void)
-{
- return ecard_register_driver(&ether1_driver);
-}
-
-static void __exit ether1_exit(void)
-{
- ecard_remove_driver(&ether1_driver);
-}
-
-module_init(ether1_init);
-module_exit(ether1_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
deleted file mode 100644
index 3a5830ab3dc7..000000000000
--- a/drivers/net/arm/ether1.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * linux/drivers/acorn/net/ether1.h
- *
- * Copyright (C) 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Network driver for Acorn Ether1 cards.
- */
-
-#ifndef _LINUX_ether1_H
-#define _LINUX_ether1_H
-
-#ifdef __ETHER1_C
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-
-#define priv(dev) ((struct ether1_priv *)netdev_priv(dev))
-
-/* Page register */
-#define REG_PAGE (priv(dev)->base + 0x0000)
-
-/* Control register */
-#define REG_CONTROL (priv(dev)->base + 0x0004)
-#define CTRL_RST 0x01
-#define CTRL_LOOPBACK 0x02
-#define CTRL_CA 0x04
-#define CTRL_ACK 0x08
-
-#define ETHER1_RAM (priv(dev)->base + 0x2000)
-
-/* HW address */
-#define IDPROM_ADDRESS (priv(dev)->base + 0x0024)
-
-struct ether1_priv {
- void __iomem *base;
- unsigned int tx_link;
- unsigned int tx_head;
- volatile unsigned int tx_tail;
- volatile unsigned int rx_head;
- volatile unsigned int rx_tail;
- unsigned char bus_type;
- unsigned char resetting;
- unsigned char initialising : 1;
- unsigned char restart : 1;
-};
-
-#define I82586_NULL (-1)
-
-typedef struct { /* tdr */
- unsigned short tdr_status;
- unsigned short tdr_command;
- unsigned short tdr_link;
- unsigned short tdr_result;
-#define TDR_TIME (0x7ff)
-#define TDR_SHORT (1 << 12)
-#define TDR_OPEN (1 << 13)
-#define TDR_XCVRPROB (1 << 14)
-#define TDR_LNKOK (1 << 15)
-} tdr_t;
-
-typedef struct { /* transmit */
- unsigned short tx_status;
- unsigned short tx_command;
- unsigned short tx_link;
- unsigned short tx_tbdoffset;
-} tx_t;
-
-typedef struct { /* tbd */
- unsigned short tbd_opts;
-#define TBD_CNT (0x3fff)
-#define TBD_EOL (1 << 15)
- unsigned short tbd_link;
- unsigned short tbd_bufl;
- unsigned short tbd_bufh;
-} tbd_t;
-
-typedef struct { /* rfd */
- unsigned short rfd_status;
-#define RFD_NOEOF (1 << 6)
-#define RFD_FRAMESHORT (1 << 7)
-#define RFD_DMAOVRN (1 << 8)
-#define RFD_NORESOURCES (1 << 9)
-#define RFD_ALIGNERROR (1 << 10)
-#define RFD_CRCERROR (1 << 11)
-#define RFD_OK (1 << 13)
-#define RFD_FDCONSUMED (1 << 14)
-#define RFD_COMPLETE (1 << 15)
- unsigned short rfd_command;
-#define RFD_CMDSUSPEND (1 << 14)
-#define RFD_CMDEL (1 << 15)
- unsigned short rfd_link;
- unsigned short rfd_rbdoffset;
- unsigned char rfd_dest[6];
- unsigned char rfd_src[6];
- unsigned short rfd_len;
-} rfd_t;
-
-typedef struct { /* rbd */
- unsigned short rbd_status;
-#define RBD_ACNT (0x3fff)
-#define RBD_ACNTVALID (1 << 14)
-#define RBD_EOF (1 << 15)
- unsigned short rbd_link;
- unsigned short rbd_bufl;
- unsigned short rbd_bufh;
- unsigned short rbd_len;
-} rbd_t;
-
-typedef struct { /* nop */
- unsigned short nop_status;
- unsigned short nop_command;
- unsigned short nop_link;
-} nop_t;
-
-typedef struct { /* set multicast */
- unsigned short mc_status;
- unsigned short mc_command;
- unsigned short mc_link;
- unsigned short mc_cnt;
- unsigned char mc_addrs[1][6];
-} mc_t;
-
-typedef struct { /* set address */
- unsigned short sa_status;
- unsigned short sa_command;
- unsigned short sa_link;
- unsigned char sa_addr[6];
-} sa_t;
-
-typedef struct { /* config command */
- unsigned short cfg_status;
- unsigned short cfg_command;
- unsigned short cfg_link;
- unsigned char cfg_bytecnt; /* size foll data: 4 - 12 */
- unsigned char cfg_fifolim; /* FIFO threshold */
- unsigned char cfg_byte8;
-#define CFG8_SRDY (1 << 6)
-#define CFG8_SAVEBADF (1 << 7)
- unsigned char cfg_byte9;
-#define CFG9_ADDRLEN(x) (x)
-#define CFG9_ADDRLENBUF (1 << 3)
-#define CFG9_PREAMB2 (0 << 4)
-#define CFG9_PREAMB4 (1 << 4)
-#define CFG9_PREAMB8 (2 << 4)
-#define CFG9_PREAMB16 (3 << 4)
-#define CFG9_ILOOPBACK (1 << 6)
-#define CFG9_ELOOPBACK (1 << 7)
- unsigned char cfg_byte10;
-#define CFG10_LINPRI(x) (x)
-#define CFG10_ACR(x) (x << 4)
-#define CFG10_BOFMET (1 << 7)
- unsigned char cfg_ifs;
- unsigned char cfg_slotl;
- unsigned char cfg_byte13;
-#define CFG13_SLOTH(x) (x)
-#define CFG13_RETRY(x) (x << 4)
- unsigned char cfg_byte14;
-#define CFG14_PROMISC (1 << 0)
-#define CFG14_DISBRD (1 << 1)
-#define CFG14_MANCH (1 << 2)
-#define CFG14_TNCRS (1 << 3)
-#define CFG14_NOCRC (1 << 4)
-#define CFG14_CRC16 (1 << 5)
-#define CFG14_BTSTF (1 << 6)
-#define CFG14_FLGPAD (1 << 7)
- unsigned char cfg_byte15;
-#define CFG15_CSTF(x) (x)
-#define CFG15_ICSS (1 << 3)
-#define CFG15_CDTF(x) (x << 4)
-#define CFG15_ICDS (1 << 7)
- unsigned short cfg_minfrmlen;
-} cfg_t;
-
-typedef struct { /* scb */
- unsigned short scb_status; /* status of 82586 */
-#define SCB_STRXMASK (7 << 4) /* Receive unit status */
-#define SCB_STRXIDLE (0 << 4) /* Idle */
-#define SCB_STRXSUSP (1 << 4) /* Suspended */
-#define SCB_STRXNRES (2 << 4) /* No resources */
-#define SCB_STRXRDY (4 << 4) /* Ready */
-#define SCB_STCUMASK (7 << 8) /* Command unit status */
-#define SCB_STCUIDLE (0 << 8) /* Idle */
-#define SCB_STCUSUSP (1 << 8) /* Suspended */
-#define SCB_STCUACTV (2 << 8) /* Active */
-#define SCB_STRNR (1 << 12) /* Receive unit not ready */
-#define SCB_STCNA (1 << 13) /* Command unit not ready */
-#define SCB_STFR (1 << 14) /* Frame received */
-#define SCB_STCX (1 << 15) /* Command completed */
- unsigned short scb_command; /* Next command */
-#define SCB_CMDRXSTART (1 << 4) /* Start (at rfa_offset) */
-#define SCB_CMDRXRESUME (2 << 4) /* Resume reception */
-#define SCB_CMDRXSUSPEND (3 << 4) /* Suspend reception */
-#define SCB_CMDRXABORT (4 << 4) /* Abort reception */
-#define SCB_CMDCUCSTART (1 << 8) /* Start (at cbl_offset) */
-#define SCB_CMDCUCRESUME (2 << 8) /* Resume execution */
-#define SCB_CMDCUCSUSPEND (3 << 8) /* Suspend execution */
-#define SCB_CMDCUCABORT (4 << 8) /* Abort execution */
-#define SCB_CMDACKRNR (1 << 12) /* Ack RU not ready */
-#define SCB_CMDACKCNA (1 << 13) /* Ack CU not ready */
-#define SCB_CMDACKFR (1 << 14) /* Ack Frame received */
-#define SCB_CMDACKCX (1 << 15) /* Ack Command complete */
- unsigned short scb_cbl_offset; /* Offset of first command unit */
- unsigned short scb_rfa_offset; /* Offset of first receive frame area */
- unsigned short scb_crc_errors; /* Properly aligned frame with CRC error*/
- unsigned short scb_aln_errors; /* Misaligned frames */
- unsigned short scb_rsc_errors; /* Frames lost due to no space */
- unsigned short scb_ovn_errors; /* Frames lost due to slow bus */
-} scb_t;
-
-typedef struct { /* iscp */
- unsigned short iscp_busy; /* set by CPU before CA */
- unsigned short iscp_offset; /* offset of SCB */
- unsigned short iscp_basel; /* base of SCB */
- unsigned short iscp_baseh;
-} iscp_t;
-
- /* this address must be 0xfff6 */
-typedef struct { /* scp */
- unsigned short scp_sysbus; /* bus size */
-#define SCP_SY_16BBUS 0x00
-#define SCP_SY_8BBUS 0x01
- unsigned short scp_junk[2]; /* junk */
- unsigned short scp_iscpl; /* lower 16 bits of iscp */
- unsigned short scp_iscph; /* upper 16 bits of iscp */
-} scp_t;
-
-/* commands */
-#define CMD_NOP 0
-#define CMD_SETADDRESS 1
-#define CMD_CONFIG 2
-#define CMD_SETMULTICAST 3
-#define CMD_TX 4
-#define CMD_TDR 5
-#define CMD_DUMP 6
-#define CMD_DIAGNOSE 7
-
-#define CMD_MASK 7
-
-#define CMD_INTR (1 << 13)
-#define CMD_SUSP (1 << 14)
-#define CMD_EOL (1 << 15)
-
-#define STAT_COLLISIONS (15)
-#define STAT_COLLEXCESSIVE (1 << 5)
-#define STAT_COLLAFTERTX (1 << 6)
-#define STAT_TXDEFERRED (1 << 7)
-#define STAT_TXSLOWDMA (1 << 8)
-#define STAT_TXLOSTCTS (1 << 9)
-#define STAT_NOCARRIER (1 << 10)
-#define STAT_FAIL (1 << 11)
-#define STAT_ABORTED (1 << 12)
-#define STAT_OK (1 << 13)
-#define STAT_BUSY (1 << 14)
-#define STAT_COMPLETE (1 << 15)
-#endif
-#endif
-
-/*
- * Ether1 card definitions:
- *
- * FAST accesses:
- * +0 Page register
- * 16 pages
- * +4 Control
- * '1' = reset
- * '2' = loopback
- * '4' = CA
- * '8' = int ack
- *
- * RAM at address + 0x2000
- * Pod. Prod id = 3
- * Words after ID block [base + 8 words]
- * +0 pcb issue (0x0c and 0xf3 invalid)
- * +1 - +6 eth hw address
- */
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
deleted file mode 100644
index 44a8746f4014..000000000000
--- a/drivers/net/arm/ether3.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * linux/drivers/acorn/net/ether3.c
- *
- * Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * SEEQ nq8005 ethernet driver for Acorn/ANT Ether3 card
- * for Acorn machines
- *
- * By Russell King, with some suggestions from borris@ant.co.uk
- *
- * Changelog:
- * 1.04 RMK 29/02/1996 Won't pass packets that are from our ethernet
- * address up to the higher levels - they're
- * silently ignored. I/F can now be put into
- * multicast mode. Receiver routine optimised.
- * 1.05 RMK 30/02/1996 Now claims interrupt at open when part of
- * the kernel rather than when a module.
- * 1.06 RMK 02/03/1996 Various code cleanups
- * 1.07 RMK 13/10/1996 Optimised interrupt routine and transmit
- * routines.
- * 1.08 RMK 14/10/1996 Fixed problem with too many packets,
- * prevented the kernel message about dropped
- * packets appearing too many times a second.
- * Now does not disable all IRQs, only the IRQ
- * used by this card.
- * 1.09 RMK 10/11/1996 Only enables TX irq when buffer space is low,
- * but we still service the TX queue if we get a
- * RX interrupt.
- * 1.10 RMK 15/07/1997 Fixed autoprobing of NQ8004.
- * 1.11 RMK 16/11/1997 Fixed autoprobing of NQ8005A.
- * 1.12 RMK 31/12/1997 Removed reference to dev_tint for Linux 2.1.
- * RMK 27/06/1998 Changed asm/delay.h to linux/delay.h.
- * 1.13 RMK 29/06/1998 Fixed problem with transmission of packets.
- * Chip seems to have a bug in, whereby if the
- * packet starts two bytes from the end of the
- * buffer, it corrupts the receiver chain, and
- * never updates the transmit status correctly.
- * 1.14 RMK 07/01/1998 Added initial code for ETHERB addressing.
- * 1.15 RMK 30/04/1999 More fixes to the transmit routine for buggy
- * hardware.
- * 1.16 RMK 10/02/2000 Updated for 2.3.43
- * 1.17 RMK 13/05/2000 Updated for 2.3.99-pre8
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/ecard.h>
-#include <asm/io.h>
-
-static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
-
-#include "ether3.h"
-
-static unsigned int net_debug = NET_DEBUG;
-
-static void ether3_setmulticastlist(struct net_device *dev);
-static int ether3_rx(struct net_device *dev, unsigned int maxcnt);
-static void ether3_tx(struct net_device *dev);
-static int ether3_open (struct net_device *dev);
-static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ether3_interrupt (int irq, void *dev_id);
-static int ether3_close (struct net_device *dev);
-static void ether3_setmulticastlist (struct net_device *dev);
-static void ether3_timeout(struct net_device *dev);
-
-#define BUS_16 2
-#define BUS_8 1
-#define BUS_UNKNOWN 0
-
-/* --------------------------------------------------------------------------- */
-
-typedef enum {
- buffer_write,
- buffer_read
-} buffer_rw_t;
-
-/*
- * ether3 read/write. Slow things down a bit...
- * The SEEQ8005 doesn't like us writing to its registers
- * too quickly.
- */
-static inline void ether3_outb(int v, const void __iomem *r)
-{
- writeb(v, r);
- udelay(1);
-}
-
-static inline void ether3_outw(int v, const void __iomem *r)
-{
- writew(v, r);
- udelay(1);
-}
-#define ether3_inb(r) ({ unsigned int __v = readb((r)); udelay(1); __v; })
-#define ether3_inw(r) ({ unsigned int __v = readw((r)); udelay(1); __v; })
-
-static int
-ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
-{
- int timeout = 1000;
-
- ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
- ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
-
- while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) {
- if (!timeout--) {
- printk("%s: setbuffer broken\n", dev->name);
- priv(dev)->broken = 1;
- return 1;
- }
- udelay(1);
- }
-
- if (read == buffer_read) {
- ether3_outw(start, REG_DMAADDR);
- ether3_outw(priv(dev)->regs.command | CMD_FIFOREAD, REG_COMMAND);
- } else {
- ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
- ether3_outw(start, REG_DMAADDR);
- }
- return 0;
-}
-
-/*
- * write data to the buffer memory
- */
-#define ether3_writebuffer(dev,data,length) \
- writesw(REG_BUFWIN, (data), (length) >> 1)
-
-#define ether3_writeword(dev,data) \
- writew((data), REG_BUFWIN)
-
-#define ether3_writelong(dev,data) { \
- void __iomem *reg_bufwin = REG_BUFWIN; \
- writew((data), reg_bufwin); \
- writew((data) >> 16, reg_bufwin); \
-}
-
-/*
- * read data from the buffer memory
- */
-#define ether3_readbuffer(dev,data,length) \
- readsw(REG_BUFWIN, (data), (length) >> 1)
-
-#define ether3_readword(dev) \
- readw(REG_BUFWIN)
-
-#define ether3_readlong(dev) \
- readw(REG_BUFWIN) | (readw(REG_BUFWIN) << 16)
-
-/*
- * Switch LED off...
- */
-static void ether3_ledoff(unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
-}
-
-/*
- * switch LED on...
- */
-static inline void ether3_ledon(struct net_device *dev)
-{
- del_timer(&priv(dev)->timer);
- priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
- priv(dev)->timer.data = (unsigned long)dev;
- priv(dev)->timer.function = ether3_ledoff;
- add_timer(&priv(dev)->timer);
- if (priv(dev)->regs.config2 & CFG2_CTRLO)
- ether3_outw(priv(dev)->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2);
-}
-
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string!!!
- */
-static int __devinit
-ether3_addr(char *addr, struct expansion_card *ec)
-{
- struct in_chunk_dir cd;
- char *s;
-
- if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
- int i;
- for (i = 0; i<6; i++) {
- addr[i] = simple_strtoul(s + 1, &s, 0x10);
- if (*s != (i==5?')' : ':' ))
- break;
- }
- if (i == 6)
- return 0;
- }
- /* I wonder if we should even let the user continue in this case
- * - no, it would be better to disable the device
- */
- printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n");
- return -ENODEV;
-}
-
-/* --------------------------------------------------------------------------- */
-
-static int __devinit
-ether3_ramtest(struct net_device *dev, unsigned char byte)
-{
- unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
- int i,ret = 0;
- int max_errors = 4;
- int bad = -1;
-
- if (!buffer)
- return 1;
-
- memset(buffer, byte, RX_END);
- ether3_setbuffer(dev, buffer_write, 0);
- ether3_writebuffer(dev, buffer, TX_END);
- ether3_setbuffer(dev, buffer_write, RX_START);
- ether3_writebuffer(dev, buffer + RX_START, RX_LEN);
- memset(buffer, byte ^ 0xff, RX_END);
- ether3_setbuffer(dev, buffer_read, 0);
- ether3_readbuffer(dev, buffer, TX_END);
- ether3_setbuffer(dev, buffer_read, RX_START);
- ether3_readbuffer(dev, buffer + RX_START, RX_LEN);
-
- for (i = 0; i < RX_END; i++) {
- if (buffer[i] != byte) {
- if (max_errors > 0 && bad != buffer[i]) {
- printk("%s: RAM failed with (%02X instead of %02X) at 0x%04X",
- dev->name, buffer[i], byte, i);
- ret = 2;
- max_errors--;
- bad = i;
- }
- } else {
- if (bad != -1) {
- if (bad != i - 1)
- printk(" - 0x%04X\n", i - 1);
- printk("\n");
- bad = -1;
- }
- }
- }
- if (bad != -1)
- printk(" - 0xffff\n");
- kfree(buffer);
-
- return ret;
-}
-
-/* ------------------------------------------------------------------------------- */
-
-static int __devinit ether3_init_2(struct net_device *dev)
-{
- int i;
-
- priv(dev)->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
- priv(dev)->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
- priv(dev)->regs.command = 0;
-
- /*
- * Set up our hardware address
- */
- ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
- for (i = 0; i < 6; i++)
- ether3_outb(dev->dev_addr[i], REG_BUFWIN);
-
- if (dev->flags & IFF_PROMISC)
- priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
- else if (dev->flags & IFF_MULTICAST)
- priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
- else
- priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
-
- /*
- * There is a problem with the NQ8005 in that it occasionally loses the
- * last two bytes. To get round this problem, we receive the CRC as
- * well. That way, if we do lose the last two, then it doesn't matter.
- */
- ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
- ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
- ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
- ether3_outw(0, REG_TRANSMITPTR);
- ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
- ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
- ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
- ether3_outw(priv(dev)->regs.command, REG_COMMAND);
-
- i = ether3_ramtest(dev, 0x5A);
- if(i)
- return i;
- i = ether3_ramtest(dev, 0x1E);
- if(i)
- return i;
-
- ether3_setbuffer(dev, buffer_write, 0);
- ether3_writelong(dev, 0);
- return 0;
-}
-
-static void
-ether3_init_for_open(struct net_device *dev)
-{
- int i;
-
- /* Reset the chip */
- ether3_outw(CFG2_RESET, REG_CONFIG2);
- udelay(4);
-
- priv(dev)->regs.command = 0;
- ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
- while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
- barrier();
-
- ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
- for (i = 0; i < 6; i++)
- ether3_outb(dev->dev_addr[i], REG_BUFWIN);
-
- priv(dev)->tx_head = 0;
- priv(dev)->tx_tail = 0;
- priv(dev)->regs.config2 |= CFG2_CTRLO;
- priv(dev)->rx_head = RX_START;
-
- ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
- ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
- ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
- ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
- ether3_outw(0, REG_TRANSMITPTR);
- ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
- ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-
- ether3_setbuffer(dev, buffer_write, 0);
- ether3_writelong(dev, 0);
-
- priv(dev)->regs.command = CMD_ENINTRX | CMD_ENINTTX;
- ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
-}
-
-static inline int
-ether3_probe_bus_8(struct net_device *dev, int val)
-{
- int write_low, write_high, read_low, read_high;
-
- write_low = val & 255;
- write_high = val >> 8;
-
- printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low);
-
- ether3_outb(write_low, REG_RECVPTR);
- ether3_outb(write_high, REG_RECVPTR + 4);
-
- read_low = ether3_inb(REG_RECVPTR);
- read_high = ether3_inb(REG_RECVPTR + 4);
-
- printk(", read8 [%02X:%02X]\n", read_high, read_low);
-
- return read_low == write_low && read_high == write_high;
-}
-
-static inline int
-ether3_probe_bus_16(struct net_device *dev, int val)
-{
- int read_val;
-
- ether3_outw(val, REG_RECVPTR);
- read_val = ether3_inw(REG_RECVPTR);
-
- printk(KERN_DEBUG "ether3_probe: write16 [%04X], read16 [%04X]\n", val, read_val);
-
- return read_val == val;
-}
-
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-ether3_open(struct net_device *dev)
-{
- if (!is_valid_ether_addr(dev->dev_addr)) {
- printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
- dev->name);
- return -EINVAL;
- }
-
- if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
- return -EAGAIN;
-
- ether3_init_for_open(dev);
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-/*
- * The inverse routine to ether3_open().
- */
-static int
-ether3_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
-
- disable_irq(dev->irq);
-
- ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
- priv(dev)->regs.command = 0;
- while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
- barrier();
- ether3_outb(0x80, REG_CONFIG2 + 4);
- ether3_outw(0, REG_COMMAND);
-
- free_irq(dev->irq, dev);
-
- return 0;
-}
-
-/*
- * Set or clear promiscuous/multicast mode filter for this adaptor.
- *
- * We don't attempt any packet filtering. The card may have a SEEQ 8004
- * in which does not have the other ethernet address registers present...
- */
-static void ether3_setmulticastlist(struct net_device *dev)
-{
- priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC;
-
- if (dev->flags & IFF_PROMISC) {
- /* promiscuous mode */
- priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
- } else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) {
- priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
- } else
- priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
-
- ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-}
-
-static void ether3_timeout(struct net_device *dev)
-{
- unsigned long flags;
-
- del_timer(&priv(dev)->timer);
-
- local_irq_save(flags);
- printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);
- printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name,
- ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2));
- printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name,
- ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR));
- printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name,
- priv(dev)->tx_head, priv(dev)->tx_tail);
- ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail);
- printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));
- local_irq_restore(flags);
-
- priv(dev)->regs.config2 |= CFG2_CTRLO;
- dev->stats.tx_errors += 1;
- ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
- priv(dev)->tx_head = priv(dev)->tx_tail = 0;
-
- netif_wake_queue(dev);
-}
-
-/*
- * Transmit a packet
- */
-static int
-ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
-{
- unsigned long flags;
- unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned int ptr, next_ptr;
-
- if (priv(dev)->broken) {
- dev_kfree_skb(skb);
- dev->stats.tx_dropped++;
- netif_start_queue(dev);
- return NETDEV_TX_OK;
- }
-
- length = (length + 1) & ~1;
- if (length != skb->len) {
- if (skb_padto(skb, length))
- goto out;
- }
-
- next_ptr = (priv(dev)->tx_head + 1) & 15;
-
- local_irq_save(flags);
-
- if (priv(dev)->tx_tail == next_ptr) {
- local_irq_restore(flags);
- return NETDEV_TX_BUSY; /* unable to queue */
- }
-
- ptr = 0x600 * priv(dev)->tx_head;
- priv(dev)->tx_head = next_ptr;
- next_ptr *= 0x600;
-
-#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
-
- ether3_setbuffer(dev, buffer_write, next_ptr);
- ether3_writelong(dev, 0);
- ether3_setbuffer(dev, buffer_write, ptr);
- ether3_writelong(dev, 0);
- ether3_writebuffer(dev, skb->data, length);
- ether3_writeword(dev, htons(next_ptr));
- ether3_writeword(dev, TXHDR_CHAINCONTINUE >> 16);
- ether3_setbuffer(dev, buffer_write, ptr);
- ether3_writeword(dev, htons((ptr + length + 4)));
- ether3_writeword(dev, TXHDR_FLAGS >> 16);
- ether3_ledon(dev);
-
- if (!(ether3_inw(REG_STATUS) & STAT_TXON)) {
- ether3_outw(ptr, REG_TRANSMITPTR);
- ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND);
- }
-
- next_ptr = (priv(dev)->tx_head + 1) & 15;
- local_irq_restore(flags);
-
- dev_kfree_skb(skb);
-
- if (priv(dev)->tx_tail == next_ptr)
- netif_stop_queue(dev);
-
- out:
- return NETDEV_TX_OK;
-}
-
-static irqreturn_t
-ether3_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- unsigned int status, handled = IRQ_NONE;
-
-#if NET_DEBUG > 1
- if(net_debug & DEBUG_INT)
- printk("eth3irq: %d ", irq);
-#endif
-
- status = ether3_inw(REG_STATUS);
-
- if (status & STAT_INTRX) {
- ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND);
- ether3_rx(dev, 12);
- handled = IRQ_HANDLED;
- }
-
- if (status & STAT_INTTX) {
- ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND);
- ether3_tx(dev);
- handled = IRQ_HANDLED;
- }
-
-#if NET_DEBUG > 1
- if(net_debug & DEBUG_INT)
- printk("done\n");
-#endif
- return handled;
-}
-
-/*
- * If we have a good packet(s), get it/them out of the buffers.
- */
-static int ether3_rx(struct net_device *dev, unsigned int maxcnt)
-{
- unsigned int next_ptr = priv(dev)->rx_head, received = 0;
-
- ether3_ledon(dev);
-
- do {
- unsigned int this_ptr, status;
- unsigned char addrs[16];
-
- /*
- * read the first 16 bytes from the buffer.
- * This contains the status bytes etc and ethernet addresses,
- * and we also check the source ethernet address to see if
- * it originated from us.
- */
- {
- unsigned int temp_ptr;
- ether3_setbuffer(dev, buffer_read, next_ptr);
- temp_ptr = ether3_readword(dev);
- status = ether3_readword(dev);
- if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) !=
- (RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr)
- break;
-
- this_ptr = next_ptr + 4;
- next_ptr = ntohs(temp_ptr);
- }
- ether3_setbuffer(dev, buffer_read, this_ptr);
- ether3_readbuffer(dev, addrs+2, 12);
-
-if (next_ptr < RX_START || next_ptr >= RX_END) {
- int i;
- printk("%s: bad next pointer @%04X: ", dev->name, priv(dev)->rx_head);
- printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8);
- for (i = 2; i < 14; i++)
- printk("%02X ", addrs[i]);
- printk("\n");
- next_ptr = priv(dev)->rx_head;
- break;
-}
- /*
- * ignore our own packets...
- */
- if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) &&
- !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) {
- maxcnt ++; /* compensate for loopedback packet */
- ether3_outw(next_ptr >> 8, REG_RECVEND);
- } else
- if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) {
- unsigned int length = next_ptr - this_ptr;
- struct sk_buff *skb;
-
- if (next_ptr <= this_ptr)
- length += RX_END - RX_START;
-
- skb = dev_alloc_skb(length + 2);
- if (skb) {
- unsigned char *buf;
-
- skb_reserve(skb, 2);
- buf = skb_put(skb, length);
- ether3_readbuffer(dev, buf + 12, length - 12);
- ether3_outw(next_ptr >> 8, REG_RECVEND);
- *(unsigned short *)(buf + 0) = *(unsigned short *)(addrs + 2);
- *(unsigned long *)(buf + 2) = *(unsigned long *)(addrs + 4);
- *(unsigned long *)(buf + 6) = *(unsigned long *)(addrs + 8);
- *(unsigned short *)(buf + 10) = *(unsigned short *)(addrs + 12);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- received ++;
- } else
- goto dropping;
- } else {
- struct net_device_stats *stats = &dev->stats;
- ether3_outw(next_ptr >> 8, REG_RECVEND);
- if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++;
- if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++;
- if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++;
- if (status & RXSTAT_SHORTPACKET) stats->rx_length_errors ++;
- stats->rx_errors++;
- }
- }
- while (-- maxcnt);
-
-done:
- dev->stats.rx_packets += received;
- priv(dev)->rx_head = next_ptr;
- /*
- * If rx went off line, then that means that the buffer may be full. We
- * have dropped at least one packet.
- */
- if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
- dev->stats.rx_dropped++;
- ether3_outw(next_ptr, REG_RECVPTR);
- ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
- }
-
- return maxcnt;
-
-dropping:{
- static unsigned long last_warned;
-
- ether3_outw(next_ptr >> 8, REG_RECVEND);
- /*
- * Don't print this message too many times...
- */
- if (time_after(jiffies, last_warned + 10 * HZ)) {
- last_warned = jiffies;
- printk("%s: memory squeeze, dropping packet.\n", dev->name);
- }
- dev->stats.rx_dropped++;
- goto done;
- }
-}
-
-/*
- * Update stats for the transmitted packet(s)
- */
-static void ether3_tx(struct net_device *dev)
-{
- unsigned int tx_tail = priv(dev)->tx_tail;
- int max_work = 14;
-
- do {
- unsigned long status;
-
- /*
- * Read the packet header
- */
- ether3_setbuffer(dev, buffer_read, tx_tail * 0x600);
- status = ether3_readlong(dev);
-
- /*
- * Check to see if this packet has been transmitted
- */
- if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) !=
- (TXSTAT_DONE | TXHDR_TRANSMIT))
- break;
-
- /*
- * Update errors
- */
- if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
- dev->stats.tx_packets++;
- else {
- dev->stats.tx_errors++;
- if (status & TXSTAT_16COLLISIONS)
- dev->stats.collisions += 16;
- if (status & TXSTAT_BABBLED)
- dev->stats.tx_fifo_errors++;
- }
-
- tx_tail = (tx_tail + 1) & 15;
- } while (--max_work);
-
- if (priv(dev)->tx_tail != tx_tail) {
- priv(dev)->tx_tail = tx_tail;
- netif_wake_queue(dev);
- }
-}
-
-static void __devinit ether3_banner(void)
-{
- static unsigned version_printed = 0;
-
- if (net_debug && version_printed++ == 0)
- printk(KERN_INFO "%s", version);
-}
-
-static const struct net_device_ops ether3_netdev_ops = {
- .ndo_open = ether3_open,
- .ndo_stop = ether3_close,
- .ndo_start_xmit = ether3_sendpacket,
- .ndo_set_multicast_list = ether3_setmulticastlist,
- .ndo_tx_timeout = ether3_timeout,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
-};
-
-static int __devinit
-ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
- const struct ether3_data *data = id->data;
- struct net_device *dev;
- int bus_type, ret;
-
- ether3_banner();
-
- ret = ecard_request_resources(ec);
- if (ret)
- goto out;
-
- dev = alloc_etherdev(sizeof(struct dev_priv));
- if (!dev) {
- ret = -ENOMEM;
- goto release;
- }
-
- SET_NETDEV_DEV(dev, &ec->dev);
-
- priv(dev)->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
- if (!priv(dev)->base) {
- ret = -ENOMEM;
- goto free;
- }
-
- ec->irqaddr = priv(dev)->base + data->base_offset;
- ec->irqmask = 0xf0;
-
- priv(dev)->seeq = priv(dev)->base + data->base_offset;
- dev->irq = ec->irq;
-
- ether3_addr(dev->dev_addr, ec);
-
- init_timer(&priv(dev)->timer);
-
- /* Reset card...
- */
- ether3_outb(0x80, REG_CONFIG2 + 4);
- bus_type = BUS_UNKNOWN;
- udelay(4);
-
- /* Test using Receive Pointer (16-bit register) to find out
- * how the ether3 is connected to the bus...
- */
- if (ether3_probe_bus_8(dev, 0x100) &&
- ether3_probe_bus_8(dev, 0x201))
- bus_type = BUS_8;
-
- if (bus_type == BUS_UNKNOWN &&
- ether3_probe_bus_16(dev, 0x101) &&
- ether3_probe_bus_16(dev, 0x201))
- bus_type = BUS_16;
-
- switch (bus_type) {
- case BUS_UNKNOWN:
- printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
- ret = -ENODEV;
- goto free;
-
- case BUS_8:
- printk(KERN_ERR "%s: %s found, but is an unsupported "
- "8-bit card\n", dev->name, data->name);
- ret = -ENODEV;
- goto free;
-
- default:
- break;
- }
-
- if (ether3_init_2(dev)) {
- ret = -ENODEV;
- goto free;
- }
-
- dev->netdev_ops = &ether3_netdev_ops;
- dev->watchdog_timeo = 5 * HZ / 100;
-
- ret = register_netdev(dev);
- if (ret)
- goto free;
-
- printk("%s: %s in slot %d, %pM\n",
- dev->name, data->name, ec->slot_no, dev->dev_addr);
-
- ecard_set_drvdata(ec, dev);
- return 0;
-
- free:
- free_netdev(dev);
- release:
- ecard_release_resources(ec);
- out:
- return ret;
-}
-
-static void __devexit ether3_remove(struct expansion_card *ec)
-{
- struct net_device *dev = ecard_get_drvdata(ec);
-
- ecard_set_drvdata(ec, NULL);
-
- unregister_netdev(dev);
- free_netdev(dev);
- ecard_release_resources(ec);
-}
-
-static struct ether3_data ether3 = {
- .name = "ether3",
- .base_offset = 0,
-};
-
-static struct ether3_data etherb = {
- .name = "etherb",
- .base_offset = 0x800,
-};
-
-static const struct ecard_id ether3_ids[] = {
- { MANU_ANT2, PROD_ANT_ETHER3, &ether3 },
- { MANU_ANT, PROD_ANT_ETHER3, &ether3 },
- { MANU_ANT, PROD_ANT_ETHERB, &etherb },
- { 0xffff, 0xffff }
-};
-
-static struct ecard_driver ether3_driver = {
- .probe = ether3_probe,
- .remove = __devexit_p(ether3_remove),
- .id_table = ether3_ids,
- .drv = {
- .name = "ether3",
- },
-};
-
-static int __init ether3_init(void)
-{
- return ecard_register_driver(&ether3_driver);
-}
-
-static void __exit ether3_exit(void)
-{
- ecard_remove_driver(&ether3_driver);
-}
-
-module_init(ether3_init);
-module_exit(ether3_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
deleted file mode 100644
index 2db63b08bdf3..000000000000
--- a/drivers/net/arm/ether3.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * linux/drivers/acorn/net/ether3.h
- *
- * Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * network driver for Acorn/ANT Ether3 cards
- */
-
-#ifndef _LINUX_ether3_H
-#define _LINUX_ether3_H
-
-/* use 0 for production, 1 for verification, >2 for debug. debug flags: */
-#define DEBUG_TX 2
-#define DEBUG_RX 4
-#define DEBUG_INT 8
-#define DEBUG_IC 16
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-
-#define priv(dev) ((struct dev_priv *)netdev_priv(dev))
-
-/* Command register definitions & bits */
-#define REG_COMMAND (priv(dev)->seeq + 0x0000)
-#define CMD_ENINTDMA 0x0001
-#define CMD_ENINTRX 0x0002
-#define CMD_ENINTTX 0x0004
-#define CMD_ENINTBUFWIN 0x0008
-#define CMD_ACKINTDMA 0x0010
-#define CMD_ACKINTRX 0x0020
-#define CMD_ACKINTTX 0x0040
-#define CMD_ACKINTBUFWIN 0x0080
-#define CMD_DMAON 0x0100
-#define CMD_RXON 0x0200
-#define CMD_TXON 0x0400
-#define CMD_DMAOFF 0x0800
-#define CMD_RXOFF 0x1000
-#define CMD_TXOFF 0x2000
-#define CMD_FIFOREAD 0x4000
-#define CMD_FIFOWRITE 0x8000
-
-/* status register */
-#define REG_STATUS (priv(dev)->seeq + 0x0000)
-#define STAT_ENINTSTAT 0x0001
-#define STAT_ENINTRX 0x0002
-#define STAT_ENINTTX 0x0004
-#define STAT_ENINTBUFWIN 0x0008
-#define STAT_INTDMA 0x0010
-#define STAT_INTRX 0x0020
-#define STAT_INTTX 0x0040
-#define STAT_INTBUFWIN 0x0080
-#define STAT_DMAON 0x0100
-#define STAT_RXON 0x0200
-#define STAT_TXON 0x0400
-#define STAT_FIFOFULL 0x2000
-#define STAT_FIFOEMPTY 0x4000
-#define STAT_FIFODIR 0x8000
-
-/* configuration register 1 */
-#define REG_CONFIG1 (priv(dev)->seeq + 0x0040)
-#define CFG1_BUFSELSTAT0 0x0000
-#define CFG1_BUFSELSTAT1 0x0001
-#define CFG1_BUFSELSTAT2 0x0002
-#define CFG1_BUFSELSTAT3 0x0003
-#define CFG1_BUFSELSTAT4 0x0004
-#define CFG1_BUFSELSTAT5 0x0005
-#define CFG1_ADDRPROM 0x0006
-#define CFG1_TRANSEND 0x0007
-#define CFG1_LOCBUFMEM 0x0008
-#define CFG1_INTVECTOR 0x0009
-#define CFG1_RECVSPECONLY 0x0000
-#define CFG1_RECVSPECBROAD 0x4000
-#define CFG1_RECVSPECBRMULTI 0x8000
-#define CFG1_RECVPROMISC 0xC000
-
-/* The following aren't in 8004 */
-#define CFG1_DMABURSTCONT 0x0000
-#define CFG1_DMABURST800NS 0x0010
-#define CFG1_DMABURST1600NS 0x0020
-#define CFG1_DMABURST3200NS 0x0030
-#define CFG1_DMABURST1 0x0000
-#define CFG1_DMABURST4 0x0040
-#define CFG1_DMABURST8 0x0080
-#define CFG1_DMABURST16 0x00C0
-#define CFG1_RECVCOMPSTAT0 0x0100
-#define CFG1_RECVCOMPSTAT1 0x0200
-#define CFG1_RECVCOMPSTAT2 0x0400
-#define CFG1_RECVCOMPSTAT3 0x0800
-#define CFG1_RECVCOMPSTAT4 0x1000
-#define CFG1_RECVCOMPSTAT5 0x2000
-
-/* configuration register 2 */
-#define REG_CONFIG2 (priv(dev)->seeq + 0x0080)
-#define CFG2_BYTESWAP 0x0001
-#define CFG2_ERRENCRC 0x0008
-#define CFG2_ERRENDRIBBLE 0x0010
-#define CFG2_ERRSHORTFRAME 0x0020
-#define CFG2_SLOTSELECT 0x0040
-#define CFG2_PREAMSELECT 0x0080
-#define CFG2_ADDRLENGTH 0x0100
-#define CFG2_RECVCRC 0x0200
-#define CFG2_XMITNOCRC 0x0400
-#define CFG2_LOOPBACK 0x0800
-#define CFG2_CTRLO 0x1000
-#define CFG2_RESET 0x8000
-
-#define REG_RECVEND (priv(dev)->seeq + 0x00c0)
-
-#define REG_BUFWIN (priv(dev)->seeq + 0x0100)
-
-#define REG_RECVPTR (priv(dev)->seeq + 0x0140)
-
-#define REG_TRANSMITPTR (priv(dev)->seeq + 0x0180)
-
-#define REG_DMAADDR (priv(dev)->seeq + 0x01c0)
-
-/*
- * Cards transmit/receive headers
- */
-#define TX_NEXT (0xffff)
-#define TXHDR_ENBABBLEINT (1 << 16)
-#define TXHDR_ENCOLLISIONINT (1 << 17)
-#define TXHDR_EN16COLLISION (1 << 18)
-#define TXHDR_ENSUCCESS (1 << 19)
-#define TXHDR_DATAFOLLOWS (1 << 21)
-#define TXHDR_CHAINCONTINUE (1 << 22)
-#define TXHDR_TRANSMIT (1 << 23)
-#define TXSTAT_BABBLED (1 << 24)
-#define TXSTAT_COLLISION (1 << 25)
-#define TXSTAT_16COLLISIONS (1 << 26)
-#define TXSTAT_DONE (1 << 31)
-
-#define RX_NEXT (0xffff)
-#define RXHDR_CHAINCONTINUE (1 << 6)
-#define RXHDR_RECEIVE (1 << 7)
-#define RXSTAT_OVERSIZE (1 << 8)
-#define RXSTAT_CRCERROR (1 << 9)
-#define RXSTAT_DRIBBLEERROR (1 << 10)
-#define RXSTAT_SHORTPACKET (1 << 11)
-#define RXSTAT_DONE (1 << 15)
-
-
-#define TX_START 0x0000
-#define TX_END 0x6000
-#define RX_START 0x6000
-#define RX_LEN 0xA000
-#define RX_END 0x10000
-/* must be a power of 2 and greater than MAX_TX_BUFFERED */
-#define MAX_TXED 16
-#define MAX_TX_BUFFERED 10
-
-struct dev_priv {
- void __iomem *base;
- void __iomem *seeq;
- struct {
- unsigned int command;
- unsigned int config1;
- unsigned int config2;
- } regs;
- unsigned char tx_head; /* buffer nr to insert next packet */
- unsigned char tx_tail; /* buffer nr of transmitting packet */
- unsigned int rx_head; /* address to fetch next packet from */
- struct timer_list timer;
- int broken; /* 0 = ok, 1 = something went wrong */
-};
-
-struct ether3_data {
- const char name[8];
- unsigned long base_offset;
-};
-
-#endif
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
deleted file mode 100644
index 03e217a868d4..000000000000
--- a/drivers/net/arm/etherh.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * linux/drivers/acorn/net/etherh.c
- *
- * Copyright (C) 2000-2002 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * NS8390 I-cubed EtherH and ANT EtherM specific driver
- * Thanks to I-Cubed for information on their cards.
- * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
- * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
- * EtherM integration re-engineered by Russell King.
- *
- * Changelog:
- * 08-12-1996 RMK 1.00 Created
- * RMK 1.03 Added support for EtherLan500 cards
- * 23-11-1997 RMK 1.04 Added media autodetection
- * 16-04-1998 RMK 1.05 Improved media autodetection
- * 10-02-2000 RMK 1.06 Updated for 2.3.43
- * 13-05-2000 RMK 1.07 Updated for 2.3.99-pre8
- * 12-10-1999 CK/TEW EtherM driver first release
- * 21-12-2000 TTC EtherH/EtherM integration
- * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver.
- * 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/ecard.h>
-#include <asm/io.h>
-
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-
-#define ei_inb(_p) readb((void __iomem *)_p)
-#define ei_outb(_v,_p) writeb(_v,(void __iomem *)_p)
-#define ei_inb_p(_p) readb((void __iomem *)_p)
-#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
-
-#define NET_DEBUG 0
-#define DEBUG_INIT 2
-
-#define DRV_NAME "etherh"
-#define DRV_VERSION "1.11"
-
-static char version[] __initdata =
- "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
-
-#include "../lib8390.c"
-
-static unsigned int net_debug = NET_DEBUG;
-
-struct etherh_priv {
- void __iomem *ioc_fast;
- void __iomem *memc;
- void __iomem *dma_base;
- unsigned int id;
- void __iomem *ctrl_port;
- unsigned char ctrl;
- u32 supported;
-};
-
-struct etherh_data {
- unsigned long ns8390_offset;
- unsigned long dataport_offset;
- unsigned long ctrlport_offset;
- int ctrl_ioc;
- const char name[16];
- u32 supported;
- unsigned char tx_start_page;
- unsigned char stop_page;
-};
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("EtherH/EtherM driver");
-MODULE_LICENSE("GPL");
-
-#define ETHERH500_DATAPORT 0x800 /* MEMC */
-#define ETHERH500_NS8390 0x000 /* MEMC */
-#define ETHERH500_CTRLPORT 0x800 /* IOC */
-
-#define ETHERH600_DATAPORT 0x040 /* MEMC */
-#define ETHERH600_NS8390 0x800 /* MEMC */
-#define ETHERH600_CTRLPORT 0x200 /* MEMC */
-
-#define ETHERH_CP_IE 1
-#define ETHERH_CP_IF 2
-#define ETHERH_CP_HEARTBEAT 2
-
-#define ETHERH_TX_START_PAGE 1
-#define ETHERH_STOP_PAGE 127
-
-/*
- * These came from CK/TEW
- */
-#define ETHERM_DATAPORT 0x200 /* MEMC */
-#define ETHERM_NS8390 0x800 /* MEMC */
-#define ETHERM_CTRLPORT 0x23c /* MEMC */
-
-#define ETHERM_TX_START_PAGE 64
-#define ETHERM_STOP_PAGE 127
-
-/* ------------------------------------------------------------------------ */
-
-#define etherh_priv(dev) \
- ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device)))
-
-static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
- unsigned char ctrl = eh->ctrl | mask;
- eh->ctrl = ctrl;
- writeb(ctrl, eh->ctrl_port);
-}
-
-static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
- unsigned char ctrl = eh->ctrl & ~mask;
- eh->ctrl = ctrl;
- writeb(ctrl, eh->ctrl_port);
-}
-
-static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
-{
- return readb(eh->ctrl_port);
-}
-
-
-
-
-static void etherh_irq_enable(ecard_t *ec, int irqnr)
-{
- struct etherh_priv *eh = ec->irq_data;
-
- etherh_set_ctrl(eh, ETHERH_CP_IE);
-}
-
-static void etherh_irq_disable(ecard_t *ec, int irqnr)
-{
- struct etherh_priv *eh = ec->irq_data;
-
- etherh_clr_ctrl(eh, ETHERH_CP_IE);
-}
-
-static expansioncard_ops_t etherh_ops = {
- .irqenable = etherh_irq_enable,
- .irqdisable = etherh_irq_disable,
-};
-
-
-
-
-static void
-etherh_setif(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned long flags;
- void __iomem *addr;
-
- local_irq_save(flags);
-
- /* set the interface type */
- switch (etherh_priv(dev)->id) {
- case PROD_I3_ETHERLAN600:
- case PROD_I3_ETHERLAN600A:
- addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
-
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- writeb((readb(addr) & 0xf8) | 1, addr);
- break;
- case IF_PORT_10BASET:
- writeb((readb(addr) & 0xf8), addr);
- break;
- }
- break;
-
- case PROD_I3_ETHERLAN500:
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF);
- break;
-
- case IF_PORT_10BASET:
- etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF);
- break;
- }
- break;
-
- default:
- break;
- }
-
- local_irq_restore(flags);
-}
-
-static int
-etherh_getifstat(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *addr;
- int stat = 0;
-
- switch (etherh_priv(dev)->id) {
- case PROD_I3_ETHERLAN600:
- case PROD_I3_ETHERLAN600A:
- addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- stat = 1;
- break;
- case IF_PORT_10BASET:
- stat = readb(addr) & 4;
- break;
- }
- break;
-
- case PROD_I3_ETHERLAN500:
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- stat = 1;
- break;
- case IF_PORT_10BASET:
- stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT;
- break;
- }
- break;
-
- default:
- stat = 0;
- break;
- }
-
- return stat != 0;
-}
-
-/*
- * Configure the interface. Note that we ignore the other
- * parts of ifmap, since its mostly meaningless for this driver.
- */
-static int etherh_set_config(struct net_device *dev, struct ifmap *map)
-{
- switch (map->port) {
- case IF_PORT_10BASE2:
- case IF_PORT_10BASET:
- /*
- * If the user explicitly sets the interface
- * media type, turn off automedia detection.
- */
- dev->flags &= ~IFF_AUTOMEDIA;
- dev->if_port = map->port;
- break;
-
- default:
- return -EINVAL;
- }
-
- etherh_setif(dev);
-
- return 0;
-}
-
-/*
- * Reset the 8390 (hard reset). Note that we can't actually do this.
- */
-static void
-etherh_reset(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *addr = (void __iomem *)dev->base_addr;
-
- writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
-
- /*
- * See if we need to change the interface type.
- * Note that we use 'interface_num' as a flag
- * to indicate that we need to change the media.
- */
- if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
- ei_local->interface_num = 0;
-
- if (dev->if_port == IF_PORT_10BASET)
- dev->if_port = IF_PORT_10BASE2;
- else
- dev->if_port = IF_PORT_10BASET;
-
- etherh_setif(dev);
- }
-}
-
-/*
- * Write a block of data out to the 8390
- */
-static void
-etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned long dma_start;
- void __iomem *dma_base, *addr;
-
- if (ei_local->dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
- " DMAstat %d irqlock %d\n", dev->name,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- /*
- * Make sure we have a round number of bytes if we're in word mode.
- */
- if (count & 1 && ei_local->word16)
- count++;
-
- ei_local->dmaing = 1;
-
- addr = (void __iomem *)dev->base_addr;
- dma_base = etherh_priv(dev)->dma_base;
-
- count = (count + 1) & ~1;
- writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-
- writeb (0x42, addr + EN0_RCNTLO);
- writeb (0x00, addr + EN0_RCNTHI);
- writeb (0x42, addr + EN0_RSARLO);
- writeb (0x00, addr + EN0_RSARHI);
- writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
- udelay (1);
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- writeb (count, addr + EN0_RCNTLO);
- writeb (count >> 8, addr + EN0_RCNTHI);
- writeb (0, addr + EN0_RSARLO);
- writeb (start_page, addr + EN0_RSARHI);
- writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
-
- if (ei_local->word16)
- writesw (dma_base, buf, count >> 1);
- else
- writesb (dma_base, buf, count);
-
- dma_start = jiffies;
-
- while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
- dev->name);
- etherh_reset (dev);
- __NS8390_init (dev, 1);
- break;
- }
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- ei_local->dmaing = 0;
-}
-
-/*
- * Read a block of data from the 8390
- */
-static void
-etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned char *buf;
- void __iomem *dma_base, *addr;
-
- if (ei_local->dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
- " DMAstat %d irqlock %d\n", dev->name,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing = 1;
-
- addr = (void __iomem *)dev->base_addr;
- dma_base = etherh_priv(dev)->dma_base;
-
- buf = skb->data;
- writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
- writeb (count, addr + EN0_RCNTLO);
- writeb (count >> 8, addr + EN0_RCNTHI);
- writeb (ring_offset, addr + EN0_RSARLO);
- writeb (ring_offset >> 8, addr + EN0_RSARHI);
- writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
- if (ei_local->word16) {
- readsw (dma_base, buf, count >> 1);
- if (count & 1)
- buf[count - 1] = readb (dma_base);
- } else
- readsb (dma_base, buf, count);
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- ei_local->dmaing = 0;
-}
-
-/*
- * Read a header from the 8390
- */
-static void
-etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *dma_base, *addr;
-
- if (ei_local->dmaing) {
- printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
- " DMAstat %d irqlock %d\n", dev->name,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing = 1;
-
- addr = (void __iomem *)dev->base_addr;
- dma_base = etherh_priv(dev)->dma_base;
-
- writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
- writeb (sizeof (*hdr), addr + EN0_RCNTLO);
- writeb (0, addr + EN0_RCNTHI);
- writeb (0, addr + EN0_RSARLO);
- writeb (ring_page, addr + EN0_RSARHI);
- writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
- if (ei_local->word16)
- readsw (dma_base, hdr, sizeof (*hdr) >> 1);
- else
- readsb (dma_base, hdr, sizeof (*hdr));
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- ei_local->dmaing = 0;
-}
-
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-etherh_open(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- if (!is_valid_ether_addr(dev->dev_addr)) {
- printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
- dev->name);
- return -EINVAL;
- }
-
- if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
- return -EAGAIN;
-
- /*
- * Make sure that we aren't going to change the
- * media type on the next reset - we are about to
- * do automedia manually now.
- */
- ei_local->interface_num = 0;
-
- /*
- * If we are doing automedia detection, do it now.
- * This is more reliable than the 8390's detection.
- */
- if (dev->flags & IFF_AUTOMEDIA) {
- dev->if_port = IF_PORT_10BASET;
- etherh_setif(dev);
- mdelay(1);
- if (!etherh_getifstat(dev)) {
- dev->if_port = IF_PORT_10BASE2;
- etherh_setif(dev);
- }
- } else
- etherh_setif(dev);
-
- etherh_reset(dev);
- __ei_open(dev);
-
- return 0;
-}
-
-/*
- * The inverse routine to etherh_open().
- */
-static int
-etherh_close(struct net_device *dev)
-{
- __ei_close (dev);
- free_irq (dev->irq, dev);
- return 0;
-}
-
-/*
- * Initialisation
- */
-
-static void __init etherh_banner(void)
-{
- static int version_printed;
-
- if (net_debug && version_printed++ == 0)
- printk(KERN_INFO "%s", version);
-}
-
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string...
- */
-static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
-{
- struct in_chunk_dir cd;
- char *s;
-
- if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
- printk(KERN_ERR "%s: unable to read podule description string\n",
- dev_name(&ec->dev));
- goto no_addr;
- }
-
- s = strchr(cd.d.string, '(');
- if (s) {
- int i;
-
- for (i = 0; i < 6; i++) {
- addr[i] = simple_strtoul(s + 1, &s, 0x10);
- if (*s != (i == 5? ')' : ':'))
- break;
- }
-
- if (i == 6)
- return 0;
- }
-
- printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
- dev_name(&ec->dev), cd.d.string);
-
- no_addr:
- return -ENODEV;
-}
-
-/*
- * Create an ethernet address from the system serial number.
- */
-static int __init etherm_addr(char *addr)
-{
- unsigned int serial;
-
- if (system_serial_low == 0 && system_serial_high == 0)
- return -ENODEV;
-
- serial = system_serial_low | system_serial_high;
-
- addr[0] = 0;
- addr[1] = 0;
- addr[2] = 0xa4;
- addr[3] = 0x10 + (serial >> 24);
- addr[4] = serial >> 16;
- addr[5] = serial >> 8;
- return 0;
-}
-
-static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
- strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev_name(dev->dev.parent),
- sizeof(info->bus_info));
-}
-
-static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- cmd->supported = etherh_priv(dev)->supported;
- ethtool_cmd_speed_set(cmd, SPEED_10);
- cmd->duplex = DUPLEX_HALF;
- cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
- cmd->autoneg = (dev->flags & IFF_AUTOMEDIA ?
- AUTONEG_ENABLE : AUTONEG_DISABLE);
- return 0;
-}
-
-static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- switch (cmd->autoneg) {
- case AUTONEG_ENABLE:
- dev->flags |= IFF_AUTOMEDIA;
- break;
-
- case AUTONEG_DISABLE:
- switch (cmd->port) {
- case PORT_TP:
- dev->if_port = IF_PORT_10BASET;
- break;
-
- case PORT_BNC:
- dev->if_port = IF_PORT_10BASE2;
- break;
-
- default:
- return -EINVAL;
- }
- dev->flags &= ~IFF_AUTOMEDIA;
- break;
-
- default:
- return -EINVAL;
- }
-
- etherh_setif(dev);
-
- return 0;
-}
-
-static const struct ethtool_ops etherh_ethtool_ops = {
- .get_settings = etherh_get_settings,
- .set_settings = etherh_set_settings,
- .get_drvinfo = etherh_get_drvinfo,
-};
-
-static const struct net_device_ops etherh_netdev_ops = {
- .ndo_open = etherh_open,
- .ndo_stop = etherh_close,
- .ndo_set_config = etherh_set_config,
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_multicast_list = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static u32 etherh_regoffsets[16];
-static u32 etherm_regoffsets[16];
-
-static int __devinit
-etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
- const struct etherh_data *data = id->data;
- struct ei_device *ei_local;
- struct net_device *dev;
- struct etherh_priv *eh;
- int ret;
-
- etherh_banner();
-
- ret = ecard_request_resources(ec);
- if (ret)
- goto out;
-
- dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
- if (!dev) {
- ret = -ENOMEM;
- goto release;
- }
-
- SET_NETDEV_DEV(dev, &ec->dev);
-
- dev->netdev_ops = &etherh_netdev_ops;
- dev->irq = ec->irq;
- dev->ethtool_ops = &etherh_ethtool_ops;
-
- if (data->supported & SUPPORTED_Autoneg)
- dev->flags |= IFF_AUTOMEDIA;
- if (data->supported & SUPPORTED_TP) {
- dev->flags |= IFF_PORTSEL;
- dev->if_port = IF_PORT_10BASET;
- } else if (data->supported & SUPPORTED_BNC) {
- dev->flags |= IFF_PORTSEL;
- dev->if_port = IF_PORT_10BASE2;
- } else
- dev->if_port = IF_PORT_UNKNOWN;
-
- eh = etherh_priv(dev);
- eh->supported = data->supported;
- eh->ctrl = 0;
- eh->id = ec->cid.product;
- eh->memc = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
- if (!eh->memc) {
- ret = -ENOMEM;
- goto free;
- }
-
- eh->ctrl_port = eh->memc;
- if (data->ctrl_ioc) {
- eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
- if (!eh->ioc_fast) {
- ret = -ENOMEM;
- goto free;
- }
- eh->ctrl_port = eh->ioc_fast;
- }
-
- dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
- eh->dma_base = eh->memc + data->dataport_offset;
- eh->ctrl_port += data->ctrlport_offset;
-
- /*
- * IRQ and control port handling - only for non-NIC slot cards.
- */
- if (ec->slot_no != 8) {
- ecard_setirq(ec, &etherh_ops, eh);
- } else {
- /*
- * If we're in the NIC slot, make sure the IRQ is enabled
- */
- etherh_set_ctrl(eh, ETHERH_CP_IE);
- }
-
- ei_local = netdev_priv(dev);
- spin_lock_init(&ei_local->page_lock);
-
- if (ec->cid.product == PROD_ANT_ETHERM) {
- etherm_addr(dev->dev_addr);
- ei_local->reg_offset = etherm_regoffsets;
- } else {
- etherh_addr(dev->dev_addr, ec);
- ei_local->reg_offset = etherh_regoffsets;
- }
-
- ei_local->name = dev->name;
- ei_local->word16 = 1;
- ei_local->tx_start_page = data->tx_start_page;
- ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
- ei_local->stop_page = data->stop_page;
- ei_local->reset_8390 = etherh_reset;
- ei_local->block_input = etherh_block_input;
- ei_local->block_output = etherh_block_output;
- ei_local->get_8390_hdr = etherh_get_header;
- ei_local->interface_num = 0;
-
- etherh_reset(dev);
- __NS8390_init(dev, 0);
-
- ret = register_netdev(dev);
- if (ret)
- goto free;
-
- printk(KERN_INFO "%s: %s in slot %d, %pM\n",
- dev->name, data->name, ec->slot_no, dev->dev_addr);
-
- ecard_set_drvdata(ec, dev);
-
- return 0;
-
- free:
- free_netdev(dev);
- release:
- ecard_release_resources(ec);
- out:
- return ret;
-}
-
-static void __devexit etherh_remove(struct expansion_card *ec)
-{
- struct net_device *dev = ecard_get_drvdata(ec);
-
- ecard_set_drvdata(ec, NULL);
-
- unregister_netdev(dev);
-
- free_netdev(dev);
-
- ecard_release_resources(ec);
-}
-
-static struct etherh_data etherm_data = {
- .ns8390_offset = ETHERM_NS8390,
- .dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT,
- .ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT,
- .name = "ANT EtherM",
- .supported = SUPPORTED_10baseT_Half,
- .tx_start_page = ETHERM_TX_START_PAGE,
- .stop_page = ETHERM_STOP_PAGE,
-};
-
-static struct etherh_data etherlan500_data = {
- .ns8390_offset = ETHERH500_NS8390,
- .dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT,
- .ctrlport_offset = ETHERH500_CTRLPORT,
- .ctrl_ioc = 1,
- .name = "i3 EtherH 500",
- .supported = SUPPORTED_10baseT_Half,
- .tx_start_page = ETHERH_TX_START_PAGE,
- .stop_page = ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600_data = {
- .ns8390_offset = ETHERH600_NS8390,
- .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
- .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
- .name = "i3 EtherH 600",
- .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
- .tx_start_page = ETHERH_TX_START_PAGE,
- .stop_page = ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600a_data = {
- .ns8390_offset = ETHERH600_NS8390,
- .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
- .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
- .name = "i3 EtherH 600A",
- .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
- .tx_start_page = ETHERH_TX_START_PAGE,
- .stop_page = ETHERH_STOP_PAGE,
-};
-
-static const struct ecard_id etherh_ids[] = {
- { MANU_ANT, PROD_ANT_ETHERM, &etherm_data },
- { MANU_I3, PROD_I3_ETHERLAN500, &etherlan500_data },
- { MANU_I3, PROD_I3_ETHERLAN600, &etherlan600_data },
- { MANU_I3, PROD_I3_ETHERLAN600A, &etherlan600a_data },
- { 0xffff, 0xffff }
-};
-
-static struct ecard_driver etherh_driver = {
- .probe = etherh_probe,
- .remove = __devexit_p(etherh_remove),
- .id_table = etherh_ids,
- .drv = {
- .name = DRV_NAME,
- },
-};
-
-static int __init etherh_init(void)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- etherh_regoffsets[i] = i << 2;
- etherm_regoffsets[i] = i << 5;
- }
-
- return ecard_register_driver(&etherh_driver);
-}
-
-static void __exit etherh_exit(void)
-{
- ecard_remove_driver(&etherh_driver);
-}
-
-module_init(etherh_init);
-module_exit(etherh_exit);
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
deleted file mode 100644
index de51e8453c13..000000000000
--- a/drivers/net/arm/ixp4xx_eth.c
+++ /dev/null
@@ -1,1489 +0,0 @@
-/*
- * Intel IXP4xx Ethernet driver for Linux
- *
- * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * Ethernet port config (0x00 is not present on IXP42X):
- *
- * logical port 0x00 0x10 0x20
- * NPE 0 (NPE-A) 1 (NPE-B) 2 (NPE-C)
- * physical PortId 2 0 1
- * TX queue 23 24 25
- * RX-free queue 26 27 28
- * TX-done queue is always 31, per-port RX and TX-ready queues are configurable
- *
- *
- * Queue entries:
- * bits 0 -> 1 - NPE ID (RX and TX-done)
- * bits 0 -> 2 - priority (TX, per 802.1D)
- * bits 3 -> 4 - port ID (user-set?)
- * bits 5 -> 31 - physical descriptor address
- */
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/etherdevice.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/net_tstamp.h>
-#include <linux/phy.h>
-#include <linux/platform_device.h>
-#include <linux/ptp_classify.h>
-#include <linux/slab.h>
-#include <mach/ixp46x_ts.h>
-#include <mach/npe.h>
-#include <mach/qmgr.h>
-
-#define DEBUG_DESC 0
-#define DEBUG_RX 0
-#define DEBUG_TX 0
-#define DEBUG_PKT_BYTES 0
-#define DEBUG_MDIO 0
-#define DEBUG_CLOSE 0
-
-#define DRV_NAME "ixp4xx_eth"
-
-#define MAX_NPES 3
-
-#define RX_DESCS 64 /* also length of all RX queues */
-#define TX_DESCS 16 /* also length of all TX queues */
-#define TXDONE_QUEUE_LEN 64 /* dwords */
-
-#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS))
-#define REGS_SIZE 0x1000
-#define MAX_MRU 1536 /* 0x600 */
-#define RX_BUFF_SIZE ALIGN((NET_IP_ALIGN) + MAX_MRU, 4)
-
-#define NAPI_WEIGHT 16
-#define MDIO_INTERVAL (3 * HZ)
-#define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */
-#define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */
-
-#define NPE_ID(port_id) ((port_id) >> 4)
-#define PHYSICAL_ID(port_id) ((NPE_ID(port_id) + 2) % 3)
-#define TX_QUEUE(port_id) (NPE_ID(port_id) + 23)
-#define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26)
-#define TXDONE_QUEUE 31
-
-#define PTP_SLAVE_MODE 1
-#define PTP_MASTER_MODE 2
-#define PORT2CHANNEL(p) NPE_ID(p->id)
-
-/* TX Control Registers */
-#define TX_CNTRL0_TX_EN 0x01
-#define TX_CNTRL0_HALFDUPLEX 0x02
-#define TX_CNTRL0_RETRY 0x04
-#define TX_CNTRL0_PAD_EN 0x08
-#define TX_CNTRL0_APPEND_FCS 0x10
-#define TX_CNTRL0_2DEFER 0x20
-#define TX_CNTRL0_RMII 0x40 /* reduced MII */
-#define TX_CNTRL1_RETRIES 0x0F /* 4 bits */
-
-/* RX Control Registers */
-#define RX_CNTRL0_RX_EN 0x01
-#define RX_CNTRL0_PADSTRIP_EN 0x02
-#define RX_CNTRL0_SEND_FCS 0x04
-#define RX_CNTRL0_PAUSE_EN 0x08
-#define RX_CNTRL0_LOOP_EN 0x10
-#define RX_CNTRL0_ADDR_FLTR_EN 0x20
-#define RX_CNTRL0_RX_RUNT_EN 0x40
-#define RX_CNTRL0_BCAST_DIS 0x80
-#define RX_CNTRL1_DEFER_EN 0x01
-
-/* Core Control Register */
-#define CORE_RESET 0x01
-#define CORE_RX_FIFO_FLUSH 0x02
-#define CORE_TX_FIFO_FLUSH 0x04
-#define CORE_SEND_JAM 0x08
-#define CORE_MDC_EN 0x10 /* MDIO using NPE-B ETH-0 only */
-
-#define DEFAULT_TX_CNTRL0 (TX_CNTRL0_TX_EN | TX_CNTRL0_RETRY | \
- TX_CNTRL0_PAD_EN | TX_CNTRL0_APPEND_FCS | \
- TX_CNTRL0_2DEFER)
-#define DEFAULT_RX_CNTRL0 RX_CNTRL0_RX_EN
-#define DEFAULT_CORE_CNTRL CORE_MDC_EN
-
-
-/* NPE message codes */
-#define NPE_GETSTATUS 0x00
-#define NPE_EDB_SETPORTADDRESS 0x01
-#define NPE_EDB_GETMACADDRESSDATABASE 0x02
-#define NPE_EDB_SETMACADDRESSSDATABASE 0x03
-#define NPE_GETSTATS 0x04
-#define NPE_RESETSTATS 0x05
-#define NPE_SETMAXFRAMELENGTHS 0x06
-#define NPE_VLAN_SETRXTAGMODE 0x07
-#define NPE_VLAN_SETDEFAULTRXVID 0x08
-#define NPE_VLAN_SETPORTVLANTABLEENTRY 0x09
-#define NPE_VLAN_SETPORTVLANTABLERANGE 0x0A
-#define NPE_VLAN_SETRXQOSENTRY 0x0B
-#define NPE_VLAN_SETPORTIDEXTRACTIONMODE 0x0C
-#define NPE_STP_SETBLOCKINGSTATE 0x0D
-#define NPE_FW_SETFIREWALLMODE 0x0E
-#define NPE_PC_SETFRAMECONTROLDURATIONID 0x0F
-#define NPE_PC_SETAPMACTABLE 0x11
-#define NPE_SETLOOPBACK_MODE 0x12
-#define NPE_PC_SETBSSIDTABLE 0x13
-#define NPE_ADDRESS_FILTER_CONFIG 0x14
-#define NPE_APPENDFCSCONFIG 0x15
-#define NPE_NOTIFY_MAC_RECOVERY_DONE 0x16
-#define NPE_MAC_RECOVERY_START 0x17
-
-
-#ifdef __ARMEB__
-typedef struct sk_buff buffer_t;
-#define free_buffer dev_kfree_skb
-#define free_buffer_irq dev_kfree_skb_irq
-#else
-typedef void buffer_t;
-#define free_buffer kfree
-#define free_buffer_irq kfree
-#endif
-
-struct eth_regs {
- u32 tx_control[2], __res1[2]; /* 000 */
- u32 rx_control[2], __res2[2]; /* 010 */
- u32 random_seed, __res3[3]; /* 020 */
- u32 partial_empty_threshold, __res4; /* 030 */
- u32 partial_full_threshold, __res5; /* 038 */
- u32 tx_start_bytes, __res6[3]; /* 040 */
- u32 tx_deferral, rx_deferral, __res7[2];/* 050 */
- u32 tx_2part_deferral[2], __res8[2]; /* 060 */
- u32 slot_time, __res9[3]; /* 070 */
- u32 mdio_command[4]; /* 080 */
- u32 mdio_status[4]; /* 090 */
- u32 mcast_mask[6], __res10[2]; /* 0A0 */
- u32 mcast_addr[6], __res11[2]; /* 0C0 */
- u32 int_clock_threshold, __res12[3]; /* 0E0 */
- u32 hw_addr[6], __res13[61]; /* 0F0 */
- u32 core_control; /* 1FC */
-};
-
-struct port {
- struct resource *mem_res;
- struct eth_regs __iomem *regs;
- struct npe *npe;
- struct net_device *netdev;
- struct napi_struct napi;
- struct phy_device *phydev;
- struct eth_plat_info *plat;
- buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
- struct desc *desc_tab; /* coherent */
- u32 desc_tab_phys;
- int id; /* logical port ID */
- int speed, duplex;
- u8 firmware[4];
- int hwts_tx_en;
- int hwts_rx_en;
-};
-
-/* NPE message structure */
-struct msg {
-#ifdef __ARMEB__
- u8 cmd, eth_id, byte2, byte3;
- u8 byte4, byte5, byte6, byte7;
-#else
- u8 byte3, byte2, eth_id, cmd;
- u8 byte7, byte6, byte5, byte4;
-#endif
-};
-
-/* Ethernet packet descriptor */
-struct desc {
- u32 next; /* pointer to next buffer, unused */
-
-#ifdef __ARMEB__
- u16 buf_len; /* buffer length */
- u16 pkt_len; /* packet length */
- u32 data; /* pointer to data buffer in RAM */
- u8 dest_id;
- u8 src_id;
- u16 flags;
- u8 qos;
- u8 padlen;
- u16 vlan_tci;
-#else
- u16 pkt_len; /* packet length */
- u16 buf_len; /* buffer length */
- u32 data; /* pointer to data buffer in RAM */
- u16 flags;
- u8 src_id;
- u8 dest_id;
- u16 vlan_tci;
- u8 padlen;
- u8 qos;
-#endif
-
-#ifdef __ARMEB__
- u8 dst_mac_0, dst_mac_1, dst_mac_2, dst_mac_3;
- u8 dst_mac_4, dst_mac_5, src_mac_0, src_mac_1;
- u8 src_mac_2, src_mac_3, src_mac_4, src_mac_5;
-#else
- u8 dst_mac_3, dst_mac_2, dst_mac_1, dst_mac_0;
- u8 src_mac_1, src_mac_0, dst_mac_5, dst_mac_4;
- u8 src_mac_5, src_mac_4, src_mac_3, src_mac_2;
-#endif
-};
-
-
-#define rx_desc_phys(port, n) ((port)->desc_tab_phys + \
- (n) * sizeof(struct desc))
-#define rx_desc_ptr(port, n) (&(port)->desc_tab[n])
-
-#define tx_desc_phys(port, n) ((port)->desc_tab_phys + \
- ((n) + RX_DESCS) * sizeof(struct desc))
-#define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS])
-
-#ifndef __ARMEB__
-static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
-{
- int i;
- for (i = 0; i < cnt; i++)
- dest[i] = swab32(src[i]);
-}
-#endif
-
-static spinlock_t mdio_lock;
-static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */
-static struct mii_bus *mdio_bus;
-static int ports_open;
-static struct port *npe_port_tab[MAX_NPES];
-static struct dma_pool *dma_pool;
-
-static struct sock_filter ptp_filter[] = {
- PTP_FILTER
-};
-
-static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
-{
- u8 *data = skb->data;
- unsigned int offset;
- u16 *hi, *id;
- u32 lo;
-
- if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
- return 0;
-
- offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
-
- if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid))
- return 0;
-
- hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID);
- id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
-
- memcpy(&lo, &hi[1], sizeof(lo));
-
- return (uid_hi == ntohs(*hi) &&
- uid_lo == ntohl(lo) &&
- seqid == ntohs(*id));
-}
-
-static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb)
-{
- struct skb_shared_hwtstamps *shhwtstamps;
- struct ixp46x_ts_regs *regs;
- u64 ns;
- u32 ch, hi, lo, val;
- u16 uid, seq;
-
- if (!port->hwts_rx_en)
- return;
-
- ch = PORT2CHANNEL(port);
-
- regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
-
- val = __raw_readl(&regs->channel[ch].ch_event);
-
- if (!(val & RX_SNAPSHOT_LOCKED))
- return;
-
- lo = __raw_readl(&regs->channel[ch].src_uuid_lo);
- hi = __raw_readl(&regs->channel[ch].src_uuid_hi);
-
- uid = hi & 0xffff;
- seq = (hi >> 16) & 0xffff;
-
- if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq)))
- goto out;
-
- lo = __raw_readl(&regs->channel[ch].rx_snap_lo);
- hi = __raw_readl(&regs->channel[ch].rx_snap_hi);
- ns = ((u64) hi) << 32;
- ns |= lo;
- ns <<= TICKS_NS_SHIFT;
-
- shhwtstamps = skb_hwtstamps(skb);
- memset(shhwtstamps, 0, sizeof(*shhwtstamps));
- shhwtstamps->hwtstamp = ns_to_ktime(ns);
-out:
- __raw_writel(RX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
-}
-
-static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
-{
- struct skb_shared_hwtstamps shhwtstamps;
- struct ixp46x_ts_regs *regs;
- struct skb_shared_info *shtx;
- u64 ns;
- u32 ch, cnt, hi, lo, val;
-
- shtx = skb_shinfo(skb);
- if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && port->hwts_tx_en))
- shtx->tx_flags |= SKBTX_IN_PROGRESS;
- else
- return;
-
- ch = PORT2CHANNEL(port);
-
- regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
-
- /*
- * This really stinks, but we have to poll for the Tx time stamp.
- * Usually, the time stamp is ready after 4 to 6 microseconds.
- */
- for (cnt = 0; cnt < 100; cnt++) {
- val = __raw_readl(&regs->channel[ch].ch_event);
- if (val & TX_SNAPSHOT_LOCKED)
- break;
- udelay(1);
- }
- if (!(val & TX_SNAPSHOT_LOCKED)) {
- shtx->tx_flags &= ~SKBTX_IN_PROGRESS;
- return;
- }
-
- lo = __raw_readl(&regs->channel[ch].tx_snap_lo);
- hi = __raw_readl(&regs->channel[ch].tx_snap_hi);
- ns = ((u64) hi) << 32;
- ns |= lo;
- ns <<= TICKS_NS_SHIFT;
-
- memset(&shhwtstamps, 0, sizeof(shhwtstamps));
- shhwtstamps.hwtstamp = ns_to_ktime(ns);
- skb_tstamp_tx(skb, &shhwtstamps);
-
- __raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
-}
-
-static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
- struct hwtstamp_config cfg;
- struct ixp46x_ts_regs *regs;
- struct port *port = netdev_priv(netdev);
- int ch;
-
- if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
- return -EFAULT;
-
- if (cfg.flags) /* reserved for future extensions */
- return -EINVAL;
-
- ch = PORT2CHANNEL(port);
- regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
-
- switch (cfg.tx_type) {
- case HWTSTAMP_TX_OFF:
- port->hwts_tx_en = 0;
- break;
- case HWTSTAMP_TX_ON:
- port->hwts_tx_en = 1;
- break;
- default:
- return -ERANGE;
- }
-
- switch (cfg.rx_filter) {
- case HWTSTAMP_FILTER_NONE:
- port->hwts_rx_en = 0;
- break;
- case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
- port->hwts_rx_en = PTP_SLAVE_MODE;
- __raw_writel(0, &regs->channel[ch].ch_control);
- break;
- case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
- port->hwts_rx_en = PTP_MASTER_MODE;
- __raw_writel(MASTER_MODE, &regs->channel[ch].ch_control);
- break;
- default:
- return -ERANGE;
- }
-
- /* Clear out any old time stamps. */
- __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED,
- &regs->channel[ch].ch_event);
-
- return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
-}
-
-static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
- int write, u16 cmd)
-{
- int cycles = 0;
-
- if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) {
- printk(KERN_ERR "%s: MII not ready to transmit\n", bus->name);
- return -1;
- }
-
- if (write) {
- __raw_writel(cmd & 0xFF, &mdio_regs->mdio_command[0]);
- __raw_writel(cmd >> 8, &mdio_regs->mdio_command[1]);
- }
- __raw_writel(((phy_id << 5) | location) & 0xFF,
- &mdio_regs->mdio_command[2]);
- __raw_writel((phy_id >> 3) | (write << 2) | 0x80 /* GO */,
- &mdio_regs->mdio_command[3]);
-
- while ((cycles < MAX_MDIO_RETRIES) &&
- (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80)) {
- udelay(1);
- cycles++;
- }
-
- if (cycles == MAX_MDIO_RETRIES) {
- printk(KERN_ERR "%s #%i: MII write failed\n", bus->name,
- phy_id);
- return -1;
- }
-
-#if DEBUG_MDIO
- printk(KERN_DEBUG "%s #%i: mdio_%s() took %i cycles\n", bus->name,
- phy_id, write ? "write" : "read", cycles);
-#endif
-
- if (write)
- return 0;
-
- if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) {
-#if DEBUG_MDIO
- printk(KERN_DEBUG "%s #%i: MII read failed\n", bus->name,
- phy_id);
-#endif
- return 0xFFFF; /* don't return error */
- }
-
- return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) |
- ((__raw_readl(&mdio_regs->mdio_status[1]) & 0xFF) << 8);
-}
-
-static int ixp4xx_mdio_read(struct mii_bus *bus, int phy_id, int location)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&mdio_lock, flags);
- ret = ixp4xx_mdio_cmd(bus, phy_id, location, 0, 0);
- spin_unlock_irqrestore(&mdio_lock, flags);
-#if DEBUG_MDIO
- printk(KERN_DEBUG "%s #%i: MII read [%i] -> 0x%X\n", bus->name,
- phy_id, location, ret);
-#endif
- return ret;
-}
-
-static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location,
- u16 val)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&mdio_lock, flags);
- ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val);
- spin_unlock_irqrestore(&mdio_lock, flags);
-#if DEBUG_MDIO
- printk(KERN_DEBUG "%s #%i: MII write [%i] <- 0x%X, err = %i\n",
- bus->name, phy_id, location, val, ret);
-#endif
- return ret;
-}
-
-static int ixp4xx_mdio_register(void)
-{
- int err;
-
- if (!(mdio_bus = mdiobus_alloc()))
- return -ENOMEM;
-
- if (cpu_is_ixp43x()) {
- /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
- if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
- return -ENODEV;
- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
- } else {
- /* All MII PHY accesses use NPE-B Ethernet registers */
- if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
- return -ENODEV;
- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
- }
-
- __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
- spin_lock_init(&mdio_lock);
- mdio_bus->name = "IXP4xx MII Bus";
- mdio_bus->read = &ixp4xx_mdio_read;
- mdio_bus->write = &ixp4xx_mdio_write;
- strcpy(mdio_bus->id, "0");
-
- if ((err = mdiobus_register(mdio_bus)))
- mdiobus_free(mdio_bus);
- return err;
-}
-
-static void ixp4xx_mdio_remove(void)
-{
- mdiobus_unregister(mdio_bus);
- mdiobus_free(mdio_bus);
-}
-
-
-static void ixp4xx_adjust_link(struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- struct phy_device *phydev = port->phydev;
-
- if (!phydev->link) {
- if (port->speed) {
- port->speed = 0;
- printk(KERN_INFO "%s: link down\n", dev->name);
- }
- return;
- }
-
- if (port->speed == phydev->speed && port->duplex == phydev->duplex)
- return;
-
- port->speed = phydev->speed;
- port->duplex = phydev->duplex;
-
- if (port->duplex)
- __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
- &port->regs->tx_control[0]);
- else
- __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX,
- &port->regs->tx_control[0]);
-
- printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n",
- dev->name, port->speed, port->duplex ? "full" : "half");
-}
-
-
-static inline void debug_pkt(struct net_device *dev, const char *func,
- u8 *data, int len)
-{
-#if DEBUG_PKT_BYTES
- int i;
-
- printk(KERN_DEBUG "%s: %s(%i) ", dev->name, func, len);
- for (i = 0; i < len; i++) {
- if (i >= DEBUG_PKT_BYTES)
- break;
- printk("%s%02X",
- ((i == 6) || (i == 12) || (i >= 14)) ? " " : "",
- data[i]);
- }
- printk("\n");
-#endif
-}
-
-
-static inline void debug_desc(u32 phys, struct desc *desc)
-{
-#if DEBUG_DESC
- printk(KERN_DEBUG "%X: %X %3X %3X %08X %2X < %2X %4X %X"
- " %X %X %02X%02X%02X%02X%02X%02X < %02X%02X%02X%02X%02X%02X\n",
- phys, desc->next, desc->buf_len, desc->pkt_len,
- desc->data, desc->dest_id, desc->src_id, desc->flags,
- desc->qos, desc->padlen, desc->vlan_tci,
- desc->dst_mac_0, desc->dst_mac_1, desc->dst_mac_2,
- desc->dst_mac_3, desc->dst_mac_4, desc->dst_mac_5,
- desc->src_mac_0, desc->src_mac_1, desc->src_mac_2,
- desc->src_mac_3, desc->src_mac_4, desc->src_mac_5);
-#endif
-}
-
-static inline int queue_get_desc(unsigned int queue, struct port *port,
- int is_tx)
-{
- u32 phys, tab_phys, n_desc;
- struct desc *tab;
-
- if (!(phys = qmgr_get_entry(queue)))
- return -1;
-
- phys &= ~0x1F; /* mask out non-address bits */
- tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0);
- tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0);
- n_desc = (phys - tab_phys) / sizeof(struct desc);
- BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS));
- debug_desc(phys, &tab[n_desc]);
- BUG_ON(tab[n_desc].next);
- return n_desc;
-}
-
-static inline void queue_put_desc(unsigned int queue, u32 phys,
- struct desc *desc)
-{
- debug_desc(phys, desc);
- BUG_ON(phys & 0x1F);
- qmgr_put_entry(queue, phys);
- /* Don't check for queue overflow here, we've allocated sufficient
- length and queues >= 32 don't support this check anyway. */
-}
-
-
-static inline void dma_unmap_tx(struct port *port, struct desc *desc)
-{
-#ifdef __ARMEB__
- dma_unmap_single(&port->netdev->dev, desc->data,
- desc->buf_len, DMA_TO_DEVICE);
-#else
- dma_unmap_single(&port->netdev->dev, desc->data & ~3,
- ALIGN((desc->data & 3) + desc->buf_len, 4),
- DMA_TO_DEVICE);
-#endif
-}
-
-
-static void eth_rx_irq(void *pdev)
-{
- struct net_device *dev = pdev;
- struct port *port = netdev_priv(dev);
-
-#if DEBUG_RX
- printk(KERN_DEBUG "%s: eth_rx_irq\n", dev->name);
-#endif
- qmgr_disable_irq(port->plat->rxq);
- napi_schedule(&port->napi);
-}
-
-static int eth_poll(struct napi_struct *napi, int budget)
-{
- struct port *port = container_of(napi, struct port, napi);
- struct net_device *dev = port->netdev;
- unsigned int rxq = port->plat->rxq, rxfreeq = RXFREE_QUEUE(port->id);
- int received = 0;
-
-#if DEBUG_RX
- printk(KERN_DEBUG "%s: eth_poll\n", dev->name);
-#endif
-
- while (received < budget) {
- struct sk_buff *skb;
- struct desc *desc;
- int n;
-#ifdef __ARMEB__
- struct sk_buff *temp;
- u32 phys;
-#endif
-
- if ((n = queue_get_desc(rxq, port, 0)) < 0) {
-#if DEBUG_RX
- printk(KERN_DEBUG "%s: eth_poll napi_complete\n",
- dev->name);
-#endif
- napi_complete(napi);
- qmgr_enable_irq(rxq);
- if (!qmgr_stat_below_low_watermark(rxq) &&
- napi_reschedule(napi)) { /* not empty again */
-#if DEBUG_RX
- printk(KERN_DEBUG "%s: eth_poll"
- " napi_reschedule successed\n",
- dev->name);
-#endif
- qmgr_disable_irq(rxq);
- continue;
- }
-#if DEBUG_RX
- printk(KERN_DEBUG "%s: eth_poll all done\n",
- dev->name);
-#endif
- return received; /* all work done */
- }
-
- desc = rx_desc_ptr(port, n);
-
-#ifdef __ARMEB__
- if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) {
- phys = dma_map_single(&dev->dev, skb->data,
- RX_BUFF_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&dev->dev, phys)) {
- dev_kfree_skb(skb);
- skb = NULL;
- }
- }
-#else
- skb = netdev_alloc_skb(dev,
- ALIGN(NET_IP_ALIGN + desc->pkt_len, 4));
-#endif
-
- if (!skb) {
- dev->stats.rx_dropped++;
- /* put the desc back on RX-ready queue */
- desc->buf_len = MAX_MRU;
- desc->pkt_len = 0;
- queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
- continue;
- }
-
- /* process received frame */
-#ifdef __ARMEB__
- temp = skb;
- skb = port->rx_buff_tab[n];
- dma_unmap_single(&dev->dev, desc->data - NET_IP_ALIGN,
- RX_BUFF_SIZE, DMA_FROM_DEVICE);
-#else
- dma_sync_single_for_cpu(&dev->dev, desc->data - NET_IP_ALIGN,
- RX_BUFF_SIZE, DMA_FROM_DEVICE);
- memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n],
- ALIGN(NET_IP_ALIGN + desc->pkt_len, 4) / 4);
-#endif
- skb_reserve(skb, NET_IP_ALIGN);
- skb_put(skb, desc->pkt_len);
-
- debug_pkt(dev, "eth_poll", skb->data, skb->len);
-
- ixp_rx_timestamp(port, skb);
- skb->protocol = eth_type_trans(skb, dev);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
- netif_receive_skb(skb);
-
- /* put the new buffer on RX-free queue */
-#ifdef __ARMEB__
- port->rx_buff_tab[n] = temp;
- desc->data = phys + NET_IP_ALIGN;
-#endif
- desc->buf_len = MAX_MRU;
- desc->pkt_len = 0;
- queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
- received++;
- }
-
-#if DEBUG_RX
- printk(KERN_DEBUG "eth_poll(): end, not all work done\n");
-#endif
- return received; /* not all work done */
-}
-
-
-static void eth_txdone_irq(void *unused)
-{
- u32 phys;
-
-#if DEBUG_TX
- printk(KERN_DEBUG DRV_NAME ": eth_txdone_irq\n");
-#endif
- while ((phys = qmgr_get_entry(TXDONE_QUEUE)) != 0) {
- u32 npe_id, n_desc;
- struct port *port;
- struct desc *desc;
- int start;
-
- npe_id = phys & 3;
- BUG_ON(npe_id >= MAX_NPES);
- port = npe_port_tab[npe_id];
- BUG_ON(!port);
- phys &= ~0x1F; /* mask out non-address bits */
- n_desc = (phys - tx_desc_phys(port, 0)) / sizeof(struct desc);
- BUG_ON(n_desc >= TX_DESCS);
- desc = tx_desc_ptr(port, n_desc);
- debug_desc(phys, desc);
-
- if (port->tx_buff_tab[n_desc]) { /* not the draining packet */
- port->netdev->stats.tx_packets++;
- port->netdev->stats.tx_bytes += desc->pkt_len;
-
- dma_unmap_tx(port, desc);
-#if DEBUG_TX
- printk(KERN_DEBUG "%s: eth_txdone_irq free %p\n",
- port->netdev->name, port->tx_buff_tab[n_desc]);
-#endif
- free_buffer_irq(port->tx_buff_tab[n_desc]);
- port->tx_buff_tab[n_desc] = NULL;
- }
-
- start = qmgr_stat_below_low_watermark(port->plat->txreadyq);
- queue_put_desc(port->plat->txreadyq, phys, desc);
- if (start) { /* TX-ready queue was empty */
-#if DEBUG_TX
- printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n",
- port->netdev->name);
-#endif
- netif_wake_queue(port->netdev);
- }
- }
-}
-
-static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- unsigned int txreadyq = port->plat->txreadyq;
- int len, offset, bytes, n;
- void *mem;
- u32 phys;
- struct desc *desc;
-
-#if DEBUG_TX
- printk(KERN_DEBUG "%s: eth_xmit\n", dev->name);
-#endif
-
- if (unlikely(skb->len > MAX_MRU)) {
- dev_kfree_skb(skb);
- dev->stats.tx_errors++;
- return NETDEV_TX_OK;
- }
-
- debug_pkt(dev, "eth_xmit", skb->data, skb->len);
-
- len = skb->len;
-#ifdef __ARMEB__
- offset = 0; /* no need to keep alignment */
- bytes = len;
- mem = skb->data;
-#else
- offset = (int)skb->data & 3; /* keep 32-bit alignment */
- bytes = ALIGN(offset + len, 4);
- if (!(mem = kmalloc(bytes, GFP_ATOMIC))) {
- dev_kfree_skb(skb);
- dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
- }
- memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
-#endif
-
- phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
- if (dma_mapping_error(&dev->dev, phys)) {
- dev_kfree_skb(skb);
-#ifndef __ARMEB__
- kfree(mem);
-#endif
- dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
- }
-
- n = queue_get_desc(txreadyq, port, 1);
- BUG_ON(n < 0);
- desc = tx_desc_ptr(port, n);
-
-#ifdef __ARMEB__
- port->tx_buff_tab[n] = skb;
-#else
- port->tx_buff_tab[n] = mem;
-#endif
- desc->data = phys + offset;
- desc->buf_len = desc->pkt_len = len;
-
- /* NPE firmware pads short frames with zeros internally */
- wmb();
- queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc);
-
- if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */
-#if DEBUG_TX
- printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name);
-#endif
- netif_stop_queue(dev);
- /* we could miss TX ready interrupt */
- /* really empty in fact */
- if (!qmgr_stat_below_low_watermark(txreadyq)) {
-#if DEBUG_TX
- printk(KERN_DEBUG "%s: eth_xmit ready again\n",
- dev->name);
-#endif
- netif_wake_queue(dev);
- }
- }
-
-#if DEBUG_TX
- printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name);
-#endif
-
- ixp_tx_timestamp(port, skb);
- skb_tx_timestamp(skb);
-
-#ifndef __ARMEB__
- dev_kfree_skb(skb);
-#endif
- return NETDEV_TX_OK;
-}
-
-
-static void eth_set_mcast_list(struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- struct netdev_hw_addr *ha;
- u8 diffs[ETH_ALEN], *addr;
- int i;
- static const u8 allmulti[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- if (dev->flags & IFF_ALLMULTI) {
- for (i = 0; i < ETH_ALEN; i++) {
- __raw_writel(allmulti[i], &port->regs->mcast_addr[i]);
- __raw_writel(allmulti[i], &port->regs->mcast_mask[i]);
- }
- __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN,
- &port->regs->rx_control[0]);
- return;
- }
-
- if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) {
- __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN,
- &port->regs->rx_control[0]);
- return;
- }
-
- memset(diffs, 0, ETH_ALEN);
-
- addr = NULL;
- netdev_for_each_mc_addr(ha, dev) {
- if (!addr)
- addr = ha->addr; /* first MAC address */
- for (i = 0; i < ETH_ALEN; i++)
- diffs[i] |= addr[i] ^ ha->addr[i];
- }
-
- for (i = 0; i < ETH_ALEN; i++) {
- __raw_writel(addr[i], &port->regs->mcast_addr[i]);
- __raw_writel(~diffs[i], &port->regs->mcast_mask[i]);
- }
-
- __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN,
- &port->regs->rx_control[0]);
-}
-
-
-static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
- struct port *port = netdev_priv(dev);
-
- if (!netif_running(dev))
- return -EINVAL;
-
- if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP)
- return hwtstamp_ioctl(dev, req, cmd);
-
- return phy_mii_ioctl(port->phydev, req, cmd);
-}
-
-/* ethtool support */
-
-static void ixp4xx_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct port *port = netdev_priv(dev);
- strcpy(info->driver, DRV_NAME);
- snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u",
- port->firmware[0], port->firmware[1],
- port->firmware[2], port->firmware[3]);
- strcpy(info->bus_info, "internal");
-}
-
-static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct port *port = netdev_priv(dev);
- return phy_ethtool_gset(port->phydev, cmd);
-}
-
-static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct port *port = netdev_priv(dev);
- return phy_ethtool_sset(port->phydev, cmd);
-}
-
-static int ixp4xx_nway_reset(struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- return phy_start_aneg(port->phydev);
-}
-
-static const struct ethtool_ops ixp4xx_ethtool_ops = {
- .get_drvinfo = ixp4xx_get_drvinfo,
- .get_settings = ixp4xx_get_settings,
- .set_settings = ixp4xx_set_settings,
- .nway_reset = ixp4xx_nway_reset,
- .get_link = ethtool_op_get_link,
-};
-
-
-static int request_queues(struct port *port)
-{
- int err;
-
- err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0,
- "%s:RX-free", port->netdev->name);
- if (err)
- return err;
-
- err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0,
- "%s:RX", port->netdev->name);
- if (err)
- goto rel_rxfree;
-
- err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0,
- "%s:TX", port->netdev->name);
- if (err)
- goto rel_rx;
-
- err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0,
- "%s:TX-ready", port->netdev->name);
- if (err)
- goto rel_tx;
-
- /* TX-done queue handles skbs sent out by the NPEs */
- if (!ports_open) {
- err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0,
- "%s:TX-done", DRV_NAME);
- if (err)
- goto rel_txready;
- }
- return 0;
-
-rel_txready:
- qmgr_release_queue(port->plat->txreadyq);
-rel_tx:
- qmgr_release_queue(TX_QUEUE(port->id));
-rel_rx:
- qmgr_release_queue(port->plat->rxq);
-rel_rxfree:
- qmgr_release_queue(RXFREE_QUEUE(port->id));
- printk(KERN_DEBUG "%s: unable to request hardware queues\n",
- port->netdev->name);
- return err;
-}
-
-static void release_queues(struct port *port)
-{
- qmgr_release_queue(RXFREE_QUEUE(port->id));
- qmgr_release_queue(port->plat->rxq);
- qmgr_release_queue(TX_QUEUE(port->id));
- qmgr_release_queue(port->plat->txreadyq);
-
- if (!ports_open)
- qmgr_release_queue(TXDONE_QUEUE);
-}
-
-static int init_queues(struct port *port)
-{
- int i;
-
- if (!ports_open)
- if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
- POOL_ALLOC_SIZE, 32, 0)))
- return -ENOMEM;
-
- if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
- &port->desc_tab_phys)))
- return -ENOMEM;
- memset(port->desc_tab, 0, POOL_ALLOC_SIZE);
- memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */
- memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab));
-
- /* Setup RX buffers */
- for (i = 0; i < RX_DESCS; i++) {
- struct desc *desc = rx_desc_ptr(port, i);
- buffer_t *buff; /* skb or kmalloc()ated memory */
- void *data;
-#ifdef __ARMEB__
- if (!(buff = netdev_alloc_skb(port->netdev, RX_BUFF_SIZE)))
- return -ENOMEM;
- data = buff->data;
-#else
- if (!(buff = kmalloc(RX_BUFF_SIZE, GFP_KERNEL)))
- return -ENOMEM;
- data = buff;
-#endif
- desc->buf_len = MAX_MRU;
- desc->data = dma_map_single(&port->netdev->dev, data,
- RX_BUFF_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&port->netdev->dev, desc->data)) {
- free_buffer(buff);
- return -EIO;
- }
- desc->data += NET_IP_ALIGN;
- port->rx_buff_tab[i] = buff;
- }
-
- return 0;
-}
-
-static void destroy_queues(struct port *port)
-{
- int i;
-
- if (port->desc_tab) {
- for (i = 0; i < RX_DESCS; i++) {
- struct desc *desc = rx_desc_ptr(port, i);
- buffer_t *buff = port->rx_buff_tab[i];
- if (buff) {
- dma_unmap_single(&port->netdev->dev,
- desc->data - NET_IP_ALIGN,
- RX_BUFF_SIZE, DMA_FROM_DEVICE);
- free_buffer(buff);
- }
- }
- for (i = 0; i < TX_DESCS; i++) {
- struct desc *desc = tx_desc_ptr(port, i);
- buffer_t *buff = port->tx_buff_tab[i];
- if (buff) {
- dma_unmap_tx(port, desc);
- free_buffer(buff);
- }
- }
- dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys);
- port->desc_tab = NULL;
- }
-
- if (!ports_open && dma_pool) {
- dma_pool_destroy(dma_pool);
- dma_pool = NULL;
- }
-}
-
-static int eth_open(struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- struct npe *npe = port->npe;
- struct msg msg;
- int i, err;
-
- if (!npe_running(npe)) {
- err = npe_load_firmware(npe, npe_name(npe), &dev->dev);
- if (err)
- return err;
-
- if (npe_recv_message(npe, &msg, "ETH_GET_STATUS")) {
- printk(KERN_ERR "%s: %s not responding\n", dev->name,
- npe_name(npe));
- return -EIO;
- }
- port->firmware[0] = msg.byte4;
- port->firmware[1] = msg.byte5;
- port->firmware[2] = msg.byte6;
- port->firmware[3] = msg.byte7;
- }
-
- memset(&msg, 0, sizeof(msg));
- msg.cmd = NPE_VLAN_SETRXQOSENTRY;
- msg.eth_id = port->id;
- msg.byte5 = port->plat->rxq | 0x80;
- msg.byte7 = port->plat->rxq << 4;
- for (i = 0; i < 8; i++) {
- msg.byte3 = i;
- if (npe_send_recv_message(port->npe, &msg, "ETH_SET_RXQ"))
- return -EIO;
- }
-
- msg.cmd = NPE_EDB_SETPORTADDRESS;
- msg.eth_id = PHYSICAL_ID(port->id);
- msg.byte2 = dev->dev_addr[0];
- msg.byte3 = dev->dev_addr[1];
- msg.byte4 = dev->dev_addr[2];
- msg.byte5 = dev->dev_addr[3];
- msg.byte6 = dev->dev_addr[4];
- msg.byte7 = dev->dev_addr[5];
- if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAC"))
- return -EIO;
-
- memset(&msg, 0, sizeof(msg));
- msg.cmd = NPE_FW_SETFIREWALLMODE;
- msg.eth_id = port->id;
- if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE"))
- return -EIO;
-
- if ((err = request_queues(port)) != 0)
- return err;
-
- if ((err = init_queues(port)) != 0) {
- destroy_queues(port);
- release_queues(port);
- return err;
- }
-
- port->speed = 0; /* force "link up" message */
- phy_start(port->phydev);
-
- for (i = 0; i < ETH_ALEN; i++)
- __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]);
- __raw_writel(0x08, &port->regs->random_seed);
- __raw_writel(0x12, &port->regs->partial_empty_threshold);
- __raw_writel(0x30, &port->regs->partial_full_threshold);
- __raw_writel(0x08, &port->regs->tx_start_bytes);
- __raw_writel(0x15, &port->regs->tx_deferral);
- __raw_writel(0x08, &port->regs->tx_2part_deferral[0]);
- __raw_writel(0x07, &port->regs->tx_2part_deferral[1]);
- __raw_writel(0x80, &port->regs->slot_time);
- __raw_writel(0x01, &port->regs->int_clock_threshold);
-
- /* Populate queues with buffers, no failure after this point */
- for (i = 0; i < TX_DESCS; i++)
- queue_put_desc(port->plat->txreadyq,
- tx_desc_phys(port, i), tx_desc_ptr(port, i));
-
- for (i = 0; i < RX_DESCS; i++)
- queue_put_desc(RXFREE_QUEUE(port->id),
- rx_desc_phys(port, i), rx_desc_ptr(port, i));
-
- __raw_writel(TX_CNTRL1_RETRIES, &port->regs->tx_control[1]);
- __raw_writel(DEFAULT_TX_CNTRL0, &port->regs->tx_control[0]);
- __raw_writel(0, &port->regs->rx_control[1]);
- __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]);
-
- napi_enable(&port->napi);
- eth_set_mcast_list(dev);
- netif_start_queue(dev);
-
- qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY,
- eth_rx_irq, dev);
- if (!ports_open) {
- qmgr_set_irq(TXDONE_QUEUE, QUEUE_IRQ_SRC_NOT_EMPTY,
- eth_txdone_irq, NULL);
- qmgr_enable_irq(TXDONE_QUEUE);
- }
- ports_open++;
- /* we may already have RX data, enables IRQ */
- napi_schedule(&port->napi);
- return 0;
-}
-
-static int eth_close(struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- struct msg msg;
- int buffs = RX_DESCS; /* allocated RX buffers */
- int i;
-
- ports_open--;
- qmgr_disable_irq(port->plat->rxq);
- napi_disable(&port->napi);
- netif_stop_queue(dev);
-
- while (queue_get_desc(RXFREE_QUEUE(port->id), port, 0) >= 0)
- buffs--;
-
- memset(&msg, 0, sizeof(msg));
- msg.cmd = NPE_SETLOOPBACK_MODE;
- msg.eth_id = port->id;
- msg.byte3 = 1;
- if (npe_send_recv_message(port->npe, &msg, "ETH_ENABLE_LOOPBACK"))
- printk(KERN_CRIT "%s: unable to enable loopback\n", dev->name);
-
- i = 0;
- do { /* drain RX buffers */
- while (queue_get_desc(port->plat->rxq, port, 0) >= 0)
- buffs--;
- if (!buffs)
- break;
- if (qmgr_stat_empty(TX_QUEUE(port->id))) {
- /* we have to inject some packet */
- struct desc *desc;
- u32 phys;
- int n = queue_get_desc(port->plat->txreadyq, port, 1);
- BUG_ON(n < 0);
- desc = tx_desc_ptr(port, n);
- phys = tx_desc_phys(port, n);
- desc->buf_len = desc->pkt_len = 1;
- wmb();
- queue_put_desc(TX_QUEUE(port->id), phys, desc);
- }
- udelay(1);
- } while (++i < MAX_CLOSE_WAIT);
-
- if (buffs)
- printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
- " left in NPE\n", dev->name, buffs);
-#if DEBUG_CLOSE
- if (!buffs)
- printk(KERN_DEBUG "Draining RX queue took %i cycles\n", i);
-#endif
-
- buffs = TX_DESCS;
- while (queue_get_desc(TX_QUEUE(port->id), port, 1) >= 0)
- buffs--; /* cancel TX */
-
- i = 0;
- do {
- while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0)
- buffs--;
- if (!buffs)
- break;
- } while (++i < MAX_CLOSE_WAIT);
-
- if (buffs)
- printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
- "left in NPE\n", dev->name, buffs);
-#if DEBUG_CLOSE
- if (!buffs)
- printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
-#endif
-
- msg.byte3 = 0;
- if (npe_send_recv_message(port->npe, &msg, "ETH_DISABLE_LOOPBACK"))
- printk(KERN_CRIT "%s: unable to disable loopback\n",
- dev->name);
-
- phy_stop(port->phydev);
-
- if (!ports_open)
- qmgr_disable_irq(TXDONE_QUEUE);
- destroy_queues(port);
- release_queues(port);
- return 0;
-}
-
-static const struct net_device_ops ixp4xx_netdev_ops = {
- .ndo_open = eth_open,
- .ndo_stop = eth_close,
- .ndo_start_xmit = eth_xmit,
- .ndo_set_multicast_list = eth_set_mcast_list,
- .ndo_do_ioctl = eth_ioctl,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static int __devinit eth_init_one(struct platform_device *pdev)
-{
- struct port *port;
- struct net_device *dev;
- struct eth_plat_info *plat = pdev->dev.platform_data;
- u32 regs_phys;
- char phy_id[MII_BUS_ID_SIZE + 3];
- int err;
-
- if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
- pr_err("ixp4xx_eth: bad ptp filter\n");
- return -EINVAL;
- }
-
- if (!(dev = alloc_etherdev(sizeof(struct port))))
- return -ENOMEM;
-
- SET_NETDEV_DEV(dev, &pdev->dev);
- port = netdev_priv(dev);
- port->netdev = dev;
- port->id = pdev->id;
-
- switch (port->id) {
- case IXP4XX_ETH_NPEA:
- port->regs = (struct eth_regs __iomem *)IXP4XX_EthA_BASE_VIRT;
- regs_phys = IXP4XX_EthA_BASE_PHYS;
- break;
- case IXP4XX_ETH_NPEB:
- port->regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
- regs_phys = IXP4XX_EthB_BASE_PHYS;
- break;
- case IXP4XX_ETH_NPEC:
- port->regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
- regs_phys = IXP4XX_EthC_BASE_PHYS;
- break;
- default:
- err = -ENODEV;
- goto err_free;
- }
-
- dev->netdev_ops = &ixp4xx_netdev_ops;
- dev->ethtool_ops = &ixp4xx_ethtool_ops;
- dev->tx_queue_len = 100;
-
- netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT);
-
- if (!(port->npe = npe_request(NPE_ID(port->id)))) {
- err = -EIO;
- goto err_free;
- }
-
- port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name);
- if (!port->mem_res) {
- err = -EBUSY;
- goto err_npe_rel;
- }
-
- port->plat = plat;
- npe_port_tab[NPE_ID(port->id)] = port;
- memcpy(dev->dev_addr, plat->hwaddr, ETH_ALEN);
-
- platform_set_drvdata(pdev, dev);
-
- __raw_writel(DEFAULT_CORE_CNTRL | CORE_RESET,
- &port->regs->core_control);
- udelay(50);
- __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
- udelay(50);
-
- snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
- port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
- if (IS_ERR(port->phydev)) {
- err = PTR_ERR(port->phydev);
- goto err_free_mem;
- }
-
- port->phydev->irq = PHY_POLL;
-
- if ((err = register_netdev(dev)))
- goto err_phy_dis;
-
- printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
- npe_name(port->npe));
-
- return 0;
-
-err_phy_dis:
- phy_disconnect(port->phydev);
-err_free_mem:
- npe_port_tab[NPE_ID(port->id)] = NULL;
- platform_set_drvdata(pdev, NULL);
- release_resource(port->mem_res);
-err_npe_rel:
- npe_release(port->npe);
-err_free:
- free_netdev(dev);
- return err;
-}
-
-static int __devexit eth_remove_one(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct port *port = netdev_priv(dev);
-
- unregister_netdev(dev);
- phy_disconnect(port->phydev);
- npe_port_tab[NPE_ID(port->id)] = NULL;
- platform_set_drvdata(pdev, NULL);
- npe_release(port->npe);
- release_resource(port->mem_res);
- free_netdev(dev);
- return 0;
-}
-
-static struct platform_driver ixp4xx_eth_driver = {
- .driver.name = DRV_NAME,
- .probe = eth_init_one,
- .remove = eth_remove_one,
-};
-
-static int __init eth_init_module(void)
-{
- int err;
- if ((err = ixp4xx_mdio_register()))
- return err;
- return platform_driver_register(&ixp4xx_eth_driver);
-}
-
-static void __exit eth_cleanup_module(void)
-{
- platform_driver_unregister(&ixp4xx_eth_driver);
- ixp4xx_mdio_remove();
-}
-
-MODULE_AUTHOR("Krzysztof Halasa");
-MODULE_DESCRIPTION("Intel IXP4xx Ethernet driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ixp4xx_eth");
-module_init(eth_init_module);
-module_exit(eth_cleanup_module);
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
deleted file mode 100644
index c827a6097d02..000000000000
--- a/drivers/net/arm/ks8695net.c
+++ /dev/null
@@ -1,1656 +0,0 @@
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- * Vincent Sanders <vince@simtec.co.uk>
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <asm/irq.h>
-
-#include <mach/regs-switch.h>
-#include <mach/regs-misc.h>
-#include <asm/mach/irq.h>
-#include <mach/regs-irq.h>
-
-#include "ks8695net.h"
-
-#define MODULENAME "ks8695_ether"
-#define MODULEVERSION "1.02"
-
-/*
- * Transmit and device reset timeout, default 5 seconds.
- */
-static int watchdog = 5000;
-
-/* Hardware structures */
-
-/**
- * struct rx_ring_desc - Receive descriptor ring element
- * @status: The status of the descriptor element (E.g. who owns it)
- * @length: The number of bytes in the block pointed to by data_ptr
- * @data_ptr: The physical address of the data block to receive into
- * @next_desc: The physical address of the next descriptor element.
- */
-struct rx_ring_desc {
- __le32 status;
- __le32 length;
- __le32 data_ptr;
- __le32 next_desc;
-};
-
-/**
- * struct tx_ring_desc - Transmit descriptor ring element
- * @owner: Who owns the descriptor
- * @status: The number of bytes in the block pointed to by data_ptr
- * @data_ptr: The physical address of the data block to receive into
- * @next_desc: The physical address of the next descriptor element.
- */
-struct tx_ring_desc {
- __le32 owner;
- __le32 status;
- __le32 data_ptr;
- __le32 next_desc;
-};
-
-/**
- * struct ks8695_skbuff - sk_buff wrapper for rx/tx rings.
- * @skb: The buffer in the ring
- * @dma_ptr: The mapped DMA pointer of the buffer
- * @length: The number of bytes mapped to dma_ptr
- */
-struct ks8695_skbuff {
- struct sk_buff *skb;
- dma_addr_t dma_ptr;
- u32 length;
-};
-
-/* Private device structure */
-
-#define MAX_TX_DESC 8
-#define MAX_TX_DESC_MASK 0x7
-#define MAX_RX_DESC 16
-#define MAX_RX_DESC_MASK 0xf
-
-/*napi_weight have better more than rx DMA buffers*/
-#define NAPI_WEIGHT 64
-
-#define MAX_RXBUF_SIZE 0x700
-
-#define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC)
-#define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC)
-#define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE)
-
-/**
- * enum ks8695_dtype - Device type
- * @KS8695_DTYPE_WAN: This device is a WAN interface
- * @KS8695_DTYPE_LAN: This device is a LAN interface
- * @KS8695_DTYPE_HPNA: This device is an HPNA interface
- */
-enum ks8695_dtype {
- KS8695_DTYPE_WAN,
- KS8695_DTYPE_LAN,
- KS8695_DTYPE_HPNA,
-};
-
-/**
- * struct ks8695_priv - Private data for the KS8695 Ethernet
- * @in_suspend: Flag to indicate if we're suspending/resuming
- * @ndev: The net_device for this interface
- * @dev: The platform device object for this interface
- * @dtype: The type of this device
- * @io_regs: The ioremapped registers for this interface
- * @napi : Add support NAPI for Rx
- * @rx_irq_name: The textual name of the RX IRQ from the platform data
- * @tx_irq_name: The textual name of the TX IRQ from the platform data
- * @link_irq_name: The textual name of the link IRQ from the
- * platform data if available
- * @rx_irq: The IRQ number for the RX IRQ
- * @tx_irq: The IRQ number for the TX IRQ
- * @link_irq: The IRQ number for the link IRQ if available
- * @regs_req: The resource request for the registers region
- * @phyiface_req: The resource request for the phy/switch region
- * if available
- * @phyiface_regs: The ioremapped registers for the phy/switch if available
- * @ring_base: The base pointer of the dma coherent memory for the rings
- * @ring_base_dma: The DMA mapped equivalent of ring_base
- * @tx_ring: The pointer in ring_base of the TX ring
- * @tx_ring_used: The number of slots in the TX ring which are occupied
- * @tx_ring_next_slot: The next slot to fill in the TX ring
- * @tx_ring_dma: The DMA mapped equivalent of tx_ring
- * @tx_buffers: The sk_buff mappings for the TX ring
- * @txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables
- * @rx_ring: The pointer in ring_base of the RX ring
- * @rx_ring_dma: The DMA mapped equivalent of rx_ring
- * @rx_buffers: The sk_buff mappings for the RX ring
- * @next_rx_desc_read: The next RX descriptor to read from on IRQ
- * @rx_lock: A lock to protect Rx irq function
- * @msg_enable: The flags for which messages to emit
- */
-struct ks8695_priv {
- int in_suspend;
- struct net_device *ndev;
- struct device *dev;
- enum ks8695_dtype dtype;
- void __iomem *io_regs;
-
- struct napi_struct napi;
-
- const char *rx_irq_name, *tx_irq_name, *link_irq_name;
- int rx_irq, tx_irq, link_irq;
-
- struct resource *regs_req, *phyiface_req;
- void __iomem *phyiface_regs;
-
- void *ring_base;
- dma_addr_t ring_base_dma;
-
- struct tx_ring_desc *tx_ring;
- int tx_ring_used;
- int tx_ring_next_slot;
- dma_addr_t tx_ring_dma;
- struct ks8695_skbuff tx_buffers[MAX_TX_DESC];
- spinlock_t txq_lock;
-
- struct rx_ring_desc *rx_ring;
- dma_addr_t rx_ring_dma;
- struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
- int next_rx_desc_read;
- spinlock_t rx_lock;
-
- int msg_enable;
-};
-
-/* Register access */
-
-/**
- * ks8695_readreg - Read from a KS8695 ethernet register
- * @ksp: The device to read from
- * @reg: The register to read
- */
-static inline u32
-ks8695_readreg(struct ks8695_priv *ksp, int reg)
-{
- return readl(ksp->io_regs + reg);
-}
-
-/**
- * ks8695_writereg - Write to a KS8695 ethernet register
- * @ksp: The device to write to
- * @reg: The register to write
- * @value: The value to write to the register
- */
-static inline void
-ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value)
-{
- writel(value, ksp->io_regs + reg);
-}
-
-/* Utility functions */
-
-/**
- * ks8695_port_type - Retrieve port-type as user-friendly string
- * @ksp: The device to return the type for
- *
- * Returns a string indicating which of the WAN, LAN or HPNA
- * ports this device is likely to represent.
- */
-static const char *
-ks8695_port_type(struct ks8695_priv *ksp)
-{
- switch (ksp->dtype) {
- case KS8695_DTYPE_LAN:
- return "LAN";
- case KS8695_DTYPE_WAN:
- return "WAN";
- case KS8695_DTYPE_HPNA:
- return "HPNA";
- }
-
- return "UNKNOWN";
-}
-
-/**
- * ks8695_update_mac - Update the MAC registers in the device
- * @ksp: The device to update
- *
- * Updates the MAC registers in the KS8695 device from the address in the
- * net_device structure associated with this interface.
- */
-static void
-ks8695_update_mac(struct ks8695_priv *ksp)
-{
- /* Update the HW with the MAC from the net_device */
- struct net_device *ndev = ksp->ndev;
- u32 machigh, maclow;
-
- maclow = ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) |
- (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5] << 0));
- machigh = ((ndev->dev_addr[0] << 8) | (ndev->dev_addr[1] << 0));
-
- ks8695_writereg(ksp, KS8695_MAL, maclow);
- ks8695_writereg(ksp, KS8695_MAH, machigh);
-
-}
-
-/**
- * ks8695_refill_rxbuffers - Re-fill the RX buffer ring
- * @ksp: The device to refill
- *
- * Iterates the RX ring of the device looking for empty slots.
- * For each empty slot, we allocate and map a new SKB and give it
- * to the hardware.
- * This can be called from interrupt context safely.
- */
-static void
-ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
-{
- /* Run around the RX ring, filling in any missing sk_buff's */
- int buff_n;
-
- for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
- if (!ksp->rx_buffers[buff_n].skb) {
- struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE);
- dma_addr_t mapping;
-
- ksp->rx_buffers[buff_n].skb = skb;
- if (skb == NULL) {
- /* Failed to allocate one, perhaps
- * we'll try again later.
- */
- break;
- }
-
- mapping = dma_map_single(ksp->dev, skb->data,
- MAX_RXBUF_SIZE,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(ksp->dev, mapping))) {
- /* Failed to DMA map this SKB, try later */
- dev_kfree_skb_irq(skb);
- ksp->rx_buffers[buff_n].skb = NULL;
- break;
- }
- ksp->rx_buffers[buff_n].dma_ptr = mapping;
- skb->dev = ksp->ndev;
- ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
-
- /* Record this into the DMA ring */
- ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping);
- ksp->rx_ring[buff_n].length =
- cpu_to_le32(MAX_RXBUF_SIZE);
-
- wmb();
-
- /* And give ownership over to the hardware */
- ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
- }
- }
-}
-
-/* Maximum number of multicast addresses which the KS8695 HW supports */
-#define KS8695_NR_ADDRESSES 16
-
-/**
- * ks8695_init_partial_multicast - Init the mcast addr registers
- * @ksp: The device to initialise
- * @addr: The multicast address list to use
- * @nr_addr: The number of addresses in the list
- *
- * This routine is a helper for ks8695_set_multicast - it writes
- * the additional-address registers in the KS8695 ethernet device
- * and cleans up any others left behind.
- */
-static void
-ks8695_init_partial_multicast(struct ks8695_priv *ksp,
- struct net_device *ndev)
-{
- u32 low, high;
- int i;
- struct netdev_hw_addr *ha;
-
- i = 0;
- netdev_for_each_mc_addr(ha, ndev) {
- /* Ran out of space in chip? */
- BUG_ON(i == KS8695_NR_ADDRESSES);
-
- low = (ha->addr[2] << 24) | (ha->addr[3] << 16) |
- (ha->addr[4] << 8) | (ha->addr[5]);
- high = (ha->addr[0] << 8) | (ha->addr[1]);
-
- ks8695_writereg(ksp, KS8695_AAL_(i), low);
- ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high);
- i++;
- }
-
- /* Clear the remaining Additional Station Addresses */
- for (; i < KS8695_NR_ADDRESSES; i++) {
- ks8695_writereg(ksp, KS8695_AAL_(i), 0);
- ks8695_writereg(ksp, KS8695_AAH_(i), 0);
- }
-}
-
-/* Interrupt handling */
-
-/**
- * ks8695_tx_irq - Transmit IRQ handler
- * @irq: The IRQ which went off (ignored)
- * @dev_id: The net_device for the interrupt
- *
- * Process the TX ring, clearing out any transmitted slots.
- * Allows the net_device to pass us new packets once slots are
- * freed.
- */
-static irqreturn_t
-ks8695_tx_irq(int irq, void *dev_id)
-{
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ks8695_priv *ksp = netdev_priv(ndev);
- int buff_n;
-
- for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
- if (ksp->tx_buffers[buff_n].skb &&
- !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) {
- rmb();
- /* An SKB which is not owned by HW is present */
- /* Update the stats for the net_device */
- ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length;
-
- /* Free the packet from the ring */
- ksp->tx_ring[buff_n].data_ptr = 0;
-
- /* Free the sk_buff */
- dma_unmap_single(ksp->dev,
- ksp->tx_buffers[buff_n].dma_ptr,
- ksp->tx_buffers[buff_n].length,
- DMA_TO_DEVICE);
- dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
- ksp->tx_buffers[buff_n].skb = NULL;
- ksp->tx_ring_used--;
- }
- }
-
- netif_wake_queue(ndev);
-
- return IRQ_HANDLED;
-}
-
-/**
- * ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit
- * @ksp: Private data for the KS8695 Ethernet
- *
- * For KS8695 document:
- * Interrupt Enable Register (offset 0xE204)
- * Bit29 : WAN MAC Receive Interrupt Enable
- * Bit16 : LAN MAC Receive Interrupt Enable
- * Interrupt Status Register (Offset 0xF208)
- * Bit29: WAN MAC Receive Status
- * Bit16: LAN MAC Receive Status
- * So, this Rx interrrupt enable/status bit number is equal
- * as Rx IRQ number.
- */
-static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp)
-{
- return ksp->rx_irq;
-}
-
-/**
- * ks8695_rx_irq - Receive IRQ handler
- * @irq: The IRQ which went off (ignored)
- * @dev_id: The net_device for the interrupt
- *
- * Inform NAPI that packet reception needs to be scheduled
- */
-
-static irqreturn_t
-ks8695_rx_irq(int irq, void *dev_id)
-{
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- spin_lock(&ksp->rx_lock);
-
- if (napi_schedule_prep(&ksp->napi)) {
- unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
- /*disable rx interrupt*/
- status &= ~mask_bit;
- writel(status , KS8695_IRQ_VA + KS8695_INTEN);
- __napi_schedule(&ksp->napi);
- }
-
- spin_unlock(&ksp->rx_lock);
- return IRQ_HANDLED;
-}
-
-/**
- * ks8695_rx - Receive packets called by NAPI poll method
- * @ksp: Private data for the KS8695 Ethernet
- * @budget: Number of packets allowed to process
- */
-static int ks8695_rx(struct ks8695_priv *ksp, int budget)
-{
- struct net_device *ndev = ksp->ndev;
- struct sk_buff *skb;
- int buff_n;
- u32 flags;
- int pktlen;
- int received = 0;
-
- buff_n = ksp->next_rx_desc_read;
- while (received < budget
- && ksp->rx_buffers[buff_n].skb
- && (!(ksp->rx_ring[buff_n].status &
- cpu_to_le32(RDES_OWN)))) {
- rmb();
- flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
-
- /* Found an SKB which we own, this means we
- * received a packet
- */
- if ((flags & (RDES_FS | RDES_LS)) !=
- (RDES_FS | RDES_LS)) {
- /* This packet is not the first and
- * the last segment. Therefore it is
- * a "spanning" packet and we can't
- * handle it
- */
- goto rx_failure;
- }
-
- if (flags & (RDES_ES | RDES_RE)) {
- /* It's an error packet */
- ndev->stats.rx_errors++;
- if (flags & RDES_TL)
- ndev->stats.rx_length_errors++;
- if (flags & RDES_RF)
- ndev->stats.rx_length_errors++;
- if (flags & RDES_CE)
- ndev->stats.rx_crc_errors++;
- if (flags & RDES_RE)
- ndev->stats.rx_missed_errors++;
-
- goto rx_failure;
- }
-
- pktlen = flags & RDES_FLEN;
- pktlen -= 4; /* Drop the CRC */
-
- /* Retrieve the sk_buff */
- skb = ksp->rx_buffers[buff_n].skb;
-
- /* Clear it from the ring */
- ksp->rx_buffers[buff_n].skb = NULL;
- ksp->rx_ring[buff_n].data_ptr = 0;
-
- /* Unmap the SKB */
- dma_unmap_single(ksp->dev,
- ksp->rx_buffers[buff_n].dma_ptr,
- ksp->rx_buffers[buff_n].length,
- DMA_FROM_DEVICE);
-
- /* Relinquish the SKB to the network layer */
- skb_put(skb, pktlen);
- skb->protocol = eth_type_trans(skb, ndev);
- netif_receive_skb(skb);
-
- /* Record stats */
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += pktlen;
- goto rx_finished;
-
-rx_failure:
- /* This ring entry is an error, but we can
- * re-use the skb
- */
- /* Give the ring entry back to the hardware */
- ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
-rx_finished:
- received++;
- buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
- }
-
- /* And note which RX descriptor we last did */
- ksp->next_rx_desc_read = buff_n;
-
- /* And refill the buffers */
- ks8695_refill_rxbuffers(ksp);
-
- /* Kick the RX DMA engine, in case it became suspended */
- ks8695_writereg(ksp, KS8695_DRSC, 0);
-
- return received;
-}
-
-
-/**
- * ks8695_poll - Receive packet by NAPI poll method
- * @ksp: Private data for the KS8695 Ethernet
- * @budget: The remaining number packets for network subsystem
- *
- * Invoked by the network core when it requests for new
- * packets from the driver
- */
-static int ks8695_poll(struct napi_struct *napi, int budget)
-{
- struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
- unsigned long work_done;
-
- unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN);
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
-
- work_done = ks8695_rx(ksp, budget);
-
- if (work_done < budget) {
- unsigned long flags;
- spin_lock_irqsave(&ksp->rx_lock, flags);
- __napi_complete(napi);
- /*enable rx interrupt*/
- writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
- spin_unlock_irqrestore(&ksp->rx_lock, flags);
- }
- return work_done;
-}
-
-/**
- * ks8695_link_irq - Link change IRQ handler
- * @irq: The IRQ which went off (ignored)
- * @dev_id: The net_device for the interrupt
- *
- * The WAN interface can generate an IRQ when the link changes,
- * report this to the net layer and the user.
- */
-static irqreturn_t
-ks8695_link_irq(int irq, void *dev_id)
-{
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
- if (ctrl & WMC_WLS) {
- netif_carrier_on(ndev);
- if (netif_msg_link(ksp))
- dev_info(ksp->dev,
- "%s: Link is now up (10%sMbps/%s-duplex)\n",
- ndev->name,
- (ctrl & WMC_WSS) ? "0" : "",
- (ctrl & WMC_WDS) ? "Full" : "Half");
- } else {
- netif_carrier_off(ndev);
- if (netif_msg_link(ksp))
- dev_info(ksp->dev, "%s: Link is now down.\n",
- ndev->name);
- }
-
- return IRQ_HANDLED;
-}
-
-
-/* KS8695 Device functions */
-
-/**
- * ks8695_reset - Reset a KS8695 ethernet interface
- * @ksp: The interface to reset
- *
- * Perform an engine reset of the interface and re-program it
- * with sensible defaults.
- */
-static void
-ks8695_reset(struct ks8695_priv *ksp)
-{
- int reset_timeout = watchdog;
- /* Issue the reset via the TX DMA control register */
- ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST);
- while (reset_timeout--) {
- if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST))
- break;
- msleep(1);
- }
-
- if (reset_timeout < 0) {
- dev_crit(ksp->dev,
- "Timeout waiting for DMA engines to reset\n");
- /* And blithely carry on */
- }
-
- /* Definitely wait long enough before attempting to program
- * the engines
- */
- msleep(10);
-
- /* RX: unicast and broadcast */
- ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB);
- /* TX: pad and add CRC */
- ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC);
-}
-
-/**
- * ks8695_shutdown - Shut down a KS8695 ethernet interface
- * @ksp: The interface to shut down
- *
- * This disables packet RX/TX, cleans up IRQs, drains the rings,
- * and basically places the interface into a clean shutdown
- * state.
- */
-static void
-ks8695_shutdown(struct ks8695_priv *ksp)
-{
- u32 ctrl;
- int buff_n;
-
- /* Disable packet transmission */
- ctrl = ks8695_readreg(ksp, KS8695_DTXC);
- ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE);
-
- /* Disable packet reception */
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
- ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE);
-
- /* Release the IRQs */
- free_irq(ksp->rx_irq, ksp->ndev);
- free_irq(ksp->tx_irq, ksp->ndev);
- if (ksp->link_irq != -1)
- free_irq(ksp->link_irq, ksp->ndev);
-
- /* Throw away any pending TX packets */
- for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
- if (ksp->tx_buffers[buff_n].skb) {
- /* Remove this SKB from the TX ring */
- ksp->tx_ring[buff_n].owner = 0;
- ksp->tx_ring[buff_n].status = 0;
- ksp->tx_ring[buff_n].data_ptr = 0;
-
- /* Unmap and bin this SKB */
- dma_unmap_single(ksp->dev,
- ksp->tx_buffers[buff_n].dma_ptr,
- ksp->tx_buffers[buff_n].length,
- DMA_TO_DEVICE);
- dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
- ksp->tx_buffers[buff_n].skb = NULL;
- }
- }
-
- /* Purge the RX buffers */
- for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
- if (ksp->rx_buffers[buff_n].skb) {
- /* Remove the SKB from the RX ring */
- ksp->rx_ring[buff_n].status = 0;
- ksp->rx_ring[buff_n].data_ptr = 0;
-
- /* Unmap and bin the SKB */
- dma_unmap_single(ksp->dev,
- ksp->rx_buffers[buff_n].dma_ptr,
- ksp->rx_buffers[buff_n].length,
- DMA_FROM_DEVICE);
- dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb);
- ksp->rx_buffers[buff_n].skb = NULL;
- }
- }
-}
-
-
-/**
- * ks8695_setup_irq - IRQ setup helper function
- * @irq: The IRQ number to claim
- * @irq_name: The name to give the IRQ claimant
- * @handler: The function to call to handle the IRQ
- * @ndev: The net_device to pass in as the dev_id argument to the handler
- *
- * Return 0 on success.
- */
-static int
-ks8695_setup_irq(int irq, const char *irq_name,
- irq_handler_t handler, struct net_device *ndev)
-{
- int ret;
-
- ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev);
-
- if (ret) {
- dev_err(&ndev->dev, "failure to request IRQ %d\n", irq);
- return ret;
- }
-
- return 0;
-}
-
-/**
- * ks8695_init_net - Initialise a KS8695 ethernet interface
- * @ksp: The interface to initialise
- *
- * This routine fills the RX ring, initialises the DMA engines,
- * allocates the IRQs and then starts the packet TX and RX
- * engines.
- */
-static int
-ks8695_init_net(struct ks8695_priv *ksp)
-{
- int ret;
- u32 ctrl;
-
- ks8695_refill_rxbuffers(ksp);
-
- /* Initialise the DMA engines */
- ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma);
- ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma);
-
- /* Request the IRQs */
- ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name,
- ks8695_rx_irq, ksp->ndev);
- if (ret)
- return ret;
- ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name,
- ks8695_tx_irq, ksp->ndev);
- if (ret)
- return ret;
- if (ksp->link_irq != -1) {
- ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name,
- ks8695_link_irq, ksp->ndev);
- if (ret)
- return ret;
- }
-
- /* Set up the ring indices */
- ksp->next_rx_desc_read = 0;
- ksp->tx_ring_next_slot = 0;
- ksp->tx_ring_used = 0;
-
- /* Bring up transmission */
- ctrl = ks8695_readreg(ksp, KS8695_DTXC);
- /* Enable packet transmission */
- ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE);
-
- /* Bring up the reception */
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
- /* Enable packet reception */
- ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE);
- /* And start the DMA engine */
- ks8695_writereg(ksp, KS8695_DRSC, 0);
-
- /* All done */
- return 0;
-}
-
-/**
- * ks8695_release_device - HW resource release for KS8695 e-net
- * @ksp: The device to be freed
- *
- * This unallocates io memory regions, dma-coherent regions etc
- * which were allocated in ks8695_probe.
- */
-static void
-ks8695_release_device(struct ks8695_priv *ksp)
-{
- /* Unmap the registers */
- iounmap(ksp->io_regs);
- if (ksp->phyiface_regs)
- iounmap(ksp->phyiface_regs);
-
- /* And release the request */
- release_resource(ksp->regs_req);
- kfree(ksp->regs_req);
- if (ksp->phyiface_req) {
- release_resource(ksp->phyiface_req);
- kfree(ksp->phyiface_req);
- }
-
- /* Free the ring buffers */
- dma_free_coherent(ksp->dev, RING_DMA_SIZE,
- ksp->ring_base, ksp->ring_base_dma);
-}
-
-/* Ethtool support */
-
-/**
- * ks8695_get_msglevel - Get the messages enabled for emission
- * @ndev: The network device to read from
- */
-static u32
-ks8695_get_msglevel(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- return ksp->msg_enable;
-}
-
-/**
- * ks8695_set_msglevel - Set the messages enabled for emission
- * @ndev: The network device to configure
- * @value: The messages to set for emission
- */
-static void
-ks8695_set_msglevel(struct net_device *ndev, u32 value)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- ksp->msg_enable = value;
-}
-
-/**
- * ks8695_wan_get_settings - Get device-specific settings.
- * @ndev: The network device to read settings from
- * @cmd: The ethtool structure to read into
- */
-static int
-ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- /* All ports on the KS8695 support these... */
- cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
- SUPPORTED_TP | SUPPORTED_MII);
- cmd->transceiver = XCVR_INTERNAL;
-
- cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
- cmd->port = PORT_MII;
- cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
- cmd->phy_address = 0;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
- if ((ctrl & WMC_WAND) == 0) {
- /* auto-negotiation is enabled */
- cmd->advertising |= ADVERTISED_Autoneg;
- if (ctrl & WMC_WANA100F)
- cmd->advertising |= ADVERTISED_100baseT_Full;
- if (ctrl & WMC_WANA100H)
- cmd->advertising |= ADVERTISED_100baseT_Half;
- if (ctrl & WMC_WANA10F)
- cmd->advertising |= ADVERTISED_10baseT_Full;
- if (ctrl & WMC_WANA10H)
- cmd->advertising |= ADVERTISED_10baseT_Half;
- if (ctrl & WMC_WANAP)
- cmd->advertising |= ADVERTISED_Pause;
- cmd->autoneg = AUTONEG_ENABLE;
-
- ethtool_cmd_speed_set(cmd,
- (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10);
- cmd->duplex = (ctrl & WMC_WDS) ?
- DUPLEX_FULL : DUPLEX_HALF;
- } else {
- /* auto-negotiation is disabled */
- cmd->autoneg = AUTONEG_DISABLE;
-
- ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ?
- SPEED_100 : SPEED_10));
- cmd->duplex = (ctrl & WMC_WANFF) ?
- DUPLEX_FULL : DUPLEX_HALF;
- }
-
- return 0;
-}
-
-/**
- * ks8695_wan_set_settings - Set device-specific settings.
- * @ndev: The network device to configure
- * @cmd: The settings to configure
- */
-static int
-ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- if ((cmd->speed != SPEED_10) && (cmd->speed != SPEED_100))
- return -EINVAL;
- if ((cmd->duplex != DUPLEX_HALF) && (cmd->duplex != DUPLEX_FULL))
- return -EINVAL;
- if (cmd->port != PORT_MII)
- return -EINVAL;
- if (cmd->transceiver != XCVR_INTERNAL)
- return -EINVAL;
- if ((cmd->autoneg != AUTONEG_DISABLE) &&
- (cmd->autoneg != AUTONEG_ENABLE))
- return -EINVAL;
-
- if (cmd->autoneg == AUTONEG_ENABLE) {
- if ((cmd->advertising & (ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full)) == 0)
- return -EINVAL;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
- WMC_WANA10F | WMC_WANA10H);
- if (cmd->advertising & ADVERTISED_100baseT_Full)
- ctrl |= WMC_WANA100F;
- if (cmd->advertising & ADVERTISED_100baseT_Half)
- ctrl |= WMC_WANA100H;
- if (cmd->advertising & ADVERTISED_10baseT_Full)
- ctrl |= WMC_WANA10F;
- if (cmd->advertising & ADVERTISED_10baseT_Half)
- ctrl |= WMC_WANA10H;
-
- /* force a re-negotiation */
- ctrl |= WMC_WANR;
- writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
- } else {
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- /* disable auto-negotiation */
- ctrl |= WMC_WAND;
- ctrl &= ~(WMC_WANF100 | WMC_WANFF);
-
- if (cmd->speed == SPEED_100)
- ctrl |= WMC_WANF100;
- if (cmd->duplex == DUPLEX_FULL)
- ctrl |= WMC_WANFF;
-
- writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
- }
-
- return 0;
-}
-
-/**
- * ks8695_wan_nwayreset - Restart the autonegotiation on the port.
- * @ndev: The network device to restart autoneotiation on
- */
-static int
-ks8695_wan_nwayreset(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- if ((ctrl & WMC_WAND) == 0)
- writel(ctrl | WMC_WANR,
- ksp->phyiface_regs + KS8695_WMC);
- else
- /* auto-negotiation not enabled */
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising
- * @ndev: The device to retrieve settings from
- * @param: The structure to fill out with the information
- */
-static void
-ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
- /* advertise Pause */
- param->autoneg = (ctrl & WMC_WANAP);
-
- /* current Rx Flow-control */
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
- param->rx_pause = (ctrl & DRXC_RFCE);
-
- /* current Tx Flow-control */
- ctrl = ks8695_readreg(ksp, KS8695_DTXC);
- param->tx_pause = (ctrl & DTXC_TFCE);
-}
-
-/**
- * ks8695_get_drvinfo - Retrieve driver information
- * @ndev: The network device to retrieve info about
- * @info: The info structure to fill out.
- */
-static void
-ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, MODULENAME, sizeof(info->driver));
- strlcpy(info->version, MODULEVERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev_name(ndev->dev.parent),
- sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops ks8695_ethtool_ops = {
- .get_msglevel = ks8695_get_msglevel,
- .set_msglevel = ks8695_set_msglevel,
- .get_drvinfo = ks8695_get_drvinfo,
-};
-
-static const struct ethtool_ops ks8695_wan_ethtool_ops = {
- .get_msglevel = ks8695_get_msglevel,
- .set_msglevel = ks8695_set_msglevel,
- .get_settings = ks8695_wan_get_settings,
- .set_settings = ks8695_wan_set_settings,
- .nway_reset = ks8695_wan_nwayreset,
- .get_link = ethtool_op_get_link,
- .get_pauseparam = ks8695_wan_get_pause,
- .get_drvinfo = ks8695_get_drvinfo,
-};
-
-/* Network device interface functions */
-
-/**
- * ks8695_set_mac - Update MAC in net dev and HW
- * @ndev: The network device to update
- * @addr: The new MAC address to set
- */
-static int
-ks8695_set_mac(struct net_device *ndev, void *addr)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- struct sockaddr *address = addr;
-
- if (!is_valid_ether_addr(address->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len);
-
- ks8695_update_mac(ksp);
-
- dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n",
- ndev->name, ndev->dev_addr);
-
- return 0;
-}
-
-/**
- * ks8695_set_multicast - Set up the multicast behaviour of the interface
- * @ndev: The net_device to configure
- *
- * This routine, called by the net layer, configures promiscuity
- * and multicast reception behaviour for the interface.
- */
-static void
-ks8695_set_multicast(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- u32 ctrl;
-
- ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-
- if (ndev->flags & IFF_PROMISC) {
- /* enable promiscuous mode */
- ctrl |= DRXC_RA;
- } else if (ndev->flags & ~IFF_PROMISC) {
- /* disable promiscuous mode */
- ctrl &= ~DRXC_RA;
- }
-
- if (ndev->flags & IFF_ALLMULTI) {
- /* enable all multicast mode */
- ctrl |= DRXC_RM;
- } else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) {
- /* more specific multicast addresses than can be
- * handled in hardware
- */
- ctrl |= DRXC_RM;
- } else {
- /* enable specific multicasts */
- ctrl &= ~DRXC_RM;
- ks8695_init_partial_multicast(ksp, ndev);
- }
-
- ks8695_writereg(ksp, KS8695_DRXC, ctrl);
-}
-
-/**
- * ks8695_timeout - Handle a network tx/rx timeout.
- * @ndev: The net_device which timed out.
- *
- * A network transaction timed out, reset the device.
- */
-static void
-ks8695_timeout(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- netif_stop_queue(ndev);
- ks8695_shutdown(ksp);
-
- ks8695_reset(ksp);
-
- ks8695_update_mac(ksp);
-
- /* We ignore the return from this since it managed to init
- * before it probably will be okay to init again.
- */
- ks8695_init_net(ksp);
-
- /* Reconfigure promiscuity etc */
- ks8695_set_multicast(ndev);
-
- /* And start the TX queue once more */
- netif_start_queue(ndev);
-}
-
-/**
- * ks8695_start_xmit - Start a packet transmission
- * @skb: The packet to transmit
- * @ndev: The network device to send the packet on
- *
- * This routine, called by the net layer, takes ownership of the
- * sk_buff and adds it to the TX ring. It then kicks the TX DMA
- * engine to ensure transmission begins.
- */
-static int
-ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- int buff_n;
- dma_addr_t dmap;
-
- spin_lock_irq(&ksp->txq_lock);
-
- if (ksp->tx_ring_used == MAX_TX_DESC) {
- /* Somehow we got entered when we have no room */
- spin_unlock_irq(&ksp->txq_lock);
- return NETDEV_TX_BUSY;
- }
-
- buff_n = ksp->tx_ring_next_slot;
-
- BUG_ON(ksp->tx_buffers[buff_n].skb);
-
- dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(ksp->dev, dmap))) {
- /* Failed to DMA map this SKB, give it back for now */
- spin_unlock_irq(&ksp->txq_lock);
- dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\
- "transmission, trying later\n", ndev->name);
- return NETDEV_TX_BUSY;
- }
-
- ksp->tx_buffers[buff_n].dma_ptr = dmap;
- /* Mapped okay, store the buffer pointer and length for later */
- ksp->tx_buffers[buff_n].skb = skb;
- ksp->tx_buffers[buff_n].length = skb->len;
-
- /* Fill out the TX descriptor */
- ksp->tx_ring[buff_n].data_ptr =
- cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr);
- ksp->tx_ring[buff_n].status =
- cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
- (skb->len & TDES_TBS));
-
- wmb();
-
- /* Hand it over to the hardware */
- ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN);
-
- if (++ksp->tx_ring_used == MAX_TX_DESC)
- netif_stop_queue(ndev);
-
- /* Kick the TX DMA in case it decided to go IDLE */
- ks8695_writereg(ksp, KS8695_DTSC, 0);
-
- /* And update the next ring slot */
- ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK;
-
- spin_unlock_irq(&ksp->txq_lock);
- return NETDEV_TX_OK;
-}
-
-/**
- * ks8695_stop - Stop (shutdown) a KS8695 ethernet interface
- * @ndev: The net_device to stop
- *
- * This disables the TX queue and cleans up a KS8695 ethernet
- * device.
- */
-static int
-ks8695_stop(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- netif_stop_queue(ndev);
- napi_disable(&ksp->napi);
-
- ks8695_shutdown(ksp);
-
- return 0;
-}
-
-/**
- * ks8695_open - Open (bring up) a KS8695 ethernet interface
- * @ndev: The net_device to open
- *
- * This resets, configures the MAC, initialises the RX ring and
- * DMA engines and starts the TX queue for a KS8695 ethernet
- * device.
- */
-static int
-ks8695_open(struct net_device *ndev)
-{
- struct ks8695_priv *ksp = netdev_priv(ndev);
- int ret;
-
- if (!is_valid_ether_addr(ndev->dev_addr))
- return -EADDRNOTAVAIL;
-
- ks8695_reset(ksp);
-
- ks8695_update_mac(ksp);
-
- ret = ks8695_init_net(ksp);
- if (ret) {
- ks8695_shutdown(ksp);
- return ret;
- }
-
- napi_enable(&ksp->napi);
- netif_start_queue(ndev);
-
- return 0;
-}
-
-/* Platform device driver */
-
-/**
- * ks8695_init_switch - Init LAN switch to known good defaults.
- * @ksp: The device to initialise
- *
- * This initialises the LAN switch in the KS8695 to a known-good
- * set of defaults.
- */
-static void __devinit
-ks8695_init_switch(struct ks8695_priv *ksp)
-{
- u32 ctrl;
-
- /* Default value for SEC0 according to datasheet */
- ctrl = 0x40819e00;
-
- /* LED0 = Speed LED1 = Link/Activity */
- ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S);
- ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY);
-
- /* Enable Switch */
- ctrl |= SEC0_ENABLE;
-
- writel(ctrl, ksp->phyiface_regs + KS8695_SEC0);
-
- /* Defaults for SEC1 */
- writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1);
-}
-
-/**
- * ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults
- * @ksp: The device to initialise
- *
- * This initialises a KS8695's WAN phy to sensible values for
- * autonegotiation etc.
- */
-static void __devinit
-ks8695_init_wan_phy(struct ks8695_priv *ksp)
-{
- u32 ctrl;
-
- /* Support auto-negotiation */
- ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H |
- WMC_WANA10F | WMC_WANA10H);
-
- /* LED0 = Activity , LED1 = Link */
- ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK);
-
- /* Restart Auto-negotiation */
- ctrl |= WMC_WANR;
-
- writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-
- writel(0, ksp->phyiface_regs + KS8695_WPPM);
- writel(0, ksp->phyiface_regs + KS8695_PPS);
-}
-
-static const struct net_device_ops ks8695_netdev_ops = {
- .ndo_open = ks8695_open,
- .ndo_stop = ks8695_stop,
- .ndo_start_xmit = ks8695_start_xmit,
- .ndo_tx_timeout = ks8695_timeout,
- .ndo_set_mac_address = ks8695_set_mac,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = ks8695_set_multicast,
-};
-
-/**
- * ks8695_probe - Probe and initialise a KS8695 ethernet interface
- * @pdev: The platform device to probe
- *
- * Initialise a KS8695 ethernet device from platform data.
- *
- * This driver requires at least one IORESOURCE_MEM for the
- * registers and two IORESOURCE_IRQ for the RX and TX IRQs
- * respectively. It can optionally take an additional
- * IORESOURCE_MEM for the switch or phy in the case of the lan or
- * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
- * port.
- */
-static int __devinit
-ks8695_probe(struct platform_device *pdev)
-{
- struct ks8695_priv *ksp;
- struct net_device *ndev;
- struct resource *regs_res, *phyiface_res;
- struct resource *rxirq_res, *txirq_res, *linkirq_res;
- int ret = 0;
- int buff_n;
- u32 machigh, maclow;
-
- /* Initialise a net_device */
- ndev = alloc_etherdev(sizeof(struct ks8695_priv));
- if (!ndev) {
- dev_err(&pdev->dev, "could not allocate device.\n");
- return -ENOMEM;
- }
-
- SET_NETDEV_DEV(ndev, &pdev->dev);
-
- dev_dbg(&pdev->dev, "ks8695_probe() called\n");
-
- /* Configure our private structure a little */
- ksp = netdev_priv(ndev);
-
- ksp->dev = &pdev->dev;
- ksp->ndev = ndev;
- ksp->msg_enable = NETIF_MSG_LINK;
-
- /* Retrieve resources */
- regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
- rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
- linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
-
- if (!(regs_res && rxirq_res && txirq_res)) {
- dev_err(ksp->dev, "insufficient resources\n");
- ret = -ENOENT;
- goto failure;
- }
-
- ksp->regs_req = request_mem_region(regs_res->start,
- resource_size(regs_res),
- pdev->name);
-
- if (!ksp->regs_req) {
- dev_err(ksp->dev, "cannot claim register space\n");
- ret = -EIO;
- goto failure;
- }
-
- ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res));
-
- if (!ksp->io_regs) {
- dev_err(ksp->dev, "failed to ioremap registers\n");
- ret = -EINVAL;
- goto failure;
- }
-
- if (phyiface_res) {
- ksp->phyiface_req =
- request_mem_region(phyiface_res->start,
- resource_size(phyiface_res),
- phyiface_res->name);
-
- if (!ksp->phyiface_req) {
- dev_err(ksp->dev,
- "cannot claim switch register space\n");
- ret = -EIO;
- goto failure;
- }
-
- ksp->phyiface_regs = ioremap(phyiface_res->start,
- resource_size(phyiface_res));
-
- if (!ksp->phyiface_regs) {
- dev_err(ksp->dev,
- "failed to ioremap switch registers\n");
- ret = -EINVAL;
- goto failure;
- }
- }
-
- ksp->rx_irq = rxirq_res->start;
- ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX";
- ksp->tx_irq = txirq_res->start;
- ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX";
- ksp->link_irq = (linkirq_res ? linkirq_res->start : -1);
- ksp->link_irq_name = (linkirq_res && linkirq_res->name) ?
- linkirq_res->name : "Ethernet Link";
-
- /* driver system setup */
- ndev->netdev_ops = &ks8695_netdev_ops;
- ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
-
- netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT);
-
- /* Retrieve the default MAC addr from the chip. */
- /* The bootloader should have left it in there for us. */
-
- machigh = ks8695_readreg(ksp, KS8695_MAH);
- maclow = ks8695_readreg(ksp, KS8695_MAL);
-
- ndev->dev_addr[0] = (machigh >> 8) & 0xFF;
- ndev->dev_addr[1] = machigh & 0xFF;
- ndev->dev_addr[2] = (maclow >> 24) & 0xFF;
- ndev->dev_addr[3] = (maclow >> 16) & 0xFF;
- ndev->dev_addr[4] = (maclow >> 8) & 0xFF;
- ndev->dev_addr[5] = maclow & 0xFF;
-
- if (!is_valid_ether_addr(ndev->dev_addr))
- dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please "
- "set using ifconfig\n", ndev->name);
-
- /* In order to be efficient memory-wise, we allocate both
- * rings in one go.
- */
- ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE,
- &ksp->ring_base_dma, GFP_KERNEL);
- if (!ksp->ring_base) {
- ret = -ENOMEM;
- goto failure;
- }
-
- /* Specify the TX DMA ring buffer */
- ksp->tx_ring = ksp->ring_base;
- ksp->tx_ring_dma = ksp->ring_base_dma;
-
- /* And initialise the queue's lock */
- spin_lock_init(&ksp->txq_lock);
- spin_lock_init(&ksp->rx_lock);
-
- /* Specify the RX DMA ring buffer */
- ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
- ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE;
-
- /* Zero the descriptor rings */
- memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE);
- memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE);
-
- /* Build the rings */
- for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
- ksp->tx_ring[buff_n].next_desc =
- cpu_to_le32(ksp->tx_ring_dma +
- (sizeof(struct tx_ring_desc) *
- ((buff_n + 1) & MAX_TX_DESC_MASK)));
- }
-
- for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
- ksp->rx_ring[buff_n].next_desc =
- cpu_to_le32(ksp->rx_ring_dma +
- (sizeof(struct rx_ring_desc) *
- ((buff_n + 1) & MAX_RX_DESC_MASK)));
- }
-
- /* Initialise the port (physically) */
- if (ksp->phyiface_regs && ksp->link_irq == -1) {
- ks8695_init_switch(ksp);
- ksp->dtype = KS8695_DTYPE_LAN;
- SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
- } else if (ksp->phyiface_regs && ksp->link_irq != -1) {
- ks8695_init_wan_phy(ksp);
- ksp->dtype = KS8695_DTYPE_WAN;
- SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops);
- } else {
- /* No initialisation since HPNA does not have a PHY */
- ksp->dtype = KS8695_DTYPE_HPNA;
- SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
- }
-
- /* And bring up the net_device with the net core */
- platform_set_drvdata(pdev, ndev);
- ret = register_netdev(ndev);
-
- if (ret == 0) {
- dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n",
- ks8695_port_type(ksp), ndev->dev_addr);
- } else {
- /* Report the failure to register the net_device */
- dev_err(ksp->dev, "ks8695net: failed to register netdev.\n");
- goto failure;
- }
-
- /* All is well */
- return 0;
-
- /* Error exit path */
-failure:
- ks8695_release_device(ksp);
- free_netdev(ndev);
-
- return ret;
-}
-
-/**
- * ks8695_drv_suspend - Suspend a KS8695 ethernet platform device.
- * @pdev: The device to suspend
- * @state: The suspend state
- *
- * This routine detaches and shuts down a KS8695 ethernet device.
- */
-static int
-ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- ksp->in_suspend = 1;
-
- if (netif_running(ndev)) {
- netif_device_detach(ndev);
- ks8695_shutdown(ksp);
- }
-
- return 0;
-}
-
-/**
- * ks8695_drv_resume - Resume a KS8695 ethernet platform device.
- * @pdev: The device to resume
- *
- * This routine re-initialises and re-attaches a KS8695 ethernet
- * device.
- */
-static int
-ks8695_drv_resume(struct platform_device *pdev)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- if (netif_running(ndev)) {
- ks8695_reset(ksp);
- ks8695_init_net(ksp);
- ks8695_set_multicast(ndev);
- netif_device_attach(ndev);
- }
-
- ksp->in_suspend = 0;
-
- return 0;
-}
-
-/**
- * ks8695_drv_remove - Remove a KS8695 net device on driver unload.
- * @pdev: The platform device to remove
- *
- * This unregisters and releases a KS8695 ethernet device.
- */
-static int __devexit
-ks8695_drv_remove(struct platform_device *pdev)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ks8695_priv *ksp = netdev_priv(ndev);
-
- platform_set_drvdata(pdev, NULL);
- netif_napi_del(&ksp->napi);
-
- unregister_netdev(ndev);
- ks8695_release_device(ksp);
- free_netdev(ndev);
-
- dev_dbg(&pdev->dev, "released and freed device\n");
- return 0;
-}
-
-static struct platform_driver ks8695_driver = {
- .driver = {
- .name = MODULENAME,
- .owner = THIS_MODULE,
- },
- .probe = ks8695_probe,
- .remove = __devexit_p(ks8695_drv_remove),
- .suspend = ks8695_drv_suspend,
- .resume = ks8695_drv_resume,
-};
-
-/* Module interface */
-
-static int __init
-ks8695_init(void)
-{
- printk(KERN_INFO "%s Ethernet driver, V%s\n",
- MODULENAME, MODULEVERSION);
-
- return platform_driver_register(&ks8695_driver);
-}
-
-static void __exit
-ks8695_cleanup(void)
-{
- platform_driver_unregister(&ks8695_driver);
-}
-
-module_init(ks8695_init);
-module_exit(ks8695_cleanup);
-
-MODULE_AUTHOR("Simtec Electronics");
-MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" MODULENAME);
-
-module_param(watchdog, int, 0400);
-MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
diff --git a/drivers/net/arm/ks8695net.h b/drivers/net/arm/ks8695net.h
deleted file mode 100644
index 80eff6ea5163..000000000000
--- a/drivers/net/arm/ks8695net.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * Copyright 2008 Simtec Electronics
- * Daniel Silverstone <dsilvers@simtec.co.uk>
- * Vincent Sanders <vince@simtec.co.uk>
- */
-
-#ifndef KS8695NET_H
-#define KS8695NET_H
-
-/* Receive descriptor flags */
-#define RDES_OWN (1 << 31) /* Ownership */
-#define RDES_FS (1 << 30) /* First Descriptor */
-#define RDES_LS (1 << 29) /* Last Descriptor */
-#define RDES_IPE (1 << 28) /* IP Checksum error */
-#define RDES_TCPE (1 << 27) /* TCP Checksum error */
-#define RDES_UDPE (1 << 26) /* UDP Checksum error */
-#define RDES_ES (1 << 25) /* Error summary */
-#define RDES_MF (1 << 24) /* Multicast Frame */
-#define RDES_RE (1 << 19) /* MII Error reported */
-#define RDES_TL (1 << 18) /* Frame too Long */
-#define RDES_RF (1 << 17) /* Runt Frame */
-#define RDES_CE (1 << 16) /* CRC error */
-#define RDES_FT (1 << 15) /* Frame Type */
-#define RDES_FLEN (0x7ff) /* Frame Length */
-
-#define RDES_RER (1 << 25) /* Receive End of Ring */
-#define RDES_RBS (0x7ff) /* Receive Buffer Size */
-
-/* Transmit descriptor flags */
-
-#define TDES_OWN (1 << 31) /* Ownership */
-
-#define TDES_IC (1 << 31) /* Interrupt on Completion */
-#define TDES_FS (1 << 30) /* First Segment */
-#define TDES_LS (1 << 29) /* Last Segment */
-#define TDES_IPCKG (1 << 28) /* IP Checksum generate */
-#define TDES_TCPCKG (1 << 27) /* TCP Checksum generate */
-#define TDES_UDPCKG (1 << 26) /* UDP Checksum generate */
-#define TDES_TER (1 << 25) /* Transmit End of Ring */
-#define TDES_TBS (0x7ff) /* Transmit Buffer Size */
-
-/*
- * Network controller register offsets
- */
-#define KS8695_DTXC (0x00) /* DMA Transmit Control */
-#define KS8695_DRXC (0x04) /* DMA Receive Control */
-#define KS8695_DTSC (0x08) /* DMA Transmit Start Command */
-#define KS8695_DRSC (0x0c) /* DMA Receive Start Command */
-#define KS8695_TDLB (0x10) /* Transmit Descriptor List
- * Base Address
- */
-#define KS8695_RDLB (0x14) /* Receive Descriptor List
- * Base Address
- */
-#define KS8695_MAL (0x18) /* MAC Station Address Low */
-#define KS8695_MAH (0x1c) /* MAC Station Address High */
-#define KS8695_AAL_(n) (0x80 + ((n)*8)) /* MAC Additional
- * Station Address
- * (0..15) Low
- */
-#define KS8695_AAH_(n) (0x84 + ((n)*8)) /* MAC Additional
- * Station Address
- * (0..15) High
- */
-
-
-/* DMA Transmit Control Register */
-#define DTXC_TRST (1 << 31) /* Soft Reset */
-#define DTXC_TBS (0x3f << 24) /* Transmit Burst Size */
-#define DTXC_TUCG (1 << 18) /* Transmit UDP
- * Checksum Generate
- */
-#define DTXC_TTCG (1 << 17) /* Transmit TCP
- * Checksum Generate
- */
-#define DTXC_TICG (1 << 16) /* Transmit IP
- * Checksum Generate
- */
-#define DTXC_TFCE (1 << 9) /* Transmit Flow
- * Control Enable
- */
-#define DTXC_TLB (1 << 8) /* Loopback mode */
-#define DTXC_TEP (1 << 2) /* Transmit Enable Padding */
-#define DTXC_TAC (1 << 1) /* Transmit Add CRC */
-#define DTXC_TE (1 << 0) /* TX Enable */
-
-/* DMA Receive Control Register */
-#define DRXC_RBS (0x3f << 24) /* Receive Burst Size */
-#define DRXC_RUCC (1 << 18) /* Receive UDP Checksum check */
-#define DRXC_RTCG (1 << 17) /* Receive TCP Checksum check */
-#define DRXC_RICG (1 << 16) /* Receive IP Checksum check */
-#define DRXC_RFCE (1 << 9) /* Receive Flow Control
- * Enable
- */
-#define DRXC_RB (1 << 6) /* Receive Broadcast */
-#define DRXC_RM (1 << 5) /* Receive Multicast */
-#define DRXC_RU (1 << 4) /* Receive Unicast */
-#define DRXC_RERR (1 << 3) /* Receive Error Frame */
-#define DRXC_RA (1 << 2) /* Receive All */
-#define DRXC_RE (1 << 0) /* RX Enable */
-
-/* Additional Station Address High */
-#define AAH_E (1 << 31) /* Address Enabled */
-
-#endif /* KS8695NET_H */
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
deleted file mode 100644
index bfea499a3513..000000000000
--- a/drivers/net/arm/w90p910_ether.c
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * 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;version 2 of the License.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#define DRV_MODULE_NAME "w90p910-emc"
-#define DRV_MODULE_VERSION "0.1"
-
-/* Ethernet MAC Registers */
-#define REG_CAMCMR 0x00
-#define REG_CAMEN 0x04
-#define REG_CAMM_BASE 0x08
-#define REG_CAML_BASE 0x0c
-#define REG_TXDLSA 0x88
-#define REG_RXDLSA 0x8C
-#define REG_MCMDR 0x90
-#define REG_MIID 0x94
-#define REG_MIIDA 0x98
-#define REG_FFTCR 0x9C
-#define REG_TSDR 0xa0
-#define REG_RSDR 0xa4
-#define REG_DMARFC 0xa8
-#define REG_MIEN 0xac
-#define REG_MISTA 0xb0
-#define REG_CTXDSA 0xcc
-#define REG_CTXBSA 0xd0
-#define REG_CRXDSA 0xd4
-#define REG_CRXBSA 0xd8
-
-/* mac controller bit */
-#define MCMDR_RXON 0x01
-#define MCMDR_ACP (0x01 << 3)
-#define MCMDR_SPCRC (0x01 << 5)
-#define MCMDR_TXON (0x01 << 8)
-#define MCMDR_FDUP (0x01 << 18)
-#define MCMDR_ENMDC (0x01 << 19)
-#define MCMDR_OPMOD (0x01 << 20)
-#define SWR (0x01 << 24)
-
-/* cam command regiser */
-#define CAMCMR_AUP 0x01
-#define CAMCMR_AMP (0x01 << 1)
-#define CAMCMR_ABP (0x01 << 2)
-#define CAMCMR_CCAM (0x01 << 3)
-#define CAMCMR_ECMP (0x01 << 4)
-#define CAM0EN 0x01
-
-/* mac mii controller bit */
-#define MDCCR (0x0a << 20)
-#define PHYAD (0x01 << 8)
-#define PHYWR (0x01 << 16)
-#define PHYBUSY (0x01 << 17)
-#define PHYPRESP (0x01 << 18)
-#define CAM_ENTRY_SIZE 0x08
-
-/* rx and tx status */
-#define TXDS_TXCP (0x01 << 19)
-#define RXDS_CRCE (0x01 << 17)
-#define RXDS_PTLE (0x01 << 19)
-#define RXDS_RXGD (0x01 << 20)
-#define RXDS_ALIE (0x01 << 21)
-#define RXDS_RP (0x01 << 22)
-
-/* mac interrupt status*/
-#define MISTA_EXDEF (0x01 << 19)
-#define MISTA_TXBERR (0x01 << 24)
-#define MISTA_TDU (0x01 << 23)
-#define MISTA_RDU (0x01 << 10)
-#define MISTA_RXBERR (0x01 << 11)
-
-#define ENSTART 0x01
-#define ENRXINTR 0x01
-#define ENRXGD (0x01 << 4)
-#define ENRXBERR (0x01 << 11)
-#define ENTXINTR (0x01 << 16)
-#define ENTXCP (0x01 << 18)
-#define ENTXABT (0x01 << 21)
-#define ENTXBERR (0x01 << 24)
-#define ENMDC (0x01 << 19)
-#define PHYBUSY (0x01 << 17)
-#define MDCCR_VAL 0xa00000
-
-/* rx and tx owner bit */
-#define RX_OWEN_DMA (0x01 << 31)
-#define RX_OWEN_CPU (~(0x03 << 30))
-#define TX_OWEN_DMA (0x01 << 31)
-#define TX_OWEN_CPU (~(0x01 << 31))
-
-/* tx frame desc controller bit */
-#define MACTXINTEN 0x04
-#define CRCMODE 0x02
-#define PADDINGMODE 0x01
-
-/* fftcr controller bit */
-#define TXTHD (0x03 << 8)
-#define BLENGTH (0x01 << 20)
-
-/* global setting for driver */
-#define RX_DESC_SIZE 50
-#define TX_DESC_SIZE 10
-#define MAX_RBUFF_SZ 0x600
-#define MAX_TBUFF_SZ 0x600
-#define TX_TIMEOUT (HZ/2)
-#define DELAY 1000
-#define CAM0 0x0
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
-
-struct w90p910_rxbd {
- unsigned int sl;
- unsigned int buffer;
- unsigned int reserved;
- unsigned int next;
-};
-
-struct w90p910_txbd {
- unsigned int mode;
- unsigned int buffer;
- unsigned int sl;
- unsigned int next;
-};
-
-struct recv_pdesc {
- struct w90p910_rxbd desclist[RX_DESC_SIZE];
- char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
-};
-
-struct tran_pdesc {
- struct w90p910_txbd desclist[TX_DESC_SIZE];
- char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
-};
-
-struct w90p910_ether {
- struct recv_pdesc *rdesc;
- struct tran_pdesc *tdesc;
- dma_addr_t rdesc_phys;
- dma_addr_t tdesc_phys;
- struct net_device_stats stats;
- struct platform_device *pdev;
- struct resource *res;
- struct sk_buff *skb;
- struct clk *clk;
- struct clk *rmiiclk;
- struct mii_if_info mii;
- struct timer_list check_timer;
- void __iomem *reg;
- int rxirq;
- int txirq;
- unsigned int cur_tx;
- unsigned int cur_rx;
- unsigned int finish_tx;
- unsigned int rx_packets;
- unsigned int rx_bytes;
- unsigned int start_tx_ptr;
- unsigned int start_rx_ptr;
- unsigned int linkflag;
-};
-
-static void update_linkspeed_register(struct net_device *dev,
- unsigned int speed, unsigned int duplex)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
-
- if (speed == SPEED_100) {
- /* 100 full/half duplex */
- if (duplex == DUPLEX_FULL) {
- val |= (MCMDR_OPMOD | MCMDR_FDUP);
- } else {
- val |= MCMDR_OPMOD;
- val &= ~MCMDR_FDUP;
- }
- } else {
- /* 10 full/half duplex */
- if (duplex == DUPLEX_FULL) {
- val |= MCMDR_FDUP;
- val &= ~MCMDR_OPMOD;
- } else {
- val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
- }
- }
-
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void update_linkspeed(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- unsigned int bmsr, bmcr, lpa, speed, duplex;
-
- pdev = ether->pdev;
-
- if (!mii_link_ok(&ether->mii)) {
- ether->linkflag = 0x0;
- netif_carrier_off(dev);
- dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
- return;
- }
-
- if (ether->linkflag == 1)
- return;
-
- bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
- bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
-
- if (bmcr & BMCR_ANENABLE) {
- if (!(bmsr & BMSR_ANEGCOMPLETE))
- return;
-
- lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA);
-
- if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
- speed = SPEED_100;
- else
- speed = SPEED_10;
-
- if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
- duplex = DUPLEX_FULL;
- else
- duplex = DUPLEX_HALF;
-
- } else {
- speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
- duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
- }
-
- update_linkspeed_register(dev, speed, duplex);
-
- dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
- (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
- ether->linkflag = 0x01;
-
- netif_carrier_on(dev);
-}
-
-static void w90p910_check_link(unsigned long dev_id)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct w90p910_ether *ether = netdev_priv(dev);
-
- update_linkspeed(dev);
- mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
-}
-
-static void w90p910_write_cam(struct net_device *dev,
- unsigned int x, unsigned char *pval)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int msw, lsw;
-
- msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
-
- lsw = (pval[4] << 24) | (pval[5] << 16);
-
- __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
- __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
-}
-
-static int w90p910_init_desc(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- struct w90p910_txbd *tdesc;
- struct w90p910_rxbd *rdesc;
- struct platform_device *pdev;
- unsigned int i;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- ether->tdesc = (struct tran_pdesc *)
- dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
- &ether->tdesc_phys, GFP_KERNEL);
-
- if (!ether->tdesc) {
- dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n");
- return -ENOMEM;
- }
-
- ether->rdesc = (struct recv_pdesc *)
- dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
- &ether->rdesc_phys, GFP_KERNEL);
-
- if (!ether->rdesc) {
- dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n");
- dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
- ether->tdesc, ether->tdesc_phys);
- return -ENOMEM;
- }
-
- for (i = 0; i < TX_DESC_SIZE; i++) {
- unsigned int offset;
-
- tdesc = &(ether->tdesc->desclist[i]);
-
- if (i == TX_DESC_SIZE - 1)
- offset = offsetof(struct tran_pdesc, desclist[0]);
- else
- offset = offsetof(struct tran_pdesc, desclist[i + 1]);
-
- tdesc->next = ether->tdesc_phys + offset;
- tdesc->buffer = ether->tdesc_phys +
- offsetof(struct tran_pdesc, tran_buf[i]);
- tdesc->sl = 0;
- tdesc->mode = 0;
- }
-
- ether->start_tx_ptr = ether->tdesc_phys;
-
- for (i = 0; i < RX_DESC_SIZE; i++) {
- unsigned int offset;
-
- rdesc = &(ether->rdesc->desclist[i]);
-
- if (i == RX_DESC_SIZE - 1)
- offset = offsetof(struct recv_pdesc, desclist[0]);
- else
- offset = offsetof(struct recv_pdesc, desclist[i + 1]);
-
- rdesc->next = ether->rdesc_phys + offset;
- rdesc->sl = RX_OWEN_DMA;
- rdesc->buffer = ether->rdesc_phys +
- offsetof(struct recv_pdesc, recv_buf[i]);
- }
-
- ether->start_rx_ptr = ether->rdesc_phys;
-
- return 0;
-}
-
-static void w90p910_set_fifo_threshold(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = TXTHD | BLENGTH;
- __raw_writel(val, ether->reg + REG_FFTCR);
-}
-
-static void w90p910_return_default_idle(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
- val |= SWR;
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_trigger_rx(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- __raw_writel(ENSTART, ether->reg + REG_RSDR);
-}
-
-static void w90p910_trigger_tx(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- __raw_writel(ENSTART, ether->reg + REG_TSDR);
-}
-
-static void w90p910_enable_mac_interrupt(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
- val |= ENTXBERR | ENRXBERR | ENTXABT;
-
- __raw_writel(val, ether->reg + REG_MIEN);
-}
-
-static void w90p910_get_and_clear_int(struct net_device *dev,
- unsigned int *val)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- *val = __raw_readl(ether->reg + REG_MISTA);
- __raw_writel(*val, ether->reg + REG_MISTA);
-}
-
-static void w90p910_set_global_maccmd(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
- val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_cam(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
- val = __raw_readl(ether->reg + REG_CAMEN);
- val |= CAM0EN;
- __raw_writel(val, ether->reg + REG_CAMEN);
-}
-
-static void w90p910_enable_cam_command(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
- __raw_writel(val, ether->reg + REG_CAMCMR);
-}
-
-static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
-
- if (enable)
- val |= MCMDR_TXON;
- else
- val &= ~MCMDR_TXON;
-
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- unsigned int val;
-
- val = __raw_readl(ether->reg + REG_MCMDR);
-
- if (enable)
- val |= MCMDR_RXON;
- else
- val &= ~MCMDR_RXON;
-
- __raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_set_curdest(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
- __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
-}
-
-static void w90p910_reset_mac(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- w90p910_enable_tx(dev, 0);
- w90p910_enable_rx(dev, 0);
- w90p910_set_fifo_threshold(dev);
- w90p910_return_default_idle(dev);
-
- if (!netif_queue_stopped(dev))
- netif_stop_queue(dev);
-
- w90p910_init_desc(dev);
-
- dev->trans_start = jiffies; /* prevent tx timeout */
- ether->cur_tx = 0x0;
- ether->finish_tx = 0x0;
- ether->cur_rx = 0x0;
-
- w90p910_set_curdest(dev);
- w90p910_enable_cam(dev);
- w90p910_enable_cam_command(dev);
- w90p910_enable_mac_interrupt(dev);
- w90p910_enable_tx(dev, 1);
- w90p910_enable_rx(dev, 1);
- w90p910_trigger_tx(dev);
- w90p910_trigger_rx(dev);
-
- dev->trans_start = jiffies; /* prevent tx timeout */
-
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
-}
-
-static void w90p910_mdio_write(struct net_device *dev,
- int phy_id, int reg, int data)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- unsigned int val, i;
-
- pdev = ether->pdev;
-
- __raw_writel(data, ether->reg + REG_MIID);
-
- val = (phy_id << 0x08) | reg;
- val |= PHYBUSY | PHYWR | MDCCR_VAL;
- __raw_writel(val, ether->reg + REG_MIIDA);
-
- for (i = 0; i < DELAY; i++) {
- if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
- break;
- }
-
- if (i == DELAY)
- dev_warn(&pdev->dev, "mdio write timed out\n");
-}
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- unsigned int val, i, data;
-
- pdev = ether->pdev;
-
- val = (phy_id << 0x08) | reg;
- val |= PHYBUSY | MDCCR_VAL;
- __raw_writel(val, ether->reg + REG_MIIDA);
-
- for (i = 0; i < DELAY; i++) {
- if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
- break;
- }
-
- if (i == DELAY) {
- dev_warn(&pdev->dev, "mdio read timed out\n");
- data = 0xffff;
- } else {
- data = __raw_readl(ether->reg + REG_MIID);
- }
-
- return data;
-}
-
-static int w90p910_set_mac_address(struct net_device *dev, void *addr)
-{
- struct sockaddr *address = addr;
-
- if (!is_valid_ether_addr(address->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
- w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
- return 0;
-}
-
-static int w90p910_ether_close(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
-
- pdev = ether->pdev;
-
- dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
- ether->rdesc, ether->rdesc_phys);
- dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
- ether->tdesc, ether->tdesc_phys);
-
- netif_stop_queue(dev);
-
- del_timer_sync(&ether->check_timer);
- clk_disable(ether->rmiiclk);
- clk_disable(ether->clk);
-
- free_irq(ether->txirq, dev);
- free_irq(ether->rxirq, dev);
-
- return 0;
-}
-
-static struct net_device_stats *w90p910_ether_stats(struct net_device *dev)
-{
- struct w90p910_ether *ether;
-
- ether = netdev_priv(dev);
-
- return &ether->stats;
-}
-
-static int w90p910_send_frame(struct net_device *dev,
- unsigned char *data, int length)
-{
- struct w90p910_ether *ether;
- struct w90p910_txbd *txbd;
- struct platform_device *pdev;
- unsigned char *buffer;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- txbd = &ether->tdesc->desclist[ether->cur_tx];
- buffer = ether->tdesc->tran_buf[ether->cur_tx];
-
- if (length > 1514) {
- dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
- length = 1514;
- }
-
- txbd->sl = length & 0xFFFF;
-
- memcpy(buffer, data, length);
-
- txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
-
- w90p910_enable_tx(dev, 1);
-
- w90p910_trigger_tx(dev);
-
- if (++ether->cur_tx >= TX_DESC_SIZE)
- ether->cur_tx = 0;
-
- txbd = &ether->tdesc->desclist[ether->cur_tx];
-
- if (txbd->mode & TX_OWEN_DMA)
- netif_stop_queue(dev);
-
- return 0;
-}
-
-static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
- ether->skb = skb;
- dev_kfree_skb_irq(skb);
- return 0;
- }
- return -EAGAIN;
-}
-
-static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
-{
- struct w90p910_ether *ether;
- struct w90p910_txbd *txbd;
- struct platform_device *pdev;
- struct net_device *dev;
- unsigned int cur_entry, entry, status;
-
- dev = dev_id;
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- w90p910_get_and_clear_int(dev, &status);
-
- cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
-
- entry = ether->tdesc_phys +
- offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
-
- while (entry != cur_entry) {
- txbd = &ether->tdesc->desclist[ether->finish_tx];
-
- if (++ether->finish_tx >= TX_DESC_SIZE)
- ether->finish_tx = 0;
-
- if (txbd->sl & TXDS_TXCP) {
- ether->stats.tx_packets++;
- ether->stats.tx_bytes += txbd->sl & 0xFFFF;
- } else {
- ether->stats.tx_errors++;
- }
-
- txbd->sl = 0x0;
- txbd->mode = 0x0;
-
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
-
- entry = ether->tdesc_phys +
- offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
- }
-
- if (status & MISTA_EXDEF) {
- dev_err(&pdev->dev, "emc defer exceed interrupt\n");
- } else if (status & MISTA_TXBERR) {
- dev_err(&pdev->dev, "emc bus error interrupt\n");
- w90p910_reset_mac(dev);
- } else if (status & MISTA_TDU) {
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
- }
-
- return IRQ_HANDLED;
-}
-
-static void netdev_rx(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- struct w90p910_rxbd *rxbd;
- struct platform_device *pdev;
- struct sk_buff *skb;
- unsigned char *data;
- unsigned int length, status, val, entry;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
- do {
- val = __raw_readl(ether->reg + REG_CRXDSA);
-
- entry = ether->rdesc_phys +
- offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
-
- if (val == entry)
- break;
-
- status = rxbd->sl;
- length = status & 0xFFFF;
-
- if (status & RXDS_RXGD) {
- data = ether->rdesc->recv_buf[ether->cur_rx];
- skb = dev_alloc_skb(length+2);
- if (!skb) {
- dev_err(&pdev->dev, "get skb buffer error\n");
- ether->stats.rx_dropped++;
- return;
- }
-
- skb_reserve(skb, 2);
- skb_put(skb, length);
- skb_copy_to_linear_data(skb, data, length);
- skb->protocol = eth_type_trans(skb, dev);
- ether->stats.rx_packets++;
- ether->stats.rx_bytes += length;
- netif_rx(skb);
- } else {
- ether->stats.rx_errors++;
-
- if (status & RXDS_RP) {
- dev_err(&pdev->dev, "rx runt err\n");
- ether->stats.rx_length_errors++;
- } else if (status & RXDS_CRCE) {
- dev_err(&pdev->dev, "rx crc err\n");
- ether->stats.rx_crc_errors++;
- } else if (status & RXDS_ALIE) {
- dev_err(&pdev->dev, "rx aligment err\n");
- ether->stats.rx_frame_errors++;
- } else if (status & RXDS_PTLE) {
- dev_err(&pdev->dev, "rx longer err\n");
- ether->stats.rx_over_errors++;
- }
- }
-
- rxbd->sl = RX_OWEN_DMA;
- rxbd->reserved = 0x0;
-
- if (++ether->cur_rx >= RX_DESC_SIZE)
- ether->cur_rx = 0;
-
- rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
- } while (1);
-}
-
-static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev;
- struct w90p910_ether *ether;
- struct platform_device *pdev;
- unsigned int status;
-
- dev = dev_id;
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- w90p910_get_and_clear_int(dev, &status);
-
- if (status & MISTA_RDU) {
- netdev_rx(dev);
- w90p910_trigger_rx(dev);
-
- return IRQ_HANDLED;
- } else if (status & MISTA_RXBERR) {
- dev_err(&pdev->dev, "emc rx bus error\n");
- w90p910_reset_mac(dev);
- }
-
- netdev_rx(dev);
- return IRQ_HANDLED;
-}
-
-static int w90p910_ether_open(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- struct platform_device *pdev;
-
- ether = netdev_priv(dev);
- pdev = ether->pdev;
-
- w90p910_reset_mac(dev);
- w90p910_set_fifo_threshold(dev);
- w90p910_set_curdest(dev);
- w90p910_enable_cam(dev);
- w90p910_enable_cam_command(dev);
- w90p910_enable_mac_interrupt(dev);
- w90p910_set_global_maccmd(dev);
- w90p910_enable_rx(dev, 1);
-
- clk_enable(ether->rmiiclk);
- clk_enable(ether->clk);
-
- ether->rx_packets = 0x0;
- ether->rx_bytes = 0x0;
-
- if (request_irq(ether->txirq, w90p910_tx_interrupt,
- 0x0, pdev->name, dev)) {
- dev_err(&pdev->dev, "register irq tx failed\n");
- return -EAGAIN;
- }
-
- if (request_irq(ether->rxirq, w90p910_rx_interrupt,
- 0x0, pdev->name, dev)) {
- dev_err(&pdev->dev, "register irq rx failed\n");
- free_irq(ether->txirq, dev);
- return -EAGAIN;
- }
-
- mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
- netif_start_queue(dev);
- w90p910_trigger_rx(dev);
-
- dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
-
- return 0;
-}
-
-static void w90p910_ether_set_multicast_list(struct net_device *dev)
-{
- struct w90p910_ether *ether;
- unsigned int rx_mode;
-
- ether = netdev_priv(dev);
-
- if (dev->flags & IFF_PROMISC)
- rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
- else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
- rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
- else
- rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
- __raw_writel(rx_mode, ether->reg + REG_CAMCMR);
-}
-
-static int w90p910_ether_ioctl(struct net_device *dev,
- struct ifreq *ifr, int cmd)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct mii_ioctl_data *data = if_mii(ifr);
-
- return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
-}
-
-static void w90p910_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, DRV_MODULE_NAME);
- strcpy(info->version, DRV_MODULE_VERSION);
-}
-
-static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_ethtool_gset(&ether->mii, cmd);
-}
-
-static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_ethtool_sset(&ether->mii, cmd);
-}
-
-static int w90p910_nway_reset(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_nway_restart(&ether->mii);
-}
-
-static u32 w90p910_get_link(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- return mii_link_ok(&ether->mii);
-}
-
-static const struct ethtool_ops w90p910_ether_ethtool_ops = {
- .get_settings = w90p910_get_settings,
- .set_settings = w90p910_set_settings,
- .get_drvinfo = w90p910_get_drvinfo,
- .nway_reset = w90p910_nway_reset,
- .get_link = w90p910_get_link,
-};
-
-static const struct net_device_ops w90p910_ether_netdev_ops = {
- .ndo_open = w90p910_ether_open,
- .ndo_stop = w90p910_ether_close,
- .ndo_start_xmit = w90p910_ether_start_xmit,
- .ndo_get_stats = w90p910_ether_stats,
- .ndo_set_multicast_list = w90p910_ether_set_multicast_list,
- .ndo_set_mac_address = w90p910_set_mac_address,
- .ndo_do_ioctl = w90p910_ether_ioctl,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
-};
-
-static void __init get_mac_address(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
- struct platform_device *pdev;
- char addr[6];
-
- pdev = ether->pdev;
-
- addr[0] = 0x00;
- addr[1] = 0x02;
- addr[2] = 0xac;
- addr[3] = 0x55;
- addr[4] = 0x88;
- addr[5] = 0xa8;
-
- if (is_valid_ether_addr(addr))
- memcpy(dev->dev_addr, &addr, 0x06);
- else
- dev_err(&pdev->dev, "invalid mac address\n");
-}
-
-static int w90p910_ether_setup(struct net_device *dev)
-{
- struct w90p910_ether *ether = netdev_priv(dev);
-
- ether_setup(dev);
- dev->netdev_ops = &w90p910_ether_netdev_ops;
- dev->ethtool_ops = &w90p910_ether_ethtool_ops;
-
- dev->tx_queue_len = 16;
- dev->dma = 0x0;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- get_mac_address(dev);
-
- ether->cur_tx = 0x0;
- ether->cur_rx = 0x0;
- ether->finish_tx = 0x0;
- ether->linkflag = 0x0;
- ether->mii.phy_id = 0x01;
- ether->mii.phy_id_mask = 0x1f;
- ether->mii.reg_num_mask = 0x1f;
- ether->mii.dev = dev;
- ether->mii.mdio_read = w90p910_mdio_read;
- ether->mii.mdio_write = w90p910_mdio_write;
-
- setup_timer(&ether->check_timer, w90p910_check_link,
- (unsigned long)dev);
-
- return 0;
-}
-
-static int __devinit w90p910_ether_probe(struct platform_device *pdev)
-{
- struct w90p910_ether *ether;
- struct net_device *dev;
- int error;
-
- dev = alloc_etherdev(sizeof(struct w90p910_ether));
- if (!dev)
- return -ENOMEM;
-
- ether = netdev_priv(dev);
-
- ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (ether->res == NULL) {
- dev_err(&pdev->dev, "failed to get I/O memory\n");
- error = -ENXIO;
- goto failed_free;
- }
-
- if (!request_mem_region(ether->res->start,
- resource_size(ether->res), pdev->name)) {
- dev_err(&pdev->dev, "failed to request I/O memory\n");
- error = -EBUSY;
- goto failed_free;
- }
-
- ether->reg = ioremap(ether->res->start, resource_size(ether->res));
- if (ether->reg == NULL) {
- dev_err(&pdev->dev, "failed to remap I/O memory\n");
- error = -ENXIO;
- goto failed_free_mem;
- }
-
- ether->txirq = platform_get_irq(pdev, 0);
- if (ether->txirq < 0) {
- dev_err(&pdev->dev, "failed to get ether tx irq\n");
- error = -ENXIO;
- goto failed_free_io;
- }
-
- ether->rxirq = platform_get_irq(pdev, 1);
- if (ether->rxirq < 0) {
- dev_err(&pdev->dev, "failed to get ether rx irq\n");
- error = -ENXIO;
- goto failed_free_txirq;
- }
-
- platform_set_drvdata(pdev, dev);
-
- ether->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(ether->clk)) {
- dev_err(&pdev->dev, "failed to get ether clock\n");
- error = PTR_ERR(ether->clk);
- goto failed_free_rxirq;
- }
-
- ether->rmiiclk = clk_get(&pdev->dev, "RMII");
- if (IS_ERR(ether->rmiiclk)) {
- dev_err(&pdev->dev, "failed to get ether clock\n");
- error = PTR_ERR(ether->rmiiclk);
- goto failed_put_clk;
- }
-
- ether->pdev = pdev;
-
- w90p910_ether_setup(dev);
-
- error = register_netdev(dev);
- if (error != 0) {
- dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n");
- error = -ENODEV;
- goto failed_put_rmiiclk;
- }
-
- return 0;
-failed_put_rmiiclk:
- clk_put(ether->rmiiclk);
-failed_put_clk:
- clk_put(ether->clk);
-failed_free_rxirq:
- free_irq(ether->rxirq, pdev);
- platform_set_drvdata(pdev, NULL);
-failed_free_txirq:
- free_irq(ether->txirq, pdev);
-failed_free_io:
- iounmap(ether->reg);
-failed_free_mem:
- release_mem_region(ether->res->start, resource_size(ether->res));
-failed_free:
- free_netdev(dev);
- return error;
-}
-
-static int __devexit w90p910_ether_remove(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct w90p910_ether *ether = netdev_priv(dev);
-
- unregister_netdev(dev);
-
- clk_put(ether->rmiiclk);
- clk_put(ether->clk);
-
- iounmap(ether->reg);
- release_mem_region(ether->res->start, resource_size(ether->res));
-
- free_irq(ether->txirq, dev);
- free_irq(ether->rxirq, dev);
-
- del_timer_sync(&ether->check_timer);
- platform_set_drvdata(pdev, NULL);
-
- free_netdev(dev);
- return 0;
-}
-
-static struct platform_driver w90p910_ether_driver = {
- .probe = w90p910_ether_probe,
- .remove = __devexit_p(w90p910_ether_remove),
- .driver = {
- .name = "nuc900-emc",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init w90p910_ether_init(void)
-{
- return platform_driver_register(&w90p910_ether_driver);
-}
-
-static void __exit w90p910_ether_exit(void)
-{
- platform_driver_unregister(&w90p910_ether_driver);
-}
-
-module_init(w90p910_ether_init);
-module_exit(w90p910_ether_exit);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 MAC driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-emc");
-