summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/Kconfig9
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/smsc9118/Makefile1
-rw-r--r--drivers/net/smsc9118/smsc911x.c2710
-rw-r--r--drivers/net/smsc9118/smsc911x.h392
5 files changed, 0 insertions, 3113 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 26612275d21f..387f7ed5a4c1 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1013,15 +1013,6 @@ config SMSC911X
<file:Documentation/networking/net-modules.txt>. The module
will be called smsc911x.
-config SMSC9118
- tristate "SMSC LAN9218 support"
- depends on NET_ETHERNET && (MACH_CC9M2443JS || MACH_CCW9M2443JS || MACH_CCWMX51JS || MACH_CCMX51JS)
- select CRC32
- select MII
- ---help---
- Say Y here if you want support for SMSC LAN921x families
- of ethernet controllers.
-
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
depends on ISA
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 9383000211c2..ead8cab3cfe1 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -249,7 +249,6 @@ obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_S6GMAC) += s6gmac.o
obj-$(CONFIG_ARM) += arm/
-obj-$(CONFIG_SMSC9118) += smsc9118/
obj-$(CONFIG_DEV_APPLETALK) += appletalk/
obj-$(CONFIG_TR) += tokenring/
obj-$(CONFIG_WAN) += wan/
diff --git a/drivers/net/smsc9118/Makefile b/drivers/net/smsc9118/Makefile
deleted file mode 100644
index d33fe1dc8e38..000000000000
--- a/drivers/net/smsc9118/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_SMSC9118) += smsc911x.o
diff --git a/drivers/net/smsc9118/smsc911x.c b/drivers/net/smsc9118/smsc911x.c
deleted file mode 100644
index e0e7707d9cb2..000000000000
--- a/drivers/net/smsc9118/smsc911x.c
+++ /dev/null
@@ -1,2710 +0,0 @@
-/***************************************************************************
- *
- * Copyright (C) 2004-2007 SMSC
- * Copyright (C) 2005 ARM
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- ***************************************************************************
- * Rewritten, heavily based on smsc911x simple driver by SMSC.
- * Partly uses io macros from smc91x.c by Nicolas Pitre
- *
- * Supported devices:
- * LAN9115, LAN9116, LAN9117, LAN9118
- * LAN9215, LAN9216, LAN9217, LAN9218
- *
- * History:
- * 05/05/2005 bahadir.balban@arm.com
- * - Transition to linux coding style
- * - Platform driver and module interface
- *
- * 17/07/2006 steve.glendinning@smsc.com
- * - Added support for LAN921x family
- * - Added workaround for multicast filters
- *
- * 31/07/2006 steve.glendinning@smsc.com
- * - Removed tasklet, using NAPI poll instead
- * - Multiple device support
- * - Large tidy-up following feedback from netdev list
- *
- * 03/08/2006 steve.glendinning@smsc.com
- * - Added ethtool support
- * - Convert to use generic MII interface
- *
- * 04/08/2006 bahadir.balban@arm.com
- * - Added ethtool eeprom r/w support
- *
- * 17/06/2007 steve.glendinning@smsc.com
- * - Incorporate changes from Bill Gatliff and Russell King
- *
- * 04/07/2007 steve.glendinning@smsc.com
- * - move irq configuration to platform_device
- * - fix link poller after interface is stopped and restarted
- *
- * 13/07/2007 bahadir.balban@arm.com
- * - set irq polarity before requesting irq
- *
- * 26/06/2007 hennerich@blackfin.uclinux.org
- * - Fixed minor style issue to pass checkpatch.pl
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/mii.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/version.h>
-#include <linux/bug.h>
-#include <linux/bitops.h>
-#include <linux/irq.h>
-#include <asm/io.h>
-
-/* For having the same platform-data as in the Vanilla kernel */
-#include <linux/smc911x.h>
-
-#include "smsc911x.h"
-
-#define SMSC_CHIPNAME "smsc911x"
-#define SMSC_DRV_VERSION "2007-07-13"
-
-MODULE_LICENSE("GPL");
-
-
-/* Base address of the connected controller: S3C2410_CS5 = 0x28000000 */
-#define printk_err(fmt, args...) printk(KERN_ERR "[ ERROR ] smsc911x: " fmt, ## args)
-#define printk_info(fmt, args...) printk(KERN_INFO "smsc911x: " fmt, ## args)
-
-#if 0
-#define SMSC911X_DEBUG
-#endif
-
-#ifdef SMSC911X_DEBUG
-# define printk_debug(fmt, args...) printk(KERN_DEBUG "smsc911x: " fmt, ## args)
-#else
-# define printk_debug(fmt, args...)
-#endif
-
-/* Enables the debug messages for the PM-operations (WOL, suspend, etc.) */
-#if 0
-#define SMSC911X_PM_DEBUG
-#endif
-
-#ifdef SMSC911X_PM_DEBUG
-# define printk_pmdbg(fmt, args...) printk(KERN_DEBUG "smsc911x: " fmt, ## args)
-#else
-# define printk_pmdbg(fmt, args...)
-#endif
-
-struct smsc911x_data {
- void __iomem *ioaddr;
-
- unsigned int idrev;
- unsigned int generation; /* used to decide which workarounds apply */
-
- /* device configuration */
- unsigned int irq_polarity;
- unsigned int irq_type;
- unsigned int irq_flags;
-
- /* This needs to be acquired before calling any of below:
- * smsc911x_mac_read(), smsc911x_mac_write()
- * smsc911x_phy_read(), smsc911x_phy_write()
- */
- spinlock_t phy_lock;
-
- struct mii_if_info mii;
- unsigned int using_extphy;
- u32 msg_enable;
-#ifdef USE_LED1_WORK_AROUND
- unsigned int gpio_setting;
- unsigned int gpio_orig_setting;
-#endif
- struct net_device *netdev;
- struct napi_struct napi;
- struct timer_list link_poll_timer;
- unsigned int stop_link_poll;
-
- unsigned int software_irq_signal;
-
-#ifdef USE_PHY_WORK_AROUND
-#define MIN_PACKET_SIZE (64)
- char loopback_tx_pkt[MIN_PACKET_SIZE];
- char loopback_rx_pkt[MIN_PACKET_SIZE];
- unsigned int resetcount;
-#endif
-
- /* Members for Multicast filter workaround */
- unsigned int multicast_update_pending;
- unsigned int set_bits_mask;
- unsigned int clear_bits_mask;
- unsigned int hashhi;
- unsigned int hashlo;
- unsigned int last_rxstat;
-
- /* Registers for the internal PM */
- unsigned long mac_wucsr;
- unsigned long pmt_ctrl;
- unsigned long phy_intmsk;
-};
-
-
-static int smsc911x_set_mac(struct net_device *dev, void *addr);
-
-#if SMSC_CAN_USE_32BIT
-
-static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
-{
- return readl(pdata->ioaddr + reg);
-}
-
-static inline void smsc911x_reg_write(u32 val, struct smsc911x_data *pdata,
- u32 reg)
-{
- writel(val, pdata->ioaddr + reg);
-}
-
-#else /* SMSC_CAN_USE_32BIT */
-
-static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
-{
- u32 reg_val;
- unsigned long flags;
-
- /* these two 16-bit reads must be performed consecutively, so must
- * not be interrupted by our own ISR (which would start another
- * read operation) */
- local_irq_save(flags);
- reg_val = ((readw(pdata->ioaddr + reg) & 0xFFFF) |
- ((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16));
- local_irq_restore(flags);
-
- return reg_val;
-}
-
-static inline void smsc911x_reg_write(u32 val, struct smsc911x_data *pdata,
- u32 reg)
-{
- unsigned long flags;
-
- /* these two 16-bit writes must be performed consecutively, so must
- * not be interrupted by our own ISR (which would start another
- * read operation) */
- local_irq_save(flags);
- writew(val & 0xFFFF, pdata->ioaddr + reg);
- writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
- local_irq_restore(flags);
-}
-
-#endif /* SMSC_CAN_USE_32BIT */
-
-#ifndef CONFIG_BLACKFIN
-/* Writes a packet to the TX_DATA_FIFO */
-static inline void
-smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
- unsigned int wordcount)
-{
- while (wordcount--)
- smsc911x_reg_write(*buf++, pdata, TX_DATA_FIFO);
-}
-
-/* Reads a packet out of the RX_DATA_FIFO */
-static inline void
-smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
- unsigned int wordcount)
-{
- while (wordcount--)
- *buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO);
-}
-#else
-/* Writes a packet to the TX_DATA_FIFO */
-static inline void
-smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
- unsigned int wordcount)
-{
- if (wordcount > 24)
- dma_outsl((u_long)pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
- else
- outsl((u_long)pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
-}
-
-/* Reads a packet out of the RX_DATA_FIFO */
-static inline void
-smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
- unsigned int wordcount)
-{
- if (wordcount > 24)
- dma_insl((u_long)pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
- else
- insl((u_long)pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
-}
-#endif
-
-/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read
- * and smsc911x_mac_write, so assumes phy_lock is held */
-static int smsc911x_mac_notbusy(struct smsc911x_data *pdata)
-{
- int i;
- u32 val;
-
- for (i = 0; i < 40; i++) {
- val = smsc911x_reg_read(pdata, MAC_CSR_CMD);
- if (!(val & MAC_CSR_CMD_CSR_BUSY_))
- return 1;
- }
- SMSC_WARNING("Timed out waiting for MAC not BUSY. "
- "MAC_CSR_CMD: 0x%08X", val);
- return 0;
-}
-
-/* Fetches a MAC register value. Assumes phy_lock is acquired */
-static u32 smsc911x_mac_read(struct smsc911x_data *pdata, unsigned int offset)
-{
- unsigned int temp;
-
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (!spin_is_locked(&pdata->phy_lock))
- SMSC_WARNING("phy_lock not held");
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
- temp = smsc911x_reg_read(pdata, MAC_CSR_CMD);
- if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) {
- SMSC_WARNING("smsc911x_mac_read failed, MAC busy at entry");
- return 0xFFFFFFFF;
- }
-
- /* Send the MAC cmd */
- smsc911x_reg_write(((offset & 0xFF) | MAC_CSR_CMD_CSR_BUSY_
- | MAC_CSR_CMD_R_NOT_W_), pdata, MAC_CSR_CMD);
-
- /* Workaround for hardware read-after-write restriction */
- temp = smsc911x_reg_read(pdata, BYTE_TEST);
-
- /* Wait for the read to happen */
- if (likely(smsc911x_mac_notbusy(pdata)))
- return smsc911x_reg_read(pdata, MAC_CSR_DATA);
-
- SMSC_WARNING("smsc911x_mac_read failed, MAC busy after read");
- return 0xFFFFFFFF;
-}
-
-/* Set a mac register, phy_lock must be acquired before calling */
-static void smsc911x_mac_write(struct smsc911x_data *pdata,
- unsigned int offset, u32 val)
-{
- unsigned int temp;
-
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (!spin_is_locked(&pdata->phy_lock))
- SMSC_WARNING("phy_lock not held");
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
- temp = smsc911x_reg_read(pdata, MAC_CSR_CMD);
- if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) {
- SMSC_WARNING("smsc911x_mac_write failed, MAC busy at entry");
- return;
- }
-
- /* Send data to write */
- smsc911x_reg_write(val, pdata, MAC_CSR_DATA);
-
- /* Write the actual data */
- smsc911x_reg_write(((offset & 0xFF) | MAC_CSR_CMD_CSR_BUSY_), pdata,
- MAC_CSR_CMD);
-
- /* Workaround for hardware read-after-write restriction */
- temp = smsc911x_reg_read(pdata, BYTE_TEST);
-
- /* Wait for the write to complete */
- if (likely(smsc911x_mac_notbusy(pdata)))
- return;
-
- SMSC_WARNING("smsc911x_mac_write failed, MAC busy after write");
-}
-
-/* Gets a phy register, phy_lock must be acquired before calling */
-static u16 smsc911x_phy_read(struct smsc911x_data *pdata, unsigned int index)
-{
- unsigned int addr;
- int i;
-
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (!spin_is_locked(&pdata->phy_lock))
- SMSC_WARNING("phy_lock not held");
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
- /* Confirm MII not busy */
- if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
- SMSC_WARNING("MII is busy in smsc911x_phy_read???");
- return 0;
- }
-
- /* Set the address, index & direction (read from PHY) */
- addr = (((pdata->mii.phy_id) & 0x1F) << 11)
- | ((index & 0x1F) << 6);
- smsc911x_mac_write(pdata, MII_ACC, addr);
-
- /* Wait for read to complete w/ timeout */
- for (i = 0; i < 100; i++) {
- /* See if MII is finished yet */
- if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
- return smsc911x_mac_read(pdata, MII_DATA);
- }
- }
- SMSC_WARNING("Timed out waiting for MII write to finish");
- return 0xFFFF;
-}
-
-/* Sets a phy register, phy_lock must be acquired before calling */
-static void smsc911x_phy_write(struct smsc911x_data *pdata,
- unsigned int index, u16 val)
-{
- unsigned int addr;
- int i;
-
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (!spin_is_locked(&pdata->phy_lock))
- SMSC_WARNING("phy_lock not held");
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
- /* Confirm MII not busy */
- if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
- SMSC_WARNING("MII is busy in smsc911x_write_phy???");
- return;
- }
-
- /* Put the data to write in the MAC */
- smsc911x_mac_write(pdata, MII_DATA, val);
-
- /* Set the address, index & direction (write to PHY) */
- addr = (((pdata->mii.phy_id) & 0x1F) << 11) |
- ((index & 0x1F) << 6) | MII_ACC_MII_WRITE_;
- smsc911x_mac_write(pdata, MII_ACC, addr);
-
- /* Wait for write to complete w/ timeout */
- for (i = 0; i < 100; i++) {
- /* See if MII is finished yet */
- if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_))
- return;
- }
- SMSC_WARNING("Timed out waiting for MII write to finish");
-}
-
-static int smsc911x_mdio_read(struct net_device *dev, int phy_id, int location)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned long flags;
- int reg;
-
- spin_lock_irqsave(&pdata->phy_lock, flags);
- reg = smsc911x_phy_read(pdata, location);
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-
- return reg;
-}
-
-static void smsc911x_mdio_write(struct net_device *dev, int phy_id,
- int location, int val)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&pdata->phy_lock, flags);
- smsc911x_phy_write(pdata, location, val);
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-}
-
-/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 flavors.
- * If something goes wrong, returns -ENODEV to revert back to internal phy.
- * Performed at initialisation only, so interrupts are enabled */
-static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata)
-{
- unsigned int address;
- unsigned int hwcfg;
- unsigned int phyid1;
- unsigned int phyid2;
-
- hwcfg = smsc911x_reg_read(pdata, HW_CFG);
-
- /* External phy is requested, supported, and detected */
- if (hwcfg & HW_CFG_EXT_PHY_DET_) {
-
- /* Attempt to switch to external phy for auto-detecting
- * its address. Assuming tx and rx are stopped because
- * smsc911x_phy_initialise is called before
- * smsc911x_rx_initialise and tx_initialise.
- */
-
- /* Disable phy clocks to the MAC */
- hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
- hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
- udelay(10); /* Enough time for clocks to stop */
-
- /* Switch to external phy */
- hwcfg |= HW_CFG_EXT_PHY_EN_;
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
-
- /* Enable phy clocks to the MAC */
- hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
- hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
- udelay(10); /* Enough time for clocks to restart */
-
- hwcfg |= HW_CFG_SMI_SEL_;
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
-
- /* Auto-detect PHY */
- spin_lock_irq(&pdata->phy_lock);
- for (address = 0; address <= 31; address++) {
- pdata->mii.phy_id = address;
- phyid1 = smsc911x_phy_read(pdata, MII_PHYSID1);
- phyid2 = smsc911x_phy_read(pdata, MII_PHYSID2);
- if ((phyid1 != 0xFFFFU) || (phyid2 != 0xFFFFU)) {
- SMSC_TRACE("Detected PHY at address = "
- "0x%02X = %d", address, address);
- break;
- }
- }
- spin_unlock_irq(&pdata->phy_lock);
-
- if ((phyid1 == 0xFFFFU) && (phyid2 == 0xFFFFU)) {
- SMSC_WARNING("External PHY is not accessable, "
- "using internal PHY instead");
- /* Revert back to internal phy settings. */
-
- /* Disable phy clocks to the MAC */
- hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
- hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
- udelay(10); /* Enough time for clocks to stop */
-
- /* Switch to internal phy */
- hwcfg &= (~HW_CFG_EXT_PHY_EN_);
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
-
- /* Enable phy clocks to the MAC */
- hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
- hwcfg |= HW_CFG_PHY_CLK_SEL_INT_PHY_;
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
- udelay(10); /* Enough time for clocks to restart */
-
- hwcfg &= (~HW_CFG_SMI_SEL_);
- smsc911x_reg_write(hwcfg, pdata, HW_CFG);
- /* Use internal phy */
- return -ENODEV;
- } else {
- SMSC_TRACE("Successfully switched to external PHY");
- pdata->using_extphy = 1;
- }
- } else {
- SMSC_WARNING("No external PHY detected.");
- SMSC_WARNING("Using internal PHY instead.");
- /* Use internal phy */
- return -ENODEV;
- }
- return 0;
-}
-
-/* called by phy_initialise and loopback test */
-static int smsc911x_phy_reset(struct smsc911x_data *pdata)
-{
- unsigned int temp;
- unsigned int i = 100000;
- unsigned long flags;
-
- SMSC_TRACE("Performing PHY BCR Reset");
- spin_lock_irqsave(&pdata->phy_lock, flags);
- smsc911x_phy_write(pdata, MII_BMCR, BMCR_RESET);
- do {
- udelay(10);
- temp = smsc911x_phy_read(pdata, MII_BMCR);
- } while ((i--) && (temp & BMCR_RESET));
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-
- if (temp & BMCR_RESET) {
- SMSC_WARNING("PHY reset failed to complete.");
- return 0;
- }
- /* Extra delay required because the phy may not be completed with
- * its reset when BMCR_RESET is cleared. Specs say 256 uS is
- * enough delay but using 1ms here to be safe
- */
- msleep(1);
-
- return 1;
-}
-
-/* Fetches a tx status out of the status fifo */
-static unsigned int smsc911x_tx_get_txstatus(struct smsc911x_data *pdata)
-{
- unsigned int result =
- smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TSUSED_;
-
- if (result != 0)
- result = smsc911x_reg_read(pdata, TX_STATUS_FIFO);
-
- return result;
-}
-
-/* Fetches the next rx status */
-static unsigned int smsc911x_rx_get_rxstatus(struct smsc911x_data *pdata)
-{
- unsigned int result =
- smsc911x_reg_read(pdata, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED_;
-
- if (result != 0)
- result = smsc911x_reg_read(pdata, RX_STATUS_FIFO);
-
- return result;
-}
-
-#ifdef USE_PHY_WORK_AROUND
-static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata)
-{
- unsigned int tries;
- u32 wrsz;
- u32 rdsz;
- u32 bufp;
-
- for (tries = 0; tries < 10; tries++) {
- unsigned int txcmd_a;
- unsigned int txcmd_b;
- unsigned int status;
- unsigned int pktlength;
- unsigned int i;
-
- /* Zero-out rx packet memory */
- memset(pdata->loopback_rx_pkt, 0, MIN_PACKET_SIZE);
-
- /* Write tx packet to 118 */
- txcmd_a = (((unsigned int)pdata->loopback_tx_pkt)
- & 0x03) << 16;
- txcmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
- txcmd_a |= MIN_PACKET_SIZE;
-
- txcmd_b = MIN_PACKET_SIZE << 16 | MIN_PACKET_SIZE;
-
- smsc911x_reg_write(txcmd_a, pdata, TX_DATA_FIFO);
- smsc911x_reg_write(txcmd_b, pdata, TX_DATA_FIFO);
-
- bufp = ((u32) pdata->loopback_tx_pkt) & 0xFFFFFFFC;
- wrsz = MIN_PACKET_SIZE + 3;
- wrsz += (((u32) pdata->loopback_tx_pkt) & 0x3);
- wrsz >>= 2;
-
- smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
-
- /* Wait till transmit is done */
- i = 60;
- do {
- udelay(5);
- status = smsc911x_tx_get_txstatus(pdata);
- } while ((i--) && (!status));
-
- if (!status) {
- SMSC_WARNING("Failed to transmit during loopback test");
- continue;
- }
- if (status & TX_STS_ES_) {
- SMSC_WARNING("Transmit encountered errors during "
- "loopback test");
- continue;
- }
-
- /* Wait till receive is done */
- i = 60;
- do {
- udelay(5);
- status = smsc911x_rx_get_rxstatus(pdata);
- } while ((i--) && (!status));
-
- if (!status) {
- SMSC_WARNING("Failed to receive during loopback test");
- continue;
- }
- if (status & RX_STS_ES_) {
- SMSC_WARNING("Receive encountered errors during "
- "loopback test");
- continue;
- }
-
- pktlength = ((status & 0x3FFF0000UL) >> 16);
- bufp = (u32)pdata->loopback_rx_pkt;
- rdsz = pktlength + 3;
- rdsz += ((u32)pdata->loopback_rx_pkt) & 0x3;
- rdsz >>= 2;
-
- smsc911x_rx_readfifo(pdata, (unsigned int *)bufp, rdsz);
-
- if (pktlength != (MIN_PACKET_SIZE + 4)) {
- SMSC_WARNING("Unexpected packet size during "
- "loop back test, size=%d, "
- "will retry", pktlength);
- } else {
- unsigned int j;
- int mismatch = 0;
- for (j = 0; j < MIN_PACKET_SIZE; j++) {
- if (pdata->loopback_tx_pkt[j]
- != pdata->loopback_rx_pkt[j]) {
- mismatch = 1;
- break;
- }
- }
- if (!mismatch) {
- SMSC_TRACE("Successfully verified "
- "loopback packet");
- return 1;
- } else {
- SMSC_WARNING("Data miss match during "
- "loop back test, will retry.");
- }
- }
- }
-
- return 0;
-}
-
-static int smsc911x_phy_loopbacktest(struct smsc911x_data *pdata)
-{
- int result = 0;
- unsigned int i;
- unsigned int val;
- unsigned long flags;
-
- /* Initialise tx packet */
- for (i = 0; i < 6; i++) {
- /* Use broadcast destination address */
- pdata->loopback_tx_pkt[i] = (char)0xFF;
- }
-
- for (i = 6; i < 12; i++) {
- /* Use incrementing source address */
- pdata->loopback_tx_pkt[i] = (char)i;
- }
-
- /* Set length type field */
- pdata->loopback_tx_pkt[12] = 0x00;
- pdata->loopback_tx_pkt[13] = 0x00;
- for (i = 14; i < MIN_PACKET_SIZE; i++) {
- pdata->loopback_tx_pkt[i] = (char)i;
- }
-
- val = smsc911x_reg_read(pdata, HW_CFG);
- val &= HW_CFG_TX_FIF_SZ_;
- val |= HW_CFG_SF_;
- smsc911x_reg_write(val, pdata, HW_CFG);
-
- smsc911x_reg_write(TX_CFG_TX_ON_, pdata, TX_CFG);
- smsc911x_reg_write((((unsigned int)pdata->loopback_rx_pkt)
- & 0x03) << 8, pdata, RX_CFG);
-
- for (i = 0; i < 10; i++) {
- /* Set PHY to 10/FD, no ANEG, and loopback mode */
- spin_lock_irqsave(&pdata->phy_lock, flags);
- smsc911x_phy_write(pdata, MII_BMCR, 0x4100);
-
- /* Enable MAC tx/rx, FD */
- smsc911x_mac_write(pdata, MAC_CR, MAC_CR_FDPX_
- | MAC_CR_TXEN_ | MAC_CR_RXEN_);
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-
- if (smsc911x_phy_check_loopbackpkt(pdata)) {
- result = 1;
- break;
- }
- pdata->resetcount++;
-
- /* Disable MAC rx */
- spin_lock_irqsave(&pdata->phy_lock, flags);
- smsc911x_mac_write(pdata, MAC_CR, 0);
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-
- smsc911x_phy_reset(pdata);
- }
-
- /* Disable MAC */
- spin_lock_irqsave(&pdata->phy_lock, flags);
- smsc911x_mac_write(pdata, MAC_CR, 0);
-
- /* Cancel PHY loopback mode */
- smsc911x_phy_write(pdata, MII_BMCR, 0);
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-
- smsc911x_reg_write(0, pdata, TX_CFG);
- smsc911x_reg_write(0, pdata, RX_CFG);
-
- return result;
-}
-#endif /* USE_PHY_WORK_AROUND */
-
-
-inline static void smsc911x_phy_dump_regs(struct smsc911x_data *pdata)
-{
- printk("BCR = 0x%04x\n", smsc911x_phy_read(pdata, MII_BMCR));
- printk("BSR = 0x%04x\n", smsc911x_phy_read(pdata, MII_BMSR));
- printk("ID1 = 0x%04x\n", smsc911x_phy_read(pdata, MII_PHYSID1));
- printk("ID2 = 0x%04x\n", smsc911x_phy_read(pdata, MII_PHYSID2));
- printk("ADVER = 0x%04x\n", smsc911x_phy_read(pdata, MII_ADVERTISE));
- printk("LPA = 0x%04x\n", smsc911x_phy_read(pdata, MII_LPA));
- printk("EXP = 0x%04x\n", smsc911x_phy_read(pdata, MII_EXPANSION));
-}
-
-/* assumes phy_lock is held */
-static void smsc911x_phy_update_flowcontrol(struct smsc911x_data *pdata)
-{
- unsigned int temp;
-
- if (pdata->mii.full_duplex) {
- unsigned int phy_adv;
- unsigned int phy_lpa;
- phy_adv = smsc911x_phy_read(pdata, MII_ADVERTISE);
- phy_lpa = smsc911x_phy_read(pdata, MII_LPA);
- if (phy_adv & phy_lpa & LPA_PAUSE_CAP) {
- /* Both ends support symmetric pause, enable
- * PAUSE receive and transmit */
- smsc911x_mac_write(pdata, FLOW, 0xFFFF0002);
- temp = smsc911x_reg_read(pdata, AFC_CFG);
- temp |= 0xF;
- smsc911x_reg_write(temp, pdata, AFC_CFG);
- } else if (((phy_adv & ADVERTISE_PAUSE_ALL) ==
- ADVERTISE_PAUSE_ALL) &&
- ((phy_lpa & LPA_PAUSE_ALL) == LPA_PAUSE_ASYM)) {
- /* We support symmetric and asym pause, the
- * other end only supports asym, Enable PAUSE
- * receive, disable PAUSE transmit */
- smsc911x_mac_write(pdata, FLOW, 0xFFFF0002);
- temp = smsc911x_reg_read(pdata, AFC_CFG);
- temp &= ~0xF;
- smsc911x_reg_write(temp, pdata, AFC_CFG);
- } else {
- /* Disable PAUSE receive and transmit */
- smsc911x_mac_write(pdata, FLOW, 0);
- temp = smsc911x_reg_read(pdata, AFC_CFG);
- temp &= ~0xF;
- smsc911x_reg_write(temp, pdata, AFC_CFG);
- }
- } else {
- smsc911x_mac_write(pdata, FLOW, 0);
- temp = smsc911x_reg_read(pdata, AFC_CFG);
- temp |= 0xF;
- smsc911x_reg_write(temp, pdata, AFC_CFG);
- }
-}
-
-static void smsc911x_phy_update_duplex(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned long flags;
- unsigned int mac_cr;
-
- spin_lock_irqsave(&pdata->phy_lock, flags);
-
- mac_cr = smsc911x_mac_read(pdata, MAC_CR);
- if (pdata->mii.full_duplex) {
- SMSC_TRACE("configuring for full duplex mode");
- mac_cr |= MAC_CR_FDPX_;
- } else {
- SMSC_TRACE("configuring for half duplex mode");
- mac_cr &= ~MAC_CR_FDPX_;
- }
- smsc911x_mac_write(pdata, MAC_CR, mac_cr);
- smsc911x_phy_update_flowcontrol(pdata);
-
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-}
-
-
-/* Update link mode if any thing has changed */
-static void smsc911x_phy_update_linkmode(struct net_device *dev, int init)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- if (mii_check_media(&pdata->mii, netif_msg_link(pdata), init))
- smsc911x_phy_update_duplex(dev);
- /* mii_check_media() exists if the media is forced... */
- if (pdata->mii.force_media) {
- int cur_link = mii_link_ok(&pdata->mii);
- int prev_link = netif_carrier_ok(dev);
-
- if (!prev_link && cur_link) {
- printk(KERN_INFO "%s: link up\n", dev->name);
- netif_carrier_on(dev);
- } else if (prev_link && !cur_link) {
- printk(KERN_INFO "%s: link down\n", dev->name);
- netif_carrier_off(dev);
- }
- }
-
-#ifdef USE_LED1_WORK_AROUND
- if (netif_carrier_ok(dev)) {
- if ((pdata->gpio_orig_setting & GPIO_CFG_LED1_EN_) &&
- (!pdata->using_extphy)) {
- /* Restore orginal GPIO configuration */
- pdata->gpio_setting = pdata->gpio_orig_setting;
- smsc911x_reg_write(pdata->gpio_setting, pdata,
- GPIO_CFG);
- }
- } else {
- /* Check global setting that LED1
- * usage is 10/100 indicator */
- pdata->gpio_setting = smsc911x_reg_read(pdata, GPIO_CFG);
- if ((pdata->gpio_setting & GPIO_CFG_LED1_EN_)
- && (!pdata->using_extphy)) {
- /* Force 10/100 LED off, after saving
- * orginal GPIO configuration */
- pdata->gpio_orig_setting = pdata->gpio_setting;
-
- pdata->gpio_setting &= ~GPIO_CFG_LED1_EN_;
- pdata->gpio_setting |= (GPIO_CFG_GPIOBUF0_
- | GPIO_CFG_GPIODIR0_
- | GPIO_CFG_GPIOD0_);
- smsc911x_reg_write(pdata->gpio_setting, pdata,
- GPIO_CFG);
- }
- }
-#endif /* USE_LED1_WORK_AROUND */
-}
-
-/* Entry point for the link poller */
-static void smsc911x_phy_checklink(unsigned long ptr)
-{
- struct net_device *dev = (struct net_device *)ptr;
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- smsc911x_phy_update_linkmode(dev, 0);
-
- if (!(pdata->stop_link_poll)) {
- pdata->link_poll_timer.expires = jiffies + 2 * HZ;
- add_timer(&pdata->link_poll_timer);
- } else {
- pdata->stop_link_poll = 0;
- }
-}
-
-static void smsc911x_phy_set_automdx(struct smsc911x_data *pdata)
-{
- u16 ctrlstatus;
-
- ctrlstatus = smsc911x_phy_read(pdata, 27);
- ctrlstatus &= 0x1fff;
- ctrlstatus |= (0x6 << 13);
- smsc911x_phy_write(pdata, 27, ctrlstatus);
-}
-
-/* Initialises the PHY layer. Called at initialisation by open() so
- * interrupts are enabled */
-static int smsc911x_phy_initialise(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned int phyid1 = 0;
- unsigned int phyid2 = 0;
- unsigned int temp;
-
- printk_debug("Calling phy_initialise()\n");
-
- pdata->using_extphy = 0;
-
- switch (pdata->idrev & 0xFFFF0000) {
- case 0x01170000:
- case 0x01150000:
- /* External PHY supported, try to autodetect */
- if (smsc911x_phy_initialise_external(pdata) < 0) {
- SMSC_TRACE("External PHY is not detected, using "
- "internal PHY instead");
- pdata->mii.phy_id = 1;
- }
- break;
- default:
- SMSC_TRACE("External PHY is not supported, using internal PHY "
- "instead");
- pdata->mii.phy_id = 1;
- break;
- }
-
- spin_lock_irq(&pdata->phy_lock);
- phyid1 = smsc911x_phy_read(pdata, MII_PHYSID1);
- phyid2 = smsc911x_phy_read(pdata, MII_PHYSID2);
- spin_unlock_irq(&pdata->phy_lock);
-
- if ((phyid1 == 0xFFFF) && (phyid2 == 0xFFFF)) {
- SMSC_WARNING("Internal PHY not detected!");
- return 0;
- }
-
- /* Reset the phy */
- if (!smsc911x_phy_reset(pdata)) {
- SMSC_WARNING("PHY reset failed to complete.");
- return 0;
- }
-#ifdef USE_PHY_WORK_AROUND
- if (!smsc911x_phy_loopbacktest(pdata)) {
- SMSC_WARNING("Failed Loop Back Test");
- return 0;
- } else {
- SMSC_TRACE("Passed Loop Back Test");
- }
-#endif /* USE_PHY_WORK_AROUND */
-
-
- smsc911x_phy_set_automdx(pdata);
-
- /* Advertise all speeds and pause capabilities */
- spin_lock_irq(&pdata->phy_lock);
- temp = smsc911x_phy_read(pdata, MII_ADVERTISE);
- temp |= (ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
- smsc911x_phy_write(pdata, MII_ADVERTISE, temp);
- pdata->mii.advertising = temp;
-
- if (!pdata->using_extphy) {
- /* using internal phy, enable PHY interrupts */
- smsc911x_phy_read(pdata, MII_INTSTS);
- smsc911x_phy_write(pdata, MII_INTMSK, PHY_INTMSK_DEFAULT_);
- }
-
- /* begin to establish link */
- smsc911x_phy_write(pdata, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
- spin_unlock_irq(&pdata->phy_lock);
-
- smsc911x_phy_update_linkmode(dev, 1);
-
- pdata->stop_link_poll = 0;
- setup_timer(&pdata->link_poll_timer, smsc911x_phy_checklink,
- (unsigned long)dev);
- pdata->link_poll_timer.expires = jiffies + 2 * HZ;
- add_timer(&pdata->link_poll_timer);
-
- printk_debug("PHY initialised succesfully\n");
- return 1;
-}
-
-/* Gets the number of tx statuses in the fifo */
-static unsigned int smsc911x_tx_get_txstatcount(struct smsc911x_data *pdata)
-{
- unsigned int result = (smsc911x_reg_read(pdata, TX_FIFO_INF)
- & TX_FIFO_INF_TSUSED_) >> 16;
- return result;
-}
-
-/* Reads tx statuses and increments counters where necessary */
-static void smsc911x_tx_update_txcounters(struct smsc911x_data *pdata)
-{
- struct net_device *netdev = pdata->netdev;
- unsigned int tx_stat;
-
- while ((tx_stat = smsc911x_tx_get_txstatus(pdata)) != 0) {
- if (unlikely(tx_stat & 0x80000000)) {
- /* In this driver the packet tag is used as the packet
- * length. Since a packet length can never reach the
- * size of 0x8000, this bit is reserved. It is worth
- * noting that the "reserved bit" in the warning above
- * does not reference a hardware defined reserved bit
- * but rather a driver defined one.
- */
- SMSC_WARNING("Packet tag reserved bit is high");
- } else {
- if (unlikely(tx_stat & 0x00008000)) {
- printk_debug("TX status error: 0x%08x (MAC 0x%08x)\n",
- tx_stat, smsc911x_mac_read(pdata, MAC_CR));
- netdev->stats.tx_errors++;
- } else {
- netdev->stats.tx_packets++;
- netdev->stats.tx_bytes += (tx_stat >> 16);
- }
- if (unlikely(tx_stat & 0x00000100)) {
- netdev->stats.collisions += 16;
- netdev->stats.tx_aborted_errors += 1;
- } else {
- netdev->stats.collisions +=
- ((tx_stat >> 3) & 0xF);
- }
- if (unlikely(tx_stat & 0x00000800)) {
- netdev->stats.tx_carrier_errors += 1;
- }
- if (unlikely(tx_stat & 0x00000200)) {
- netdev->stats.collisions++;
- netdev->stats.tx_aborted_errors++;
- }
- }
- }
-}
-
-/* Increments the Rx error counters */
-static void
-smsc911x_rx_counterrors(struct smsc911x_data *pdata, unsigned int rxstat)
-{
- struct net_device *netdev = pdata->netdev;
- int crc_err = 0;
-
- if (unlikely(rxstat & 0x00008000)) {
- netdev->stats.rx_errors++;
- if (unlikely(rxstat & 0x00000002)) {
- netdev->stats.rx_crc_errors++;
- crc_err = 1;
- }
- }
- if (likely(!crc_err)) {
- if (unlikely((rxstat & 0x00001020) == 0x00001020)) {
- /* Frame type indicates length,
- * and length error is set */
- netdev->stats.rx_length_errors++;
- }
- if (rxstat & RX_STS_MCAST_)
- netdev->stats.multicast++;
- }
-}
-
-/* Quickly dumps bad packets */
-static void
-smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
-{
- unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
-
- if (likely(pktwords >= 4)) {
- unsigned int timeout = 500;
- unsigned int val;
- smsc911x_reg_write(RX_DP_CTRL_RX_FFWD_, pdata, RX_DP_CTRL);
- do {
- udelay(1);
- val = smsc911x_reg_read(pdata, RX_DP_CTRL);
- } while (timeout-- && (val & RX_DP_CTRL_RX_FFWD_));
-
- if (unlikely(timeout == 0))
- SMSC_WARNING("Timed out waiting for RX FFWD "
- "to finish, RX_DP_CTRL: 0x%08X", val);
- } else {
- unsigned int temp;
- while (pktwords--)
- temp = smsc911x_reg_read(pdata, RX_DATA_FIFO);
- }
-}
-
-/* NAPI poll function */
-static int smsc911x_poll(struct napi_struct *napi, int budget)
-{
- struct smsc911x_data *pdata = container_of(napi, struct smsc911x_data, napi);
- struct net_device *dev = pdata->netdev;
- int npackets = 0;
-
- while (npackets < budget) {
- unsigned int pktlength;
- unsigned int pktwords;
- unsigned int rxstat = smsc911x_rx_get_rxstatus(pdata);
-
- /* break out of while loop if there are no more packets waiting */
- if (!rxstat) {
- printk_debug("Stopping the RX poll\n");
- break;
- }
-
- pktlength = ((rxstat & 0x3FFF0000) >> 16);
- pktwords = (pktlength + NET_IP_ALIGN + 3) >> 2;
- printk_debug("Going to read %i words (pktlen %i)\n",
- pktwords, pktlength);
-
- smsc911x_rx_counterrors(pdata, rxstat);
-
- if (likely((rxstat & RX_STS_ES_) == 0)) {
- struct sk_buff *skb;
- skb = dev_alloc_skb(pktlength + NET_IP_ALIGN);
- if (likely(skb)) {
- skb->data = skb->head;
- skb->tail = skb->head;
- /* Align IP on 16B boundary */
- skb_reserve(skb, NET_IP_ALIGN);
- skb_put(skb, pktlength - 4);
- smsc911x_rx_readfifo(pdata,
- (unsigned int *)skb->head,
- pktwords);
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
- netif_receive_skb(skb);
-
- /* Update counters */
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += (pktlength - 4);
- dev->last_rx = jiffies;
- npackets++;
- continue;
- } else {
- SMSC_WARNING("Unable to allocate sk_buff "
- "for rx packet, in PIO path");
- dev->stats.rx_dropped++;
- }
- }
- /* At this point, the packet is to be read out
- * of the fifo and discarded */
- smsc911x_rx_fastforward(pdata, pktlength);
- }
-
- dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
- smsc911x_reg_write(INT_STS_RSFL_, pdata, INT_STS);
-
- if (npackets < budget) {
- unsigned int temp;
- /* We processed all packets available. Tell NAPI it can
- * stop polling then re-enable rx interrupts */
- napi_complete(napi);
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp |= INT_EN_RSFL_EN_;
- smsc911x_reg_write(temp, pdata, INT_EN);
- }
-
- /* Return total received packets */
- return npackets;
-}
-
-/* Returns hash bit number for given MAC address
- * Example:
- * 01 00 5E 00 00 01 -> returns bit number 31 */
-static unsigned int smsc911x_hash(char addr[ETH_ALEN])
-{
- unsigned int crc;
- unsigned int result;
-
- crc = ether_crc(ETH_ALEN, addr);
- result = (crc >> 26) & 0x3f;
-
- return result;
-}
-
-static void smsc911x_rx_multicast_update(struct smsc911x_data *pdata)
-{
- /* Performs the multicast & mac_cr update. This is called when
- * safe on the current hardware, and with the phy_lock held */
- unsigned int mac_cr = smsc911x_mac_read(pdata, MAC_CR);
- mac_cr |= pdata->set_bits_mask;
- mac_cr &= ~(pdata->clear_bits_mask);
- smsc911x_mac_write(pdata, MAC_CR, mac_cr);
- smsc911x_mac_write(pdata, HASHH, pdata->hashhi);
- smsc911x_mac_write(pdata, HASHL, pdata->hashlo);
-}
-
-static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata)
-{
- unsigned int mac_cr;
-
- /* This function is only called for older LAN911x devices
- * (revA or revB), where MAC_CR, HASHH and HASHL should not
- * be modified during Rx - newer devices immediately update the
- * registers.
- *
- * This is called from interrupt context */
-
- spin_lock(&pdata->phy_lock);
-
- /* Check Rx has stopped */
- if (smsc911x_mac_read(pdata, MAC_CR) & MAC_CR_RXEN_)
- SMSC_WARNING("Rx not stopped\n");
-
- /* Perform the update - safe to do now Rx has stopped */
- smsc911x_rx_multicast_update(pdata);
-
- /* Re-enable Rx */
- mac_cr = smsc911x_mac_read(pdata, MAC_CR);
- mac_cr |= MAC_CR_RXEN_;
- smsc911x_mac_write(pdata, MAC_CR, mac_cr);
-
- pdata->multicast_update_pending = 0;
-
- spin_unlock(&pdata->phy_lock);
-}
-
-/* Sets the device MAC address to dev_addr, called with phy_lock held */
-static void
-smsc911x_set_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6])
-{
- u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4];
- u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
- (dev_addr[1] << 8) | dev_addr[0];
-
- smsc911x_mac_write(pdata, ADDRH, mac_high16);
- smsc911x_mac_write(pdata, ADDRL, mac_low32);
-}
-
-static int smsc911x_open(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned int timeout;
- unsigned int temp;
- unsigned int intcfg = 0;
- struct sockaddr addr;
-
- /* Reset the LAN911x */
- smsc911x_reg_write(HW_CFG_SRST_, pdata, HW_CFG);
- timeout = 10;
- do {
- udelay(10);
- temp = smsc911x_reg_read(pdata, HW_CFG);
- } while ((--timeout) && (temp & HW_CFG_SRST_));
-
- if (unlikely(temp & HW_CFG_SRST_)) {
- printk_err("Failed to complete reset");
- return -ENODEV;
- }
-
- smsc911x_reg_write(0x00050000, pdata, HW_CFG);
- smsc911x_reg_write(0x006E3740, pdata, AFC_CFG);
-
- /* Make sure EEPROM has finished loading before setting GPIO_CFG */
- timeout = 50;
- while ((timeout--) &&
- (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
- udelay(10);
- }
-
- if (unlikely(timeout == 0)) {
- SMSC_WARNING("Timed out waiting for EEPROM "
- "busy bit to clear");
- }
-#if USE_DEBUG >= 1
- smsc911x_reg_write(0x00670700, pdata, GPIO_CFG);
-#else
- smsc911x_reg_write(0x70070000, pdata, GPIO_CFG);
-#endif
-
- /* Initialise irqs, but leave all sources disabled */
- smsc911x_reg_write(0, pdata, INT_EN);
- smsc911x_reg_write(0xFFFFFFFF, pdata, INT_STS);
-
- /* Set interrupt deassertion to 100uS */
- //intcfg = ((0x38 << 24) | INT_CFG_IRQ_EN_);
- intcfg = ((0x00 << 24) | INT_CFG_IRQ_EN_);
- // PPH modified intcfg = ((10 << 24) | INT_CFG_IRQ_EN_);
-
- if (pdata->irq_polarity) {
- SMSC_TRACE("irq polarity: active high");
- intcfg |= INT_CFG_IRQ_POL_;
- } else {
- SMSC_TRACE("irq polarity: active low");
- }
-
- if (pdata->irq_type) {
- SMSC_TRACE("irq type: push-pull");
- intcfg |= INT_CFG_IRQ_TYPE_;
- } else {
- SMSC_TRACE("irq type: open drain");
- }
-
- smsc911x_reg_write(intcfg, pdata, INT_CFG);
-
- printk_debug("Testing irq handler using IRQ %d\n", dev->irq);
- pdata->software_irq_signal = 0;
- smp_wmb();
-
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp |= INT_EN_SW_INT_EN_;
- smsc911x_reg_write(temp, pdata, INT_EN);
-
- timeout = 1000;
- while (timeout--) {
- smp_rmb();
- if (pdata->software_irq_signal)
- break;
- msleep(1);
- }
-
- if (!pdata->software_irq_signal) {
- printk(KERN_WARNING "%s: ISR failed signaling test (IRQ %d)\n",
- dev->name, dev->irq);
- return -ENODEV;
- }
-
- printk_debug("IRQ handler passed test using IRQ %d\n", dev->irq);
- netif_carrier_off(dev);
-
- if (!smsc911x_phy_initialise(dev)) {
- printk_err("Failed to initialize the PHY");
- return -ENODEV;
- }
-
- temp = smsc911x_reg_read(pdata, HW_CFG);
- temp &= HW_CFG_TX_FIF_SZ_;
- temp |= HW_CFG_SF_;
- smsc911x_reg_write(temp, pdata, HW_CFG);
-
- temp = smsc911x_reg_read(pdata, FIFO_INT);
- temp |= FIFO_INT_TX_AVAIL_LEVEL_;
- temp &= ~(FIFO_INT_RX_STS_LEVEL_);
- smsc911x_reg_write(temp, pdata, FIFO_INT);
-
- /* set RX Data offset to 2 bytes for alignment */
- smsc911x_reg_write((2 << 8), pdata, RX_CFG);
-
- /* enable the polling before enabling the interrupts */
- napi_enable(&pdata->napi);
-
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_ | INT_EN_RDFL_EN_);
- smsc911x_reg_write(temp, pdata, INT_EN);
-
- spin_lock_irq(&pdata->phy_lock);
-
- /*
- * Reenable the full duplex mode, otherwise the TX engine will generate
- * status errors (Luis Galdos)
- */
- temp = smsc911x_mac_read(pdata, MAC_CR);
- temp |= (MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_ | MAC_CR_FDPX_);
- smsc911x_mac_write(pdata, MAC_CR, temp);
- spin_unlock_irq(&pdata->phy_lock);
-
- smsc911x_reg_write(TX_CFG_TX_ON_, pdata, TX_CFG);
-
- /* Set the MAC once again */
- memcpy(addr.sa_data, dev->dev_addr, dev->addr_len);
- if(smsc911x_set_mac(dev, &addr))
- printk_err("Couldn't set the MAC address.\n");
-
- netif_start_queue(dev);
- return 0;
-}
-
-/* Entry point for stopping the interface */
-static int smsc911x_stop(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- printk_info("Stopping the interface\n");
-
- napi_disable(&pdata->napi);
-
- /* disable interrupts */
- smsc911x_reg_write(0, pdata, INT_EN);
-
- pdata->stop_link_poll = 1;
- del_timer_sync(&pdata->link_poll_timer);
-
- netif_stop_queue(dev);
-
- /* At this point all Rx and Tx activity is stopped */
- dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
- smsc911x_tx_update_txcounters(pdata);
-
- /* Stop sending data after the last transmission */
- smsc911x_reg_write(TX_CFG_STOP_TX_, pdata, TX_CFG);
-
- SMSC_TRACE("Interface stopped");
- return 0;
-}
-
-/* Entry point for transmitting a packet */
-static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned int freespace;
- unsigned int tx_cmd_a;
- unsigned int tx_cmd_b;
- unsigned int temp;
- u32 wrsz;
- u32 bufp;
-
- freespace = smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TDFREE_;
-
- if (unlikely(freespace < TX_FIFO_LOW_THRESHOLD))
- SMSC_WARNING("Tx data fifo low, space available: %d",
- freespace);
-
- /* Word alignment adjustment */
- tx_cmd_a = ((((unsigned int)(skb->data)) & 0x03) << 16);
- tx_cmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
- tx_cmd_a |= (unsigned int)skb->len;
-
- tx_cmd_b = ((unsigned int)skb->len) << 16;
- tx_cmd_b |= (unsigned int)skb->len;
-
- smsc911x_reg_write(tx_cmd_a, pdata, TX_DATA_FIFO);
- smsc911x_reg_write(tx_cmd_b, pdata, TX_DATA_FIFO);
-
- bufp = ((u32)skb->data) & 0xFFFFFFFC;
- wrsz = (u32)skb->len + 3;
- wrsz += ((u32)skb->data) & 0x3;
- wrsz >>= 2;
-
- smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
- freespace -= (skb->len + 32);
- dev_kfree_skb(skb);
- dev->trans_start = jiffies;
-
- if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
- smsc911x_tx_update_txcounters(pdata);
-
- if (freespace < TX_FIFO_LOW_THRESHOLD) {
- netif_stop_queue(dev);
- temp = smsc911x_reg_read(pdata, FIFO_INT);
- temp &= 0x00FFFFFF;
- temp |= 0x32000000;
- smsc911x_reg_write(temp, pdata, FIFO_INT);
- }
-
- return NETDEV_TX_OK;
-}
-
-/* Entry point for getting status counters */
-static struct net_device_stats *smsc911x_get_stats(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- smsc911x_tx_update_txcounters(pdata);
- dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
- return &dev->stats;
-}
-
-/* Entry point for setting addressing modes */
-static void smsc911x_set_multicast_list(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned long flags;
-
- if (dev->flags & IFF_PROMISC) {
- /* Enabling promiscuous mode */
- pdata->set_bits_mask = MAC_CR_PRMS_;
- pdata->clear_bits_mask = (MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
- pdata->hashhi = 0;
- pdata->hashlo = 0;
- } else if (dev->flags & IFF_ALLMULTI) {
- /* Enabling all multicast mode */
- pdata->set_bits_mask = MAC_CR_MCPAS_;
- pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_HPFILT_);
- pdata->hashhi = 0;
- pdata->hashlo = 0;
- } else if (dev->mc_count > 0) {
- /* Enabling specific multicast addresses */
- unsigned int hash_high = 0;
- unsigned int hash_low = 0;
- unsigned int count = 0;
- struct dev_mc_list *mc_list = dev->mc_list;
-
- pdata->set_bits_mask = MAC_CR_HPFILT_;
- pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_MCPAS_);
-
- while (mc_list) {
- count++;
- if ((mc_list->dmi_addrlen) == ETH_ALEN) {
- unsigned int bitnum =
- smsc911x_hash(mc_list->dmi_addr);
- unsigned int mask = 0x01 << (bitnum & 0x1F);
- if (bitnum & 0x20)
- hash_high |= mask;
- else
- hash_low |= mask;
- } else {
- SMSC_WARNING("dmi_addrlen != 6");
- }
- mc_list = mc_list->next;
- }
- if (count != (unsigned int)dev->mc_count)
- SMSC_WARNING("mc_count != dev->mc_count");
-
- pdata->hashhi = hash_high;
- pdata->hashlo = hash_low;
- } else {
- /* Enabling local MAC address only */
- pdata->set_bits_mask = 0;
- pdata->clear_bits_mask =
- (MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
- pdata->hashhi = 0;
- pdata->hashlo = 0;
- }
-
- spin_lock_irqsave(&pdata->phy_lock, flags);
-
- if (pdata->generation <= 1) {
- /* Older hardware revision - cannot change these flags while
- * receiving data */
- if (!pdata->multicast_update_pending) {
- unsigned int temp;
- SMSC_TRACE("scheduling mcast update");
- pdata->multicast_update_pending = 1;
-
- /* Request the hardware to stop, then perform the
- * update when we get an RX_STOP interrupt */
- smsc911x_reg_write(INT_STS_RXSTOP_INT_, pdata, INT_STS);
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp |= INT_EN_RXSTOP_INT_EN_;
- smsc911x_reg_write(temp, pdata, INT_EN);
-
- temp = smsc911x_mac_read(pdata, MAC_CR);
- temp &= ~(MAC_CR_RXEN_);
- smsc911x_mac_write(pdata, MAC_CR, temp);
- } else {
- /* There is another update pending, this should now
- * use the newer values */
- }
- } else {
- /* Newer hardware revision - can write immediately */
- smsc911x_rx_multicast_update(pdata);
- }
-
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-}
-
-static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned int intsts;
- unsigned int inten;
- unsigned int temp;
- unsigned int intcfg;
- int serviced = IRQ_NONE;
-
- intcfg = smsc911x_reg_read(pdata, INT_CFG);
- intsts = smsc911x_reg_read(pdata, INT_STS);
- inten = smsc911x_reg_read(pdata, INT_EN);
-
- printk_debug("New IRQ: intsts 0x%08x\n", intsts);
-
- if ((intcfg & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != (INT_CFG_IRQ_INT_ |
- INT_CFG_IRQ_EN_))
- return serviced;
-
-
- if (unlikely(intsts & inten & INT_STS_SW_INT_)) {
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp &= (~INT_EN_SW_INT_EN_);
- smsc911x_reg_write(temp, pdata, INT_EN);
- smsc911x_reg_write(INT_STS_SW_INT_, pdata, INT_STS);
- pdata->software_irq_signal = 1;
- smp_wmb();
- serviced = IRQ_HANDLED;
- }
-
- if (unlikely(intsts & inten & INT_STS_RXSTOP_INT_)) {
- /* Called when there is a multicast update scheduled and
- * it is now safe to complete the update */
- SMSC_TRACE("RX Stop interrupt");
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp &= (~INT_EN_RXSTOP_INT_EN_);
- smsc911x_reg_write(temp, pdata, INT_EN);
- smsc911x_reg_write(INT_STS_RXSTOP_INT_, pdata, INT_STS);
- smsc911x_rx_multicast_update_workaround(pdata);
- serviced = IRQ_HANDLED;
- }
-
- if (intsts & inten & INT_STS_TDFA_) {
- temp = smsc911x_reg_read(pdata, FIFO_INT);
- temp |= FIFO_INT_TX_AVAIL_LEVEL_;
- smsc911x_reg_write(temp, pdata, FIFO_INT);
- smsc911x_reg_write(INT_STS_TDFA_, pdata, INT_STS);
- netif_wake_queue(dev);
- serviced = IRQ_HANDLED;
- }
-
- if (unlikely(intsts & inten & INT_STS_RXE_)) {
- smsc911x_reg_write(INT_STS_RXE_, pdata, INT_STS);
- serviced = IRQ_HANDLED;
- }
-
- if (likely(intsts & inten & INT_STS_RSFL_)) {
- if (likely(napi_schedule_prep(&pdata->napi))) {
- /* Disable Rx interrupts and schedule NAPI poll */
- temp = smsc911x_reg_read(pdata, INT_EN);
- temp &= (~INT_EN_RSFL_EN_);
- smsc911x_reg_write(temp, pdata, INT_EN);
- __napi_schedule(&pdata->napi);
- }
-
- serviced = IRQ_HANDLED;
- }
-
- if (unlikely(intsts & inten & INT_STS_PHY_INT_)) {
- smsc911x_reg_write(INT_STS_PHY_INT_, pdata, INT_STS);
- spin_lock(&pdata->phy_lock);
- temp = smsc911x_phy_read(pdata, MII_INTSTS);
- spin_unlock(&pdata->phy_lock);
- SMSC_TRACE("PHY interrupt, sts 0x%04X", (u16)temp);
- smsc911x_phy_update_linkmode(dev, 0);
- serviced = IRQ_HANDLED;
- }
- return serviced;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void smsc911x_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- smsc911x_irqhandler(0, dev);
- enable_irq(dev->irq);
-}
-#endif /* CONFIG_NET_POLL_CONTROLLER */
-
-/* Standard ioctls for mii-tool */
-static int smsc911x_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned int chg_in_duplex;
- int ret;
-
- if (!netif_running(dev))
- return -EINVAL;
- ret = generic_mii_ioctl(&pdata->mii, if_mii(ifr), cmd, &chg_in_duplex);
- if ((ret == 0) && (chg_in_duplex != 0))
- smsc911x_phy_update_duplex(dev);
-
- return ret;
-}
-
-static int
-smsc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- cmd->maxtxpkt = 1;
- cmd->maxrxpkt = 1;
- return mii_ethtool_gset(&pdata->mii, cmd);
-}
-
-static int
-smsc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- return mii_ethtool_sset(&pdata->mii, cmd);
-}
-
-static void smsc911x_ethtool_getdrvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver));
- strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev_name(dev->dev.parent),
- sizeof(info->bus_info));
-}
-
-static int smsc911x_ethtool_nwayreset(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- return mii_nway_restart(&pdata->mii);
-}
-
-static u32 smsc911x_ethtool_getmsglevel(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- return pdata->msg_enable;
-}
-
-static void smsc911x_ethtool_setmsglevel(struct net_device *dev, u32 level)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- pdata->msg_enable = level;
-}
-
-static int smsc911x_ethtool_getregslen(struct net_device *dev)
-{
- return (((E2P_CMD - ID_REV) / 4 + 1) + (WUCSR - MAC_CR) + 1 + 32) *
- sizeof(u32);
-}
-
-static void
-smsc911x_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs,
- void *buf)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned long flags;
- unsigned int i;
- unsigned int j = 0;
- u32 *data = buf;
-
- regs->version = pdata->idrev;
- for (i = ID_REV; i <= E2P_CMD; i += (sizeof(u32)))
- data[j++] = smsc911x_reg_read(pdata, i);
-
- spin_lock_irqsave(&pdata->phy_lock, flags);
- for (i = MAC_CR; i <= WUCSR; i++)
- data[j++] = smsc911x_mac_read(pdata, i);
- for (i = 0; i <= 31; i++)
- data[j++] = smsc911x_phy_read(pdata, i);
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-}
-
-static void smsc911x_eeprom_enable_access(struct smsc911x_data *pdata)
-{
- unsigned int temp = smsc911x_reg_read(pdata, GPIO_CFG);
- temp &= ~GPIO_CFG_EEPR_EN_;
- smsc911x_reg_write(temp, pdata, GPIO_CFG);
- msleep(1);
-}
-
-static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op)
-{
- int timeout = 100;
- u32 e2cmd;
-
- SMSC_TRACE("op 0x%08x", op);
- if (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) {
- SMSC_WARNING("Busy at start");
- return -EBUSY;
- }
-
- e2cmd = op | E2P_CMD_EPC_BUSY_;
- smsc911x_reg_write(e2cmd, pdata, E2P_CMD);
-
- do {
- msleep(1);
- e2cmd = smsc911x_reg_read(pdata, E2P_CMD);
- } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
-
- if (!timeout) {
- SMSC_TRACE("TIMED OUT");
- return -EAGAIN;
- }
-
- if (e2cmd & E2P_CMD_EPC_TIMEOUT_) {
- SMSC_TRACE("Error occured during eeprom operation");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int smsc911x_eeprom_read_location(struct smsc911x_data *pdata,
- u8 address, u8 *data)
-{
- u32 op = E2P_CMD_EPC_CMD_READ_ | address;
- int ret;
-
- SMSC_TRACE("address 0x%x", address);
- ret = smsc911x_eeprom_send_cmd(pdata, op);
-
- if (!ret)
- data[address] = smsc911x_reg_read(pdata, E2P_DATA);
-
- return ret;
-}
-
-static int smsc911x_eeprom_write_location(struct smsc911x_data *pdata,
- u8 address, u8 data)
-{
- u32 op = E2P_CMD_EPC_CMD_ERASE_ | address;
- int ret;
-
- SMSC_TRACE("address 0x%x, data 0x%x", address, data);
- ret = smsc911x_eeprom_send_cmd(pdata, op);
-
- if (!ret) {
- op = E2P_CMD_EPC_CMD_WRITE_ | address;
- smsc911x_reg_write((u32)data, pdata, E2P_DATA);
- ret = smsc911x_eeprom_send_cmd(pdata, op);
- }
-
- return ret;
-}
-
-static int smsc911x_ethtool_get_eeprom_len(struct net_device *dev)
-{
- return SMSC911X_EEPROM_SIZE;
-}
-
-static int smsc911x_ethtool_get_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
- u8 eeprom_data[SMSC911X_EEPROM_SIZE];
- int len;
- int i;
-
- smsc911x_eeprom_enable_access(pdata);
-
- len = min(eeprom->len, SMSC911X_EEPROM_SIZE);
- for (i = 0; i < len; i++) {
- int ret = smsc911x_eeprom_read_location(pdata, i, eeprom_data);
- if (ret < 0) {
- eeprom->len = 0;
- return ret;
- }
- }
-
- memcpy(data, &eeprom_data[eeprom->offset], len);
- eeprom->len = len;
- return 0;
-}
-
-static int smsc911x_ethtool_set_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- int ret;
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- smsc911x_eeprom_enable_access(pdata);
- smsc911x_eeprom_send_cmd(pdata, E2P_CMD_EPC_CMD_EWEN_);
- ret = smsc911x_eeprom_write_location(pdata, eeprom->offset, *data);
- smsc911x_eeprom_send_cmd(pdata, E2P_CMD_EPC_CMD_EWDS_);
-
- /* Single byte write, according to man page */
- eeprom->len = 1;
-
- return ret;
-}
-
-static int smsc911x_ethtool_set_wol(struct net_device *dev,
- struct ethtool_wolinfo *wol)
-{
- struct smsc911x_data *pdata;
-
- /* Check for unsupported options */
- if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_UCAST | WAKE_MCAST
- | WAKE_BCAST | WAKE_ARP))
- return -EINVAL;
-
- pdata = netdev_priv(dev);
-
- /* When disable the WOL options need to disable the PHY-interrupts too */
- if (!wol->wolopts) {
- printk_pmdbg("[ WOL ] Disabling all sources\n");
- pdata->pmt_ctrl &= ~(PMT_CTRL_WOL_EN_ | PMT_CTRL_ED_EN_);
- pdata->phy_intmsk &= ~PHY_INTMSK_ENERGYON_;
- pdata->mac_wucsr = 0;
- goto exit_set_wol;
- }
-
- /*
- * For the magic packet we MUST configure the MAC too, but we can't do it
- * at this point, cause the controller stops working.
- */
- if (wol->wolopts & WAKE_MAGIC) {
- printk_pmdbg("WOL: Enabling magic frame\n");
- pdata->mac_wucsr |= WUCSR_MPEN_;
- pdata->pmt_ctrl |= PMT_CTRL_WOL_EN_;
- }
-
- /* For the PHY-wakeup we must use the energy detection */
- if (wol->wolopts & WAKE_PHY) {
- printk_pmdbg("[ WOL ] Enabling PHY energy\n");
- pdata->phy_intmsk |= PHY_INTMSK_ENERGYON_;
- pdata->pmt_ctrl |= PMT_CTRL_ED_EN_;
- }
-
- exit_set_wol:
- return 0;
-}
-
-/* Function for getting the infos about the WOL */
-static void smsc911x_ethtool_get_wol(struct net_device *net_dev,
- struct ethtool_wolinfo *wol)
-{
- /* Only for magic and PHY power detection available up now */
- wol->supported = WAKE_MAGIC | WAKE_PHY;
-}
-
-static struct ethtool_ops smsc911x_ethtool_ops = {
- .get_settings = smsc911x_ethtool_getsettings,
- .set_settings = smsc911x_ethtool_setsettings,
- .get_link = ethtool_op_get_link,
- .get_drvinfo = smsc911x_ethtool_getdrvinfo,
- .nway_reset = smsc911x_ethtool_nwayreset,
- .get_msglevel = smsc911x_ethtool_getmsglevel,
- .set_msglevel = smsc911x_ethtool_setmsglevel,
- .get_regs_len = smsc911x_ethtool_getregslen,
- .get_regs = smsc911x_ethtool_getregs,
- .get_eeprom_len = smsc911x_ethtool_get_eeprom_len,
- .get_eeprom = smsc911x_ethtool_get_eeprom,
- .set_eeprom = smsc911x_ethtool_set_eeprom,
- .get_wol = smsc911x_ethtool_get_wol,
- .set_wol = smsc911x_ethtool_set_wol,
-};
-
-
-static int smsc911x_set_mac(struct net_device *dev, void *addr)
-{
- unsigned int reg;
- int retval;
- unsigned long flags;
- struct smsc911x_data *pdata;
- unsigned int low, high;
- struct sockaddr *paddr = addr;
-
- printk_debug("Set mac called\n");
-
- pdata = netdev_priv(dev);
-
- spin_lock_irqsave(&pdata->phy_lock, flags);
-
- /* First check that the MAC is not busy */
- reg = smsc911x_reg_read(pdata, MAC_CSR_CMD);
- if (unlikely(reg & MAC_CSR_CMD_CSR_BUSY_)) {
- printk_err("smsc911x_mac_read failed, MAC busy at entry");
- retval = -EBUSY;
- goto exit_unlock;
- }
-
- /* Get the MAC address */
- high = 0;
- memcpy(&low, &(paddr->sa_data[0]), 4);
- memcpy(&high, &(paddr->sa_data[4]), 2);
- printk_debug("Going to set the MAC %04X%08X\n", high, low);
-
- /* Now set the high address */
- smsc911x_reg_write(high, pdata, MAC_CSR_DATA);
- smsc911x_reg_write(ADDRH | MAC_CSR_CMD_CSR_BUSY_, pdata, MAC_CSR_CMD);
- reg = smsc911x_reg_read(pdata, BYTE_TEST);
- if (!smsc911x_mac_notbusy(pdata)) {
- retval = -EBUSY;
- goto exit_unlock;
- }
-
- /* First set the low address */
- smsc911x_reg_write(low, pdata, MAC_CSR_DATA);
- smsc911x_reg_write(ADDRL | MAC_CSR_CMD_CSR_BUSY_, pdata, MAC_CSR_CMD);
- reg = smsc911x_reg_read(pdata, BYTE_TEST);
- if (!smsc911x_mac_notbusy(pdata)) {
- retval = -EBUSY;
- goto exit_unlock;
- }
-
- /* And save the IP inside the driver structure */
- memcpy(dev->dev_addr, paddr->sa_data, dev->addr_len);
-
- printk_debug("MAC successful changed to %02X%08X\n",
- smsc911x_mac_read(pdata, ADDRH),
- smsc911x_mac_read(pdata, ADDRL));
-
- retval = 0;
-
- exit_unlock:
- spin_unlock_irqrestore(&pdata->phy_lock, flags);
-
- return retval;
-}
-
-static const struct net_device_ops smsc911x_netdev_ops = {
- .ndo_open = smsc911x_open,
- .ndo_stop = smsc911x_stop,
- .ndo_start_xmit = smsc911x_hard_start_xmit,
- .ndo_get_stats = smsc911x_get_stats,
- .ndo_set_multicast_list = smsc911x_set_multicast_list,
- .ndo_do_ioctl = smsc911x_do_ioctl,
- .ndo_set_mac_address = smsc911x_set_mac,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = smsc911x_poll_controller,
-#endif
-};
-/* Initializing private device structures */
-static int smsc911x_init(struct net_device *dev)
-{
- struct smsc911x_data *pdata = netdev_priv(dev);
-
- SMSC_TRACE("Driver Parameters:");
- SMSC_TRACE("LAN base: 0x%08lX", (unsigned long)pdata->ioaddr);
- SMSC_TRACE("IRQ: %d", dev->irq);
- SMSC_TRACE("PHY will be autodetected.");
-
- if (pdata->ioaddr == 0) {
- SMSC_WARNING("pdata->ioaddr: 0x00000000");
- return -ENODEV;
- }
-
- /* Default generation to zero (all workarounds apply) */
- pdata->generation = 0;
-
- pdata->idrev = smsc911x_reg_read(pdata, ID_REV);
- if (((pdata->idrev >> 16) & 0xFFFF) == (pdata->idrev & 0xFFFF)) {
- SMSC_WARNING("idrev top 16 bits equal to bottom 16 bits, "
- "idrev: 0x%08X", pdata->idrev);
- SMSC_TRACE("This may mean the chip is set for 32 bit while "
- "the bus is reading as 16 bit");
- return -ENODEV;
- }
- switch (pdata->idrev & 0xFFFF0000) {
- case 0x01180000:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_TRACE("LAN9118 Beacon identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 0;
- break;
- case 1UL:
- SMSC_TRACE
- ("LAN9118 Concord A0 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 1;
- break;
- case 2UL:
- SMSC_TRACE
- ("LAN9118 Concord A1 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- default:
- SMSC_TRACE
- ("LAN9118 Concord A1 identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- }
- break;
-
- case 0x01170000:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_TRACE("LAN9117 Beacon identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 0;
- break;
- case 1UL:
- SMSC_TRACE
- ("LAN9117 Concord A0 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 1;
- break;
- case 2UL:
- SMSC_TRACE
- ("LAN9117 Concord A1 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- default:
- SMSC_TRACE
- ("LAN9117 Concord A1 identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- }
- break;
-
- case 0x01160000:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_WARNING("LAN911x not identified, idrev: 0x%08X",
- pdata->idrev);
- return -ENODEV;
- case 1UL:
- SMSC_TRACE
- ("LAN9116 Concord A0 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 1;
- break;
- case 2UL:
- SMSC_TRACE
- ("LAN9116 Concord A1 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- default:
- SMSC_TRACE
- ("LAN9116 Concord A1 identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- }
- break;
-
- case 0x01150000:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_WARNING("LAN911x not identified, idrev: 0x%08X",
- pdata->idrev);
- return -ENODEV;
- case 1UL:
- SMSC_TRACE
- ("LAN9115 Concord A0 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 1;
- break;
- case 2UL:
- SMSC_TRACE
- ("LAN9115 Concord A1 identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- default:
- SMSC_TRACE
- ("LAN9115 Concord A1 identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 2;
- break;
- }
- break;
-
- case 0x118A0000UL:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_TRACE
- ("LAN9218 Boylston identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- default:
- SMSC_TRACE
- ("LAN9218 Boylston identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- }
- break;
-
- case 0x117A0000UL:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_TRACE
- ("LAN9217 Boylston identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- default:
- SMSC_TRACE
- ("LAN9217 Boylston identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- }
- break;
-
- case 0x116A0000UL:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_TRACE
- ("LAN9216 Boylston identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- default:
- SMSC_TRACE
- ("LAN9216 Boylston identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- }
- break;
-
- case 0x115A0000UL:
- switch (pdata->idrev & 0x0000FFFFUL) {
- case 0UL:
- SMSC_TRACE
- ("LAN9215 Boylston identified, idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- default:
- SMSC_TRACE
- ("LAN9215 Boylston identified (NEW), idrev: 0x%08X",
- pdata->idrev);
- pdata->generation = 3;
- break;
- }
- break;
-
- case 0x92100000UL:
- case 0x92110000UL:
- case 0x92200000UL:
- case 0x92210000UL:
- /* LAN9210/LAN9211/LAN9220/LAN9221 */
- pdata->generation = 4;
- break;
-
- default:
- SMSC_WARNING("LAN911x not identified, idrev: 0x%08X",
- pdata->idrev);
- return -ENODEV;
- }
-
- if (pdata->generation == 0)
- SMSC_WARNING("This driver is not intended "
- "for this chip revision");
-
- ether_setup(dev);
- dev->flags |= IFF_MULTICAST;
- netif_napi_add(dev, &pdata->napi, smsc911x_poll, 64);//SMSC_NAPI_WEIGHT
- dev->netdev_ops = &smsc911x_netdev_ops;
- dev->ethtool_ops = &smsc911x_ethtool_ops;
-
- pdata->mii.phy_id_mask = 0x1f;
- pdata->mii.reg_num_mask = 0x1f;
- pdata->mii.force_media = 0;
- pdata->mii.full_duplex = 0;
- pdata->mii.dev = dev;
- pdata->mii.mdio_read = smsc911x_mdio_read;
- pdata->mii.mdio_write = smsc911x_mdio_write;
-
- pdata->msg_enable = NETIF_MSG_LINK;
-
- return 0;
-}
-
-static int smsc911x_drv_remove(struct platform_device *pdev)
-{
- struct net_device *dev;
- struct smsc911x_data *pdata;
- struct resource *res;
-
- dev = platform_get_drvdata(pdev);
- BUG_ON(!dev);
- pdata = netdev_priv(dev);
- BUG_ON(!pdata);
- BUG_ON(!pdata->ioaddr);
-
- SMSC_TRACE("Stopping driver.");
- platform_set_drvdata(pdev, NULL);
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "smsc911x-memory");
- if (!res)
- platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- release_mem_region(res->start, res->end - res->start);
-
- iounmap(pdata->ioaddr);
-
- free_netdev(dev);
-
- return 0;
-}
-
-static int smsc911x_drv_probe(struct platform_device *pdev)
-{
- struct net_device *dev;
- struct smsc911x_data *pdata;
- struct resource *res;
- unsigned int intcfg = 0;
- int res_size;
- int retval;
-
- printk(KERN_INFO "%s: Driver version %s.\n", SMSC_CHIPNAME,
- SMSC_DRV_VERSION);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "smsc911x-memory");
- if (!res)
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- printk(KERN_WARNING "%s: Could not allocate resource.\n",
- SMSC_CHIPNAME);
- retval = -ENODEV;
- goto out_0;
- }
- res_size = res->end - res->start;
-
- if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) {
- retval = -EBUSY;
- goto out_0;
- }
-
- dev = alloc_etherdev(sizeof(struct smsc911x_data));
- if (!dev) {
- printk(KERN_WARNING "%s: Could not allocate device.\n",
- SMSC_CHIPNAME);
- retval = -ENOMEM;
- goto out_release_io_1;
- }
-
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- pdata = netdev_priv(dev);
- pdata->netdev = dev;
-
- dev->irq = platform_get_irq(pdev, 0);
- pdata->ioaddr = ioremap_nocache(res->start, res_size);
-
- /* copy config parameters across if present, otherwise pdata
- * defaults to zeros */
- if (pdev->dev.platform_data) {
- struct smc911x_platdata *config = pdev->dev.platform_data;
- pdata->irq_polarity = config->irq_polarity;
- pdata->irq_flags = config->irq_flags;
- pdata->irq_type = config->irq_type;
- }
-
- if (pdata->ioaddr == NULL) {
- SMSC_WARNING("Error smsc911x base address invalid");
- retval = -ENOMEM;
- goto out_free_netdev_2;
- }
-
- retval = smsc911x_init(dev);
- if (retval < 0)
- goto out_unmap_io_3;
-
- /* configure irq polarity and type before connecting isr */
- if (pdata->irq_polarity)
- intcfg |= INT_CFG_IRQ_POL_;
-
- if (pdata->irq_type)
- intcfg |= INT_CFG_IRQ_TYPE_;
-
- smsc911x_reg_write(intcfg, pdata, INT_CFG);
-
- retval = request_irq(dev->irq, smsc911x_irqhandler,
- pdata->irq_flags,
- SMSC_CHIPNAME, dev);
- if (retval) {
- SMSC_WARNING("Unable to claim requested irq: %d", dev->irq);
- goto out_unmap_io_3;
- }
-
- platform_set_drvdata(pdev, dev);
-
- retval = register_netdev(dev);
- if (retval) {
- SMSC_WARNING("Error %i registering device", retval);
- goto out_unset_drvdata_4;
- } else {
- SMSC_TRACE("Network interface: \"%s\"", dev->name);
- }
-
- spin_lock_init(&pdata->phy_lock);
-
- spin_lock_irq(&pdata->phy_lock);
-
- /* Check if mac address has been specified when bringing interface up */
- if (is_valid_ether_addr(dev->dev_addr)) {
- smsc911x_set_mac(dev, dev->dev_addr);
- SMSC_TRACE("MAC Address is specified by configuration");
- } else {
- /* Try reading mac address from device. if EEPROM is present
- * it will already have been set */
- u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
- u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL);
- dev->dev_addr[0] = (u8)(mac_low32);
- dev->dev_addr[1] = (u8)(mac_low32 >> 8);
- dev->dev_addr[2] = (u8)(mac_low32 >> 16);
- dev->dev_addr[3] = (u8)(mac_low32 >> 24);
- dev->dev_addr[4] = (u8)(mac_high16);
- dev->dev_addr[5] = (u8)(mac_high16 >> 8);
-
- if (is_valid_ether_addr(dev->dev_addr)) {
- /* eeprom values are valid so use them */
- SMSC_TRACE("Mac Address is read from LAN911x EEPROM");
- } else {
- /* eeprom values are invalid, generate random MAC */
- random_ether_addr(dev->dev_addr);
- smsc911x_set_mac_address(pdata, dev->dev_addr);
- SMSC_TRACE("MAC Address is set to random_ether_addr");
- }
- }
-
- spin_unlock_irq(&pdata->phy_lock);
-
- printk_info("%s: MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
- dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-
- /* Enable the wakeup over this device (Luis Galdos) */
- device_init_wakeup(&pdev->dev, 1);
- device_set_wakeup_enable(&pdev->dev, 0);
- return 0;
-
-out_unset_drvdata_4:
- platform_set_drvdata(pdev, NULL);
- free_irq(dev->irq, dev);
-out_unmap_io_3:
- iounmap(pdata->ioaddr);
-out_free_netdev_2:
- free_netdev(dev);
-out_release_io_1:
- release_mem_region(res->start, res->end - res->start);
-out_0:
- return retval;
-}
-
-/* Enter in the suspend mode */
-#if defined(CONFIG_PM)
-
-/*
- * For the mode D1 we MUST left the interrupts enabled
- */
-static int smsc911x_drv_state_wakeup(struct smsc911x_data *pdata, int mode)
-{
- int retval;
- unsigned long regval;
-
- retval = 0;
-
- if (mode != 1 && mode != 2)
- return -EINVAL;
-
- /* Clear already received WUs */
- regval = smsc911x_mac_read(pdata, WUCSR);
- regval &= ~(WUCSR_MPR_ | WUCSR_WUFR_);
- regval |= pdata->mac_wucsr; /* Magic packet enable 'WUCSR_MPEN_' */
- printk_pmdbg("[ SUSP ] WUCSR 0x%08lx\n", regval);
- smsc911x_mac_write(pdata, WUCSR, regval);
-
- /* For the D2 we must enable the PHY interrupt for the energy detection */
- regval = smsc911x_reg_read(pdata, INT_EN);
- regval |= (INT_EN_PME_INT_EN_ | INT_EN_PHY_INT_EN_);
- printk_pmdbg("[ SUSP ] INT_EN 0x%08lx\n", regval);
- smsc911x_reg_write(regval, pdata, INT_EN);
-
- if (mode /* @FIXME: Enabled only for D2 */) {
- u16 phy_mode;
-
- phy_mode = smsc911x_phy_read(pdata, MII_INTMSK);
- phy_mode |= PHY_INTMSK_ENERGYON_;
- smsc911x_phy_write(pdata, MII_INTMSK, phy_mode);
- }
-
- /* Clear the PM mode and clear the current wakeup status */
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- regval &= ~PMT_CTRL_PM_MODE_;
- regval |= PMT_CTRL_WUPS_;
- printk_pmdbg("[ SUSP ] PMT_CTRL 0x%08lx\n", regval);
- smsc911x_reg_write(regval, pdata, PMT_CTRL);
-
- /* Enable the PME at prior and the wake on LAN */
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- regval |= pdata->pmt_ctrl; /* Enable the ENERGY detect or WOL interrupt */
- regval |= PMT_CTRL_PME_EN_;
-
- if (mode == 1)
- regval |= PMT_CTRL_PM_MODE_D1_;
- else
- regval |= PMT_CTRL_PM_MODE_D2_;
-
- printk_pmdbg("[ SUSP ] PMT_CTRL 0x%08lx\n", regval);
- smsc911x_reg_write(regval, pdata, PMT_CTRL);
-
- return retval;
-}
-
-/* For the state D2 we must disable the host-interrupts */
-static int smsc911x_drv_state_d2(struct smsc911x_data *pdata)
-{
- unsigned long regval;
-
- /* Disable the interrupts of the controller */
- regval = smsc911x_reg_read(pdata, INT_CFG);
- regval &= ~INT_CFG_IRQ_EN_;
- smsc911x_reg_write(regval, pdata, INT_CFG);
-
- /* Set the phy to the power down mode */
- regval = smsc911x_phy_read(pdata, MII_BMCR);
- regval |= BMCR_PDOWN;
- smsc911x_phy_write(pdata, MII_BMCR, regval);
-
- /*
- * Enter into the power mode D2 (the controller doesn't
- * support the mode D3)
- */
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- regval &= ~PMT_CTRL_PM_MODE_;
- regval |= PMT_CTRL_PM_MODE_D2_;
- smsc911x_reg_write(regval, pdata, PMT_CTRL);
-
- return 0;
-}
-
-static int smsc911x_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct net_device *ndev;
- struct smsc911x_data *pdata;
- int retval;
-
- ndev = platform_get_drvdata(pdev);
- pdata = netdev_priv(ndev);
-
- if (!ndev)
- return -ENODEV;
-
- /* @FIXME: Implement the other supported power modes of the smsc911x */
- if (state.event != PM_EVENT_SUSPEND)
- return -ENOTSUPP;
-
- if (netif_running(ndev)) {
-
- /* The below code is coming from the WinCE guys */
- netif_device_detach(ndev);
-
- /*
- * If configured as wakeup-source enter the mode D1 for packet
- * detection using the standard IRQ-line
- */
- if (device_may_wakeup(&pdev->dev)) {
-
- /*
- * Sanity check for verifying that a wakeup-source was
- * configured from the user space. If the energy-detect
- * wakeup was enabled, then use the D2 for entering into the
- * power mode
- */
- if (!(pdata->pmt_ctrl & (PMT_CTRL_WOL_EN_ | PMT_CTRL_ED_EN_))) {
- printk_err("[ SUSP ] No WOL source defined.\n");
- retval = -EINVAL;
- goto err_attach;
- }
-
- /*
- * By the WOL (magic packet, etc.) we can ONLY use the D1, but
- * for the energy detect over the PHY we can change into D2
- */
- if (pdata->pmt_ctrl & PMT_CTRL_WOL_EN_) {
- printk_pmdbg("[ SUSP ] Preparing D1 with wakeup\n");
- smsc911x_drv_state_wakeup(pdata, 1);
- } else {
- /* @TEST: Use first only D1 for the wakups */
- printk_pmdbg("[ SUSP ] Preparing D2 with wakeup\n");
- smsc911x_drv_state_wakeup(pdata, 2);
- }
-
- enable_irq_wake(ndev->irq);
-
- } else {
- /*
- * Enter into the power mode D2 (the controller doesn't
- * support the mode D3)
- */
- smsc911x_drv_state_d2(pdata);
- }
- }
-
- return 0;
-
-err_attach:
- netif_device_attach(ndev);
- return retval;
-}
-
-static int smsc911x_drv_resume(struct platform_device *pdev)
-{
- int retval;
- struct net_device *ndev;
- unsigned long pmt_ctrl;
-
- pmt_ctrl = 0;
- ndev = platform_get_drvdata(pdev);
- retval = 0;
- if (ndev) {
- struct smsc911x_data *pdata = netdev_priv(ndev);
-
- if (netif_running(ndev)) {
- unsigned long timeout;
- unsigned long regval, pmt_ctrl;
-
- /* Assert the byte test register for waking up */
- smsc911x_reg_write(0x0, pdata, BYTE_TEST);
-
- timeout = 100000;
- do {
- timeout--;
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- udelay(1);
- } while (timeout && !(regval & PMT_CTRL_READY_));
-
- if (!timeout) {
- printk_err("Wakeup timeout by the controller\n");
- retval = -EBUSY;
- goto exit_resume;
- }
-
- /*
- * Check if we received a PM interrupt
- * Please take note that we are supporting ONLY the Wake On LAN
- * interrupts, and not the energy-on
- * (Luis Galdos)
- */
- pmt_ctrl = smsc911x_reg_read(pdata, PMT_CTRL);
- regval = smsc911x_reg_read(pdata, INT_STS);
- printk_pmdbg("[ WAKE ] PMT_CTRL 0x%08lx\n", pmt_ctrl);
- printk_pmdbg("[ WAKE ] INT_STS 0x%08lx\n", regval);
- if (regval & (INT_STS_PME_INT_ | INT_STS_PHY_INT_)) {
-
- /* Disable the power management interrupts */
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- pmt_ctrl = regval & (PMT_CTRL_WOL_EN_ | PMT_CTRL_ED_EN_);
- regval &= ~(PMT_CTRL_WOL_EN_ | PMT_CTRL_PME_EN_ |
- PMT_CTRL_ED_EN_);
- smsc911x_reg_write(regval, pdata, PMT_CTRL);
-
- /* Disable the PM interrupts */
- regval = smsc911x_reg_read(pdata, INT_EN);
- regval &= ~(INT_EN_PME_INT_EN_ | INT_EN_PHY_INT_EN_);
- smsc911x_reg_write(regval, pdata, INT_EN);
-
- /* Disable the wakeup-events on the MAC */
- regval = smsc911x_mac_read(pdata, WUCSR);
- regval &= ~(WUCSR_MPEN_);
- smsc911x_mac_write(pdata, WUCSR, regval);
- }
-
- /* @XXX: Clear only the interrupts that were generated */
- regval = (INT_STS_PME_INT_ | INT_STS_PHY_INT_);
- smsc911x_reg_write(regval, pdata, INT_STS);
-
- /* Set the controller into the state D0 */
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- regval &= ~PMT_CTRL_PM_MODE_;
- regval |= PMT_CTRL_PM_MODE_D0_;
- smsc911x_reg_write(regval, pdata, PMT_CTRL);
-
- /* Paranoic sanity checks */
- regval = smsc911x_reg_read(pdata, PMT_CTRL);
- if (regval & PMT_CTRL_PM_MODE_)
- printk_err("PM mode isn't disabled (0x%04lx)\n", regval);
-
- if (!(regval & PMT_CTRL_READY_)) {
- retval = -EBUSY;
- printk_err("Device is still NOT ready.\n");
- goto exit_resume;
- }
-
- regval = smsc911x_phy_read(pdata, MII_BMCR);
- regval &= ~BMCR_PDOWN;
- smsc911x_phy_write(pdata, MII_BMCR, regval);
-
- /* Reenable the interrupts now */
- regval = smsc911x_reg_read(pdata, INT_CFG);
- regval |= INT_CFG_IRQ_EN_;
- smsc911x_reg_write(regval, pdata, INT_CFG);
-
- /* Reset the wakeup control and status register */
- smsc911x_mac_write(pdata, WUCSR, 0x00);
-
- netif_device_attach(ndev);
- }
- }
-
-exit_resume:
- return retval;
-}
-#else
-#define smsc911x_drv_suspend NULL
-#define smsc911x_drv_resume NULL
-#endif /* defined(CONFIG_PM) */
-
-static struct platform_driver smsc911x_driver = {
- .probe = smsc911x_drv_probe,
- .remove = smsc911x_drv_remove,
- .suspend = smsc911x_drv_suspend,
- .resume = smsc911x_drv_resume,
- .driver = {
- .name = SMSC_CHIPNAME,
- },
-};
-
-/* Entry point for loading the module */
-static int __init smsc911x_init_module(void)
-{
- printk(KERN_INFO "SMSC 911X: Starting the platform driver.\n");
- return platform_driver_register(&smsc911x_driver);
-}
-
-/* entry point for unloading the module */
-static void __exit smsc911x_cleanup_module(void)
-{
- platform_driver_unregister(&smsc911x_driver);
-}
-
-module_init(smsc911x_init_module);
-module_exit(smsc911x_cleanup_module);
diff --git a/drivers/net/smsc9118/smsc911x.h b/drivers/net/smsc9118/smsc911x.h
deleted file mode 100644
index 75bb3252b866..000000000000
--- a/drivers/net/smsc9118/smsc911x.h
+++ /dev/null
@@ -1,392 +0,0 @@
-/***************************************************************************
- *
- * Copyright (C) 2004-2007 SMSC
- * Copyright (C) 2005 ARM
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- ***************************************************************************/
-#ifndef __SMSC911X_H__
-#define __SMSC911X_H__
-
-#if defined(CONFIG_MACH_CC9M2443JS) || defined(CONFIG_MACH_CCW9M2443JS) || \
- defined(CONFIG_MACH_CCWMX51JS) || defined(CONFIG_MACH_CCMX51JS)
-# define SMSC_CAN_USE_32BIT 0
-#else
-# define SMSC_CAN_USE_32BIT 1
-#endif
-
-#define TX_FIFO_LOW_THRESHOLD (u32)1600
-#define SMSC911X_EEPROM_SIZE (u32)7
-#define USE_DEBUG 0
-//#define USE_DEBUG 2
-
-/* implements a PHY loopback test at initialisation time, to ensure a packet
- * can be succesfully looped back */
-#define USE_PHY_WORK_AROUND
-
-/* 10/100 LED link-state inversion when media is disconnected */
-/* #define USE_LED1_WORK_AROUND */
-
-/* platform_device configuration data, should be assigned to
- * the platform_device's dev.platform_data */
-struct smsc911x_platform_config {
- unsigned int irq_polarity;
- unsigned int irq_type;
-};
-
-#if USE_DEBUG >= 1
-#define SMSC_WARNING(fmt, args...) \
- printk(KERN_EMERG "SMSC_WARNING: %s: " fmt "\n", \
- __FUNCTION__ , ## args)
-#else
-#define SMSC_WARNING(msg, args...)
-#endif /* USE_DEBUG >= 1 */
-
-#if USE_DEBUG >= 2
-#define SMSC_TRACE(fmt,args...) \
- printk(KERN_EMERG "SMSC_TRACE: %s: " fmt "\n", \
- __FUNCTION__ , ## args)
-#else
-#define SMSC_TRACE(msg, args...)
-#endif /* USE_DEBUG >= 2 */
-
-/* SMSC911x registers and bitfields */
-#define RX_DATA_FIFO 0x00
-
-#define TX_DATA_FIFO 0x20
-#define TX_CMD_A_ON_COMP_ 0x80000000
-#define TX_CMD_A_BUF_END_ALGN_ 0x03000000
-#define TX_CMD_A_4_BYTE_ALGN_ 0x00000000
-#define TX_CMD_A_16_BYTE_ALGN_ 0x01000000
-#define TX_CMD_A_32_BYTE_ALGN_ 0x02000000
-#define TX_CMD_A_DATA_OFFSET_ 0x001F0000
-#define TX_CMD_A_FIRST_SEG_ 0x00002000
-#define TX_CMD_A_LAST_SEG_ 0x00001000
-#define TX_CMD_A_BUF_SIZE_ 0x000007FF
-#define TX_CMD_B_PKT_TAG_ 0xFFFF0000
-#define TX_CMD_B_ADD_CRC_DISABLE_ 0x00002000
-#define TX_CMD_B_DISABLE_PADDING_ 0x00001000
-#define TX_CMD_B_PKT_BYTE_LENGTH_ 0x000007FF
-
-#define RX_STATUS_FIFO 0x40
-#define RX_STS_ES_ 0x00008000
-#define RX_STS_MCAST_ 0x00000400
-
-#define RX_STATUS_FIFO_PEEK 0x44
-
-#define TX_STATUS_FIFO 0x48
-#define TX_STS_ES_ 0x00008000
-
-#define TX_STATUS_FIFO_PEEK 0x4C
-
-#define ID_REV 0x50
-#define ID_REV_CHIP_ID_ 0xFFFF0000
-#define ID_REV_REV_ID_ 0x0000FFFF
-
-#define INT_CFG 0x54
-#define INT_CFG_INT_DEAS_ 0xFF000000
-#define INT_CFG_INT_DEAS_CLR_ 0x00004000
-#define INT_CFG_INT_DEAS_STS_ 0x00002000
-#define INT_CFG_IRQ_INT_ 0x00001000
-#define INT_CFG_IRQ_EN_ 0x00000100
-#define INT_CFG_IRQ_POL_ 0x00000010
-#define INT_CFG_IRQ_TYPE_ 0x00000001
-
-#define INT_STS 0x58
-#define INT_STS_SW_INT_ 0x80000000
-#define INT_STS_TXSTOP_INT_ 0x02000000
-#define INT_STS_RXSTOP_INT_ 0x01000000
-#define INT_STS_RXDFH_INT_ 0x00800000
-#define INT_STS_RXDF_INT_ 0x00400000
-#define INT_STS_TX_IOC_ 0x00200000
-#define INT_STS_RXD_INT_ 0x00100000
-#define INT_STS_GPT_INT_ 0x00080000
-#define INT_STS_PHY_INT_ 0x00040000
-#define INT_STS_PME_INT_ 0x00020000
-#define INT_STS_TXSO_ 0x00010000
-#define INT_STS_RWT_ 0x00008000
-#define INT_STS_RXE_ 0x00004000
-#define INT_STS_TXE_ 0x00002000
-#define INT_STS_TDFU_ 0x00000800
-#define INT_STS_TDFO_ 0x00000400
-#define INT_STS_TDFA_ 0x00000200
-#define INT_STS_TSFF_ 0x00000100
-#define INT_STS_TSFL_ 0x00000080
-#define INT_STS_RXDF_ 0x00000040
-#define INT_STS_RDFL_ 0x00000020
-#define INT_STS_RSFF_ 0x00000010
-#define INT_STS_RSFL_ 0x00000008
-#define INT_STS_GPIO2_INT_ 0x00000004
-#define INT_STS_GPIO1_INT_ 0x00000002
-#define INT_STS_GPIO0_INT_ 0x00000001
-
-#define INT_EN 0x5C
-#define INT_EN_SW_INT_EN_ 0x80000000
-#define INT_EN_TXSTOP_INT_EN_ 0x02000000
-#define INT_EN_RXSTOP_INT_EN_ 0x01000000
-#define INT_EN_RXDFH_INT_EN_ 0x00800000
-#define INT_EN_TIOC_INT_EN_ 0x00200000
-#define INT_EN_RXD_INT_EN_ 0x00100000
-#define INT_EN_GPT_INT_EN_ 0x00080000
-#define INT_EN_PHY_INT_EN_ 0x00040000
-#define INT_EN_PME_INT_EN_ 0x00020000
-#define INT_EN_TXSO_EN_ 0x00010000
-#define INT_EN_RWT_EN_ 0x00008000
-#define INT_EN_RXE_EN_ 0x00004000
-#define INT_EN_TXE_EN_ 0x00002000
-#define INT_EN_TDFU_EN_ 0x00000800
-#define INT_EN_TDFO_EN_ 0x00000400
-#define INT_EN_TDFA_EN_ 0x00000200
-#define INT_EN_TSFF_EN_ 0x00000100
-#define INT_EN_TSFL_EN_ 0x00000080
-#define INT_EN_RXDF_EN_ 0x00000040
-#define INT_EN_RDFL_EN_ 0x00000020
-#define INT_EN_RSFF_EN_ 0x00000010
-#define INT_EN_RSFL_EN_ 0x00000008
-#define INT_EN_GPIO2_INT_ 0x00000004
-#define INT_EN_GPIO1_INT_ 0x00000002
-#define INT_EN_GPIO0_INT_ 0x00000001
-
-#define BYTE_TEST 0x64
-
-#define FIFO_INT 0x68
-#define FIFO_INT_TX_AVAIL_LEVEL_ 0xFF000000
-#define FIFO_INT_TX_STS_LEVEL_ 0x00FF0000
-#define FIFO_INT_RX_AVAIL_LEVEL_ 0x0000FF00
-#define FIFO_INT_RX_STS_LEVEL_ 0x000000FF
-
-#define RX_CFG 0x6C
-#define RX_CFG_RX_END_ALGN_ 0xC0000000
-#define RX_CFG_RX_END_ALGN4_ 0x00000000
-#define RX_CFG_RX_END_ALGN16_ 0x40000000
-#define RX_CFG_RX_END_ALGN32_ 0x80000000
-#define RX_CFG_RX_DMA_CNT_ 0x0FFF0000
-#define RX_CFG_RX_DUMP_ 0x00008000
-#define RX_CFG_RXDOFF_ 0x00001F00
-
-#define TX_CFG 0x70
-#define TX_CFG_TXS_DUMP_ 0x00008000
-#define TX_CFG_TXD_DUMP_ 0x00004000
-#define TX_CFG_TXSAO_ 0x00000004
-#define TX_CFG_TX_ON_ 0x00000002
-#define TX_CFG_STOP_TX_ 0x00000001
-
-#define HW_CFG 0x74
-#define HW_CFG_TTM_ 0x00200000
-#define HW_CFG_SF_ 0x00100000
-#define HW_CFG_TX_FIF_SZ_ 0x000F0000
-#define HW_CFG_TR_ 0x00003000
-#define HW_CFG_SRST_ 0x00000001
-
-/* only available on 115/117 */
-#define HW_CFG_PHY_CLK_SEL_ 0x00000060
-#define HW_CFG_PHY_CLK_SEL_INT_PHY_ 0x00000000
-#define HW_CFG_PHY_CLK_SEL_EXT_PHY_ 0x00000020
-#define HW_CFG_PHY_CLK_SEL_CLK_DIS_ 0x00000040
-#define HW_CFG_SMI_SEL_ 0x00000010
-#define HW_CFG_EXT_PHY_DET_ 0x00000008
-#define HW_CFG_EXT_PHY_EN_ 0x00000004
-#define HW_CFG_SRST_TO_ 0x00000002
-
-/* only available on 116/118 */
-#define HW_CFG_32_16_BIT_MODE_ 0x00000004
-
-#define RX_DP_CTRL 0x78
-#define RX_DP_CTRL_RX_FFWD_ 0x80000000
-
-#define RX_FIFO_INF 0x7C
-#define RX_FIFO_INF_RXSUSED_ 0x00FF0000
-#define RX_FIFO_INF_RXDUSED_ 0x0000FFFF
-
-#define TX_FIFO_INF 0x80
-#define TX_FIFO_INF_TSUSED_ 0x00FF0000
-#define TX_FIFO_INF_TDFREE_ 0x0000FFFF
-
-#define PMT_CTRL 0x84
-#define PMT_CTRL_PM_MODE_ 0x00003000
-#define PMT_CTRL_PM_MODE_D0_ 0x00000000
-#define PMT_CTRL_PM_MODE_D1_ 0x00001000
-#define PMT_CTRL_PM_MODE_D2_ 0x00002000
-#define PMT_CTRL_PM_MODE_D3_ 0x00003000
-#define PMT_CTRL_PHY_RST_ 0x00000400
-#define PMT_CTRL_WOL_EN_ 0x00000200
-#define PMT_CTRL_ED_EN_ 0x00000100
-#define PMT_CTRL_PME_TYPE_ 0x00000040
-#define PMT_CTRL_WUPS_ 0x00000030
-#define PMT_CTRL_WUPS_NOWAKE_ 0x00000000
-#define PMT_CTRL_WUPS_ED_ 0x00000010
-#define PMT_CTRL_WUPS_WOL_ 0x00000020
-#define PMT_CTRL_WUPS_MULTI_ 0x00000030
-#define PMT_CTRL_PME_IND_ 0x00000008
-#define PMT_CTRL_PME_POL_ 0x00000004
-#define PMT_CTRL_PME_EN_ 0x00000002
-#define PMT_CTRL_READY_ 0x00000001
-
-#define GPIO_CFG 0x88
-#define GPIO_CFG_LED3_EN_ 0x40000000
-#define GPIO_CFG_LED2_EN_ 0x20000000
-#define GPIO_CFG_LED1_EN_ 0x10000000
-#define GPIO_CFG_GPIO2_INT_POL_ 0x04000000
-#define GPIO_CFG_GPIO1_INT_POL_ 0x02000000
-#define GPIO_CFG_GPIO0_INT_POL_ 0x01000000
-#define GPIO_CFG_EEPR_EN_ 0x00700000
-#define GPIO_CFG_GPIOBUF2_ 0x00040000
-#define GPIO_CFG_GPIOBUF1_ 0x00020000
-#define GPIO_CFG_GPIOBUF0_ 0x00010000
-#define GPIO_CFG_GPIODIR2_ 0x00000400
-#define GPIO_CFG_GPIODIR1_ 0x00000200
-#define GPIO_CFG_GPIODIR0_ 0x00000100
-#define GPIO_CFG_GPIOD4_ 0x00000020
-#define GPIO_CFG_GPIOD3_ 0x00000010
-#define GPIO_CFG_GPIOD2_ 0x00000004
-#define GPIO_CFG_GPIOD1_ 0x00000002
-#define GPIO_CFG_GPIOD0_ 0x00000001
-
-#define GPT_CFG 0x8C
-#define GPT_CFG_TIMER_EN_ 0x20000000
-#define GPT_CFG_GPT_LOAD_ 0x0000FFFF
-
-#define GPT_CNT 0x90
-#define GPT_CNT_GPT_CNT_ 0x0000FFFF
-
-#define ENDIAN 0x98
-
-#define FREE_RUN 0x9C
-
-#define RX_DROP 0xA0
-
-#define MAC_CSR_CMD 0xA4
-#define MAC_CSR_CMD_CSR_BUSY_ 0x80000000
-#define MAC_CSR_CMD_R_NOT_W_ 0x40000000
-#define MAC_CSR_CMD_CSR_ADDR_ 0x000000FF
-
-#define MAC_CSR_DATA 0xA8
-
-#define AFC_CFG 0xAC
-#define AFC_CFG_AFC_HI_ 0x00FF0000
-#define AFC_CFG_AFC_LO_ 0x0000FF00
-#define AFC_CFG_BACK_DUR_ 0x000000F0
-#define AFC_CFG_FCMULT_ 0x00000008
-#define AFC_CFG_FCBRD_ 0x00000004
-#define AFC_CFG_FCADD_ 0x00000002
-#define AFC_CFG_FCANY_ 0x00000001
-
-#define E2P_CMD 0xB0
-#define E2P_CMD_EPC_BUSY_ 0x80000000
-#define E2P_CMD_EPC_CMD_ 0x70000000
-#define E2P_CMD_EPC_CMD_READ_ 0x00000000
-#define E2P_CMD_EPC_CMD_EWDS_ 0x10000000
-#define E2P_CMD_EPC_CMD_EWEN_ 0x20000000
-#define E2P_CMD_EPC_CMD_WRITE_ 0x30000000
-#define E2P_CMD_EPC_CMD_WRAL_ 0x40000000
-#define E2P_CMD_EPC_CMD_ERASE_ 0x50000000
-#define E2P_CMD_EPC_CMD_ERAL_ 0x60000000
-#define E2P_CMD_EPC_CMD_RELOAD_ 0x70000000
-#define E2P_CMD_EPC_TIMEOUT_ 0x00000200
-#define E2P_CMD_MAC_ADDR_LOADED_ 0x00000100
-#define E2P_CMD_EPC_ADDR_ 0x000000FF
-
-#define E2P_DATA 0xB4
-#define E2P_DATA_EEPROM_DATA_ 0x000000FF
-#define LAN_REGISTER_EXTENT 0x00000100
-
-/*
- * MAC Control and Status Register (Indirect Address)
- * Offset (through the MAC_CSR CMD and DATA port)
- */
-#define MAC_CR 0x01
-#define MAC_CR_RXALL_ 0x80000000
-#define MAC_CR_HBDIS_ 0x10000000
-#define MAC_CR_RCVOWN_ 0x00800000
-#define MAC_CR_LOOPBK_ 0x00200000
-#define MAC_CR_FDPX_ 0x00100000
-#define MAC_CR_MCPAS_ 0x00080000
-#define MAC_CR_PRMS_ 0x00040000
-#define MAC_CR_INVFILT_ 0x00020000
-#define MAC_CR_PASSBAD_ 0x00010000
-#define MAC_CR_HFILT_ 0x00008000
-#define MAC_CR_HPFILT_ 0x00002000
-#define MAC_CR_LCOLL_ 0x00001000
-#define MAC_CR_BCAST_ 0x00000800
-#define MAC_CR_DISRTY_ 0x00000400
-#define MAC_CR_PADSTR_ 0x00000100
-#define MAC_CR_BOLMT_MASK_ 0x000000C0
-#define MAC_CR_DFCHK_ 0x00000020
-#define MAC_CR_TXEN_ 0x00000008
-#define MAC_CR_RXEN_ 0x00000004
-
-#define ADDRH 0x02
-
-#define ADDRL 0x03
-
-#define HASHH 0x04
-
-#define HASHL 0x05
-
-#define MII_ACC 0x06
-#define MII_ACC_PHY_ADDR_ 0x0000F800
-#define MII_ACC_MIIRINDA_ 0x000007C0
-#define MII_ACC_MII_WRITE_ 0x00000002
-#define MII_ACC_MII_BUSY_ 0x00000001
-
-#define MII_DATA 0x07
-
-#define FLOW 0x08
-#define FLOW_FCPT_ 0xFFFF0000
-#define FLOW_FCPASS_ 0x00000004
-#define FLOW_FCEN_ 0x00000002
-#define FLOW_FCBSY_ 0x00000001
-
-#define VLAN1 0x09
-
-#define VLAN2 0x0A
-
-#define WUFF 0x0B
-
-#define WUCSR 0x0C
-#define WUCSR_GUE_ 0x00000200
-#define WUCSR_WUFR_ 0x00000040
-#define WUCSR_MPR_ 0x00000020
-#define WUCSR_WAKE_EN_ 0x00000004
-#define WUCSR_MPEN_ 0x00000002
-
-/*
- * Phy definitions (vendor-specific)
- */
-#define LAN9118_PHY_ID 0x00C0001C
-
-#define MII_INTSTS 0x1D
-
-#define MII_INTMSK 0x1E
-#define PHY_INTMSK_AN_RCV_ (1 << 1)
-#define PHY_INTMSK_PDFAULT_ (1 << 2)
-#define PHY_INTMSK_AN_ACK_ (1 << 3)
-#define PHY_INTMSK_LNKDOWN_ (1 << 4)
-#define PHY_INTMSK_RFAULT_ (1 << 5)
-#define PHY_INTMSK_AN_COMP_ (1 << 6)
-#define PHY_INTMSK_ENERGYON_ (1 << 7)
-#define PHY_INTMSK_DEFAULT_ (PHY_INTMSK_ENERGYON_ | \
- PHY_INTMSK_AN_COMP_ | \
- PHY_INTMSK_RFAULT_ | \
- PHY_INTMSK_LNKDOWN_)
-
-#define ADVERTISE_PAUSE_ALL (ADVERTISE_PAUSE_CAP | \
- ADVERTISE_PAUSE_ASYM)
-
-#define LPA_PAUSE_ALL (LPA_PAUSE_CAP | \
- LPA_PAUSE_ASYM)
-
-#endif /* __SMSC911X_H__ */