diff options
author | Bhuvanchandra DV <bhuvanchandra.dv@toradex.com> | 2016-04-25 15:15:45 +0530 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2016-06-27 08:58:09 +0200 |
commit | 62ff23d64d1a504e5869643b442f806631b7c6e8 (patch) | |
tree | a465f58100bf3cb0287e89cd960fb4c3c012c1ff | |
parent | aed3304118e4fe4ceceeb9aaff2874bbd9b27def (diff) |
net: ethernet: freescale: vf610_l2_switch
Drop the ioctl configuration functionality and configure
the switch in a default switching mode.
Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
-rw-r--r-- | drivers/net/ethernet/freescale/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fsl_l2_switch.c | 4245 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fsl_l2_switch.h (renamed from include/linux/fsl_l2_switch.h) | 616 |
3 files changed, 735 insertions, 4130 deletions
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 1a239f458617..84e29f5da4ba 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -32,10 +32,10 @@ config FEC config FSL_L2_SWITCH bool "Ethernet switch controller(Freescale ColdFire and Vybrid platform)" - depends on (SOC_MVFA5 || SOC_VF610) + depends on (SOC_VF610) help Say Y here if you want to use the built-in ethernet switch - controller on some ColdFire processors. + controller on Vybrid processors. The Integrated Ethernet switch engine is compatible with 10/100 MAC-NET core. diff --git a/drivers/net/ethernet/freescale/fsl_l2_switch.c b/drivers/net/ethernet/freescale/fsl_l2_switch.c index ecad59c2c151..4d961c0dab3b 100644 --- a/drivers/net/ethernet/freescale/fsl_l2_switch.c +++ b/drivers/net/ethernet/freescale/fsl_l2_switch.c @@ -14,13 +14,8 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/string.h> -#include <linux/ptrace.h> #include <linux/errno.h> #include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/pci.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/netdevice.h> @@ -29,3056 +24,507 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/bitops.h> -#include <linux/platform_device.h> -#include <linux/of_platform.h> -#include <linux/of_address.h> -#include <linux/fsl_devices.h> #include <linux/phy.h> -#include <linux/kthread.h> #include <linux/syscalls.h> -#include <linux/uaccess.h> -#include <linux/io.h> -#include <linux/signal.h> #include <linux/clk.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/of_net.h> -#include <asm/irq.h> -#include <asm/pgtable.h> -#include <asm/cacheflush.h> -#include <linux/version.h> -#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */ -#include <mach/hardware.h> -#include <mach/fsl_l2_switch.h> -#else -#include <linux/fsl_l2_switch.h> -#endif +#include "fsl_l2_switch.h" -#define SWITCH_MAX_PORTS 1 -#define CONFIG_FEC_SHARED_PHY +/* switch ports status */ +struct port_status ports_link_status; static unsigned char macaddr[ETH_ALEN]; module_param_array(macaddr, byte, NULL, 0); MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); -/* Interrupt events/masks */ -#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ -#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ -#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ -#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ -#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ -#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ -#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ -#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ -#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ -#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ - -static int switch_enet_open(struct net_device *dev); -static int switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t switch_enet_interrupt(int irq, void *dev_id); -static void switch_enet_tx(struct net_device *dev); -static void switch_enet_rx(struct net_device *dev); -static int switch_enet_close(struct net_device *dev); -#ifdef UNUSED -static void set_multicast_list(struct net_device *dev); -#endif -static void switch_restart(struct net_device *dev, int duplex); -static void switch_stop(struct net_device *dev); -static void switch_get_mac_address(struct net_device *dev); - -#define NMII 20 - -/* Make MII read/write commands for the FEC */ -#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) -#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ - (VAL & 0xffff)) -/* MII MMFR bits definition */ -#define ESW_MMFR_ST (1 << 30) -#define ESW_MMFR_OP_READ (2 << 28) -#define ESW_MMFR_OP_WRITE (1 << 28) -#define ESW_MMFR_PA(v) ((v & 0x1f) << 23) -#define ESW_MMFR_RA(v) ((v & 0x1f) << 18) -#define ESW_MMFR_TA (2 << 16) -#define ESW_MMFR_DATA(v) (v & 0xffff) - -#define ESW_MII_TIMEOUT 30 /* ms */ - -/* Transmitter timeout.*/ -#define TX_TIMEOUT (2*HZ) - -/*last read entry from learning interface*/ -eswPortInfo g_info; -/* switch ports status */ -struct port_status ports_link_status; - -/* the user space pid, used to send the link change to user space */ -long user_pid = 1; - -/* ----------------------------------------------------------------*/ -/* - * Calculate Galois Field Arithmetic CRC for Polynom x^8+x^2+x+1. - * It omits the final shift in of 8 zeroes a "normal" CRC would do - * (getting the remainder). - * - * Examples (hexadecimal values):<br> - * 10-11-12-13-14-15 => CRC=0xc2 - * 10-11-cc-dd-ee-00 => CRC=0xe6 - * - * param: pmacaddress - * A 6-byte array with the MAC address. - * The first byte is the first byte transmitted - * return The 8-bit CRC in bits 7:0 - */ -int crc8_calc(unsigned char *pmacaddress) -{ - /* byte index */ - int byt; - /* bit index */ - int bit; - int inval; - int crc; - /* preset */ - crc = 0x12; - for (byt = 0; byt < 6; byt++) { - inval = (((int)pmacaddress[byt]) & 0xff); - /* - * shift bit 0 to bit 8 so all our bits - * travel through bit 8 - * (simplifies below calc) - */ - inval <<= 8; - - for (bit = 0; bit < 8; bit++) { - /* next input bit comes into d7 after shift */ - crc |= inval & 0x100; - if (crc & 0x01) - /* before shift */ - crc ^= 0x1c0; - - crc >>= 1; - inval >>= 1; - } - - } - /* upper bits are clean as we shifted in zeroes! */ - return crc; -} - -void read_atable(struct switch_enet_private *fep, - int index, unsigned long *read_lo, unsigned long *read_hi) -{ - unsigned long atable_base = (unsigned long)fep->macbase; - - *read_lo = readl((void *)(atable_base + (index << 3))); - *read_hi = readl((void *)(atable_base + (index << 3) + 4)); -} - -void write_atable(struct switch_enet_private *fep, - int index, unsigned long write_lo, unsigned long write_hi) -{ - unsigned long atable_base = (unsigned long)fep->macbase; - - writel(write_lo, (void *)atable_base + (index << 3)); - writel(write_hi, (void *)atable_base + (index<<3) + 4); -} - -/* Check if the Port Info FIFO has data available - * for reading. 1 valid, 0 invalid*/ -int esw_portinfofifo_status(struct switch_enet_private *fep) -{ - return readl(fep->membase + FEC_ESW_LSR); -} - -/* Initialize the Port Info FIFO. */ -void esw_portinfofifo_initialize(struct switch_enet_private *fep) -{ - unsigned long tmp; - - /* disable all learn */ - tmp = readl(fep->membase + FEC_ESW_IMR); - tmp &= (~FSL_ESW_IMR_LRN); - writel(tmp, fep->membase + FEC_ESW_IMR); - - /* remove all entries from FIFO */ - while (esw_portinfofifo_status(fep)) { - /* read one data word */ - tmp = readl(fep->membase + FEC_ESW_LREC0); - tmp = readl(fep->membase + FEC_ESW_LREC1); - } - -} - -/* Read one element from the HW receive FIFO (Queue) - * if available and return it. - * return ms_HwPortInfo or null if no data is available - */ -eswPortInfo *esw_portinfofifo_read(struct switch_enet_private *fep) -{ - unsigned long tmp; - - /* check learning record valid */ - if (!(readl(fep->membase + FEC_ESW_LSR))) - return NULL; - - /*read word from FIFO*/ - g_info.maclo = readl(fep->membase + FEC_ESW_LREC0); - - /*but verify that we actually did so - * (0=no data available)*/ - if (g_info.maclo == 0) - return NULL; - - /* read 2nd word from FIFO */ - tmp = readl(fep->membase + FEC_ESW_LREC1); - g_info.machi = tmp & 0xffff; - g_info.hash = (tmp >> 16) & 0xff; - g_info.port = (tmp >> 24) & 0xf; - - return &g_info; -} - -/* Clear complete MAC Look Up Table */ -void esw_clear_atable(struct switch_enet_private *fep) -{ - int index; - for (index = 0; index < 2048; index++) - write_atable(fep, index, 0, 0); -} - -void esw_dump_atable(struct switch_enet_private *fep) -{ - int index; - unsigned long read_lo, read_hi; - for (index = 0; index < 2048; index++) - read_atable(fep, index, &read_lo, &read_hi); -} - -/* - * pdates MAC address lookup table with a static entry - * Searches if the MAC address is already there in the block and replaces - * the older entry with new one. If MAC address is not there then puts a - * new entry in the first empty slot available in the block - * - * mac_addr Pointer to the array containing MAC address to - * be put as static entry - * port Port bitmask numbers to be added in static entry, - * valid values are 1-7 - * priority Priority for the static entry in table - * - * return 0 for a successful update else -1 when no slot available - */ -int esw_update_atable_static(unsigned char *mac_addr, - unsigned int port, unsigned int priority, - struct switch_enet_private *fep) -{ - unsigned long block_index, entry, index_end; - unsigned long read_lo, read_hi; - unsigned long write_lo, write_hi; - - write_lo = (unsigned long)((mac_addr[3] << 24) | - (mac_addr[2] << 16) | - (mac_addr[1] << 8) | - mac_addr[0]); - write_hi = (unsigned long)(0 | - (port << AT_SENTRY_PORTMASK_shift) | - (priority << AT_SENTRY_PRIO_shift) | - (AT_ENTRY_TYPE_STATIC << AT_ENTRY_TYPE_shift) | - (AT_ENTRY_RECORD_VALID << AT_ENTRY_VALID_shift) | - (mac_addr[5] << 8) | (mac_addr[4])); - - block_index = GET_BLOCK_PTR(crc8_calc(mac_addr)); - index_end = block_index + ATABLE_ENTRY_PER_SLOT; - /* Now search all the entries in the selected block */ - for (entry = block_index; entry < index_end; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - /* - * MAC address matched, so update the - * existing entry - * even if its a dynamic one - */ - if ((read_lo == write_lo) && ((read_hi & 0x0000ffff) == - (write_hi & 0x0000ffff))) { - write_atable(fep, entry, write_lo, write_hi); - return 0; - } else if (!(read_hi & (1 << 16))) { - /* - * Fill this empty slot (valid bit zero), - * assuming no holes in the block - */ - write_atable(fep, entry, write_lo, write_hi); - fep->atCurrEntries++; - return 0; - } - } - - /* No space available for this static entry */ - return -1; -} - -/* lookup entry in given Address Table slot and - * insert (learn) it if it is not found. - * return 0 if entry was found and updated. - * 1 if entry was not found and has been inserted (learned). - */ -int esw_update_atable_dynamic(unsigned char *mac_addr, unsigned int port, - unsigned int currTime, struct switch_enet_private *fep) +static void switch_adjust_link1(struct net_device *dev) { - unsigned long block_index, entry, index_end; - unsigned long read_lo, read_hi; - unsigned long write_lo, write_hi; - unsigned long tmp; - int time, timeold, indexold; - - /* prepare update port and timestamp */ - write_hi = (mac_addr[5] << 8) | (mac_addr[4]); - write_lo = (unsigned long)((mac_addr[3] << 24) | - (mac_addr[2] << 16) | - (mac_addr[1] << 8) | - mac_addr[0]); - tmp = AT_ENTRY_RECORD_VALID << AT_ENTRY_VALID_shift; - tmp |= AT_ENTRY_TYPE_DYNAMIC << AT_ENTRY_TYPE_shift; - tmp |= currTime << AT_DENTRY_TIME_shift; - tmp |= port << AT_DENTRY_PORT_shift; - tmp |= write_hi; - - /* - * linear search through all slot - * entries and update if found - */ - block_index = GET_BLOCK_PTR(crc8_calc(mac_addr)); - index_end = block_index + ATABLE_ENTRY_PER_SLOT; - /* Now search all the entries in the selected block */ - for (entry = block_index; entry < index_end; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - - if ((read_lo == write_lo) && - ((read_hi & 0x0000ffff) == - (write_hi & 0x0000ffff))) { - /* found correct address, - * update timestamp. */ - write_atable(fep, entry, write_lo, tmp); - return 0; - } else if (!(read_hi & (1 << 16))) { - /* slot is empty, then use it - * for new entry - * Note: There are no holes, - * therefore cannot be any - * more that need to be compared. - */ - write_atable(fep, entry, write_lo, tmp); - /* statistics (we do it between writing - * .hi an .lo due to - * hardware limitation... - */ - fep->atCurrEntries++; - /* newly inserted */ - return 1; - } - } - - /* - * no more entry available in blockk ... - * overwrite oldest - */ - timeold = 0; - indexold = 0; - for (entry = block_index; entry < index_end; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - time = AT_EXTRACT_TIMESTAMP(read_hi); - time = TIMEDELTA(currTime, time); - if (time > timeold) { - /* is it older ?*/ - timeold = time; - indexold = entry; - } - } - - write_atable(fep, indexold, write_lo, tmp); - /* Statistics (do it inbetween - * writing to .lo and .hi*/ - fep->atBlockOverflows++; - /* newly inserted */ - return 1; -} + struct switch_enet_private *priv = netdev_priv(dev); + struct phy_device *phydev1 = priv->phydev[0]; + int new_state = 0; -int esw_update_atable_dynamic1(unsigned long write_lo, unsigned long write_hi, - int block_index, unsigned int port, unsigned int currTime, - struct switch_enet_private *fep) -{ - unsigned long entry, index_end; - unsigned long read_lo, read_hi; - unsigned long tmp; - int time, timeold, indexold; - - /* prepare update port and timestamp */ - tmp = AT_ENTRY_RECORD_VALID << AT_ENTRY_VALID_shift; - tmp |= AT_ENTRY_TYPE_DYNAMIC << AT_ENTRY_TYPE_shift; - tmp |= currTime << AT_DENTRY_TIME_shift; - tmp |= port << AT_DENTRY_PORT_shift; - tmp |= write_hi; - - /* - * linear search through all slot - * entries and update if found - */ - index_end = block_index + ATABLE_ENTRY_PER_SLOT; - /* Now search all the entries in the selected block */ - for (entry = block_index; entry < index_end; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - if ((read_lo == write_lo) && - ((read_hi & 0x0000ffff) == - (write_hi & 0x0000ffff))) { - /* found correct address, - * update timestamp. */ - write_atable(fep, entry, write_lo, tmp); - return 0; - } else if (!(read_hi & (1 << 16))) { - /* slot is empty, then use it - * for new entry - * Note: There are no holes, - * therefore cannot be any - * more that need to be compared. - */ - write_atable(fep, entry, write_lo, tmp); - /* statistics (we do it between writing - * .hi an .lo due to - * hardware limitation... - */ - fep->atCurrEntries++; - /* newly inserted */ - return 1; + if (phydev1->link != PHY_DOWN) { + if (phydev1->duplex != priv->phy1_duplex) { + new_state = 1; + priv->phy1_duplex = phydev1->duplex; } - } - /* - * no more entry available in block ... - * overwrite oldest - */ - timeold = 0; - indexold = 0; - for (entry = block_index; entry < index_end; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - time = AT_EXTRACT_TIMESTAMP(read_hi); - time = TIMEDELTA(currTime, time); - if (time > timeold) { - /* is it older ?*/ - timeold = time; - indexold = entry; + if (phydev1->speed != priv->phy1_speed) { + new_state = 1; + priv->phy1_speed = phydev1->speed; } - } - - write_atable(fep, indexold, write_lo, tmp); - /* Statistics (do it inbetween - * writing to .lo and .hi*/ - fep->atBlockOverflows++; - /* newly inserted */ - return 1; -} -/* - * Delete one dynamic entry within the given block - * of 64-bit entries. - * return number of valid entries in the block after deletion. - */ -int esw_del_atable_dynamic(struct switch_enet_private *fep, - int blockidx, int entryidx) -{ - unsigned long index_start, index_end; - int i; - unsigned long read_lo, read_hi; - - /* the entry to delete */ - index_start = blockidx + entryidx; - /* one after last */ - index_end = blockidx + ATABLE_ENTRY_PER_SLOT; - /* Statistics */ - fep->atCurrEntries--; - - if (entryidx == (ATABLE_ENTRY_PER_SLOT - 1)) { - /* if it is the very last entry, - * just delete it without further efford*/ - write_atable(fep, index_start, 0, 0); - /*number of entries left*/ - i = ATABLE_ENTRY_PER_SLOT - 1; - return i; - } else { - /*not the last in the block, then - * shift all that follow the one - * that is deleted to avoid "holes". - */ - for (i = index_start; i < (index_end - 1); i++) { - read_atable(fep, i + 1, &read_lo, &read_hi); - /* move it down */ - write_atable(fep, i, read_lo, read_hi); - if (!(read_hi & (1 << 16))) { - /* stop if we just copied the last */ - return i - blockidx; - } + if (priv->phy1_old_link == PHY_DOWN) { + new_state = 1; + priv->phy1_old_link = phydev1->link; } - - /*moved all entries up to the last. - * then set invalid flag in the last*/ - write_atable(fep, index_end - 1, 0, 0); - /* number of valid entries left */ - return i - blockidx; + } else if (priv->phy1_old_link) { + new_state = 1; + priv->phy1_old_link = PHY_DOWN; + priv->phy1_speed = 0; + priv->phy1_duplex = -1; } -} -void esw_atable_dynamicms_del_entries_for_port( - struct switch_enet_private *fep, int port_index) -{ - unsigned long read_lo, read_hi; - unsigned int port_idx; - int i; - - for (i = 0; i < ESW_ATABLE_MEM_NUM_ENTRIES; i++) { - read_atable(fep, i, &read_lo, &read_hi); - if (read_hi & (1 << 16)) { - port_idx = AT_EXTRACT_PORT(read_hi); - - if (port_idx == port_index) - write_atable(fep, i, 0, 0); - } + if (new_state) { + ports_link_status.port1_link_status = phydev1->link; + phy_print_status(phydev1); } } -void esw_atable_dynamicms_del_entries_for_other_port( - struct switch_enet_private *fep, - int port_index) +static void switch_adjust_link2(struct net_device *dev) { - unsigned long read_lo, read_hi; - unsigned int port_idx; - int i; - - for (i = 0; i < ESW_ATABLE_MEM_NUM_ENTRIES; i++) { - read_atable(fep, i, &read_lo, &read_hi); - if (read_hi & (1 << 16)) { - port_idx = AT_EXTRACT_PORT(read_hi); + struct switch_enet_private *priv = netdev_priv(dev); + struct phy_device *phydev2 = priv->phydev[1]; + int new_state = 0; - if (port_idx != port_index) - write_atable(fep, i, 0, 0); + if (phydev2->link != PHY_DOWN) { + if (phydev2->duplex != priv->phy2_duplex) { + new_state = 1; + priv->phy2_duplex = phydev2->duplex; } - } -} -/* - * Scan one complete block (Slot) for outdated entries and delete them. - * blockidx index of block of entries that should be analyzed. - * return number of deleted entries, 0 if nothing was modified. - */ -int esw_atable_dynamicms_check_block_age( - struct switch_enet_private *fep, int blockidx) { - - int i, tm, tdelta; - int deleted = 0, entries = 0; - unsigned long read_lo, read_hi; - /* Scan all entries from last down to - * have faster deletion speed if necessary*/ - for (i = (blockidx + ATABLE_ENTRY_PER_SLOT - 1); - i >= blockidx; i--) { - read_atable(fep, i, &read_lo, &read_hi); - - if (read_hi & (1 << 16)) { - /* the entry is valide*/ - tm = AT_EXTRACT_TIMESTAMP(read_hi); - tdelta = TIMEDELTA(fep->currTime, tm); - if (tdelta > fep->ageMax) { - esw_del_atable_dynamic(fep, - blockidx, i-blockidx); - deleted++; - } else { - /* statistics */ - entries++; - } + if (phydev2->speed != priv->phy2_speed) { + new_state = 1; + priv->phy2_speed = phydev2->speed; } - } - - /*update statistics*/ - if (fep->atMaxEntriesPerBlock < entries) - fep->atMaxEntriesPerBlock = entries; - return deleted; -} - -/* scan the complete address table and find the most current entry. - * The time of the most current entry then is used as current time - * for the context structure. - * In addition the atCurrEntries value is updated as well. - * return time that has been set in the context. - */ -int esw_atable_dynamicms_find_set_latesttime( - struct switch_enet_private *fep) { - - int tm_min, tm_max, tm; - int delta, cur, i; - unsigned long read_lo, read_hi; - - tm_min = (1 << AT_DENTRY_TIMESTAMP_WIDTH) - 1; - tm_max = 0; - cur = 0; - - for (i = 0; i < ESW_ATABLE_MEM_NUM_ENTRIES; i++) { - read_atable(fep, i, &read_lo, &read_hi); - if (read_hi & (1 << 16)) { - /*the entry is valid*/ - tm = AT_EXTRACT_TIMESTAMP(read_hi); - if (tm > tm_max) - tm_max = tm; - if (tm < tm_min) - tm_min = tm; - cur++; + if (priv->phy2_old_link == PHY_DOWN) { + new_state = 1; + priv->phy2_old_link = phydev2->link; } + } else if (priv->phy2_old_link) { + new_state = 1; + priv->phy2_old_link = PHY_DOWN; + priv->phy2_speed = 0; + priv->phy2_duplex = -1; } - delta = TIMEDELTA(tm_max, tm_min); - if (delta < fep->ageMax) { - /*Difference must be in range*/ - fep->currTime = tm_max; - } else { - fep->currTime = tm_min; + if (new_state) { + ports_link_status.port2_link_status = phydev2->link; + phy_print_status(phydev2); } - - fep->atCurrEntries = cur; - return fep->currTime; } -int esw_atable_dynamicms_get_port( - struct switch_enet_private *fep, - unsigned long write_lo, - unsigned long write_hi, - int block_index) +static void switch_hw_init(struct net_device *dev) { - int i, index_end; - unsigned long read_lo, read_hi, port; - - index_end = block_index + ATABLE_ENTRY_PER_SLOT; - /* Now search all the entries in the selected block */ - for (i = block_index; i < index_end; i++) { - read_atable(fep, i, &read_lo, &read_hi); - - if ((read_lo == write_lo) && - ((read_hi & 0x0000ffff) == - (write_hi & 0x0000ffff))) { - /* found correct address,*/ - if (read_hi & (1 << 16)) { - /*extract the port index from the valid entry*/ - port = AT_EXTRACT_PORT(read_hi); - return port; - } - } - } - - return -1; -} + struct switch_enet_private *fep = netdev_priv(dev); -/* Get the port index from the source MAC address - * of the received frame - * @return port index - */ -int esw_atable_dynamicms_get_portindex_from_mac( - struct switch_enet_private *fep, - unsigned char *mac_addr, - unsigned long write_lo, - unsigned long write_hi) -{ - int blockIdx; - int rc; - /*compute the block index*/ - blockIdx = GET_BLOCK_PTR(crc8_calc(mac_addr)); - /* Get the ingress port index of the received BPDU */ - rc = esw_atable_dynamicms_get_port(fep, - write_lo, write_hi, blockIdx); - - return rc; -} + /* Initialize MAC 0/1 */ + writel(FSL_FEC_RCR_MAX_FL(1522) | FSL_FEC_RCR_RMII_MODE + | FSL_FEC_RCR_PROM | FSL_FEC_RCR_MII_MODE + | FSL_FEC_RCR_MII_MODE, fep->enetbase + FSL_FEC_RCR0); + writel(FSL_FEC_RCR_MAX_FL(1522) | FSL_FEC_RCR_RMII_MODE + | FSL_FEC_RCR_PROM | FSL_FEC_RCR_MII_MODE + | FSL_FEC_RCR_MII_MODE, fep->enetbase + FSL_FEC_RCR1); -/* dynamicms MAC address table learn and migration*/ -int esw_atable_dynamicms_learn_migration( - struct switch_enet_private *fep, - int currTime) -{ - eswPortInfo *pESWPortInfo; - int index; - int inserted = 0; - - pESWPortInfo = esw_portinfofifo_read(fep); - /* Anything to learn */ - if (pESWPortInfo != 0) { - /*get block index from lookup table*/ - index = GET_BLOCK_PTR(pESWPortInfo->hash); - inserted = esw_update_atable_dynamic1( - pESWPortInfo->maclo, - pESWPortInfo->machi, index, - pESWPortInfo->port, currTime, fep); - } + writel(FSL_FEC_TCR_FDEN, fep->enetbase + FSL_FEC_TCR0); + writel(FSL_FEC_TCR_FDEN, fep->enetbase + FSL_FEC_TCR1); - return 0; -} -/* -----------------------------------------------------------------*/ -/* - * esw_forced_forward - * The frame is forwared to the forced destination ports. - * It only replace the MAC lookup function, - * all other filtering(eg.VLAN verification) act as normal - */ -int esw_forced_forward(struct switch_enet_private *fep, - int port1, int port2, int enable) -{ - unsigned long tmp = 0; + writel(0x1a, fep->enetbase + FSL_FEC_MSCR0); - /* Enable Forced forwarding for port num */ - if ((port1 == 1) && (port2 == 1)) - tmp |= FSL_ESW_P0FFEN_FD(3); - else if (port1 == 1) - /*Enable Forced forwarding for port 1 only*/ - tmp |= FSL_ESW_P0FFEN_FD(1); - else if (port2 == 1) - /*Enable Forced forwarding for port 2 only*/ - tmp |= FSL_ESW_P0FFEN_FD(2); - else { - printk(KERN_ERR "%s:do not support " - "the forced forward mode" - "port1 %x port2 %x\n", - __func__, port1, port2); - return -1; - } + /* Set the station address for the ENET Adapter */ + writel(dev->dev_addr[3] | + dev->dev_addr[2] << 8 | + dev->dev_addr[1] << 16 | + dev->dev_addr[0] << 24, fep->enetbase + FSL_FEC_PALR0); + writel((dev->dev_addr[5] << 16) | + (dev->dev_addr[4] << 24), + fep->enetbase + FSL_FEC_PAUR0); + writel(dev->dev_addr[3] | + dev->dev_addr[2] << 8 | + dev->dev_addr[1] << 16 | + dev->dev_addr[0] << 24, fep->enetbase + FSL_FEC_PALR1); + writel((dev->dev_addr[5] << 16) | + (dev->dev_addr[4] << 24), + fep->enetbase + FSL_FEC_PAUR1); - if (enable == 1) - tmp |= FSL_ESW_P0FFEN_FEN; - else if (enable == 0) - tmp &= ~FSL_ESW_P0FFEN_FEN; - else { - printk(KERN_ERR "%s: the enable %x is error\n", - __func__, enable); - return -2; - } + writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->enetbase + FSL_FEC_EIMR0); + writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->enetbase + FSL_FEC_EIMR1); - writel(tmp, fep->membase + FEC_ESW_P0FFEN); - return 0; + writel(FSL_FEC_ECR_ETHER_EN | + (0x1 << 8), fep->enetbase + FSL_FEC_ECR0); + writel(FSL_FEC_ECR_ETHER_EN | + (0x1 << 8), fep->enetbase + FSL_FEC_ECR1); + udelay(20); } -void esw_get_forced_forward( - struct switch_enet_private *fep, - unsigned long *ulForceForward) +/* Set a MAC change in hardware.*/ +static void switch_get_mac_address(struct net_device *dev) { - *ulForceForward = readl(fep->membase + FEC_ESW_P0FFEN); -} + struct switch_enet_private *fep = netdev_priv(dev); + unsigned char *iap, tmpaddr[ETH_ALEN]; -void esw_get_port_enable( - struct switch_enet_private *fep, - unsigned long *ulPortEnable) -{ - *ulPortEnable = readl(fep->membase + FEC_ESW_PER); -} + iap = macaddr; -/* - * enable or disable port n tx or rx - * tx_en 0 disable port n tx - * tx_en 1 enable port n tx - * rx_en 0 disbale port n rx - * rx_en 1 enable port n rx - */ -int esw_port_enable_config(struct switch_enet_private *fep, - int port, int tx_en, int rx_en) -{ - unsigned long tmp = 0; + if (!is_valid_ether_addr(iap)) { + struct device_node *np = fep->pdev->dev.of_node; - tmp = readl(fep->membase + FEC_ESW_PER); - if (tx_en == 1) { - if (port == 0) - tmp |= FSL_ESW_PER_TE0; - else if (port == 1) - tmp |= FSL_ESW_PER_TE1; - else if (port == 2) - tmp |= FSL_ESW_PER_TE2; - else { - printk(KERN_ERR "%s:do not support the" - " port %x tx enable\n", - __func__, port); - return -1; - } - } else if (tx_en == 0) { - if (port == 0) - tmp &= (~FSL_ESW_PER_TE0); - else if (port == 1) - tmp &= (~FSL_ESW_PER_TE1); - else if (port == 2) - tmp &= (~FSL_ESW_PER_TE2); - else { - printk(KERN_ERR "%s:do not support " - "the port %x tx disable\n", - __func__, port); - return -2; - } - } else { - printk(KERN_ERR "%s:do not support the port %x" - " tx op value %x\n", - __func__, port, tx_en); - return -3; - } + if (np) { + const char *mac = of_get_mac_address(np); - if (rx_en == 1) { - if (port == 0) - tmp |= FSL_ESW_PER_RE0; - else if (port == 1) - tmp |= FSL_ESW_PER_RE1; - else if (port == 2) - tmp |= FSL_ESW_PER_RE2; - else { - printk(KERN_ERR "%s:do not support the " - "port %x rx enable\n", - __func__, port); - return -4; - } - } else if (rx_en == 0) { - if (port == 0) - tmp &= (~FSL_ESW_PER_RE0); - else if (port == 1) - tmp &= (~FSL_ESW_PER_RE1); - else if (port == 2) - tmp &= (~FSL_ESW_PER_RE2); - else { - printk(KERN_ERR "%s:do not support the " - "port %x rx disable\n", - __func__, port); - return -5; + if (mac) + iap = (unsigned char *) mac; } - } else { - printk(KERN_ERR "%s:do not support the port %x" - " rx op value %x\n", - __func__, port, tx_en); - return -6; - } - - writel(tmp, fep->membase + FEC_ESW_PER); - return 0; -} - - -void esw_get_port_broadcast(struct switch_enet_private *fep, - unsigned long *ulPortBroadcast) -{ - *ulPortBroadcast = readl(fep->membase + FEC_ESW_DBCR); -} - -int esw_port_broadcast_config(struct switch_enet_private *fep, - int port, int enable) -{ - unsigned long tmp = 0; - - if ((port > 2) || (port < 0)) { - printk(KERN_ERR "%s:do not support the port %x" - " default broadcast\n", - __func__, port); - return -1; } - tmp = readl(fep->membase + FEC_ESW_DBCR); - if (enable == 1) { - if (port == 0) - tmp |= FSL_ESW_DBCR_P0; - else if (port == 1) - tmp |= FSL_ESW_DBCR_P1; - else if (port == 2) - tmp |= FSL_ESW_DBCR_P2; - } else if (enable == 0) { - if (port == 0) - tmp &= ~FSL_ESW_DBCR_P0; - else if (port == 1) - tmp &= ~FSL_ESW_DBCR_P1; - else if (port == 2) - tmp &= ~FSL_ESW_DBCR_P2; - } - - writel(tmp, fep->membase + FEC_ESW_DBCR); - return 0; -} - - -void esw_get_port_multicast(struct switch_enet_private *fep, - unsigned long *ulPortMulticast) -{ - *ulPortMulticast = readl(fep->membase + FEC_ESW_DMCR); -} - -int esw_port_multicast_config(struct switch_enet_private *fep, - int port, int enable) -{ - unsigned long tmp = 0; - - if ((port > 2) || (port < 0)) { - printk(KERN_ERR "%s:do not support the port %x" - " default broadcast\n", - __func__, port); - return -1; - } - - tmp = readl(fep->membase + FEC_ESW_DMCR); - if (enable == 1) { - if (port == 0) - tmp |= FSL_ESW_DMCR_P0; - else if (port == 1) - tmp |= FSL_ESW_DMCR_P1; - else if (port == 2) - tmp |= FSL_ESW_DMCR_P2; - } else if (enable == 0) { - if (port == 0) - tmp &= ~FSL_ESW_DMCR_P0; - else if (port == 1) - tmp &= ~FSL_ESW_DMCR_P1; - else if (port == 2) - tmp &= ~FSL_ESW_DMCR_P2; - } - - writel(tmp, fep->membase + FEC_ESW_DMCR); - return 0; -} - - -void esw_get_port_blocking(struct switch_enet_private *fep, - unsigned long *ulPortBlocking) -{ - *ulPortBlocking = readl(fep->membase + FEC_ESW_BKLR) & 0x0000000f; -} - -int esw_port_blocking_config(struct switch_enet_private *fep, - int port, int enable) -{ - unsigned long tmp = 0; - - if ((port > 2) || (port < 0)) { - printk(KERN_ERR "%s:do not support the port %x" - " default broadcast\n", - __func__, port); - return -1; - } - - tmp = readl(fep->membase + FEC_ESW_BKLR); - if (enable == 1) { - if (port == 0) - tmp |= FSL_ESW_BKLR_BE0; - else if (port == 1) - tmp |= FSL_ESW_BKLR_BE1; - else if (port == 2) - tmp |= FSL_ESW_BKLR_BE2; - } else if (enable == 0) { - if (port == 0) - tmp &= ~FSL_ESW_BKLR_BE0; - else if (port == 1) - tmp &= ~FSL_ESW_BKLR_BE1; - else if (port == 2) - tmp &= ~FSL_ESW_BKLR_BE2; - } - - writel(tmp, fep->membase + FEC_ESW_BKLR); - return 0; -} - - -void esw_get_port_learning(struct switch_enet_private *fep, - unsigned long *ulPortLearning) -{ - *ulPortLearning = - (readl(fep->membase + FEC_ESW_BKLR) & 0x000f0000) >> 16; -} - -int esw_port_learning_config(struct switch_enet_private *fep, - int port, int disable) -{ - unsigned long tmp = 0; - - if ((port > 2) || (port < 0)) { - printk(KERN_ERR "%s:do not support the port %x" - " default broadcast\n", - __func__, port); - return -1; + if (!is_valid_ether_addr(iap)) { + *((__be32 *)&tmpaddr[0]) = + cpu_to_be32(readl(fep->enetbase + FSL_FEC_PALR0)); + *((__be16 *)&tmpaddr[4]) = + cpu_to_be16(readl(fep->enetbase + FSL_FEC_PAUR0) >> 16); + iap = &tmpaddr[0]; } - tmp = readl(fep->membase + FEC_ESW_BKLR); - if (disable == 0) { - fep->learning_irqhandle_enable = 0; - if (port == 0) - tmp |= FSL_ESW_BKLR_LD0; - else if (port == 1) - tmp |= FSL_ESW_BKLR_LD1; - else if (port == 2) - tmp |= FSL_ESW_BKLR_LD2; - } else if (disable == 1) { - if (port == 0) - tmp &= ~FSL_ESW_BKLR_LD0; - else if (port == 1) - tmp &= ~FSL_ESW_BKLR_LD1; - else if (port == 2) - tmp &= ~FSL_ESW_BKLR_LD2; + if (!is_valid_ether_addr(iap)) { + /* Report it and use a random ethernet address instead */ + netdev_err(dev, "Invalid MAC address: %pM\n", iap); + eth_hw_addr_random(dev); + netdev_info(dev, "Using random MAC address: %pM\n", + dev->dev_addr); + return; } - writel(tmp, fep->membase + FEC_ESW_BKLR); - return 0; -} - -/*********************************************************************/ -void esw_mac_lookup_table_range(struct switch_enet_private *fep) -{ - int index; - unsigned long read_lo, read_hi; - /* Pointer to switch address look up memory*/ - for (index = 0; index < 2048; index++) - write_atable(fep, index, index, (~index)); - - /* Pointer to switch address look up memory*/ - for (index = 0; index < 2048; index++) { - read_atable(fep, index, &read_lo, &read_hi); - if (read_lo != index) { - printk(KERN_ERR "%s:Mismatch at low %d\n", - __func__, index); - return; - } + memcpy(dev->dev_addr, iap, ETH_ALEN); - if (read_hi != (~index)) { - printk(KERN_ERR "%s:Mismatch at high %d\n", - __func__, index); - return; - } - } + /* Adjust MAC if using macaddr */ + if (iap == macaddr) + dev->dev_addr[ETH_ALEN - 1] = + macaddr[ETH_ALEN - 1] + fep->dev_id; } -/* - * Checks IP Snoop options of handling the snooped frame. - * mode 0 : The snooped frame is forward only to management port - * mode 1 : The snooped frame is copy to management port and - * normal forwarding is checked. - * mode 2 : The snooped frame is discarded. - * mode 3 : Disable the ip snoop function - * ip_header_protocol : the IP header protocol field +/* This function is called to start or restart the FEC during a link + * change. This only happens when switching between half and full + * duplex. */ -int esw_ip_snoop_config(struct switch_enet_private *fep, - int mode, unsigned long ip_header_protocol) -{ - unsigned long tmp = 0, protocol_type = 0; - int num = 0; - - /* Config IP Snooping */ - if (mode == 0) { - /* Enable IP Snooping */ - tmp = FSL_ESW_IPSNP_EN; - tmp |= FSL_ESW_IPSNP_MODE(0);/*For Forward*/ - } else if (mode == 1) { - /* Enable IP Snooping */ - tmp = FSL_ESW_IPSNP_EN; - /*For Forward and copy_to_mangmnt_port*/ - tmp |= FSL_ESW_IPSNP_MODE(1); - } else if (mode == 2) { - /* Enable IP Snooping */ - tmp = FSL_ESW_IPSNP_EN; - tmp |= FSL_ESW_IPSNP_MODE(2);/*discard*/ - } else if (mode == 3) { - /* disable IP Snooping */ - tmp = FSL_ESW_IPSNP_EN; - tmp &= ~FSL_ESW_IPSNP_EN; - } else { - printk(KERN_ERR "%s: the mode %x " - "we do not support\n", __func__, mode); - return -1; - } - - protocol_type = ip_header_protocol; - for (num = 0; num < 8; num++) { - unsigned long reg = readl(fep->membase + FEC_ESW_IPSNP(num)); - if (protocol_type == - AT_EXTRACT_IP_PROTOCOL(reg)) { - writel(tmp | FSL_ESW_IPSNP_PROTOCOL(protocol_type), - fep->membase + FEC_ESW_IPSNP(num)); - break; - } else if (!reg) { - writel(tmp | FSL_ESW_IPSNP_PROTOCOL(protocol_type), - fep->membase + FEC_ESW_IPSNP(num)); - break; - } - } - if (num == 8) { - printk(KERN_INFO "IP snooping table is full\n"); - return 0; - } - - return 0; -} - -void esw_get_ip_snoop_config(struct switch_enet_private *fep, - unsigned long *ulpESW_IPSNP) +static void switch_restart(struct net_device *dev, int duplex) { + struct switch_enet_private *fep; int i; - for (i = 0; i < 8; i++) - *(ulpESW_IPSNP + i) = readl(fep->membase + FEC_ESW_IPSNP(i)); -} -/* - * Checks TCP/UDP Port Snoop options of handling the snooped frame. - * mode 0 : The snooped frame is forward only to management port - * mode 1 : The snooped frame is copy to management port and - * normal forwarding is checked. - * mode 2 : The snooped frame is discarded. - * mode 3 : Disable the TCP/UDP port snoop function - * compare_port : port number in the TCP/UDP header - * compare_num 1: TCP/UDP source port number is compared - * compare_num 2: TCP/UDP destination port number is compared - * compare_num 3: TCP/UDP source and destination port number is compared - */ -int esw_tcpudp_port_snoop_config(struct switch_enet_private *fep, - int mode, int compare_port, int compare_num) -{ - unsigned long tmp; - int num; - - /* Enable TCP/UDP port Snooping */ - tmp = FSL_ESW_PSNP_EN; - if (mode == 0) - tmp |= FSL_ESW_PSNP_MODE(0);/*For Forward*/ - else if (mode == 1)/*For Forward and copy_to_mangmnt_port*/ - tmp |= FSL_ESW_PSNP_MODE(1); - else if (mode == 2) - tmp |= FSL_ESW_PSNP_MODE(2);/*discard*/ - else if (mode == 3) /*disable the port function*/ - tmp &= (~FSL_ESW_PSNP_EN); - else { - printk(KERN_ERR "%s: the mode %x we do not support\n", - __func__, mode); - return -1; - } + fep = netdev_priv(dev); - if (compare_num == 1) - tmp |= FSL_ESW_PSNP_CS; - else if (compare_num == 2) - tmp |= FSL_ESW_PSNP_CD; - else if (compare_num == 3) - tmp |= FSL_ESW_PSNP_CD | FSL_ESW_PSNP_CS; - else { - printk(KERN_ERR "%s: the compare port address %x" - " we do not support\n", - __func__, compare_num); - return -1; - } + /* Whack a reset. We should wait for this.*/ + writel(1, fep->enetbase + FSL_FEC_ECR0); + writel(1, fep->enetbase + FSL_FEC_ECR1); + udelay(10); - for (num = 0; num < 8; num++) { - u32 reg = readl(fep->membase + FEC_ESW_PSNP(num)); - if (compare_port == - AT_EXTRACT_TCP_UDP_PORT(reg)) { - writel(tmp | FSL_ESW_PSNP_PORT_COMPARE(compare_port), - fep->membase + FEC_ESW_PSNP(num)); - break; - } else if (!reg) { - writel(tmp | FSL_ESW_PSNP_PORT_COMPARE(compare_port), - fep->membase + FEC_ESW_PSNP(num)); - break; - } - } - if (num == 8) { - printk(KERN_INFO "TCP/UDP port snooping table is full\n"); - return 0; - } + writel(FSL_ESW_MODE_SW_RST, fep->membase + FEC_ESW_MODE); + udelay(10); + writel(FSL_ESW_MODE_STATRST, fep->membase + FEC_ESW_MODE); + writel(FSL_ESW_MODE_SW_EN, fep->membase + FEC_ESW_MODE); - return 0; -} + /* Enable transmit/receive on all ports */ + writel(0xffffffff, fep->membase + FEC_ESW_PER); -void esw_get_tcpudp_port_snoop_config( - struct switch_enet_private *fep, - unsigned long *ulpESW_PSNP) -{ - int i; + /* Management port configuration, + * make port 0 as management port + */ + writel(0, fep->membase + FEC_ESW_BMPC); - for (i = 0; i < 8; i++) - *(ulpESW_PSNP + i) = readl(fep->membase + FEC_ESW_PSNP(i)); -} + /* Clear any outstanding interrupt.*/ + writel(0xffffffff, fep->membase + FEC_ESW_ISR); -/*mirror*/ -void esw_get_port_mirroring(struct switch_enet_private *fep) -{ - unsigned long tmp, tmp1, tmp2; - - tmp = readl(fep->membase + FEC_ESW_MCR); - - printk(KERN_INFO "Mirror Port: %ld Egress Port Match:%s " - "Ingress Port Match:%s\n", tmp & 0xf, - tmp & 1 ? "Y" : "N", - tmp & 1 ? "Y" : "N"); - - if ((tmp >> 6) & 1) - printk(KERN_INFO "Egress Port to be mirrored: Port %d\n", - readl(fep->membase + FEC_ESW_EGMAP) >> 1); - if ((tmp >> 5) & 1) - printk(KERN_INFO "Ingress Port to be mirrored: Port %d\n", - readl(fep->membase + FEC_ESW_INGMAP) >> 1); - - printk(KERN_INFO "Egress Des Address Match:%s " - "Egress Src Address Match:%s\n", - (tmp >> 10) & 1 ? "Y" : "N", - (tmp >> 9) & 1 ? "Y" : "N"); - printk(KERN_INFO "Ingress Des Address Match:%s " - "Ingress Src Address Match:%s\n", - (tmp >> 8) & 1 ? "Y" : "N", - (tmp >> 7) & 1 ? "Y" : "N"); - - if ((tmp >> 10) & 1) { - tmp1 = readl(fep->membase + FEC_ESW_ENGDAL); - tmp2 = readl(fep->membase + FEC_ESW_ENGDAH); - printk(KERN_INFO "Egress Des Address to be mirrored: " - "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n", - tmp1 & 0xff, - (tmp1 >> 8) & 0xff, - (tmp1 >> 16) & 0xff, - (tmp1 >> 24) & 0xff, - tmp2 & 0xff, - (tmp2 >> 8) & 0xff); - } - if ((tmp >> 9) & 1) { - tmp1 = readl(fep->membase + FEC_ESW_ENGSAL); - tmp2 = readl(fep->membase + FEC_ESW_ENGSAH); - printk("Egress Src Address to be mirrored: " - "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n", - tmp1 & 0xff, - (tmp1 >> 8) & 0xff, - (tmp1 >> 16) & 0xff, - (tmp1 >> 24) & 0xff, - tmp2 & 0xff, - (tmp2 >> 8) & 0xff); - } - if ((tmp >> 8) & 1) { - tmp1 = readl(fep->membase + FEC_ESW_INGDAL); - tmp2 = readl(fep->membase + FEC_ESW_INGDAH); - printk("Ingress Des Address to be mirrored: " - "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n", - tmp1 & 0xff, - (tmp1 >> 8) & 0xff, - (tmp1 >> 16) & 0xff, - (tmp1 >> 24) & 0xff, - tmp2 & 0xff, - (tmp2 >> 8) & 0xff); - } - if ((tmp >> 7) & 1) { - tmp1 = readl(fep->membase + FEC_ESW_INGSAL); - tmp2 = readl(fep->membase + FEC_ESW_INGSAH); - printk("Ingress Src Address to be mirrored: " - "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n", - tmp1 & 0xff, - (tmp1 >> 8) & 0xff, - (tmp1 >> 16) & 0xff, - (tmp1 >> 24) & 0xff, - tmp2 & 0xff, - (tmp2 >> 8) & 0xff); - } -} + switch_hw_init(dev); -int esw_port_mirroring_config_port_match(struct switch_enet_private *fep, - int mirror_port, int port_match_en, int port) -{ - unsigned long tmp = 0; + /* Set station address.*/ + switch_get_mac_address(dev); - tmp = readl(fep->membase + FEC_ESW_MCR); - if (mirror_port != (tmp & 0xf)) - tmp = 0; - - switch (port_match_en) { - case MIRROR_EGRESS_PORT_MATCH: - tmp |= FSL_ESW_MCR_EGMAP; - if (port == 0) - writel(FSL_ESW_EGMAP_EG0, fep->membase + FEC_ESW_EGMAP); - else if (port == 1) - writel(FSL_ESW_EGMAP_EG1, fep->membase + FEC_ESW_EGMAP); - else if (port == 2) - writel(FSL_ESW_EGMAP_EG2, fep->membase + FEC_ESW_EGMAP); - break; - case MIRROR_INGRESS_PORT_MATCH: - tmp |= FSL_ESW_MCR_INGMAP; - if (port == 0) - writel(FSL_ESW_INGMAP_ING0, - fep->membase + FEC_ESW_INGMAP); - else if (port == 1) - writel(FSL_ESW_INGMAP_ING1, - fep->membase + FEC_ESW_INGMAP); - else if (port == 2) - writel(FSL_ESW_INGMAP_ING2, - fep->membase + FEC_ESW_INGMAP); - break; - default: - tmp = 0; - break; - } + writel(0, fep->membase + FEC_ESW_IMR); + udelay(10); - tmp = tmp & 0x07e0; - if (port_match_en) - tmp |= FSL_ESW_MCR_MEN | FSL_ESW_MCR_PORT(mirror_port); + /* Set maximum receive buffer size. */ + writel(PKT_MAXBLR_SIZE, fep->membase + FEC_ESW_MRBR); - writel(tmp, fep->membase + FEC_ESW_MCR); - return 0; -} + /* Set receive and transmit descriptor base. */ + writel(fep->bd_dma, fep->membase + FEC_ESW_RDSR); + writel((unsigned long)fep->bd_dma + + sizeof(struct bufdesc) * RX_RING_SIZE, + fep->membase + FEC_ESW_TDSR); -int esw_port_mirroring_config(struct switch_enet_private *fep, - int mirror_port, int port, int mirror_enable, - unsigned char *src_mac, unsigned char *des_mac, - int egress_en, int ingress_en, - int egress_mac_src_en, int egress_mac_des_en, - int ingress_mac_src_en, int ingress_mac_des_en) -{ - unsigned long tmp; - - /*mirroring config*/ - tmp = 0; - if (egress_en == 1) { - tmp |= FSL_ESW_MCR_EGMAP; - if (port == 0) - writel(FSL_ESW_EGMAP_EG0, fep->membase + FEC_ESW_EGMAP); - else if (port == 1) - writel(FSL_ESW_EGMAP_EG1, fep->membase + FEC_ESW_EGMAP); - else if (port == 2) - writel(FSL_ESW_EGMAP_EG2, fep->membase + FEC_ESW_EGMAP); - else { - printk(KERN_ERR "%s: the port %x we do not support\n", - __func__, port); - return -1; - } - } else if (egress_en == 0) { - tmp &= (~FSL_ESW_MCR_EGMAP); - } else { - printk(KERN_ERR "%s: egress_en %x we do not support\n", - __func__, egress_en); - return -1; - } + fep->cur_tx = fep->tx_bd_base; + fep->dirty_tx = fep->cur_tx; + fep->cur_rx = fep->rx_bd_base; - if (ingress_en == 1) { - tmp |= FSL_ESW_MCR_INGMAP; - if (port == 0) - writel(FSL_ESW_INGMAP_ING0, - fep->membase + FEC_ESW_INGMAP); - else if (port == 1) - writel(FSL_ESW_INGMAP_ING1, - fep->membase + FEC_ESW_INGMAP); - else if (port == 2) - writel(FSL_ESW_INGMAP_ING2, - fep->membase + FEC_ESW_INGMAP); - else { - printk(KERN_ERR "%s: the port %x we do not support\n", - __func__, port); - return -1; + /* Reset SKB transmit buffers. */ + fep->skb_cur = 0; + fep->skb_dirty = 0; + for (i = 0; i <= TX_RING_MOD_MASK; i++) { + if (fep->tx_skbuff[i] != NULL) { + dev_kfree_skb_any(fep->tx_skbuff[i]); + fep->tx_skbuff[i] = NULL; } - } else if (ingress_en == 0) { - tmp &= ~FSL_ESW_MCR_INGMAP; - } else{ - printk(KERN_ERR "%s: ingress_en %x we do not support\n", - __func__, ingress_en); - return -1; - } - - if (egress_mac_src_en == 1) { - tmp |= FSL_ESW_MCR_EGSA; - writel((src_mac[5] << 8) | (src_mac[4]), - fep->membase + FEC_ESW_ENGSAH); - writel((unsigned long)((src_mac[3] << 24) | (src_mac[2] << 16) | - (src_mac[1] << 8) | src_mac[0]), - fep->membase + FEC_ESW_ENGSAL); - } else if (egress_mac_src_en == 0) { - tmp &= ~FSL_ESW_MCR_EGSA; - } else { - printk(KERN_ERR "%s: egress_mac_src_en %x we do not support\n", - __func__, egress_mac_src_en); - return -1; } - if (egress_mac_des_en == 1) { - tmp |= FSL_ESW_MCR_EGDA; - writel((des_mac[5] << 8) | (des_mac[4]), - fep->membase + FEC_ESW_ENGDAH); - writel((unsigned long)((des_mac[3] << 24) | (des_mac[2] << 16) | - (des_mac[1] << 8) | des_mac[0]), - fep->membase + FEC_ESW_ENGDAL); - } else if (egress_mac_des_en == 0) { - tmp &= ~FSL_ESW_MCR_EGDA; - } else { - printk(KERN_ERR "%s: egress_mac_des_en %x we do not support\n", - __func__, egress_mac_des_en); - return -1; - } - - if (ingress_mac_src_en == 1) { - tmp |= FSL_ESW_MCR_INGSA; - writel((src_mac[5] << 8) | (src_mac[4]), - fep->membase + FEC_ESW_INGSAH); - writel((unsigned long)((src_mac[3] << 24) | (src_mac[2] << 16) | - (src_mac[1] << 8) | src_mac[0]), - fep->membase + FEC_ESW_INGSAL); - } else if (ingress_mac_src_en == 0) { - tmp &= ~FSL_ESW_MCR_INGSA; - } else { - printk(KERN_ERR "%s: ingress_mac_src_en %x " - "we do not support\n", - __func__, ingress_mac_src_en); - return -1; - } - - if (ingress_mac_des_en == 1) { - tmp |= FSL_ESW_MCR_INGDA; - writel((des_mac[5] << 8) | (des_mac[4]), - fep->membase + FEC_ESW_INGDAH); - writel((unsigned long)((des_mac[3] << 24) | (des_mac[2] << 16) | - (des_mac[1] << 8) | des_mac[0]), - fep->membase + FEC_ESW_INGDAL); - } else if (ingress_mac_des_en == 0) { - tmp &= ~FSL_ESW_MCR_INGDA; - } else { - printk(KERN_ERR "%s: ingress_mac_des_en %x we do not support\n", - __func__, ingress_mac_des_en); - return -1; - } - - if (mirror_enable == 1) - tmp |= FSL_ESW_MCR_MEN | FSL_ESW_MCR_PORT(mirror_port); - else if (mirror_enable == 0) - tmp &= ~FSL_ESW_MCR_MEN; - else - printk(KERN_ERR "%s: the mirror enable %x is error\n", - __func__, mirror_enable); - - - writel(tmp, fep->membase + FEC_ESW_MCR); - return 0; -} - -int esw_port_mirroring_config_addr_match(struct switch_enet_private *fep, - int mirror_port, int addr_match_enable, unsigned char *mac_addr) -{ - unsigned long tmp = 0; - - tmp = readl(fep->membase + FEC_ESW_MCR); - if (mirror_port != (tmp & 0xf)) - tmp = 0; - - switch (addr_match_enable) { - case MIRROR_EGRESS_SOURCE_MATCH: - tmp |= FSL_ESW_MCR_EGSA; - writel((mac_addr[5] << 8) | (mac_addr[4]), - fep->membase + FEC_ESW_ENGSAH); - writel((unsigned long)((mac_addr[3] << 24) | - (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]), - fep->membase + FEC_ESW_ENGSAL); - break; - case MIRROR_INGRESS_SOURCE_MATCH: - tmp |= FSL_ESW_MCR_INGSA; - writel((mac_addr[5] << 8) | (mac_addr[4]), - fep->membase + FEC_ESW_INGSAH); - writel((unsigned long)((mac_addr[3] << 24) | - (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]), - fep->membase + FEC_ESW_INGSAL); - break; - case MIRROR_EGRESS_DESTINATION_MATCH: - tmp |= FSL_ESW_MCR_EGDA; - writel((mac_addr[5] << 8) | (mac_addr[4]), - fep->membase + FEC_ESW_ENGDAH); - writel((unsigned long)((mac_addr[3] << 24) | - (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]), - fep->membase + FEC_ESW_ENGDAL); - break; - case MIRROR_INGRESS_DESTINATION_MATCH: - tmp |= FSL_ESW_MCR_INGDA; - writel((mac_addr[5] << 8) | (mac_addr[4]), - fep->membase + FEC_ESW_INGDAH); - writel((unsigned long)((mac_addr[3] << 24) | - (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]), - fep->membase + FEC_ESW_INGDAL); - break; - default: - tmp = 0; - break; - } - - tmp = tmp & 0x07e0; - if (addr_match_enable) - tmp |= FSL_ESW_MCR_MEN | FSL_ESW_MCR_PORT(mirror_port); - - writel(tmp, fep->membase + FEC_ESW_MCR); - return 0; -} + /* hardware has set in hw_init */ + fep->full_duplex = duplex; -void esw_get_vlan_verification(struct switch_enet_private *fep, - unsigned long *ulValue) -{ - *ulValue = readl(fep->membase + FEC_ESW_VLANV); + /* Clear any outstanding interrupt.*/ + writel(0xffffffff, fep->membase + FEC_ESW_ISR); + writel(FSL_ESW_IMR_RXF | FSL_ESW_IMR_TXF, fep->membase + FEC_ESW_IMR); } -int esw_set_vlan_verification(struct switch_enet_private *fep, int port, - int vlan_domain_verify_en, int vlan_discard_unknown_en) +static int switch_init_phy(struct net_device *dev) { - u32 tmp; - - if ((port < 0) || (port > 2)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; - } - tmp = readl(fep->membase + FEC_ESW_VLANV); - if (vlan_domain_verify_en == 1) { - if (port == 0) - tmp |= FSL_ESW_VLANV_VV0; - else if (port == 1) - tmp |= FSL_ESW_VLANV_VV1; - else if (port == 2) - tmp |= FSL_ESW_VLANV_VV2; - } else if (vlan_domain_verify_en == 0) { - if (port == 0) - tmp &= ~FSL_ESW_VLANV_VV0; - else if (port == 1) - tmp &= ~FSL_ESW_VLANV_VV1; - else if (port == 2) - tmp &= ~FSL_ESW_VLANV_VV2; - } else { - printk(KERN_INFO "%s: donot support " - "vlan_domain_verify %x\n", - __func__, vlan_domain_verify_en); - return -2; - } + struct switch_enet_private *priv = netdev_priv(dev); + struct phy_device *phydev[SWITCH_EPORT_NUMBER] = {NULL, NULL}; + int i, j = 0; - if (vlan_discard_unknown_en == 1) { - if (port == 0) - tmp |= FSL_ESW_VLANV_DU0; - else if (port == 1) - tmp |= FSL_ESW_VLANV_DU1; - else if (port == 2) - tmp |= FSL_ESW_VLANV_DU2; - } else if (vlan_discard_unknown_en == 0) { - if (port == 0) - tmp &= ~FSL_ESW_VLANV_DU0; - else if (port == 1) - tmp &= ~FSL_ESW_VLANV_DU1; - else if (port == 2) - tmp &= ~FSL_ESW_VLANV_DU2; - } else { - printk(KERN_INFO "%s: donot support " - "vlan_discard_unknown %x\n", - __func__, vlan_discard_unknown_en); - return -3; - } + /* search for connect PHY device */ + for (i = 0; i < PHY_MAX_ADDR; i++) { + struct phy_device *const tmp_phydev = + priv->mdio_bus->phy_map[i]; - writel(tmp, fep->membase + FEC_ESW_VLANV); - return 0; -} + if (!tmp_phydev) + continue; -void esw_get_vlan_resolution_table(struct switch_enet_private *fep, - struct eswVlanTableItem *tableaddr) -{ - int vnum = 0; - int i; - u32 tmp; - - for (i = 0; i < 32; i++) { - tmp = readl(fep->membase + FEC_ESW_VRES(i)); - if (tmp) { - tableaddr->table[i].port_vlanid = - tmp >> 3; - tableaddr->table[i].vlan_domain_port = - tmp & 7; - vnum++; - } + phydev[j++] = tmp_phydev; + if (j >= SWITCH_EPORT_NUMBER) + break; } - tableaddr->valid_num = vnum; -} -int esw_set_vlan_id(struct switch_enet_private *fep, unsigned long configData) -{ - int i; - u32 tmp; - - for (i = 0; i < 32; i++) { - tmp = readl(fep->membase + FEC_ESW_VRES(i)); - if (tmp == 0) { - writel(FSL_ESW_VRES_VLANID(configData), - fep->membase + FEC_ESW_VRES(i)); - return 0; - } else if (((tmp >> 3) & 0xfff) == configData) { - printk(KERN_INFO "The VLAN already exists\n"); - return 0; - } + /* now we are supposed to have a proper phydev, to attach to... */ + if ((!phydev[0]) && (!phydev[1])) { + netdev_info(dev, "%s: Didn't find any PHY device at all\n", + dev->name); + return -ENODEV; } - printk(KERN_INFO "The VLAN can't create, because VLAN table is full\n"); - return 0; -} - -int esw_set_vlan_id_cleared(struct switch_enet_private *fep, - unsigned long configData) -{ - int i; - u32 tmp; - - for (i = 0; i < 32; i++) { - tmp = readl(fep->membase + FEC_ESW_VRES(i)); - if (((tmp >> 3) & 0xfff) == configData) { - writel(0, fep->membase + FEC_ESW_VRES(i)); - break; - } - } - return 0; -} + priv->phy1_link = PHY_DOWN; + priv->phy1_old_link = PHY_DOWN; + priv->phy1_speed = 0; + priv->phy1_duplex = -1; -int esw_set_port_in_vlan_id(struct switch_enet_private *fep, - eswIoctlVlanResoultionTable configData) -{ - int i; - int lastnum = 0; - u32 tmp; + priv->phy2_link = PHY_DOWN; + priv->phy2_old_link = PHY_DOWN; + priv->phy2_speed = 0; + priv->phy2_duplex = -1; - for (i = 0; i < 32; i++) { - tmp = readl(fep->membase + FEC_ESW_VRES(i)); - if (tmp == 0) { - lastnum = i; - break; - } else if (((tmp >> 3) & 0xfff) == - configData.port_vlanid) { - /* update the port members of this vlan */ - tmp |= 1 << configData.vlan_domain_port; - writel(tmp, fep->membase + FEC_ESW_VRES(i)); - return 0; - } + phydev[0] = phy_connect(dev, dev_name(&phydev[0]->dev), + &switch_adjust_link1, PHY_INTERFACE_MODE_RMII); + if (IS_ERR(phydev[0])) { + netdev_err(dev, " %s phy_connect failed\n", __func__); + return PTR_ERR(phydev[0]); } - /* creat a new vlan in vlan table */ - writel(FSL_ESW_VRES_VLANID(configData.port_vlanid) | - (1 << configData.vlan_domain_port), - fep->membase + FEC_ESW_VRES(lastnum)); - return 0; -} -int esw_set_vlan_resolution_table(struct switch_enet_private *fep, - unsigned short port_vlanid, int vlan_domain_num, - int vlan_domain_port) -{ - if ((vlan_domain_num < 0) - || (vlan_domain_num > 31)) { - printk(KERN_ERR "%s: do not support the " - "vlan_domain_num %d\n", - __func__, vlan_domain_num); - return -1; + phydev[1] = phy_connect(dev, dev_name(&phydev[1]->dev), + &switch_adjust_link2, PHY_INTERFACE_MODE_RMII); + if (IS_ERR(phydev[1])) { + netdev_err(dev, " %s phy_connect failed\n", __func__); + return PTR_ERR(phydev[1]); } - if ((vlan_domain_port < 0) - || (vlan_domain_port > 7)) { - printk(KERN_ERR "%s: do not support the " - "vlan_domain_port %d\n", - __func__, vlan_domain_port); - return -2; + for (i = 0; i < SWITCH_EPORT_NUMBER; i++) { + phydev[i]->supported &= PHY_BASIC_FEATURES; + phydev[i]->advertising = phydev[i]->supported; + priv->phydev[i] = phydev[i]; + netdev_info(dev, "attached phy %i to driver %s " + "(mii_bus:phy_addr=%s, irq=%d)\n", + phydev[i]->addr, phydev[i]->drv->name, + dev_name(&priv->phydev[i]->dev), + priv->phydev[i]->irq); } - writel( - FSL_ESW_VRES_VLANID(port_vlanid) - | vlan_domain_port, - fep->membase + FEC_ESW_VRES(vlan_domain_num)); - return 0; } -void esw_get_vlan_input_config(struct switch_enet_private *fep, - eswIoctlVlanInputStatus *pVlanInputConfig) +static void switch_stop(struct net_device *dev) { - int i; - - for (i = 0; i < 3; i++) - pVlanInputConfig->ESW_PID[i] = - readl(fep->membase + FEC_ESW_PID(i)); + struct switch_enet_private *fep = netdev_priv(dev); - pVlanInputConfig->ESW_VLANV = readl(fep->membase + FEC_ESW_VLANV); - pVlanInputConfig->ESW_VIMSEL = readl(fep->membase + FEC_ESW_VIMSEL); - pVlanInputConfig->ESW_VIMEN = readl(fep->membase + FEC_ESW_VIMEN); + /* We cannot expect a graceful transmit + * stop without link + */ + if (fep->phy1_link) + udelay(10); + if (fep->phy2_link) + udelay(10); - for (i = 0; i < 32; i++) - pVlanInputConfig->ESW_VRES[i] = - readl(fep->membase + FEC_ESW_VRES(i)); + /* Whack a reset. We should wait for this */ + udelay(10); } - -int esw_vlan_input_process(struct switch_enet_private *fep, - int port, int mode, unsigned short port_vlanid) +static int switch_enet_clk_enable(struct net_device *ndev, bool enable) { - u32 tmp; - - if ((mode < 0) || (mode > 5)) { - printk(KERN_ERR "%s: do not support the" - " VLAN input processing mode %d\n", - __func__, mode); - return -1; - } + struct switch_enet_private *fep = netdev_priv(ndev); + int ret; - if ((port < 0) || (port > 3)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, mode); - return -2; - } + if (enable) { + ret = clk_prepare_enable(fep->clk_esw); + if (ret) + goto failed_clk_esw; - writel(FSL_ESW_PID_VLANID(port_vlanid), - fep->membase + FEC_ESW_PID(port)); + ret = clk_prepare_enable(fep->clk_enet); + if (ret) + goto failed_clk_enet; - if (port == 0) { - tmp = readl(fep->membase + FEC_ESW_VIMEN); - if (mode == 4) - tmp &= ~FSL_ESW_VIMEN_EN0; - else - tmp |= FSL_ESW_VIMEN_EN0; - writel(tmp, fep->membase + FEC_ESW_VIMEN); - - tmp = readl(fep->membase + FEC_ESW_VIMSEL); - tmp &= ~FSL_ESW_VIMSEL_IM0(3); - tmp |= FSL_ESW_VIMSEL_IM0(mode); - writel(tmp, fep->membase + FEC_ESW_VIMSEL); - } else if (port == 1) { - tmp = readl(fep->membase + FEC_ESW_VIMEN); - if (mode == 4) - tmp &= ~FSL_ESW_VIMEN_EN1; - else - tmp |= FSL_ESW_VIMEN_EN1; - writel(tmp, fep->membase + FEC_ESW_VIMEN); - - tmp = readl(fep->membase + FEC_ESW_VIMSEL); - tmp &= ~FSL_ESW_VIMSEL_IM1(3); - tmp |= FSL_ESW_VIMSEL_IM1(mode); - writel(tmp, fep->membase + FEC_ESW_VIMSEL); - } else if (port == 2) { - tmp = readl(fep->membase + FEC_ESW_VIMEN); - if (mode == 4) - tmp &= ~FSL_ESW_VIMEN_EN2; - else - tmp |= FSL_ESW_VIMEN_EN2; - writel(tmp, fep->membase + FEC_ESW_VIMEN); + ret = clk_prepare_enable(fep->clk_enet0); + if (ret) + goto failed_clk_enet0; - tmp = readl(fep->membase + FEC_ESW_VIMSEL); - tmp &= ~FSL_ESW_VIMSEL_IM2(3); - tmp |= FSL_ESW_VIMSEL_IM2(mode); - writel(tmp, fep->membase + FEC_ESW_VIMSEL); + ret = clk_prepare_enable(fep->clk_enet1); + if (ret) + goto failed_clk_enet1; } else { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -2; + clk_disable_unprepare(fep->clk_esw); + clk_disable_unprepare(fep->clk_enet); + clk_disable_unprepare(fep->clk_enet0); + clk_disable_unprepare(fep->clk_enet1); } return 0; -} -void esw_get_vlan_output_config(struct switch_enet_private *fep, - unsigned long *ulVlanOutputConfig) -{ - *ulVlanOutputConfig = readl(fep->membase + FEC_ESW_VOMSEL); -} - -int esw_vlan_output_process(struct switch_enet_private *fep, - int port, int mode) -{ - u32 tmp; +failed_clk_esw: + clk_disable_unprepare(fep->clk_esw); +failed_clk_enet: + clk_disable_unprepare(fep->clk_enet); +failed_clk_enet0: + clk_disable_unprepare(fep->clk_enet0); +failed_clk_enet1: + clk_disable_unprepare(fep->clk_enet1); - if ((port < 0) || (port > 2)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, mode); - return -1; - } - tmp = readl(fep->membase + FEC_ESW_VOMSEL); - if (port == 0) { - tmp &= ~FSL_ESW_VOMSEL_OM0(3); - tmp |= FSL_ESW_VOMSEL_OM0(mode); - } else if (port == 1) { - tmp &= ~FSL_ESW_VOMSEL_OM1(3); - tmp |= FSL_ESW_VOMSEL_OM1(mode); - } else if (port == 2) { - tmp &= ~FSL_ESW_VOMSEL_OM2(3); - tmp |= FSL_ESW_VOMSEL_OM2(mode); - } else { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; - } - writel(tmp, fep->membase + FEC_ESW_VOMSEL); - return 0; + return ret; } -/* - * frame calssify and priority resolution - * vlan priority lookup - */ -int esw_framecalssify_vlan_priority_lookup(struct switch_enet_private *fep, - int port, int func_enable, int vlan_pri_table_num, - int vlan_pri_table_value) +static void switch_enet_free_buffers(struct net_device *ndev) { - u32 tmp; - - if ((port < 0) || (port > 3)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; - } + struct switch_enet_private *fep = netdev_priv(ndev); + int i; + struct sk_buff *skb; + cbd_t *bdp; - if (func_enable == 0) { - tmp = readl(fep->membase + FEC_ESW_PRES(port)); - tmp &= ~FSL_ESW_PRES_VLAN; - writel(tmp, fep->membase + FEC_ESW_PRES(port)); - printk(KERN_ERR "%s: disable port %d VLAN priority " - "lookup function\n", __func__, port); - return 0; - } + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + skb = fep->rx_skbuff[i]; - if ((vlan_pri_table_num < 0) || (vlan_pri_table_num > 7)) { - printk(KERN_ERR "%s: do not support the priority %d\n", - __func__, vlan_pri_table_num); - return -1; + if (bdp->cbd_bufaddr) + dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + SWITCH_ENET_RX_FRSIZE, DMA_FROM_DEVICE); + if (skb) + dev_kfree_skb(skb); + bdp++; } - tmp = readl(fep->membase + FEC_ESW_PVRES(port)); - tmp |= ((vlan_pri_table_value & 0x3) - << (vlan_pri_table_num*3)); - writel(tmp, fep->membase + FEC_ESW_PVRES(port)); - - /* enable port VLAN priority lookup function*/ - tmp = readl(fep->membase + FEC_ESW_PRES(port)); - tmp |= FSL_ESW_PRES_VLAN; - writel(tmp, fep->membase + FEC_ESW_PRES(port)); - return 0; + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) + kfree(fep->tx_bounce[i]); } -int esw_framecalssify_ip_priority_lookup(struct switch_enet_private *fep, - int port, int func_enable, int ipv4_en, int ip_priority_num, - int ip_priority_value) +static int switch_alloc_buffers(struct net_device *ndev) { - unsigned long tmp = 0, tmp_prio = 0; - - if ((port < 0) || (port > 3)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; - } - - if (func_enable == 0) { - tmp = readl(fep->membase + FEC_ESW_PRES(port)); - tmp &= ~FSL_ESW_PRES_IP; - writel(tmp, fep->membase + FEC_ESW_PRES(port)); - printk(KERN_ERR "%s: disable port %d ip priority " - "lookup function\n", __func__, port); - return 0; - } + struct switch_enet_private *fep = netdev_priv(ndev); + int i; + struct sk_buff *skb; + cbd_t *bdp; - /* IPV4 priority 64 entry table lookup*/ - /* IPv4 head 6 bit TOS field*/ - if (ipv4_en == 1) { - if ((ip_priority_num < 0) || (ip_priority_num > 63)) { - printk(KERN_ERR "%s: do not support the table entry %d\n", - __func__, ip_priority_num); - return -2; - } - } else { /* IPV6 priority 256 entry table lookup*/ - /* IPv6 head 8 bit COS field*/ - if ((ip_priority_num < 0) || (ip_priority_num > 255)) { - printk(KERN_ERR "%s: do not support the table entry %d\n", - __func__, ip_priority_num); - return -3; + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + skb = dev_alloc_skb(SWITCH_ENET_RX_FRSIZE); + if (!skb) { + switch_enet_free_buffers(ndev); + return -ENOMEM; } - } - - /* IP priority table lookup : address*/ - tmp = FSL_ESW_IPRES_ADDRESS(ip_priority_num); - /* IP priority table lookup : ipv4sel*/ - if (ipv4_en == 1) - tmp = tmp | FSL_ESW_IPRES_IPV4SEL; - /* IP priority table lookup : priority*/ - if (port == 0) - tmp |= FSL_ESW_IPRES_PRI0(ip_priority_value); - else if (port == 1) - tmp |= FSL_ESW_IPRES_PRI1(ip_priority_value); - else if (port == 2) - tmp |= FSL_ESW_IPRES_PRI2(ip_priority_value); - - /* configure*/ - writel(FSL_ESW_IPRES_READ | FSL_ESW_IPRES_ADDRESS(ip_priority_num), - fep->membase + FEC_ESW_IPRES); - tmp_prio = readl(fep->membase + FEC_ESW_IPRES); - - writel(tmp | tmp_prio, fep->membase + FEC_ESW_IPRES); - - writel(FSL_ESW_IPRES_READ | FSL_ESW_IPRES_ADDRESS(ip_priority_num), - fep->membase + FEC_ESW_IPRES); - tmp_prio = readl(fep->membase + FEC_ESW_IPRES); - - /* enable port IP priority lookup function*/ - tmp = readl(fep->membase + FEC_ESW_PRES(port)); - tmp |= FSL_ESW_PRES_IP; - writel(tmp, fep->membase + FEC_ESW_PRES(port)); - return 0; -} - -int esw_framecalssify_mac_priority_lookup( - struct switch_enet_private *fep, int port) -{ - u32 tmp; - - if ((port < 0) || (port > 3)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; - } - - tmp = readl(fep->membase + FEC_ESW_PRES(port)); - tmp |= FSL_ESW_PRES_MAC; - writel(tmp, fep->membase + FEC_ESW_PRES(port)); - - return 0; -} - -int esw_frame_calssify_priority_init(struct switch_enet_private *fep, - int port, unsigned char priority_value) -{ - if ((port < 0) || (port > 3)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; - } - /*disable all priority lookup function*/ - writel(0, fep->membase + FEC_ESW_PRES(port)); - writel(FSL_ESW_PRES_DFLT_PRI(priority_value & 0x7), - fep->membase + FEC_ESW_PRES(port)); - - return 0; -} + fep->rx_skbuff[i] = skb; -int esw_get_statistics_status(struct switch_enet_private *fep, - esw_statistics_status *pStatistics) -{ - pStatistics->ESW_DISCN = readl(fep->membase + FEC_ESW_DISCN); - pStatistics->ESW_DISCB = readl(fep->membase + FEC_ESW_DISCB); - pStatistics->ESW_NDISCN = readl(fep->membase + FEC_ESW_NDISCN); - pStatistics->ESW_NDISCB = readl(fep->membase + FEC_ESW_NDISCB); - return 0; -} + bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, + SWITCH_ENET_RX_FRSIZE, DMA_FROM_DEVICE); + bdp->cbd_sc = BD_ENET_RX_EMPTY; -int esw_get_port_statistics_status(struct switch_enet_private *fep, - int port, esw_port_statistics_status *pPortStatistics) -{ - if ((port < 0) || (port > 3)) { - printk(KERN_ERR "%s: do not support the port %d\n", - __func__, port); - return -1; + bdp++; } - pPortStatistics->FSL_ESW_POQC = - readl(fep->membase + FEC_ESW_POQC(port)); - pPortStatistics->FSL_ESW_PMVID = - readl(fep->membase + FEC_ESW_PMVID(port)); - pPortStatistics->FSL_ESW_PMVTAG = - readl(fep->membase + FEC_ESW_PMVTAG(port)); - pPortStatistics->FSL_ESW_PBL = - readl(fep->membase + FEC_ESW_PBL(port)); - return 0; -} - -int esw_get_output_queue_status(struct switch_enet_private *fep, - esw_output_queue_status *pOutputQueue) -{ - pOutputQueue->ESW_MMSR = readl(fep->membase + FEC_ESW_MMSR); - pOutputQueue->ESW_LMT = readl(fep->membase + FEC_ESW_LMT); - pOutputQueue->ESW_LFC = readl(fep->membase + FEC_ESW_LFC); - pOutputQueue->ESW_IOSR = readl(fep->membase + FEC_ESW_IOSR); - pOutputQueue->ESW_PCSR = readl(fep->membase + FEC_ESW_PCSR); - pOutputQueue->ESW_QWT = readl(fep->membase + FEC_ESW_QWT); - pOutputQueue->ESW_P0BCT = readl(fep->membase + FEC_ESW_P0BCT); - return 0; -} - -/* set output queue memory status and configure*/ -int esw_set_output_queue_memory(struct switch_enet_private *fep, - int fun_num, esw_output_queue_status *pOutputQueue) -{ - if (fun_num == 1) { - /* memory manager status*/ - writel(pOutputQueue->ESW_MMSR, fep->membase + FEC_ESW_MMSR); - } else if (fun_num == 2) { - /*low memory threshold*/ - writel(pOutputQueue->ESW_LMT, fep->membase + FEC_ESW_LMT); - } else if (fun_num == 3) { - /*lowest number of free cells*/ - writel(pOutputQueue->ESW_LFC, fep->membase + FEC_ESW_LFC); - } else if (fun_num == 4) { - /*queue weights*/ - writel(pOutputQueue->ESW_QWT, fep->membase + FEC_ESW_QWT); - } else if (fun_num == 5) { - /*port 0 backpressure congenstion thresled*/ - writel(pOutputQueue->ESW_P0BCT, fep->membase + FEC_ESW_P0BCT); - } else { - printk(KERN_ERR "%s: do not support the cmd %x\n", - __func__, fun_num); - return -1; - } - return 0; -} + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; -int esw_get_irq_status(struct switch_enet_private *fep, - eswIoctlIrqStatus *pIrqStatus) -{ - pIrqStatus->isr = readl(fep->membase + FEC_ESW_ISR); - pIrqStatus->imr = readl(fep->membase + FEC_ESW_IMR); - pIrqStatus->rx_buf_pointer = readl(fep->membase + FEC_ESW_RDSR); - pIrqStatus->tx_buf_pointer = readl(fep->membase + FEC_ESW_TDSR); - pIrqStatus->rx_max_size = readl(fep->membase + FEC_ESW_MRBR); - pIrqStatus->rx_buf_active = readl(fep->membase + FEC_ESW_RDAR); - pIrqStatus->tx_buf_active = readl(fep->membase + FEC_ESW_TDAR); - return 0; -} + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) { + fep->tx_bounce[i] = kmalloc(SWITCH_ENET_TX_FRSIZE, GFP_KERNEL); -int esw_set_irq_mask(struct switch_enet_private *fep, - unsigned long mask, int enable) -{ - u32 tmp = readl(fep->membase + FEC_ESW_IMR); - - if (enable == 1) - tmp |= mask; - else if (enable == 1) - tmp &= (~mask); - else { - printk(KERN_INFO "%s: enable %lx is error value\n", - __func__, mask); - return -1; + bdp->cbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; } - writel(tmp, fep->membase + FEC_ESW_IMR); - return 0; -} -void esw_clear_irq_event(struct switch_enet_private *fep, - unsigned long mask) -{ - u32 tmp = readl(fep->membase + FEC_ESW_ISR); - tmp |= mask; - writel(tmp, fep->membase + FEC_ESW_ISR); -} - -void esw_get_switch_mode(struct switch_enet_private *fep, - unsigned long *ulModeConfig) -{ - *ulModeConfig = readl(fep->membase + FEC_ESW_MODE); -} - -void esw_switch_mode_configure(struct switch_enet_private *fep, - unsigned long configure) -{ - u32 tmp = readl(fep->membase + FEC_ESW_MODE); - tmp |= configure; - writel(tmp, fep->membase + FEC_ESW_MODE); -} - -void esw_get_bridge_port(struct switch_enet_private *fep, - unsigned long *ulBMPConfig) -{ - *ulBMPConfig = readl(fep->membase + FEC_ESW_BMPC); -} - -void esw_bridge_port_configure(struct switch_enet_private *fep, - unsigned long configure) -{ - writel(configure, fep->membase + FEC_ESW_BMPC); -} + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; -int esw_get_port_all_status(struct switch_enet_private *fep, - unsigned char portnum, struct port_all_status *port_alstatus) -{ - unsigned long PortBlocking; - unsigned long PortLearning; - unsigned long VlanVerify; - unsigned long DiscardUnknown; - unsigned long MultiReso; - unsigned long BroadReso; - unsigned long FTransmit; - unsigned long FReceive; - - PortBlocking = readl(fep->membase + FEC_ESW_BKLR) & 0x0000000f; - PortLearning = (readl(fep->membase + FEC_ESW_BKLR) & 0x000f0000) >> 16; - VlanVerify = readl(fep->membase + FEC_ESW_VLANV) & 0x0000000f; - DiscardUnknown = (readl(fep->membase + FEC_ESW_VLANV) & 0x000f0000) - >> 16; - MultiReso = readl(fep->membase + FEC_ESW_DMCR) & 0x0000000f; - BroadReso = readl(fep->membase + FEC_ESW_DBCR) & 0x0000000f; - FTransmit = readl(fep->membase + FEC_ESW_PER) & 0x0000000f; - FReceive = (readl(fep->membase + FEC_ESW_PER) & 0x000f0000) >> 16; - - switch (portnum) { - case 0: - port_alstatus->link_status = 1; - port_alstatus->block_status = PortBlocking & 1; - port_alstatus->learn_status = PortLearning & 1; - port_alstatus->vlan_verify = VlanVerify & 1; - port_alstatus->discard_unknown = DiscardUnknown & 1; - port_alstatus->multi_reso = MultiReso & 1; - port_alstatus->broad_reso = BroadReso & 1; - port_alstatus->ftransmit = FTransmit & 1; - port_alstatus->freceive = FReceive & 1; - break; - case 1: - port_alstatus->link_status = - ports_link_status.port1_link_status; - port_alstatus->block_status = (PortBlocking >> 1) & 1; - port_alstatus->learn_status = (PortLearning >> 1) & 1; - port_alstatus->vlan_verify = (VlanVerify >> 1) & 1; - port_alstatus->discard_unknown = (DiscardUnknown >> 1) & 1; - port_alstatus->multi_reso = (MultiReso >> 1) & 1; - port_alstatus->broad_reso = (BroadReso >> 1) & 1; - port_alstatus->ftransmit = (FTransmit >> 1) & 1; - port_alstatus->freceive = (FReceive >> 1) & 1; - break; - case 2: - port_alstatus->link_status = - ports_link_status.port2_link_status; - port_alstatus->block_status = (PortBlocking >> 2) & 1; - port_alstatus->learn_status = (PortLearning >> 2) & 1; - port_alstatus->vlan_verify = (VlanVerify >> 2) & 1; - port_alstatus->discard_unknown = (DiscardUnknown >> 2) & 1; - port_alstatus->multi_reso = (MultiReso >> 2) & 1; - port_alstatus->broad_reso = (BroadReso >> 2) & 1; - port_alstatus->ftransmit = (FTransmit >> 2) & 1; - port_alstatus->freceive = (FReceive >> 2) & 1; - break; - default: - printk(KERN_ERR "%s:do not support the port %d", - __func__, portnum); - break; - } return 0; } -int esw_atable_get_entry_port_number(struct switch_enet_private *fep, - unsigned char *mac_addr, unsigned char *port) +static int switch_enet_open(struct net_device *dev) { - int block_index, block_index_end, entry; - unsigned long read_lo, read_hi; - unsigned long mac_addr_lo, mac_addr_hi; - - mac_addr_lo = (unsigned long)((mac_addr[3]<<24) | (mac_addr[2]<<16) | - (mac_addr[1]<<8) | mac_addr[0]); - mac_addr_hi = (unsigned long)((mac_addr[5]<<8) | (mac_addr[4])); - - block_index = GET_BLOCK_PTR(crc8_calc(mac_addr)); - block_index_end = block_index + ATABLE_ENTRY_PER_SLOT; - - /* now search all the entries in the selected block */ - for (entry = block_index; entry < block_index_end; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - if ((read_lo == mac_addr_lo) && - ((read_hi & 0x0000ffff) == - (mac_addr_hi & 0x0000ffff))) { - /* found the correct address */ - if ((read_hi & (1 << 16)) && (!(read_hi & (1 << 17)))) - *port = AT_EXTRACT_PORT(read_hi); - break; - } else - *port = -1; - } + struct switch_enet_private *fep = netdev_priv(dev); + int port = 0; + unsigned long tmp = 0; - return 0; -} + fep->phy1_link = 0; + fep->phy2_link = 0; -int esw_get_mac_address_lookup_table(struct switch_enet_private *fep, - unsigned long *tableaddr, unsigned long *dnum, unsigned long *snum) -{ - unsigned long read_lo, read_hi; - unsigned long entry; - unsigned long dennum = 0; - unsigned long sennum = 0; - - for (entry = 0; entry < ESW_ATABLE_MEM_NUM_ENTRIES; entry++) { - read_atable(fep, entry, &read_lo, &read_hi); - if ((read_hi & (1 << 17)) && (read_hi & (1 << 16))) { - /* static entry */ - *(tableaddr + (2047 - sennum) * 11) = entry; - *(tableaddr + (2047 - sennum) * 11 + 2) = - read_lo & 0x000000ff; - *(tableaddr + (2047 - sennum) * 11 + 3) = - (read_lo & 0x0000ff00) >> 8; - *(tableaddr + (2047 - sennum) * 11 + 4) = - (read_lo & 0x00ff0000) >> 16; - *(tableaddr + (2047 - sennum) * 11 + 5) = - (read_lo & 0xff000000) >> 24; - *(tableaddr + (2047 - sennum) * 11 + 6) = - read_hi & 0x000000ff; - *(tableaddr + (2047 - sennum) * 11 + 7) = - (read_hi & 0x0000ff00) >> 8; - *(tableaddr + (2047 - sennum) * 11 + 8) = - AT_EXTRACT_PORTMASK(read_hi); - *(tableaddr + (2047 - sennum) * 11 + 9) = - AT_EXTRACT_PRIO(read_hi); - sennum++; - } else if ((read_hi & (1 << 16)) && (!(read_hi & (1 << 17)))) { - /* dynamic entry */ - *(tableaddr + dennum * 11) = entry; - *(tableaddr + dennum * 11 + 2) = read_lo & 0xff; - *(tableaddr + dennum * 11 + 3) = - (read_lo & 0x0000ff00) >> 8; - *(tableaddr + dennum * 11 + 4) = - (read_lo & 0x00ff0000) >> 16; - *(tableaddr + dennum * 11 + 5) = - (read_lo & 0xff000000) >> 24; - *(tableaddr + dennum * 11 + 6) = read_hi & 0xff; - *(tableaddr + dennum * 11 + 7) = - (read_hi & 0x0000ff00) >> 8; - *(tableaddr + dennum * 11 + 8) = - AT_EXTRACT_PORT(read_hi); - *(tableaddr + dennum * 11 + 9) = - AT_EXTRACT_TIMESTAMP(read_hi); - dennum++; - } + switch_init_phy(dev); + for (port = 0; port < SWITCH_EPORT_NUMBER; port++) { + phy_write(fep->phydev[port], MII_BMCR, BMCR_RESET); + udelay(10); + phy_start(fep->phydev[port]); } - *dnum = dennum; - *snum = sennum; - return 0; -} - -/* The timer should create an interrupt every 4 seconds*/ -static void l2switch_aging_timer(unsigned long data) -{ - struct switch_enet_private *fep; + fep->phy1_old_link = 0; + fep->phy2_old_link = 0; + fep->phy1_link = 1; + fep->phy2_link = 1; - fep = (struct switch_enet_private *)data; + /* no phy, go full duplex, it's most likely a hub chip */ + switch_restart(dev, 1); - if (fep) { - TIMEINCREMENT(fep->currTime); - fep->timeChanged++; - } + /* if the fec open firstly, we need to do nothing + * otherwise, we need to restart the FEC + */ + if (fep->sequence_done == 0) + switch_restart(dev, 1); + else + fep->sequence_done = 0; - mod_timer(&fep->timer_aging, jiffies + LEARNING_AGING_TIMER); -} + writel(0x70007, fep->membase + FEC_ESW_PER); + writel(FSL_ESW_DBCR_P0 | FSL_ESW_DBCR_P1 | FSL_ESW_DBCR_P2, + fep->membase + FEC_ESW_DBCR); + writel(FSL_ESW_DMCR_P0 | FSL_ESW_DMCR_P1 | FSL_ESW_DMCR_P2, + fep->membase + FEC_ESW_DMCR); -static int switch_enet_learning(void *arg) -{ - struct switch_enet_private *fep = arg; + /* Disable port learning */ + tmp = readl(fep->membase + FEC_ESW_BKLR); + tmp &= ~FSL_ESW_BKLR_LDX; + writel(tmp, fep->membase + FEC_ESW_BKLR); - while (!kthread_should_stop()) { + netif_start_queue(dev); - set_current_state(TASK_INTERRUPTIBLE); + /* And last, enable the receive processing. */ + writel(FSL_ESW_RDAR_R_DES_ACTIVE, fep->membase + FEC_ESW_RDAR); - /* check learning record valid */ - if (readl(fep->membase + FEC_ESW_LSR)) - esw_atable_dynamicms_learn_migration(fep, - fep->currTime); - else - schedule_timeout(HZ/100); - } + fep->opened = 1; return 0; } -static int switch_enet_ioctl(struct net_device *dev, - struct ifreq *ifr, int cmd) +static int switch_enet_close(struct net_device *dev) { struct switch_enet_private *fep = netdev_priv(dev); - int ret = 0; - - switch (cmd) { - case ESW_SET_PORTENABLE_CONF: - { - eswIoctlPortEnableConfig configData; - ret = copy_from_user(&configData, - ifr->ifr_data, - sizeof(eswIoctlPortEnableConfig)); - if (ret) - return -EFAULT; - - ret = esw_port_enable_config(fep, - configData.port, - configData.tx_enable, - configData.rx_enable); - } - break; - case ESW_SET_BROADCAST_CONF: - { - eswIoctlPortConfig configData; - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPortConfig)); - if (ret) - return -EFAULT; - - ret = esw_port_broadcast_config(fep, - configData.port, configData.enable); - } - break; - - case ESW_SET_MULTICAST_CONF: - { - eswIoctlPortConfig configData; - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPortConfig)); - if (ret) - return -EFAULT; - - ret = esw_port_multicast_config(fep, - configData.port, configData.enable); - } - break; - - case ESW_SET_BLOCKING_CONF: - { - eswIoctlPortConfig configData; - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPortConfig)); - - if (ret) - return -EFAULT; - - ret = esw_port_blocking_config(fep, - configData.port, configData.enable); - } - break; - - case ESW_SET_LEARNING_CONF: - { - eswIoctlPortConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPortConfig)); - if (ret) - return -EFAULT; - - ret = esw_port_learning_config(fep, - configData.port, configData.enable); - } - break; - - case ESW_SET_PORT_ENTRY_EMPTY: - { - unsigned long portnum; - - ret = copy_from_user(&portnum, - ifr->ifr_data, sizeof(portnum)); - if (ret) - return -EFAULT; - esw_atable_dynamicms_del_entries_for_port(fep, portnum); - } - break; - - case ESW_SET_OTHER_PORT_ENTRY_EMPTY: - { - unsigned long portnum; - - ret = copy_from_user(&portnum, - ifr->ifr_data, sizeof(portnum)); - if (ret) - return -EFAULT; - - esw_atable_dynamicms_del_entries_for_other_port(fep, portnum); - } - break; - - case ESW_SET_IP_SNOOP_CONF: - { - eswIoctlIpsnoopConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlIpsnoopConfig)); - if (ret) - return -EFAULT; - - ret = esw_ip_snoop_config(fep, configData.mode, - configData.ip_header_protocol); - } - break; - - case ESW_SET_PORT_SNOOP_CONF: - { - eswIoctlPortsnoopConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPortsnoopConfig)); - if (ret) - return -EFAULT; - - ret = esw_tcpudp_port_snoop_config(fep, configData.mode, - configData.compare_port, - configData.compare_num); - } - break; - - case ESW_SET_PORT_MIRROR_CONF_PORT_MATCH: - { - struct eswIoctlMirrorCfgPortMatch configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(configData)); - if (ret) - return -EFAULT; - ret = esw_port_mirroring_config_port_match(fep, - configData.mirror_port, configData.port_match_en, - configData.port); - } - break; - - case ESW_SET_PORT_MIRROR_CONF: - { - eswIoctlPortMirrorConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPortMirrorConfig)); - if (ret) - return -EFAULT; - - ret = esw_port_mirroring_config(fep, - configData.mirror_port, configData.port, - configData.mirror_enable, - configData.src_mac, configData.des_mac, - configData.egress_en, configData.ingress_en, - configData.egress_mac_src_en, - configData.egress_mac_des_en, - configData.ingress_mac_src_en, - configData.ingress_mac_des_en); - } - break; - - case ESW_SET_PORT_MIRROR_CONF_ADDR_MATCH: - { - struct eswIoctlMirrorCfgAddrMatch configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(configData)); - if (ret) - return -EFAULT; - - ret = esw_port_mirroring_config_addr_match(fep, - configData.mirror_port, configData.addr_match_en, - configData.mac_addr); - } - break; - - case ESW_SET_PIRORITY_VLAN: - { - eswIoctlPriorityVlanConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPriorityVlanConfig)); - if (ret) - return -EFAULT; - - ret = esw_framecalssify_vlan_priority_lookup(fep, - configData.port, configData.func_enable, - configData.vlan_pri_table_num, - configData.vlan_pri_table_value); - } - break; - - case ESW_SET_PIRORITY_IP: - { - eswIoctlPriorityIPConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPriorityIPConfig)); - if (ret) - return -EFAULT; - - ret = esw_framecalssify_ip_priority_lookup(fep, - configData.port, configData.func_enable, - configData.ipv4_en, configData.ip_priority_num, - configData.ip_priority_value); - } - break; - - case ESW_SET_PIRORITY_MAC: - { - eswIoctlPriorityMacConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPriorityMacConfig)); - if (ret) - return -EFAULT; - - ret = esw_framecalssify_mac_priority_lookup(fep, - configData.port); - } - break; - - case ESW_SET_PIRORITY_DEFAULT: - { - eswIoctlPriorityDefaultConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlPriorityDefaultConfig)); - if (ret) - return -EFAULT; - - ret = esw_frame_calssify_priority_init(fep, - configData.port, configData.priority_value); - } - break; - - case ESW_SET_P0_FORCED_FORWARD: - { - eswIoctlP0ForcedForwardConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlP0ForcedForwardConfig)); - if (ret) - return -EFAULT; - - ret = esw_forced_forward(fep, configData.port1, - configData.port2, configData.enable); - } - break; - - case ESW_SET_BRIDGE_CONFIG: - { - unsigned long configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(unsigned long)); - if (ret) - return -EFAULT; - - esw_bridge_port_configure(fep, configData); - } - break; - - case ESW_SET_SWITCH_MODE: - { - unsigned long configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(unsigned long)); - if (ret) - return -EFAULT; - - esw_switch_mode_configure(fep, configData); - } - break; - - case ESW_SET_OUTPUT_QUEUE_MEMORY: - { - eswIoctlOutputQueue configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlOutputQueue)); - if (ret) - return -EFAULT; - - ret = esw_set_output_queue_memory(fep, - configData.fun_num, &configData.sOutputQueue); - } - break; - - case ESW_SET_VLAN_OUTPUT_PROCESS: - { - eswIoctlVlanOutputConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlVlanOutputConfig)); - if (ret) - return -EFAULT; - - ret = esw_vlan_output_process(fep, - configData.port, configData.mode); - } - break; - - case ESW_SET_VLAN_INPUT_PROCESS: - { - eswIoctlVlanInputConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, - sizeof(eswIoctlVlanInputConfig)); - if (ret) - return -EFAULT; - - ret = esw_vlan_input_process(fep, configData.port, - configData.mode, configData.port_vlanid); - } - break; - - case ESW_SET_VLAN_DOMAIN_VERIFICATION: - { - eswIoctlVlanVerificationConfig configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, - sizeof(eswIoctlVlanVerificationConfig)); - if (ret) - return -EFAULT; - - ret = esw_set_vlan_verification( - fep, configData.port, - configData.vlan_domain_verify_en, - configData.vlan_discard_unknown_en); - } - break; - - case ESW_SET_VLAN_RESOLUTION_TABLE: - { - eswIoctlVlanResoultionTable configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, - sizeof(eswIoctlVlanResoultionTable)); - if (ret) - return -EFAULT; - - ret = esw_set_vlan_resolution_table( - fep, configData.port_vlanid, - configData.vlan_domain_num, - configData.vlan_domain_port); - - } - break; - - case ESW_SET_VLAN_ID: - { - unsigned long configData; - ret = copy_from_user(&configData, ifr->ifr_data, - sizeof(configData)); - if (ret) - return -EFAULT; - - ret = esw_set_vlan_id(fep, configData); - } - break; - - case ESW_SET_VLAN_ID_CLEARED: - { - unsigned long configData; - ret = copy_from_user(&configData, ifr->ifr_data, - sizeof(configData)); - if (ret) - return -EFAULT; - - ret = esw_set_vlan_id_cleared(fep, configData); - } - break; - - case ESW_SET_PORT_IN_VLAN_ID: - { - eswIoctlVlanResoultionTable configData; - - ret = copy_from_user(&configData, ifr->ifr_data, - sizeof(configData)); - if (ret) - return -EFAULT; - - ret = esw_set_port_in_vlan_id(fep, configData); - } - break; - - case ESW_UPDATE_STATIC_MACTABLE: - { - eswIoctlUpdateStaticMACtable configData; - - ret = copy_from_user(&configData, - ifr->ifr_data, sizeof(eswIoctlUpdateStaticMACtable)); - if (ret) - return -EFAULT; - - ret = esw_update_atable_static(configData.mac_addr, - configData.port, configData.priority, fep); - } - break; - - case ESW_CLEAR_ALL_MACTABLE: - { - esw_clear_atable(fep); - } - break; - - /*get*/ - case ESW_GET_STATISTICS_STATUS: - { - esw_statistics_status Statistics; - esw_port_statistics_status PortSta; - int i; - - ret = esw_get_statistics_status(fep, &Statistics); - if (ret != 0) { - printk(KERN_ERR "%s: cmd %x fail\n", __func__, cmd); - return -1; - } - printk(KERN_INFO "DISCN : %10ld DISCB : %10ld\n", - Statistics.ESW_DISCN, Statistics.ESW_DISCB); - printk(KERN_INFO "NDISCN: %10ld NDISCB: %10ld\n", - Statistics.ESW_NDISCN, Statistics.ESW_NDISCB); - - for (i = 0; i < 3; i++) { - ret = esw_get_port_statistics_status(fep, i, - &PortSta); - if (ret != 0) { - printk(KERN_ERR "%s: cmd %x fail\n", - __func__, cmd); - return -1; - } - printk(KERN_INFO "port %d: POQC : %ld\n", - i, PortSta.FSL_ESW_POQC); - printk(KERN_INFO " PMVID : %ld\n", - PortSta.FSL_ESW_PMVID); - printk(KERN_INFO " PMVTAG: %ld\n", - PortSta.FSL_ESW_PMVTAG); - printk(KERN_INFO " PBL : %ld\n", - PortSta.FSL_ESW_PBL); - } - } - break; - - case ESW_GET_LEARNING_CONF: - { - unsigned long PortLearning; - - esw_get_port_learning(fep, &PortLearning); - ret = copy_to_user(ifr->ifr_data, &PortLearning, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_BLOCKING_CONF: - { - unsigned long PortBlocking; - - esw_get_port_blocking(fep, &PortBlocking); - ret = copy_to_user(ifr->ifr_data, &PortBlocking, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_MULTICAST_CONF: - { - unsigned long PortMulticast; - - esw_get_port_multicast(fep, &PortMulticast); - ret = copy_to_user(ifr->ifr_data, &PortMulticast, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_BROADCAST_CONF: - { - unsigned long PortBroadcast; - - esw_get_port_broadcast(fep, &PortBroadcast); - ret = copy_to_user(ifr->ifr_data, &PortBroadcast, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_PORTENABLE_CONF: - { - unsigned long PortEnable; - - esw_get_port_enable(fep, &PortEnable); - ret = copy_to_user(ifr->ifr_data, &PortEnable, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_IP_SNOOP_CONF: - { - unsigned long ESW_IPSNP[8]; - int i; - - esw_get_ip_snoop_config(fep, (unsigned long *)ESW_IPSNP); - printk(KERN_INFO "IP Protocol Mode Type\n"); - for (i = 0; i < 8; i++) { - if (ESW_IPSNP[i] != 0) - printk(KERN_INFO "%3ld " - "%1ld %s\n", - (ESW_IPSNP[i] >> 8) & 0xff, - (ESW_IPSNP[i] >> 1) & 3, - ESW_IPSNP[i] & 1 ? "Active" : - "Inactive"); - } - } - break; - - case ESW_GET_PORT_SNOOP_CONF: - { - unsigned long ESW_PSNP[8]; - int i; - - esw_get_tcpudp_port_snoop_config(fep, - (unsigned long *)ESW_PSNP); - printk(KERN_INFO "TCP/UDP Port SrcCompare DesCompare " - "Mode Type\n"); - for (i = 0; i < 8; i++) { - if (ESW_PSNP[i] != 0) - printk(KERN_INFO "%5ld %s " - "%s %1ld %s\n", - (ESW_PSNP[i] >> 16) & 0xffff, - (ESW_PSNP[i] >> 4) & 1 ? "Y" : "N", - (ESW_PSNP[i] >> 3) & 1 ? "Y" : "N", - (ESW_PSNP[i] >> 1) & 3, - ESW_PSNP[i] & 1 ? "Active" : - "Inactive"); - } - } - break; - - case ESW_GET_PORT_MIRROR_CONF: - esw_get_port_mirroring(fep); - break; - - case ESW_GET_P0_FORCED_FORWARD: - { - unsigned long ForceForward; - - esw_get_forced_forward(fep, &ForceForward); - ret = copy_to_user(ifr->ifr_data, &ForceForward, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_SWITCH_MODE: - { - unsigned long Config; - - esw_get_switch_mode(fep, &Config); - ret = copy_to_user(ifr->ifr_data, &Config, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_BRIDGE_CONFIG: - { - unsigned long Config; - - esw_get_bridge_port(fep, &Config); - ret = copy_to_user(ifr->ifr_data, &Config, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - case ESW_GET_OUTPUT_QUEUE_STATUS: - { - esw_output_queue_status Config; - esw_get_output_queue_status(fep, - &Config); - ret = copy_to_user(ifr->ifr_data, &Config, - sizeof(esw_output_queue_status)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_VLAN_OUTPUT_PROCESS: - { - unsigned long Config; - int tmp; - int i; - - esw_get_vlan_output_config(fep, &Config); - - for (i = 0; i < 3; i++) { - tmp = (Config >> (i << 1)) & 3; - - if (tmp != 0) - printk(KERN_INFO "port %d: vlan output " - "manipulation enable (mode %d)\n", - i, tmp); - else - printk(KERN_INFO "port %d: vlan output " - "manipulation disable\n", i); - } - } - break; - - case ESW_GET_VLAN_INPUT_PROCESS: - { - eswIoctlVlanInputStatus Config; - int i; - - esw_get_vlan_input_config(fep, &Config); - - for (i = 0; i < 3; i++) { - if (((Config.ESW_VIMEN >> i) & 1) == 0) - printk(KERN_INFO "port %d: vlan input " - "manipulation disable\n", i); - else - printk("port %d: vlan input manipulation enable" - " (mode %ld, vlan id %ld)\n", i, - (((Config.ESW_VIMSEL >> (i << 1)) & 3) - + 1), Config.ESW_PID[i]); - } - } - break; - - case ESW_GET_VLAN_RESOLUTION_TABLE: - { - struct eswVlanTableItem vtableitem; - unsigned char tmp0, tmp1, tmp2; - int i; - - esw_get_vlan_resolution_table(fep, &vtableitem); - - printk(KERN_INFO "VLAN Name VLAN Id Ports\n"); - for (i = 0; i < vtableitem.valid_num; i++) { - tmp0 = vtableitem.table[i].vlan_domain_port & 1; - tmp1 = (vtableitem.table[i].vlan_domain_port >> 1) & 1; - tmp2 = (vtableitem.table[i].vlan_domain_port >> 2) & 1; - printk(KERN_INFO "%2d %4d %s%s%s\n", - i, vtableitem.table[i].port_vlanid, - tmp0 ? "0 " : "", tmp1 ? "1 " : "", - tmp2 ? "2" : ""); - } - } - break; - - case ESW_GET_VLAN_DOMAIN_VERIFICATION: - { - unsigned long Config; - - esw_get_vlan_verification(fep, &Config); - ret = copy_to_user(ifr->ifr_data, &Config, - sizeof(unsigned long)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_ENTRY_PORT_NUMBER: - { - unsigned char mac_addr[6]; - unsigned char portnum; - - ret = copy_from_user(mac_addr, - ifr->ifr_data, sizeof(mac_addr)); - if (ret) - return -EFAULT; - - ret = esw_atable_get_entry_port_number(fep, mac_addr, - &portnum); - - ret = copy_to_user(ifr->ifr_data, &portnum, - sizeof(unsigned char)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_LOOKUP_TABLE: - { - unsigned long *ConfigData; - unsigned long dennum, sennum; - int i; - int tmp; - - ConfigData = kmalloc(sizeof(struct eswAddrTableEntryExample) * - ESW_ATABLE_MEM_NUM_ENTRIES, GFP_KERNEL); - ret = esw_get_mac_address_lookup_table(fep, ConfigData, - &dennum, &sennum); - printk(KERN_INFO "Dynamic entries number: %ld\n", dennum); - printk(KERN_INFO "Static entries number: %ld\n", sennum); - printk(KERN_INFO "Type MAC address Port Timestamp\n"); - for (i = 0; i < dennum; i++) { - printk(KERN_INFO "dynamic " - "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx " - "%01lx %4ld\n", *(ConfigData + i * 11 + 2), - *(ConfigData + i * 11 + 3), - *(ConfigData + i * 11 + 4), - *(ConfigData + i * 11 + 5), - *(ConfigData + i * 11 + 6), - *(ConfigData + i * 11 + 7), - *(ConfigData + i * 11 + 8), - *(ConfigData + i * 11 + 9)); - } - - if (sennum != 0) - printk(KERN_INFO "Type MAC address" - " Port Priority\n"); - - for (i = 0; i < sennum; i++) { - printk(KERN_INFO "static %02lx-%02lx-%02lx-%02lx" - "-%02lx-%02lx ", - *(ConfigData + (2047 - i) * 11 + 2), - *(ConfigData + (2047 - i) * 11 + 3), - *(ConfigData + (2047 - i) * 11 + 4), - *(ConfigData + (2047 - i) * 11 + 5), - *(ConfigData + (2047 - i) * 11 + 6), - *(ConfigData + (2047 - i) * 11 + 7)); - - tmp = *(ConfigData + (2047 - i) * 11 + 8); - if ((tmp == 0) || (tmp == 2) || (tmp == 4)) - printk("%01x ", tmp >> 1); - else if (tmp == 3) - printk("0,1 "); - else if (tmp == 5) - printk("0,2 "); - else if (tmp == 6) - printk("1,2 "); - - printk("%4ld\n", *(ConfigData + (2047 - i) * 11 + 9)); - } - kfree(ConfigData); - } - break; - - case ESW_GET_PORT_STATUS: - { - unsigned long PortBlocking; - - esw_get_port_blocking(fep, &PortBlocking); - - ports_link_status.port0_block_status = PortBlocking & 1; - ports_link_status.port1_block_status = (PortBlocking >> 1) & 1; - ports_link_status.port2_block_status = PortBlocking >> 2; - - ret = copy_to_user(ifr->ifr_data, &ports_link_status, - sizeof(ports_link_status)); - if (ret) - return -EFAULT; - } - break; - - case ESW_GET_PORT_ALL_STATUS: - { - unsigned char portnum; - struct port_all_status port_astatus; - - ret = copy_from_user(&portnum, - ifr->ifr_data, sizeof(portnum)); - if (ret) - return -EFAULT; - - esw_get_port_all_status(fep, portnum, &port_astatus); - printk(KERN_INFO "Port %d status:\n", portnum); - printk(KERN_INFO "Link:%-4s Blocking:%1s " - "Learning:%1s\n", - port_astatus.link_status ? "Up" : "Down", - port_astatus.block_status ? "Y" : "N", - port_astatus.learn_status ? "N" : "Y"); - printk(KERN_INFO "VLAN Verify:%1s Discard Unknown:%1s " - "Multicast Res:%1s\n", - port_astatus.vlan_verify ? "Y" : "N", - port_astatus.discard_unknown ? "Y" : "N", - port_astatus.multi_reso ? "Y" : "N"); - printk(KERN_INFO "Broadcast Res:%1s Transmit:%-7s " - "Receive:%7s\n", - port_astatus.broad_reso ? "Y" : "N", - port_astatus.ftransmit ? "Enable" : "Disable", - port_astatus.freceive ? "Enable" : "Disable"); - - } - break; - - case ESW_GET_USER_PID: - { - long get_pid = 0; - ret = copy_from_user(&get_pid, - ifr->ifr_data, sizeof(get_pid)); + int i; - if (ret) - return -EFAULT; - user_pid = get_pid; - } - break; + /* Don't know what to do yet. */ + fep->opened = 0; + netif_stop_queue(dev); + switch_stop(dev); - default: - return -EOPNOTSUPP; + for (i = 0; i < SWITCH_EPORT_NUMBER; i++) { + phy_disconnect(fep->phydev[i]); + phy_stop(fep->phydev[i]); + phy_write(fep->phydev[i], MII_BMCR, BMCR_PDOWN); } - return ret; + return 0; } static netdev_tx_t switch_enet_start_xmit(struct sk_buff *skb, @@ -3101,19 +547,18 @@ static netdev_tx_t switch_enet_start_xmit(struct sk_buff *skb, /* Clear all of the status flags */ status &= ~BD_ENET_TX_STATS; - /* Set buffer length and buffer pointer. - */ + /* Set buffer length and buffer pointer. */ bufaddr = skb->data; bdp->cbd_datlen = skb->len; - /* - * On some FEC implementations data must be aligned on + /* On some FEC implementations data must be aligned on * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ if (((unsigned long)bufaddr) & 0xf) { unsigned int index; index = bdp - fep->tx_bd_base; + memcpy(fep->tx_bounce[index], (void *)skb->data, bdp->cbd_datlen); bufaddr = fep->tx_bounce[index]; @@ -3123,7 +568,7 @@ static netdev_tx_t switch_enet_start_xmit(struct sk_buff *skb, fep->tx_skbuff[fep->skb_cur] = skb; dev->stats.tx_bytes += skb->len; - fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; + fep->skb_cur = (fep->skb_cur + 1) & TX_RING_MOD_MASK; /* Push the data cache so the CPM does not get stale memory * data. @@ -3144,7 +589,8 @@ static netdev_tx_t switch_enet_start_xmit(struct sk_buff *skb, writel(FSL_ESW_TDAR_X_DES_ACTIVE, fep->membase + FEC_ESW_TDAR); /* If this was the last BD in the ring, - * start at the beginning again.*/ + * start at the beginning again. + */ if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; else @@ -3153,7 +599,7 @@ static netdev_tx_t switch_enet_start_xmit(struct sk_buff *skb, if (bdp == fep->dirty_tx) { fep->tx_full = 1; netif_stop_queue(dev); - printk(KERN_ERR "%s: net stop\n", __func__); + netdev_err(dev, "%s: net stop\n", __func__); } fep->cur_tx = (cbd_t *)bdp; @@ -3167,41 +613,101 @@ static void switch_timeout(struct net_device *dev) { struct switch_enet_private *fep = netdev_priv(dev); - printk(KERN_ERR "%s: transmit timed out.\n", dev->name); + netdev_err(dev, "%s: transmit timed out.\n", dev->name); dev->stats.tx_errors++; switch_restart(dev, fep->full_duplex); netif_wake_queue(dev); } -/* The interrupt handler. - * This is called from the MPC core interrupt. - */ -static irqreturn_t switch_enet_interrupt(int irq, void *dev_id) +static const struct net_device_ops switch_netdev_ops = { + .ndo_open = switch_enet_open, + .ndo_stop = switch_enet_close, + .ndo_start_xmit = switch_enet_start_xmit, + .ndo_tx_timeout = switch_timeout, +}; + +/* Initialize the FEC Ethernet. */ +static int switch_enet_init(struct net_device *dev) { - struct net_device *dev = dev_id; struct switch_enet_private *fep = netdev_priv(dev); - uint int_events; - irqreturn_t ret = IRQ_NONE; + cbd_t *cbd_base = NULL; + int ret = 0; - /* Get the interrupt events that caused us to be here. - */ - do { - int_events = readl(fep->membase + FEC_ESW_ISR); - writel(int_events, fep->membase + FEC_ESW_ISR); + /* Allocate memory for buffer descriptors. */ + cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, + GFP_KERNEL); + if (!cbd_base) { + return -ENOMEM; + } - /* Handle receive event in its own function. */ + spin_lock_init(&fep->hw_lock); + spin_lock_init(&fep->mii_lock); - if (int_events & FSL_ESW_ISR_RXF) { - ret = IRQ_HANDLED; - switch_enet_rx(dev); - } + writel(FSL_ESW_MODE_SW_RST, fep->membase + FEC_ESW_MODE); + udelay(10); + writel(FSL_ESW_MODE_STATRST, fep->membase + FEC_ESW_MODE); + writel(FSL_ESW_MODE_SW_EN, fep->membase + FEC_ESW_MODE); - if (int_events & FSL_ESW_ISR_TXF) { - ret = IRQ_HANDLED; - switch_enet_tx(dev); - } + /* Enable transmit/receive on all ports */ + writel(0xffffffff, fep->membase + FEC_ESW_PER); - } while (int_events); + /* Management port configuration, + * make port 0 as management port + */ + writel(0, fep->membase + FEC_ESW_BMPC); + + /* Clear any outstanding interrupt.*/ + writel(0xffffffff, fep->membase + FEC_ESW_ISR); + writel(0, fep->membase + FEC_ESW_IMR); + udelay(100); + + /* Get the Ethernet address */ + switch_get_mac_address(dev); + + /* Set receive and transmit descriptor base. */ + fep->rx_bd_base = cbd_base; + fep->tx_bd_base = cbd_base + RX_RING_SIZE; + + dev->base_addr = (unsigned long)fep->membase; + + /* The FEC Ethernet specific entries in the device structure. */ + dev->watchdog_timeo = TX_TIMEOUT; + dev->netdev_ops = &switch_netdev_ops; + + fep->skb_cur = fep->skb_dirty = 0; + + ret = switch_alloc_buffers(dev); + if (ret) + goto err_enet_alloc; + + /* Set receive and transmit descriptor base */ + writel(fep->bd_dma, fep->membase + FEC_ESW_RDSR); + writel((unsigned long)fep->bd_dma + + sizeof(struct bufdesc) * RX_RING_SIZE, + fep->membase + FEC_ESW_TDSR); + + /* set mii */ + switch_hw_init(dev); + + /* Clear any outstanding interrupt. */ + writel(0xffffffff, fep->membase + FEC_ESW_ISR); + writel(FSL_ESW_IMR_RXF | FSL_ESW_IMR_TXF, fep->membase + FEC_ESW_IMR); + + /* Queue up command to detect the PHY and initialize the + * remainder of the interface. + */ +#ifndef CONFIG_FEC_SHARED_PHY + fep->phy_addr = 0; +#else + fep->phy_addr = fep->index; +#endif + + fep->sequence_done = 1; + + return ret; + +err_enet_alloc: + switch_enet_clk_enable(dev, false); return ret; } @@ -3271,7 +777,7 @@ static void switch_enet_tx(struct net_device *dev) */ if (fep->tx_full) { fep->tx_full = 0; - printk(KERN_ERR "%s: tx full is zero\n", __func__); + netdev_err(dev, "%s: tx full is zero\n", __func__); if (netif_queue_stopped(dev)) netif_wake_queue(dev); } @@ -3280,7 +786,6 @@ static void switch_enet_tx(struct net_device *dev) spin_unlock_irqrestore(&fep->hw_lock, flags); } - /* During a receive, the cur_rx points to the current incoming buffer. * When we update through the ring, if the next incoming buffer has * not been given to the system, we just set the empty indicator, @@ -3305,12 +810,11 @@ static void switch_enet_rx(struct net_device *dev) bdp = fep->cur_rx; while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { - /* Since we have allocated space to hold a complete frame, * the last indicator should be set. - * */ + */ if ((status & BD_ENET_RX_LAST) == 0) - printk(KERN_ERR "SWITCH ENET: rcv is not +last\n"); + netdev_err(dev, "SWITCH ENET: rcv is not +last\n"); if (!fep->opened) goto rx_processing_done; @@ -3333,7 +837,7 @@ static void switch_enet_rx(struct net_device *dev) /* Report late collisions as a frame error. * On this error, the BD is closed, but we don't know what we * have in the buffer. So, just drop this frame on the floor. - * */ + */ if (status & BD_ENET_RX_CL) { dev->stats.rx_errors++; dev->stats.rx_frame_errors++; @@ -3353,15 +857,16 @@ static void switch_enet_rx(struct net_device *dev) * The packet length includes FCS, but we don't want to * include that when passing upstream as it messes up * bridging applications. - * */ + */ skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN); - if (skb == NULL) + if (!skb) dev->stats.rx_dropped++; if (unlikely(!skb)) { - printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", - dev->name); + netdev_err(dev, + "%s:Memory squeeze, dropping packet.\n", + dev->name); dev->stats.rx_dropped++; } else { skb_reserve(skb, NET_IP_ALIGN); @@ -3391,7 +896,7 @@ rx_processing_done: /* Doing this here will keep the FEC running while we process * incoming frames. On a heavily loaded network, we should be * able to keep up at the expense of system resources. - * */ + */ writel(FSL_ESW_RDAR_R_DES_ACTIVE, fep->membase + FEC_ESW_RDAR); } fep->cur_rx = (cbd_t *)bdp; @@ -3402,10 +907,10 @@ rx_processing_done: static int fec_mdio_transfer(struct mii_bus *bus, int phy_id, int reg, int regval) { - unsigned long flags; + struct switch_enet_private *fep = bus->priv; - int retval = 0; - int tries = 100; + unsigned long flags; + int retval = 0, tries = 100; spin_lock_irqsave(&fep->mii_lock, flags); @@ -3416,7 +921,8 @@ static int fec_mdio_transfer(struct mii_bus *bus, int phy_id, writel(regval, fep->enetbase + FSL_FEC_MMFR0); /* wait for it to finish, this takes about 23 us on lite5200b */ - while (!(readl(fep->enetbase + FSL_FEC_EIR0) & FEC_ENET_MII) && --tries) + while (!(readl(fep->enetbase + FSL_FEC_EIR0) + & FEC_ENET_MII) && --tries) udelay(5); if (!tries) { printk(KERN_ERR "%s timeout\n", __func__); @@ -3433,7 +939,8 @@ static int fec_mdio_transfer(struct mii_bus *bus, int phy_id, static int fec_enet_mdio_read(struct mii_bus *bus, int phy_id, int reg) { - int ret; + int ret = 0; + ret = fec_mdio_transfer(bus, phy_id, reg, mk_mii_read(reg)); return ret; @@ -3446,586 +953,48 @@ static int fec_enet_mdio_write(struct mii_bus *bus, mk_mii_write(reg, data)); } -static void switch_adjust_link1(struct net_device *dev) -{ - struct switch_enet_private *priv = netdev_priv(dev); - struct phy_device *phydev1 = priv->phydev[0]; - int new_state = 0; - - if (phydev1->link != PHY_DOWN) { - if (phydev1->duplex != priv->phy1_duplex) { - new_state = 1; - priv->phy1_duplex = phydev1->duplex; - } - - if (phydev1->speed != priv->phy1_speed) { - new_state = 1; - priv->phy1_speed = phydev1->speed; - } - - if (priv->phy1_old_link == PHY_DOWN) { - new_state = 1; - priv->phy1_old_link = phydev1->link; - } - } else if (priv->phy1_old_link) { - new_state = 1; - priv->phy1_old_link = PHY_DOWN; - priv->phy1_speed = 0; - priv->phy1_duplex = -1; - } - - if (new_state) { - ports_link_status.port1_link_status = phydev1->link; - if (phydev1->link == PHY_DOWN) - esw_atable_dynamicms_del_entries_for_port(priv, 1); - - /*Send the new status to user space*/ - if (user_pid != 1) - sys_tkill(user_pid, SIGUSR1); - phy_print_status(phydev1); - } -} - -static void switch_adjust_link2(struct net_device *dev) -{ - struct switch_enet_private *priv = netdev_priv(dev); - struct phy_device *phydev2 = priv->phydev[1]; - int new_state = 0; - - if (phydev2->link != PHY_DOWN) { - if (phydev2->duplex != priv->phy2_duplex) { - new_state = 1; - priv->phy2_duplex = phydev2->duplex; - } - - if (phydev2->speed != priv->phy2_speed) { - new_state = 1; - priv->phy2_speed = phydev2->speed; - } - - if (priv->phy2_old_link == PHY_DOWN) { - new_state = 1; - priv->phy2_old_link = phydev2->link; - } - } else if (priv->phy2_old_link) { - new_state = 1; - priv->phy2_old_link = PHY_DOWN; - priv->phy2_speed = 0; - priv->phy2_duplex = -1; - } - - if (new_state) { - ports_link_status.port2_link_status = phydev2->link; - if (phydev2->link == PHY_DOWN) - esw_atable_dynamicms_del_entries_for_port(priv, 2); - - /*Send the new status to user space*/ - if (user_pid != 1) - sys_tkill(user_pid, SIGUSR1); - phy_print_status(phydev2); - } -} - -static int switch_init_phy(struct net_device *dev) -{ - struct switch_enet_private *priv = netdev_priv(dev); - struct phy_device *phydev[SWITCH_EPORT_NUMBER] = {NULL, NULL}; - int i, j = 0; - - /* search for connect PHY device */ - for (i = 0; i < PHY_MAX_ADDR; i++) { - struct phy_device *const tmp_phydev = - priv->mdio_bus->phy_map[i]; - - if (!tmp_phydev) - continue; - - phydev[j++] = tmp_phydev; - if (j >= SWITCH_EPORT_NUMBER) - break; - } - - /* now we are supposed to have a proper phydev, to attach to... */ - if ((!phydev[0]) && (!phydev[1])) { - printk(KERN_INFO "%s: Don't found any phy device at all\n", - dev->name); - return -ENODEV; - } - - priv->phy1_link = PHY_DOWN; - priv->phy1_old_link = PHY_DOWN; - priv->phy1_speed = 0; - priv->phy1_duplex = -1; - - priv->phy2_link = PHY_DOWN; - priv->phy2_old_link = PHY_DOWN; - priv->phy2_speed = 0; - priv->phy2_duplex = -1; - - phydev[0] = phy_connect(dev, dev_name(&phydev[0]->dev), - &switch_adjust_link1, PHY_INTERFACE_MODE_RMII); - if (IS_ERR(phydev[0])) { - printk(KERN_ERR " %s phy_connect failed\n", __func__); - return PTR_ERR(phydev[0]); - } - - phydev[1] = phy_connect(dev, dev_name(&phydev[1]->dev), - &switch_adjust_link2, PHY_INTERFACE_MODE_RMII); - if (IS_ERR(phydev[1])) { - printk(KERN_ERR " %s phy_connect failed\n", __func__); - return PTR_ERR(phydev[1]); - } - - for (i = 0; i < SWITCH_EPORT_NUMBER; i++) { - phydev[i]->supported &= PHY_BASIC_FEATURES; - phydev[i]->advertising = phydev[i]->supported; - priv->phydev[i] = phydev[i]; - printk(KERN_INFO "attached phy %i to driver %s " - "(mii_bus:phy_addr=%s, irq=%d)\n", - phydev[i]->addr, phydev[i]->drv->name, - dev_name(&priv->phydev[i]->dev), - priv->phydev[i]->irq); - } - - return 0; -} - -static void switch_enet_free_buffers(struct net_device *ndev) -{ - struct switch_enet_private *fep = netdev_priv(ndev); - int i; - struct sk_buff *skb; - cbd_t *bdp; - - bdp = fep->rx_bd_base; - for (i = 0; i < RX_RING_SIZE; i++) { - skb = fep->rx_skbuff[i]; - - if (bdp->cbd_bufaddr) - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - SWITCH_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - if (skb) - dev_kfree_skb(skb); - bdp++; - } - - bdp = fep->tx_bd_base; - for (i = 0; i < TX_RING_SIZE; i++) - kfree(fep->tx_bounce[i]); -} - -static int switch_alloc_buffers(struct net_device *ndev) -{ - struct switch_enet_private *fep = netdev_priv(ndev); - int i; - struct sk_buff *skb; - cbd_t *bdp; - - bdp = fep->rx_bd_base; - for (i = 0; i < RX_RING_SIZE; i++) { - skb = dev_alloc_skb(SWITCH_ENET_RX_FRSIZE); - if (!skb) { - switch_enet_free_buffers(ndev); - return -ENOMEM; - } - fep->rx_skbuff[i] = skb; - - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, - SWITCH_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - bdp->cbd_sc = BD_ENET_RX_EMPTY; - - bdp++; - } - - /* Set the last buffer to wrap. */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - bdp = fep->tx_bd_base; - for (i = 0; i < TX_RING_SIZE; i++) { - fep->tx_bounce[i] = kmalloc(SWITCH_ENET_TX_FRSIZE, GFP_KERNEL); - - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } - - /* Set the last buffer to wrap. */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - return 0; -} - -static int switch_enet_open(struct net_device *dev) -{ - struct switch_enet_private *fep = netdev_priv(dev); - int i; - - fep->phy1_link = 0; - fep->phy2_link = 0; - - switch_init_phy(dev); - for (i = 0; i < SWITCH_EPORT_NUMBER; i++) { - phy_write(fep->phydev[i], MII_BMCR, BMCR_RESET); - udelay(10); - phy_start(fep->phydev[i]); - } - - fep->phy1_old_link = 0; - fep->phy2_old_link = 0; - fep->phy1_link = 1; - fep->phy2_link = 1; - - /* no phy, go full duplex, it's most likely a hub chip */ - switch_restart(dev, 1); - - /* if the fec open firstly, we need to do nothing*/ - /* otherwise, we need to restart the FEC*/ - if (fep->sequence_done == 0) - switch_restart(dev, 1); - else - fep->sequence_done = 0; - - fep->currTime = 0; - fep->learning_irqhandle_enable = 0; - - writel(0x70007, fep->membase + FEC_ESW_PER); - writel(FSL_ESW_DBCR_P0 | FSL_ESW_DBCR_P1 | FSL_ESW_DBCR_P2, - fep->membase + FEC_ESW_DBCR); - writel(FSL_ESW_DMCR_P0 | FSL_ESW_DMCR_P1 | FSL_ESW_DMCR_P2, - fep->membase + FEC_ESW_DMCR); - - writel(0,fep->membase + FEC_ESW_BKLR); - - netif_start_queue(dev); - - /* And last, enable the receive processing.*/ - writel(FSL_ESW_RDAR_R_DES_ACTIVE, fep->membase + FEC_ESW_RDAR); - - fep->opened = 1; - - return 0; -} - -static int switch_enet_close(struct net_device *dev) +/* The interrupt handler */ +static irqreturn_t switch_enet_interrupt(int irq, void *dev_id) { + struct net_device *dev = dev_id; struct switch_enet_private *fep = netdev_priv(dev); - int i; - - /* Don't know what to do yet.*/ - fep->opened = 0; - netif_stop_queue(dev); - switch_stop(dev); - - for (i = 0; i < SWITCH_EPORT_NUMBER; i++) { - phy_disconnect(fep->phydev[i]); - phy_stop(fep->phydev[i]); - phy_write(fep->phydev[i], MII_BMCR, BMCR_PDOWN); - } - - return 0; -} - -#define HASH_BITS 6 /* #bits in hash */ -#define CRC32_POLY 0xEDB88320 -#ifdef UNUSED -static void set_multicast_list(struct net_device *dev) -{ - struct switch_enet_private *fep; - unsigned int i, bit, data, crc; - struct netdev_hw_addr *ha; + uint int_events; + irqreturn_t ret = IRQ_NONE; - fep = netdev_priv(dev); + /* Get the interrupt events that caused us to be here. */ + do { + int_events = readl(fep->membase + FEC_ESW_ISR); + writel(int_events, fep->membase + FEC_ESW_ISR); - if (dev->flags & IFF_PROMISC) { - printk(KERN_INFO "%s IFF_PROMISC\n", __func__); - } else { - if (dev->flags & IFF_ALLMULTI) - /* Catch all multicast addresses, so set the - * filter to all 1's. - */ - printk(KERN_INFO "%s IFF_ALLMULTI\n", __func__); - else { - netdev_for_each_mc_addr(ha, dev) { - if (!(ha->addr[0] & 1)) - continue; - - /* calculate crc32 value of mac address - */ - crc = 0xffffffff; - - for (i = 0; i < dev->addr_len; i++) { - data = ha->addr[i]; - for (bit = 0; bit < 8; bit++, - data >>= 1) { - crc = (crc >> 1) ^ - (((crc ^ data) & 1) ? - CRC32_POLY : 0); - } - } + /* Handle receive event in its own function. */ - } + if (int_events & FSL_ESW_ISR_RXF) { + ret = IRQ_HANDLED; + switch_enet_rx(dev); } - } -} -#endif - -/* Set a MAC change in hardware.*/ -static void switch_get_mac_address(struct net_device *dev) -{ - struct switch_enet_private *fep = netdev_priv(dev); - struct switch_platform_data *pdata = fep->pdev->dev.platform_data; - unsigned char *iap, tmpaddr[ETH_ALEN]; - - iap = macaddr; - - if (!is_valid_ether_addr(iap)) - if (pdata) - memcpy(iap, pdata->mac, ETH_ALEN); - - if (!is_valid_ether_addr(iap)) { - *((unsigned long *) &tmpaddr[0]) = - be32_to_cpu(readl(fep->enetbase + FSL_FEC_PALR0)); - *((unsigned short *) &tmpaddr[4]) = - be16_to_cpu(readl(fep->enetbase + FSL_FEC_PAUR0) >> 16); - iap = &tmpaddr[0]; - } - - memcpy(dev->dev_addr, iap, ETH_ALEN); - - /* Adjust MAC if using macaddr */ - if (iap == macaddr) - dev->dev_addr[ETH_ALEN-1] = - macaddr[ETH_ALEN-1] + fep->pdev->id; -} - -static void switch_hw_init(struct net_device *dev) -{ - struct switch_enet_private *fep = netdev_priv(dev); - - /* Initialize MAC 0/1 */ - writel(FSL_FEC_RCR_MAX_FL(1522) | FSL_FEC_RCR_RMII_MODE | FSL_FEC_RCR_PROM - | FSL_FEC_RCR_MII_MODE | FSL_FEC_RCR_MII_MODE, - fep->enetbase + FSL_FEC_RCR0); - writel(FSL_FEC_RCR_MAX_FL(1522) | FSL_FEC_RCR_RMII_MODE | FSL_FEC_RCR_PROM - | FSL_FEC_RCR_MII_MODE | FSL_FEC_RCR_MII_MODE, - fep->enetbase + FSL_FEC_RCR1); - - writel(FSL_FEC_TCR_FDEN, fep->enetbase + FSL_FEC_TCR0); - writel(FSL_FEC_TCR_FDEN, fep->enetbase + FSL_FEC_TCR1); - - writel(0x1a, fep->enetbase + FSL_FEC_MSCR0); - - /* Set the station address for the ENET Adapter */ - writel(dev->dev_addr[3] | - dev->dev_addr[2] << 8 | - dev->dev_addr[1] << 16 | - dev->dev_addr[0] << 24, fep->enetbase + FSL_FEC_PALR0); - writel((dev->dev_addr[5] << 16) | - (dev->dev_addr[4] << 24), - fep->enetbase + FSL_FEC_PAUR0); - writel(dev->dev_addr[3] | - dev->dev_addr[2] << 8 | - dev->dev_addr[1] << 16 | - dev->dev_addr[0] << 24, fep->enetbase + FSL_FEC_PALR1); - writel((dev->dev_addr[5] << 16) | - (dev->dev_addr[4] << 24), - fep->enetbase + FSL_FEC_PAUR1); - - writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->enetbase + FSL_FEC_EIMR0); - writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->enetbase + FSL_FEC_EIMR1); - - writel(FSL_FEC_ECR_ETHER_EN | (0x1 << 8), fep->enetbase + FSL_FEC_ECR0); - writel(FSL_FEC_ECR_ETHER_EN | (0x1 << 8), fep->enetbase + FSL_FEC_ECR1); - udelay(20); -} - -static const struct net_device_ops switch_netdev_ops = { - .ndo_open = switch_enet_open, - .ndo_stop = switch_enet_close, - .ndo_start_xmit = switch_enet_start_xmit, - .ndo_do_ioctl = switch_enet_ioctl, - .ndo_tx_timeout = switch_timeout, -}; - -/* Initialize the FEC Ethernet. - */ - /* - * XXX: We need to clean up on failure exits here. - */ -static int switch_enet_init(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct switch_enet_private *fep = netdev_priv(dev); - cbd_t *cbd_base; - int ret = 0; - - /* Allocate memory for buffer descriptors. */ - cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, - GFP_KERNEL); - if (!cbd_base) { - printk(KERN_ERR "FEC: allocate descriptor memory failed?\n"); - return -ENOMEM; - } - - spin_lock_init(&fep->hw_lock); - spin_lock_init(&fep->mii_lock); - - writel(FSL_ESW_MODE_SW_RST, fep->membase + FEC_ESW_MODE); - udelay(10); - writel(FSL_ESW_MODE_STATRST, fep->membase + FEC_ESW_MODE); - writel(FSL_ESW_MODE_SW_EN, fep->membase + FEC_ESW_MODE); - - /* Enable transmit/receive on all ports */ - writel(0xffffffff, fep->membase + FEC_ESW_PER); - - /* Management port configuration, - * make port 0 as management port */ - writel(0, fep->membase + FEC_ESW_BMPC); - - /* Clear any outstanding interrupt.*/ - writel(0xffffffff, fep->membase + FEC_ESW_ISR); - writel(0, fep->membase + FEC_ESW_IMR); - udelay(100); - - switch_get_mac_address(dev); - - /* Set receive and transmit descriptor base. - */ - fep->rx_bd_base = cbd_base; - fep->tx_bd_base = cbd_base + RX_RING_SIZE; - - dev->base_addr = (unsigned long)fep->membase; - - /* The FEC Ethernet specific entries in the device structure. */ - dev->watchdog_timeo = TX_TIMEOUT; - dev->netdev_ops = &switch_netdev_ops; - - fep->skb_cur = fep->skb_dirty = 0; - - ret = switch_alloc_buffers(dev); - if (ret) - return ret; - - /* Set receive and transmit descriptor base.*/ - writel(fep->bd_dma, fep->membase + FEC_ESW_RDSR); - writel((unsigned long)fep->bd_dma + - sizeof(struct bufdesc) * RX_RING_SIZE, - fep->membase + FEC_ESW_TDSR); - - /*set mii*/ - switch_hw_init(dev); - /* Clear any outstanding interrupt.*/ - writel(0xffffffff, fep->membase + FEC_ESW_ISR); - writel(FSL_ESW_IMR_RXF | FSL_ESW_IMR_TXF, fep->membase + FEC_ESW_IMR); - esw_clear_atable(fep); - - /* Queue up command to detect the PHY and initialize the - * remainder of the interface. - */ -#ifndef CONFIG_FEC_SHARED_PHY - fep->phy_addr = 0; -#else - fep->phy_addr = fep->index; -#endif - - fep->sequence_done = 1; - - return ret; -} - -/* This function is called to start or restart the FEC during a link - * change. This only happens when switching between half and full - * duplex. - */ -static void switch_restart(struct net_device *dev, int duplex) -{ - struct switch_enet_private *fep; - int i; - - fep = netdev_priv(dev); - - /* Whack a reset. We should wait for this.*/ - writel(1, fep->enetbase + FSL_FEC_ECR0); - writel(1, fep->enetbase + FSL_FEC_ECR1); - udelay(10); - - writel(FSL_ESW_MODE_SW_RST, fep->membase + FEC_ESW_MODE); - udelay(10); - writel(FSL_ESW_MODE_STATRST, fep->membase + FEC_ESW_MODE); - writel(FSL_ESW_MODE_SW_EN, fep->membase + FEC_ESW_MODE); - - /* Enable transmit/receive on all ports */ - writel(0xffffffff, fep->membase + FEC_ESW_PER); - - /* Management port configuration, - * make port 0 as management port */ - writel(0, fep->membase + FEC_ESW_BMPC); - - /* Clear any outstanding interrupt.*/ - writel(0xffffffff, fep->membase + FEC_ESW_ISR); - - switch_hw_init(dev); - - /* Set station address.*/ - switch_get_mac_address(dev); - - writel(0, fep->membase + FEC_ESW_IMR); - udelay(10); - - /* Set maximum receive buffer size. - */ - writel(PKT_MAXBLR_SIZE, fep->membase + FEC_ESW_MRBR); - - /* Set receive and transmit descriptor base. - */ - writel(fep->bd_dma, fep->membase + FEC_ESW_RDSR); - writel((unsigned long)fep->bd_dma + - sizeof(struct bufdesc) * RX_RING_SIZE, - fep->membase + FEC_ESW_TDSR); - - fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; - fep->cur_rx = fep->rx_bd_base; - - /* Reset SKB transmit buffers. - */ - fep->skb_cur = fep->skb_dirty = 0; - for (i = 0; i <= TX_RING_MOD_MASK; i++) { - if (fep->tx_skbuff[i] != NULL) { - dev_kfree_skb_any(fep->tx_skbuff[i]); - fep->tx_skbuff[i] = NULL; + if (int_events & FSL_ESW_ISR_TXF) { + ret = IRQ_HANDLED; + switch_enet_tx(dev); } - } - /*hardware has set in hw_init*/ - fep->full_duplex = duplex; + } while (int_events); - /* Clear any outstanding interrupt.*/ - writel(0xffffffff, fep->membase + FEC_ESW_ISR); - writel(FSL_ESW_IMR_RXF | FSL_ESW_IMR_TXF, fep->membase + FEC_ESW_IMR); + return ret; } -static void switch_stop(struct net_device *dev) +static void switch_enet_mdio_remove(struct switch_enet_private *fep) { - struct switch_enet_private *fep = netdev_priv(dev); - - /* We cannot expect a graceful transmit - * stop without link */ - if (fep->phy1_link) - udelay(10); - if (fep->phy2_link) - udelay(10); - - /* Whack a reset. We should wait for this */ - udelay(10); + mdiobus_unregister(fep->mdio_bus); + kfree(fep->mdio_bus->irq); + mdiobus_free(fep->mdio_bus); } -static int fec_mdio_register(struct net_device *dev) +static int fec_mdio_register(struct platform_device *pdev) { - int i, err = 0; - struct switch_enet_private *fep = netdev_priv(dev); + struct net_device *ndev = platform_get_drvdata(pdev); + struct switch_enet_private *fep = netdev_priv(ndev); + int phy_addr = 0, ret = 0; fep->mdio_bus = mdiobus_alloc(); if (!fep->mdio_bus) { @@ -4035,32 +1004,61 @@ static int fec_mdio_register(struct net_device *dev) fep->mdio_bus->name = "fsl l2 switch MII Bus"; - snprintf(fep->mdio_bus->id, MII_BUS_ID_SIZE, "%x", fep->pdev->id); + snprintf(fep->mdio_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id); fep->mdio_bus->read = &fec_enet_mdio_read; fep->mdio_bus->write = &fec_enet_mdio_write; fep->mdio_bus->priv = fep; + fep->mdio_bus->parent = &pdev->dev; fep->mdio_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!fep->mdio_bus->irq) { - err = -ENOMEM; - return err; + ret = -ENOMEM; + return ret; } - for (i = 0; i < PHY_MAX_ADDR; i++) - fep->mdio_bus->irq[i] = PHY_POLL; + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) + fep->mdio_bus->irq[phy_addr] = PHY_POLL; - err = mdiobus_register(fep->mdio_bus); - if (err) { + ret = mdiobus_register(fep->mdio_bus); + if (ret) { mdiobus_free(fep->mdio_bus); - printk(KERN_ERR "%s: ethernet mdiobus_register fail\n", - dev->name); + netdev_err(ndev, "%s: ethernet mdiobus_register fail\n", + ndev->name); return -EIO; } printk(KERN_INFO "%s mdiobus(%s) register ok.\n", fep->mdio_bus->name, fep->mdio_bus->id); - return err; + return ret; +} + +static int eth_switch_remove(struct platform_device *pdev) +{ + struct net_device *dev = NULL; + struct switch_enet_private *fep; + struct switch_platform_private *chip; + int slot = 0; + + chip = platform_get_drvdata(pdev); + if (chip) { + for (slot = 0; slot < chip->num_slots; slot++) { + fep = chip->fep_host[slot]; + dev = fep->netdev; + fep->sequence_done = 1; + unregister_netdev(dev); + free_netdev(dev); + } + + platform_set_drvdata(pdev, NULL); + kfree(chip); + + } else + netdev_err(dev, "%s: Can not get the " + "switch_platform_private %x\n", __func__, + (unsigned int)chip); + + return 0; } static const struct of_device_id of_eth_switch_match[] = { @@ -4070,181 +1068,116 @@ static const struct of_device_id of_eth_switch_match[] = { MODULE_DEVICE_TABLE(of, of_eth_switch_match); +/* TODO: suspend/resume related code */ + static int eth_switch_probe(struct platform_device *pdev) { - struct net_device *ndev; - int err; - struct switch_enet_private *fep; - struct task_struct *task; - int i, irq, ret = 0; - struct resource *res=NULL; + struct net_device *ndev = NULL; + struct switch_enet_private *fep = NULL; + int irq = 0, ret = 0, err = 0; + struct resource *res = NULL; const struct of_device_id *match; + static int dev_id; - printk(KERN_INFO "Ethernet Switch Version 1.0\n"); match = of_match_device(of_eth_switch_match, &pdev->dev); - if (!match){ + if (!match) return -EINVAL; - } - else{ - pdev->id_entry = match->data; - } + pdev->id_entry = match->data; + + /* Initialize network device */ ndev = alloc_etherdev(sizeof(struct switch_enet_private)); - if (!ndev) { - printk(KERN_ERR "%s: ethernet switch alloc_etherdev fail\n", - ndev->name); + if (!ndev) return -ENOMEM; - } + SET_NETDEV_DEV(ndev, &pdev->dev); fep = netdev_priv(ndev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - printk(KERN_ERR "get platform resource error\n"); - return -ENXIO; + fep->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fep->membase)) { + ret = PTR_ERR(fep->membase); + goto failed_ioremap; } - ret = of_address_to_resource(pdev->dev.of_node, 0, res); - if (ret) { - /* Fail */ - printk(KERN_ERR "get address resource error!\n"); - return -ENXIO; - } - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (!res) - return -EBUSY; - memset(fep, 0, sizeof(*fep)); - - fep->membase = ioremap(res->start, resource_size(res)); - if (!fep->membase) - return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) - return -ENXIO; - - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (!res) - return -EBUSY; - fep->macbase = ioremap(res->start, resource_size(res)); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - if (!res) - return -ENXIO; - - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (!res) - return -EBUSY; - fep->enetbase = ioremap(res->start, resource_size(res)); - if (!fep->enetbase) - return -ENOMEM; + fep->enetbase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fep->enetbase)) { + ret = PTR_ERR(fep->enetbase); + goto failed_ioremap; + } fep->pdev = pdev; + fep->dev_id = dev_id++; + platform_set_drvdata(pdev, ndev); - printk(KERN_INFO "%s: ethernet switch init\n", __func__); + irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(&pdev->dev, irq, switch_enet_interrupt, + 0, pdev->name, ndev); + if (ret) + return ret; - /* This device has up to three irqs on some platforms */ - for (i = 0; i < 3; i++) { - irq = platform_get_irq(pdev, i); - if (i && irq < 0) - break; - ret = request_irq(irq, switch_enet_interrupt, IRQF_DISABLED, - pdev->name, ndev); - if (ret) { - while (--i >= 0) { - irq = platform_get_irq(pdev, i); - free_irq(irq, ndev); - } - return -ENOMEM; - } + fep->clk_esw = devm_clk_get(&pdev->dev, "esw"); + if (IS_ERR(fep->clk_esw)) { + ret = PTR_ERR(fep->clk_esw); + goto failed_clk; + } + + fep->clk_enet = devm_clk_get(&pdev->dev, "enet"); + if (IS_ERR(fep->clk_enet)) { + ret = PTR_ERR(fep->clk_enet); + goto failed_clk; } - fep->clk = clk_get(&pdev->dev, "switch_clk"); + fep->clk_enet0 = devm_clk_get(&pdev->dev, "enet0"); + if (IS_ERR(fep->clk_enet0)) { + ret = PTR_ERR(fep->clk_enet0); + goto failed_clk; + } - if (IS_ERR(fep->clk)) { - ret = PTR_ERR(fep->clk); + fep->clk_enet1 = devm_clk_get(&pdev->dev, "enet1"); + if (IS_ERR(fep->clk_enet1)) { + ret = PTR_ERR(fep->clk_enet1); goto failed_clk; } - clk_enable(fep->clk); - err = switch_enet_init(pdev); + switch_enet_clk_enable(ndev, true); + + err = switch_enet_init(ndev); if (err) { free_netdev(ndev); platform_set_drvdata(pdev, NULL); return -EIO; } - err = fec_mdio_register(ndev); + err = fec_mdio_register(pdev); if (err) { - printk(KERN_ERR "%s: L2 switch fec_mdio_register error!\n", + netdev_err(ndev, "%s: L2 switch fec_mdio_register error!\n", ndev->name); free_netdev(ndev); platform_set_drvdata(pdev, NULL); return -ENOMEM; } - /* setup timer for Learning Aging function */ - init_timer(&fep->timer_aging); - fep->timer_aging.function = l2switch_aging_timer; - fep->timer_aging.data = (unsigned long) fep; - fep->timer_aging.expires = jiffies + LEARNING_AGING_TIMER; - add_timer(&fep->timer_aging); - - /* register network device*/ - if (register_netdev(ndev) != 0) { - /* XXX: missing cleanup here */ - free_netdev(ndev); - platform_set_drvdata(pdev, NULL); - printk(KERN_ERR "%s: L2 switch register_netdev fail\n", - ndev->name); - return -EIO; - } - - task = kthread_run(switch_enet_learning, fep, - "fsl_l2switch_learning"); - if (IS_ERR(task)) { - err = PTR_ERR(task); - return err; - } + /* register network device */ + ret = register_netdev(ndev); + if (ret) + goto failed_register; - printk(KERN_INFO "%s: ethernet switch %pM\n", + netdev_info(ndev, "%s: Ethernet switch %pM\n", ndev->name, ndev->dev_addr); - return 0; -failed_clk: - iounmap(fep->membase); - return ret; -} - -static int eth_switch_remove(struct platform_device *pdev) -{ - int i; - struct net_device *dev; - struct switch_enet_private *fep; - struct switch_platform_private *chip; - chip = platform_get_drvdata(pdev); - if (chip) { - for (i = 0; i < chip->num_slots; i++) { - fep = chip->fep_host[i]; - dev = fep->netdev; - fep->sequence_done = 1; - unregister_netdev(dev); - free_netdev(dev); - - del_timer_sync(&fep->timer_aging); - } - - platform_set_drvdata(pdev, NULL); - kfree(chip); + return 0; - } else - printk(KERN_ERR "%s: can not get the " - "switch_platform_private %x\n", __func__, - (unsigned int)chip); +failed_register: + switch_enet_mdio_remove(fep); +failed_clk: +failed_ioremap: + free_netdev(ndev); - return 0; + return ret; } static struct platform_driver eth_switch_driver = { @@ -4257,31 +1190,6 @@ static struct platform_driver eth_switch_driver = { }, }; -static int fec_mac_addr_setup(char *mac_addr) -{ - char *ptr, *p = mac_addr; - unsigned long tmp; - int i = 0, ret = 0; - - while (p && (*p) && i < 6) { - ptr = strchr(p, ':'); - if (ptr) - *ptr++ = '\0'; - - if (strlen(p)) { - ret = strict_strtoul(p, 16, &tmp); - if (ret < 0 || tmp > 0xff) - break; - macaddr[i++] = tmp; - } - p = ptr; - } - - return 0; -} - -__setup("fec_mac=", fec_mac_addr_setup); - static int __init fsl_l2_switch_init(void) { return platform_driver_register(ð_switch_driver); @@ -4292,7 +1200,6 @@ static void __exit fsl_l2_switch_exit(void) platform_driver_unregister(ð_switch_driver); } - module_init(fsl_l2_switch_init); module_exit(fsl_l2_switch_exit); MODULE_LICENSE("GPL"); diff --git a/include/linux/fsl_l2_switch.h b/drivers/net/ethernet/freescale/fsl_l2_switch.h index 8ded0d659023..b85345db1b27 100644 --- a/include/linux/fsl_l2_switch.h +++ b/drivers/net/ethernet/freescale/fsl_l2_switch.h @@ -11,25 +11,52 @@ #ifndef FSL_L2_SWITCH_H #define FSL_L2_SWITCH_H -/* The Switch stores dest/src/type, data, and checksum for receive packets. */ +/* Interrupt events/masks */ +#define FEC_ENET_HBERR BIT(31) /* Heartbeat error */ +#define FEC_ENET_BABR BIT(30) /* Babbling receiver */ +#define FEC_ENET_BABT BIT(29) /* Babbling transmitter */ +#define FEC_ENET_GRA BIT(28) /* Graceful stop complete */ +#define FEC_ENET_TXF BIT(27) /* Full frame transmitted */ +#define FEC_ENET_TXB BIT(26) /* A buffer was transmitted */ +#define FEC_ENET_RXF BIT(25) /* Full frame received */ +#define FEC_ENET_RXB BIT(24) /* A buffer was received */ +#define FEC_ENET_MII BIT(23) /* MII interrupt */ +#define FEC_ENET_EBERR BIT(22) /* SDMA bus error */ + +#define NMII 20 + +/* Make MII read/write commands for the FEC */ +#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ + (VAL & 0xffff)) +/* MII MMFR bits definition */ +#define ESW_MMFR_ST BIT(30) +#define ESW_MMFR_OP_READ (2 << 28) +#define ESW_MMFR_OP_WRITE BIT(28) +#define ESW_MMFR_PA(v) ((v & 0x1f) << 23) +#define ESW_MMFR_RA(v) ((v & 0x1f) << 18) +#define ESW_MMFR_TA (2 << 16) +#define ESW_MMFR_DATA(v) (v & 0xffff) + +#define ESW_MII_TIMEOUT 30 /* ms */ + +/* Transmitter timeout.*/ +#define TX_TIMEOUT (2 * HZ) + +/* The Switch stores dest/src/type, data, + * and checksum for receive packets. + */ #define PKT_MAXBUF_SIZE 1518 #define PKT_MINBUF_SIZE 64 #define PKT_MAXBLR_SIZE 1520 -/* - * The 5441x RX control register also contains maximum frame +/* The 5441x RX control register also contains maximum frame * size bits. */ #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) -/* - * Some hardware gets it MAC address out of local flash memory. - * if this is non-zero then assume it is the address to get MAC from. - */ -#define FEC_FLASHMAC 0 - -/* The number of Tx and Rx buffers. These are allocated from the page - * pool. The code may assume these are power of two, so it it best +/* The number of Tx and Rx buffers. These are allocated from the page + * pool. The code may assume these are power of two, so it it best * to keep them that size. * We don't need to allocate pages for the transmitter. We just use * the skbuffer directly. @@ -40,18 +67,18 @@ #define SWITCH_ENET_RX_PAGES 8 #endif -#define SWITCH_ENET_RX_FRSIZE 2048 -#define SWITCH_ENET_RX_FRPPG (PAGE_SIZE / SWITCH_ENET_RX_FRSIZE) -#define RX_RING_SIZE (SWITCH_ENET_RX_FRPPG * SWITCH_ENET_RX_PAGES) -#define SWITCH_ENET_TX_FRSIZE 2048 -#define SWITCH_ENET_TX_FRPPG (PAGE_SIZE / SWITCH_ENET_TX_FRSIZE) +#define SWITCH_ENET_RX_FRSIZE 2048 +#define SWITCH_ENET_RX_FRPPG (PAGE_SIZE / SWITCH_ENET_RX_FRSIZE) +#define RX_RING_SIZE (SWITCH_ENET_RX_FRPPG * SWITCH_ENET_RX_PAGES) +#define SWITCH_ENET_TX_FRSIZE 2048 +#define SWITCH_ENET_TX_FRPPG (PAGE_SIZE / SWITCH_ENET_TX_FRSIZE) #ifdef CONFIG_SWITCH_DMA_USE_SRAM -#define TX_RING_SIZE 8 /* Must be power of two */ -#define TX_RING_MOD_MASK 7 /* for this to work */ +#define TX_RING_SIZE 8 /* Must be power of two */ +#define TX_RING_MOD_MASK 7 /* for this to work */ #else -#define TX_RING_SIZE 16 /* Must be power of two */ -#define TX_RING_MOD_MASK 15 /* for this to work */ +#define TX_RING_SIZE 16 /* Must be power of two */ +#define TX_RING_MOD_MASK 15 /* for this to work */ #endif #define SWITCH_EPORT_NUMBER 2 @@ -105,20 +132,20 @@ #define FEC_ESW_IPRES 0x140 -/*port0-port2 Priority Configuration 0xFC0D_C180-C188*/ +/* port0-port2 Priority Configuration 0xFC0D_C180-C188 */ #define FEC_ESW_PRES(n) (0x180 + n * 4) -/*port0-port2 VLAN ID 0xFC0D_C200-C208*/ +/* port0-port2 VLAN ID 0xFC0D_C200-C208 */ #define FEC_ESW_PID(n) (0x200 + 4 * n) -/*port0-port2 VLAN domain resolution entry 0xFC0D_C280-C2FC*/ +/* port0-port2 VLAN domain resolution entry 0xFC0D_C280-C2FC */ #define FEC_ESW_VRES(n) (0x280 + n * 4) #define FEC_ESW_DISCN 0x300 #define FEC_ESW_DISCB 0x304 #define FEC_ESW_NDISCN 0x308 #define FEC_ESW_NDISCB 0x30C -/*per port statistics 0xFC0DC310_C33C*/ +/* per port statistics 0xFC0DC310_C33C */ #define FEC_ESW_POQC(n) (0x310 + n * 16) #define FEC_ESW_PMVID(n) (0x310 + n * 16 + 0x04) @@ -130,8 +157,8 @@ #define FEC_ESW_RDSR 0x408 /* Receive descriptor ring */ #define FEC_ESW_TDSR 0x40C /* Transmit descriptor ring */ #define FEC_ESW_MRBR 0x410 /* Maximum receive buff size */ -#define FEC_ESW_RDAR 0x414 /* Receive descriptor active*/ -#define FEC_ESW_TDAR 0x418 /* Transmit descriptor active*/ +#define FEC_ESW_RDAR 0x414 /* Receive descriptor active */ +#define FEC_ESW_TDAR 0x418 /* Transmit descriptor active */ #define FEC_ESW_LREC0 0x500 #define FEC_ESW_LREC1 0x504 @@ -143,55 +170,6 @@ struct switch_platform_data { unsigned char mac[ETH_ALEN]; }; -typedef struct l2switch_output_queue_status { - unsigned long ESW_MMSR; - unsigned long ESW_LMT; - unsigned long ESW_LFC; - unsigned long ESW_PCSR; - unsigned long ESW_IOSR; - unsigned long ESW_QWT; - unsigned long esw_reserved; - unsigned long ESW_P0BCT; -} esw_output_queue_status; - -typedef struct l2switch_statistics_status { - /* - * Total number of incoming frames processed - * but discarded in switch - */ - unsigned long ESW_DISCN; - /*Sum of bytes of frames counted in ESW_DISCN*/ - unsigned long ESW_DISCB; - /* - * Total number of incoming frames processed - * but not discarded in switch - */ - unsigned long ESW_NDISCN; - /*Sum of bytes of frames counted in ESW_NDISCN*/ - unsigned long ESW_NDISCB; -} esw_statistics_status; - -typedef struct l2switch_port_statistics_status { - /*outgoing frames discarded due to transmit queue congestion*/ - unsigned long FSL_ESW_POQC; - /*incoming frames discarded due to VLAN domain mismatch*/ - unsigned long FSL_ESW_PMVID; - /*incoming frames discarded due to untagged discard*/ - unsigned long FSL_ESW_PMVTAG; - /*incoming frames discarded due port is in blocking state*/ - unsigned long FSL_ESW_PBL; -} esw_port_statistics_status; - -typedef struct _64bTableEntry { - unsigned int lo; /* lower 32 bits */ - unsigned int hi; /* upper 32 bits */ -} AddrTable64bEntry; - -typedef struct l2switchaddrtable { - AddrTable64bEntry eswTable64bEntry[2048]; -} eswAddrTable_t; - -/*unsigned long FSL_ESW_LOOKUP_MEM;*/ #define FSL_FEC_MMFR0 (0x40) #define FSL_FEC_MSCR0 (0x44) #define FSL_FEC_MSCR1 (0x1044) @@ -223,271 +201,28 @@ typedef struct l2switchaddrtable { #define FSL_FEC_ECR_ETHER_EN (0x00000002) #define FSL_FEC_ECR_ENA_1588 (0x00000010) -/*ioctl commands*/ -#define ESW_SET_LEARNING_CONF 0x9101 -#define ESW_GET_LEARNING_CONF 0x9201 -#define ESW_SET_BLOCKING_CONF 0x9102 -#define ESW_GET_BLOCKING_CONF 0x9202 -#define ESW_SET_MULTICAST_CONF 0x9103 -#define ESW_GET_MULTICAST_CONF 0x9203 -#define ESW_SET_BROADCAST_CONF 0x9104 -#define ESW_GET_BROADCAST_CONF 0x9204 -#define ESW_SET_PORTENABLE_CONF 0x9105 -#define ESW_GET_PORTENABLE_CONF 0x9205 -#define ESW_SET_IP_SNOOP_CONF 0x9106 -#define ESW_GET_IP_SNOOP_CONF 0x9206 -#define ESW_SET_PORT_SNOOP_CONF 0x9107 -#define ESW_GET_PORT_SNOOP_CONF 0x9207 -#define ESW_SET_PORT_MIRROR_CONF 0x9108 -#define ESW_GET_PORT_MIRROR_CONF 0x9208 -#define ESW_SET_PIRORITY_VLAN 0x9109 -#define ESW_GET_PIRORITY_VLAN 0x9209 -#define ESW_SET_PIRORITY_IP 0x910A -#define ESW_GET_PIRORITY_IP 0x920A -#define ESW_SET_PIRORITY_MAC 0x910B -#define ESW_GET_PIRORITY_MAC 0x920B -#define ESW_SET_PIRORITY_DEFAULT 0x910C -#define ESW_GET_PIRORITY_DEFAULT 0x920C -#define ESW_SET_P0_FORCED_FORWARD 0x910D -#define ESW_GET_P0_FORCED_FORWARD 0x920D -#define ESW_SET_SWITCH_MODE 0x910E -#define ESW_GET_SWITCH_MODE 0x920E -#define ESW_SET_BRIDGE_CONFIG 0x910F -#define ESW_GET_BRIDGE_CONFIG 0x920F -#define ESW_SET_VLAN_OUTPUT_PROCESS 0x9110 -#define ESW_GET_VLAN_OUTPUT_PROCESS 0x9210 -#define ESW_SET_VLAN_INPUT_PROCESS 0x9111 -#define ESW_GET_VLAN_INPUT_PROCESS 0x9211 -#define ESW_SET_VLAN_DOMAIN_VERIFICATION 0x9112 -#define ESW_GET_VLAN_DOMAIN_VERIFICATION 0x9212 -#define ESW_SET_VLAN_RESOLUTION_TABLE 0x9113 -#define ESW_GET_VLAN_RESOLUTION_TABLE 0x9213 -#define ESW_GET_ENTRY_PORT_NUMBER 0x9214 -#define ESW_GET_LOOKUP_TABLE 0x9215 -#define ESW_GET_PORT_STATUS 0x9216 -#define ESW_SET_VLAN_ID 0x9114 -#define ESW_SET_VLAN_ID_CLEARED 0x9115 -#define ESW_SET_PORT_IN_VLAN_ID 0x9116 -#define ESW_SET_PORT_ENTRY_EMPTY 0x9117 -#define ESW_SET_OTHER_PORT_ENTRY_EMPTY 0x9118 -#define ESW_GET_PORT_ALL_STATUS 0x9217 -#define ESW_SET_PORT_MIRROR_CONF_PORT_MATCH 0x9119 -#define ESW_SET_PORT_MIRROR_CONF_ADDR_MATCH 0x911A - -#define ESW_GET_STATISTICS_STATUS 0x9221 -#define ESW_SET_OUTPUT_QUEUE_MEMORY 0x9125 -#define ESW_GET_OUTPUT_QUEUE_STATUS 0x9225 -#define ESW_UPDATE_STATIC_MACTABLE 0x9226 -#define ESW_CLEAR_ALL_MACTABLE 0x9227 -#define ESW_GET_USER_PID 0x9228 - -typedef struct _eswIOCTL_PORT_CONF { - int port; - int enable; -} eswIoctlPortConfig; - -typedef struct _eswIOCTL_PORT_EN_CONF { - int port; - int tx_enable; - int rx_enable; -} eswIoctlPortEnableConfig; - -typedef struct _eswIOCTL_IP_SNOOP_CONF { - int mode; - unsigned long ip_header_protocol; -} eswIoctlIpsnoopConfig; - -typedef struct _eswIOCTL_P0_FORCED_FORWARD_CONF { - int port1; - int port2; - int enable; -} eswIoctlP0ForcedForwardConfig; - -typedef struct _eswIOCTL_PORT_SNOOP_CONF { - int mode; - unsigned short compare_port; - int compare_num; -} eswIoctlPortsnoopConfig; - -typedef struct _eswIOCTL_PORT_Mirror_CONF { - int mirror_port; - int port; - int egress_en; - int ingress_en; - int egress_mac_src_en; - int egress_mac_des_en; - int ingress_mac_src_en; - int ingress_mac_des_en; - unsigned char *src_mac; - unsigned char *des_mac; - int mirror_enable; -} eswIoctlPortMirrorConfig; - -struct eswIoctlMirrorCfgPortMatch { - int mirror_port; - int port_match_en; - int port; -}; - -struct eswIoctlMirrorCfgAddrMatch { - int mirror_port; - int addr_match_en; - unsigned char *mac_addr; -}; - -typedef struct _eswIOCTL_PRIORITY_VLAN_CONF { - int port; - int func_enable; - int vlan_pri_table_num; - int vlan_pri_table_value; -} eswIoctlPriorityVlanConfig; - -typedef struct _eswIOCTL_PRIORITY_IP_CONF { - int port; - int func_enable; - int ipv4_en; - int ip_priority_num; - int ip_priority_value; -} eswIoctlPriorityIPConfig; - -typedef struct _eswIOCTL_PRIORITY_MAC_CONF { - int port; -} eswIoctlPriorityMacConfig; - -typedef struct _eswIOCTL_PRIORITY_DEFAULT_CONF { - int port; - unsigned char priority_value; -} eswIoctlPriorityDefaultConfig; - -typedef struct _eswIOCTL_IRQ_STATUS { - unsigned long isr; - unsigned long imr; - unsigned long rx_buf_pointer; - unsigned long tx_buf_pointer; - unsigned long rx_max_size; - unsigned long rx_buf_active; - unsigned long tx_buf_active; -} eswIoctlIrqStatus; - -typedef struct _eswIOCTL_PORT_Mirror_STATUS { - unsigned long ESW_MCR; - unsigned long ESW_EGMAP; - unsigned long ESW_INGMAP; - unsigned long ESW_INGSAL; - unsigned long ESW_INGSAH; - unsigned long ESW_INGDAL; - unsigned long ESW_INGDAH; - unsigned long ESW_ENGSAL; - unsigned long ESW_ENGSAH; - unsigned long ESW_ENGDAL; - unsigned long ESW_ENGDAH; - unsigned long ESW_MCVAL; -} eswIoctlPortMirrorStatus; - -typedef struct _eswIOCTL_VLAN_OUTPUT_CONF { - int port; - int mode; -} eswIoctlVlanOutputConfig; - -typedef struct _eswIOCTL_VLAN_INPUT_CONF { - int port; - int mode; - unsigned short port_vlanid; -} eswIoctlVlanInputConfig; - -typedef struct _eswIOCTL_VLAN_DOMAIN_VERIFY_CONF { - int port; - int vlan_domain_verify_en; - int vlan_discard_unknown_en; -} eswIoctlVlanVerificationConfig; - -typedef struct _eswIOCTL_VLAN_RESOULATION_TABLE { - unsigned short port_vlanid; - unsigned char vlan_domain_port; - unsigned char vlan_domain_num; -} eswIoctlVlanResoultionTable; - -struct eswVlanTableItem { - eswIoctlVlanResoultionTable table[32]; - unsigned char valid_num; -}; - -typedef struct _eswIOCTL_VLAN_INPUT_STATUS { - unsigned long ESW_VLANV; - unsigned long ESW_PID[3]; - unsigned long ESW_VIMSEL; - unsigned long ESW_VIMEN; - unsigned long ESW_VRES[32]; -} eswIoctlVlanInputStatus; - -typedef struct _eswIOCTL_Static_MACTable { - unsigned char *mac_addr; - int port; - int priority; -} eswIoctlUpdateStaticMACtable; - -typedef struct _eswIOCTL_OUTPUT_QUEUE { - int fun_num; - esw_output_queue_status sOutputQueue; -} eswIoctlOutputQueue; - #define LEARNING_AGING_TIMER (10 * HZ) -/* - * Info received from Hardware Learning FIFO, - * holding MAC address and corresponding Hash Value and - * port number where the frame was received (disassembled). - */ -typedef struct _eswPortInfo { - /* MAC lower 32 bits (first byte is 7:0). */ - unsigned int maclo; - /* MAC upper 16 bits (47:32). */ - unsigned int machi; - /* the hash value for this MAC address. */ - unsigned int hash; - /* the port number this MAC address is associated with. */ - unsigned int port; -} eswPortInfo; -/* - * Hardware Look up Address Table 64-bit element. - */ -typedef struct _64bitTableEntry { - unsigned int lo; /* lower 32 bits */ - unsigned int hi; /* upper 32 bits */ -} eswTable64bitEntry; - -struct eswAddrTableEntryExample { - /* the entry number */ - unsigned short entrynum; - /* mac address array */ - unsigned char mac_addr[6]; - unsigned char item1; - unsigned short item2; -}; -/* - * Define the buffer descriptor structure. - */ +/* Define the buffer descriptor structure. */ typedef struct bufdesc { unsigned short cbd_datlen; /* Data length */ unsigned short cbd_sc; /* Control and status info */ unsigned long cbd_bufaddr; /* Buffer address */ } cbd_t; - typedef struct bufdesc_rx { unsigned short cbd_datlen; /* Data length */ unsigned short cbd_sc; /* Control and status info */ unsigned long cbd_bufaddr; /* Buffer address */ } cbd_t_r; -/* Forward declarations of some structures to support different PHYs - */ -typedef struct { +/* Forward declarations of some structures to support different PHYs */ +typedef struct _phy_cmd_t { uint mii_data; void (*funct)(uint mii_reg, struct net_device *dev); } phy_cmd_t; -typedef struct { +typedef struct _phy_info_t { uint id; char *name; @@ -507,27 +242,6 @@ struct port_status { int port2_block_status; }; -struct port_all_status { - /* 1: link is up, 0: link is down */ - int link_status; - /* 1: blocking, 0: unblocking */ - int block_status; - /* 1: unlearning, 0: learning */ - int learn_status; - /* vlan domain verify 1: enable 0: disable */ - int vlan_verify; - /* discard unknow 1: enable 0: disable */ - int discard_unknown; - /* multicast resolution 1: enable 0: disable */ - int multi_reso; - /* broadcast resolution 1: enable 0: disalbe */ - int broad_reso; - /* transmit 1: enable 0: disable */ - int ftransmit; - /* receive 1: enable 0: disable */ - int freceive; -}; - /* The switch buffer descriptors track the ring buffers. The rx_bd_base and * tx_bd_base always point to the base of the buffer descriptors. The * cur_rx and cur_tx point to the currently available buffer. @@ -541,11 +255,17 @@ struct switch_enet_private { void __iomem *membase; void __iomem *macbase; /* MAC address lookup table */ void __iomem *enetbase; - struct clk *clk; - eswAddrTable_t *hwentry; + + struct clk *clk_esw; + struct clk *clk_enet; + struct clk *clk_enet0; + struct clk *clk_enet1; struct net_device *netdev; struct platform_device *pdev; + + int dev_id; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff *tx_skbuff[TX_RING_SIZE]; @@ -556,10 +276,10 @@ struct switch_enet_private { /* CPM dual port RAM relative addresses */ dma_addr_t bd_dma; - cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ + cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ cbd_t *tx_bd_base; - cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ - cbd_t *dirty_tx; /* The ring entries to be free()ed. */ + cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ + cbd_t *dirty_tx; /* The ring entries to be free()ed. */ uint tx_full; /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ spinlock_t hw_lock; @@ -597,39 +317,14 @@ struct switch_enet_private { int phy2_old_link; int phy2_duplex; int phy2_speed; - /* Statistics */ - /* when a new element deleted a element with in - * a block due to lack of space */ - int atBlockOverflows; - /* Peak number of valid entries in the address table */ - int atMaxEntries; - /* current number of valid entries in the address table */ - int atCurrEntries; - /* maximum entries within a block found - * (updated within ageing)*/ - int atMaxEntriesPerBlock; - - /* ageing function */ - /* maximum age allowed for an entry */ - int ageMax; - /* last LUT entry to block that was - * inspected by the Ageing task*/ - int ageLutIdx; - /* last element within block inspected by the Ageing task */ - int ageBlockElemIdx; - /* complete table has been processed by ageing process */ - int ageCompleted; - /* delay setting */ - int ageDelay; - /* current delay Counter */ - int ageDelayCnt; /* timer related */ /* current time (for timestamping) */ - int currTime; - /* flag set by timer when currTime changed - * and cleared by serving function*/ - int timeChanged; + int curr_time; + /* flag set by timer when curr_time changed + * and cleared by serving function + */ + int time_changed; /* Timer for Aging */ struct timer_list timer_aging; @@ -642,7 +337,7 @@ struct switch_platform_private { struct switch_enet_private *fep_host[0]; /* Pointers to hosts */ }; -/* Recieve is empty */ +/* Receive is empty */ #define BD_SC_EMPTY ((unsigned short)0x8000) /* Transmit is ready */ #define BD_SC_READY ((unsigned short)0x8000) @@ -650,7 +345,7 @@ struct switch_platform_private { #define BD_SC_WRAP ((unsigned short)0x2000) /* Interrupt on change */ #define BD_SC_INTRPT ((unsigned short)0x1000) -/* Continous mode */ +/* Continuous mode */ #define BD_SC_CM ((unsigned short)0x0200) /* Rec'd too many idles */ #define BD_SC_ID ((unsigned short)0x0100) @@ -679,10 +374,11 @@ struct switch_platform_private { #define BD_ENET_RX_CR ((unsigned short)0x0004) #define BD_ENET_RX_OV ((unsigned short)0x0002) #define BD_ENET_RX_CL ((unsigned short)0x0001) + /* All status bits */ #define BD_ENET_RX_STATS ((unsigned short)0x013f) -/* Buffer descriptor control/status used by Ethernet transmit.*/ +/* Buffer descriptor control/status used by Ethernet transmit. */ #define BD_ENET_TX_READY ((unsigned short)0x8000) #define BD_ENET_TX_PAD ((unsigned short)0x4000) #define BD_ENET_TX_WRAP ((unsigned short)0x2000) @@ -696,10 +392,11 @@ struct switch_platform_private { #define BD_ENET_TX_RCMASK ((unsigned short)0x003c) #define BD_ENET_TX_UN ((unsigned short)0x0002) #define BD_ENET_TX_CSL ((unsigned short)0x0001) + /* All status bits */ #define BD_ENET_TX_STATS ((unsigned short)0x03ff) -/*Copy from validation code */ +/* Copy from validation code */ #define RX_BUFFER_SIZE 1520 #define TX_BUFFER_SIZE 1520 #define NUM_RXBDS 20 @@ -752,12 +449,12 @@ struct switch_platform_private { #define RX_BD_BDU 0x80000000 /* Address Table size in bytes(2048 64bit entry ) */ -#define ESW_ATABLE_MEM_SIZE (2048*8) +#define ESW_ATABLE_MEM_SIZE (2048 * 8) /* How many 64-bit elements fit in the address table */ #define ESW_ATABLE_MEM_NUM_ENTRIES (2048) /* Address Table Maximum number of entries in each Slot */ #define ATABLE_ENTRY_PER_SLOT 8 -/* log2(ATABLE_ENTRY_PER_SLOT)*/ +/* log2(ATABLE_ENTRY_PER_SLOT) */ #define ATABLE_ENTRY_PER_SLOT_bits 3 /* entry size in byte */ #define ATABLE_ENTRY_SIZE 8 @@ -800,15 +497,15 @@ struct switch_platform_private { /* return block corresponding to the 8 bit hash value calculated */ #define GET_BLOCK_PTR(hash) (hash << 3) #define AT_EXTRACT_TIMESTAMP(x) \ - ((x >> AT_DENTRY_TIME_shift) & ((1 << AT_DENTRY_TIMESTAMP_WIDTH)-1)) + ((x >> AT_DENTRY_TIME_shift) & ((1 << AT_DENTRY_TIMESTAMP_WIDTH) - 1)) #define AT_EXTRACT_PORT(x) \ - ((x >> AT_DENTRY_PORT_shift) & ((1 << AT_DENTRY_PORT_WIDTH)-1)) + ((x >> AT_DENTRY_PORT_shift) & ((1 << AT_DENTRY_PORT_WIDTH) - 1)) #define AT_SEXTRACT_PORT(x) \ ((~((x >> AT_SENTRY_PORTMASK_shift) & \ - ((1 << AT_DENTRY_PORT_WIDTH)-1))) >> 1) + ((1 << AT_DENTRY_PORT_WIDTH) - 1))) >> 1) #define TIMEDELTA(newtime, oldtime) \ ((newtime - oldtime) & \ - ((1 << AT_DENTRY_TIMESTAMP_WIDTH)-1)) + ((1 << AT_DENTRY_TIMESTAMP_WIDTH) - 1)) #define AT_EXTRACT_IP_PROTOCOL(x) ((x >> 8) & 0xff) #define AT_EXTRACT_TCP_UDP_PORT(x) ((x >> 16) & 0xffff) @@ -818,8 +515,8 @@ struct switch_platform_private { ((time) = ((time)+1) & ((1 << AT_DENTRY_TIMESTAMP_WIDTH)-1)) /* Bit definitions and macros for FSL_ESW_REVISION */ -#define FSL_ESW_REVISION_CORE_REVISION(x) (((x)&0x0000FFFF)<<0) -#define FSL_ESW_REVISION_CUSTOMER_REVISION(x) (((x)&0x0000FFFF)<<16) +#define FSL_ESW_REVISION_CORE_REVISION(x) (((x)&0x0000FFFF) << 0) +#define FSL_ESW_REVISION_CUSTOMER_REVISION(x) (((x)&0x0000FFFF) << 16) /* Bit definitions and macros for FSL_ESW_PER */ #define FSL_ESW_PER_TE0 (0x00000001) @@ -848,20 +545,21 @@ struct switch_platform_private { #define FSL_ESW_DMCR_P2 (0x00000004) /* Bit definitions and macros for FSL_ESW_BKLR */ -#define FSL_ESW_BKLR_BE0 (0x00000001) -#define FSL_ESW_BKLR_BE1 (0x00000002) -#define FSL_ESW_BKLR_BE2 (0x00000004) -#define FSL_ESW_BKLR_LD0 (0x00010000) -#define FSL_ESW_BKLR_LD1 (0x00020000) -#define FSL_ESW_BKLR_LD2 (0x00040000) +#define FSL_ESW_BKLR_BE0 (0x00000001) +#define FSL_ESW_BKLR_BE1 (0x00000002) +#define FSL_ESW_BKLR_BE2 (0x00000004) +#define FSL_ESW_BKLR_LD0 (0x00010000) +#define FSL_ESW_BKLR_LD1 (0x00020000) +#define FSL_ESW_BKLR_LD2 (0x00040000) +#define FSL_ESW_BKLR_LDX (0x00070007) /* Bit definitions and macros for FSL_ESW_BMPC */ -#define FSL_ESW_BMPC_PORT(x) (((x)&0x0000000F)<<0) +#define FSL_ESW_BMPC_PORT(x) (((x) & 0x0000000F) << 0) #define FSL_ESW_BMPC_MSG_TX (0x00000020) #define FSL_ESW_BMPC_EN (0x00000040) #define FSL_ESW_BMPC_DIS (0x00000080) -#define FSL_ESW_BMPC_PRIORITY(x) (((x)&0x00000007)<<13) -#define FSL_ESW_BMPC_PORTMASK(x) (((x)&0x00000007)<<16) +#define FSL_ESW_BMPC_PRIORITY(x) (((x) & 0x00000007) << 13) +#define FSL_ESW_BMPC_PORTMASK(x) (((x) & 0x00000007) << 16) /* Bit definitions and macros for FSL_ESW_MODE */ #define FSL_ESW_MODE_SW_RST (0x00000001) @@ -872,14 +570,14 @@ struct switch_platform_private { #define FSL_ESW_MODE_STATRST (0x80000000) /* Bit definitions and macros for FSL_ESW_VIMSEL */ -#define FSL_ESW_VIMSEL_IM0(x) (((x)&0x00000003)<<0) -#define FSL_ESW_VIMSEL_IM1(x) (((x)&0x00000003)<<2) -#define FSL_ESW_VIMSEL_IM2(x) (((x)&0x00000003)<<4) +#define FSL_ESW_VIMSEL_IM0(x) (((x) & 0x00000003) << 0) +#define FSL_ESW_VIMSEL_IM1(x) (((x) & 0x00000003) << 2) +#define FSL_ESW_VIMSEL_IM2(x) (((x) & 0x00000003) << 4) /* Bit definitions and macros for FSL_ESW_VOMSEL */ -#define FSL_ESW_VOMSEL_OM0(x) (((x)&0x00000003)<<0) -#define FSL_ESW_VOMSEL_OM1(x) (((x)&0x00000003)<<2) -#define FSL_ESW_VOMSEL_OM2(x) (((x)&0x00000003)<<4) +#define FSL_ESW_VOMSEL_OM0(x) (((x) & 0x00000003) << 0) +#define FSL_ESW_VOMSEL_OM1(x) (((x) & 0x00000003) << 2) +#define FSL_ESW_VOMSEL_OM2(x) (((x) & 0x00000003) << 4) /* Bit definitions and macros for FSL_ESW_VIMEN */ #define FSL_ESW_VIMEN_EN0 (0x00000001) @@ -887,10 +585,10 @@ struct switch_platform_private { #define FSL_ESW_VIMEN_EN2 (0x00000004) /* Bit definitions and macros for FSL_ESW_VID */ -#define FSL_ESW_VID_TAG(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_VID_TAG(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_MCR */ -#define FSL_ESW_MCR_PORT(x) (((x)&0x0000000F)<<0) +#define FSL_ESW_MCR_PORT(x) (((x) & 0x0000000F) << 0) #define FSL_ESW_MCR_MEN (0x00000010) #define FSL_ESW_MCR_INGMAP (0x00000020) #define FSL_ESW_MCR_EGMAP (0x00000040) @@ -910,31 +608,31 @@ struct switch_platform_private { #define FSL_ESW_INGMAP_ING2 (0x00000004) /* Bit definitions and macros for FSL_ESW_INGSAL */ -#define FSL_ESW_INGSAL_ADDLOW(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_INGSAL_ADDLOW(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_INGSAH */ -#define FSL_ESW_INGSAH_ADDHIGH(x) (((x)&0x0000FFFF)<<0) +#define FSL_ESW_INGSAH_ADDHIGH(x) (((x) & 0x0000FFFF) << 0) /* Bit definitions and macros for FSL_ESW_INGDAL */ -#define FSL_ESW_INGDAL_ADDLOW(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_INGDAL_ADDLOW(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_INGDAH */ -#define FSL_ESW_INGDAH_ADDHIGH(x) (((x)&0x0000FFFF)<<0) +#define FSL_ESW_INGDAH_ADDHIGH(x) (((x) & 0x0000FFFF) << 0) /* Bit definitions and macros for FSL_ESW_ENGSAL */ -#define FSL_ESW_ENGSAL_ADDLOW(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_ENGSAL_ADDLOW(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_ENGSAH */ -#define FSL_ESW_ENGSAH_ADDHIGH(x) (((x)&0x0000FFFF)<<0) +#define FSL_ESW_ENGSAH_ADDHIGH(x) (((x) & 0x0000FFFF) << 0) /* Bit definitions and macros for FSL_ESW_ENGDAL */ -#define FSL_ESW_ENGDAL_ADDLOW(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_ENGDAL_ADDLOW(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_ENGDAH */ -#define FSL_ESW_ENGDAH_ADDHIGH(x) (((x)&0x0000FFFF)<<0) +#define FSL_ESW_ENGDAH_ADDHIGH(x) (((x) & 0x0000FFFF) << 0) /* Bit definitions and macros for FSL_ESW_MCVAL */ -#define FSL_ESW_MCVAL_COUNT(x) (((x)&0x000000FF)<<0) +#define FSL_ESW_MCVAL_COUNT(x) (((x) & 0x000000FF) << 0) /* Bit definitions and macros for FSL_ESW_MMSR */ #define FSL_ESW_MMSR_BUSY (0x00000001) @@ -942,13 +640,13 @@ struct switch_platform_private { #define FSL_ESW_MMSR_MEMFULL (0x00000004) #define FSL_ESW_MMSR_MFLATCH (0x00000008) #define FSL_ESW_MMSR_DQ_GRNT (0x00000040) -#define FSL_ESW_MMSR_CELLS_AVAIL(x) (((x)&0x000000FF)<<16) +#define FSL_ESW_MMSR_CELLS_AVAIL(x) (((x) & 0x000000FF) << 16) /* Bit definitions and macros for FSL_ESW_LMT */ -#define FSL_ESW_LMT_THRESH(x) (((x)&0x000000FF)<<0) +#define FSL_ESW_LMT_THRESH(x) (((x) & 0x000000FF) << 0) /* Bit definitions and macros for FSL_ESW_LFC */ -#define FSL_ESW_LFC_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_LFC_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_PCSR */ #define FSL_ESW_PCSR_PC0 (0x00000001) @@ -961,86 +659,86 @@ struct switch_platform_private { #define FSL_ESW_IOSR_OR2 (0x00000004) /* Bit definitions and macros for FSL_ESW_QWT */ -#define FSL_ESW_QWT_Q0WT(x) (((x)&0x0000001F)<<0) -#define FSL_ESW_QWT_Q1WT(x) (((x)&0x0000001F)<<8) -#define FSL_ESW_QWT_Q2WT(x) (((x)&0x0000001F)<<16) -#define FSL_ESW_QWT_Q3WT(x) (((x)&0x0000001F)<<24) +#define FSL_ESW_QWT_Q0WT(x) (((x) & 0x0000001F) << 0) +#define FSL_ESW_QWT_Q1WT(x) (((x) & 0x0000001F) << 8) +#define FSL_ESW_QWT_Q2WT(x) (((x) & 0x0000001F) << 16) +#define FSL_ESW_QWT_Q3WT(x) (((x) & 0x0000001F) << 24) /* Bit definitions and macros for FSL_ESW_P0BCT */ -#define FSL_ESW_P0BCT_THRESH(x) (((x)&0x000000FF)<<0) +#define FSL_ESW_P0BCT_THRESH(x) (((x) & 0x000000FF) << 0) /* Bit definitions and macros for FSL_ESW_P0FFEN */ #define FSL_ESW_P0FFEN_FEN (0x00000001) -#define FSL_ESW_P0FFEN_FD(x) (((x)&0x00000003)<<2) +#define FSL_ESW_P0FFEN_FD(x) (((x) & 0x00000003) << 2) /* Bit definitions and macros for FSL_ESW_PSNP */ #define FSL_ESW_PSNP_EN (0x00000001) -#define FSL_ESW_PSNP_MODE(x) (((x)&0x00000003)<<1) +#define FSL_ESW_PSNP_MODE(x) (((x) & 0x00000003) << 1) #define FSL_ESW_PSNP_CD (0x00000008) #define FSL_ESW_PSNP_CS (0x00000010) -#define FSL_ESW_PSNP_PORT_COMPARE(x) (((x)&0x0000FFFF)<<16) +#define FSL_ESW_PSNP_PORT_COMPARE(x) (((x) & 0x0000FFFF) << 16) /* Bit definitions and macros for FSL_ESW_IPSNP */ #define FSL_ESW_IPSNP_EN (0x00000001) -#define FSL_ESW_IPSNP_MODE(x) (((x)&0x00000003)<<1) -#define FSL_ESW_IPSNP_PROTOCOL(x) (((x)&0x000000FF)<<8) +#define FSL_ESW_IPSNP_MODE(x) (((x) & 0x00000003) << 1) +#define FSL_ESW_IPSNP_PROTOCOL(x) (((x) & 0x000000FF) << 8) /* Bit definitions and macros for FSL_ESW_PVRES */ -#define FSL_ESW_PVRES_PRI0(x) (((x)&0x00000007)<<0) -#define FSL_ESW_PVRES_PRI1(x) (((x)&0x00000007)<<3) -#define FSL_ESW_PVRES_PRI2(x) (((x)&0x00000007)<<6) -#define FSL_ESW_PVRES_PRI3(x) (((x)&0x00000007)<<9) -#define FSL_ESW_PVRES_PRI4(x) (((x)&0x00000007)<<12) -#define FSL_ESW_PVRES_PRI5(x) (((x)&0x00000007)<<15) -#define FSL_ESW_PVRES_PRI6(x) (((x)&0x00000007)<<18) -#define FSL_ESW_PVRES_PRI7(x) (((x)&0x00000007)<<21) +#define FSL_ESW_PVRES_PRI0(x) (((x) & 0x00000007) << 0) +#define FSL_ESW_PVRES_PRI1(x) (((x) & 0x00000007) << 3) +#define FSL_ESW_PVRES_PRI2(x) (((x) & 0x00000007) << 6) +#define FSL_ESW_PVRES_PRI3(x) (((x) & 0x00000007) << 9) +#define FSL_ESW_PVRES_PRI4(x) (((x) & 0x00000007) << 12) +#define FSL_ESW_PVRES_PRI5(x) (((x) & 0x00000007) << 15) +#define FSL_ESW_PVRES_PRI6(x) (((x) & 0x00000007) << 18) +#define FSL_ESW_PVRES_PRI7(x) (((x) & 0x00000007) << 21) /* Bit definitions and macros for FSL_ESW_IPRES */ -#define FSL_ESW_IPRES_ADDRESS(x) (((x)&0x000000FF)<<0) +#define FSL_ESW_IPRES_ADDRESS(x) (((x) & 0x000000FF) << 0) #define FSL_ESW_IPRES_IPV4SEL (0x00000100) -#define FSL_ESW_IPRES_PRI0(x) (((x)&0x00000003)<<9) -#define FSL_ESW_IPRES_PRI1(x) (((x)&0x00000003)<<11) -#define FSL_ESW_IPRES_PRI2(x) (((x)&0x00000003)<<13) +#define FSL_ESW_IPRES_PRI0(x) (((x) & 0x00000003) << 9) +#define FSL_ESW_IPRES_PRI1(x) (((x) & 0x00000003) << 11) +#define FSL_ESW_IPRES_PRI2(x) (((x) & 0x00000003) << 13) #define FSL_ESW_IPRES_READ (0x80000000) /* Bit definitions and macros for FSL_ESW_PRES */ #define FSL_ESW_PRES_VLAN (0x00000001) #define FSL_ESW_PRES_IP (0x00000002) #define FSL_ESW_PRES_MAC (0x00000004) -#define FSL_ESW_PRES_DFLT_PRI(x) (((x)&0x00000007)<<4) +#define FSL_ESW_PRES_DFLT_PRI(x) (((x) & 0x00000007) << 4) /* Bit definitions and macros for FSL_ESW_PID */ -#define FSL_ESW_PID_VLANID(x) (((x)&0x0000FFFF)<<0) +#define FSL_ESW_PID_VLANID(x) (((x) & 0x0000FFFF) << 0) /* Bit definitions and macros for FSL_ESW_VRES */ #define FSL_ESW_VRES_P0 (0x00000001) #define FSL_ESW_VRES_P1 (0x00000002) #define FSL_ESW_VRES_P2 (0x00000004) -#define FSL_ESW_VRES_VLANID(x) (((x)&0x00000FFF)<<3) +#define FSL_ESW_VRES_VLANID(x) (((x) & 0x00000FFF) << 3) /* Bit definitions and macros for FSL_ESW_DISCN */ -#define FSL_ESW_DISCN_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_DISCN_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_DISCB */ -#define FSL_ESW_DISCB_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_DISCB_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_NDISCN */ -#define FSL_ESW_NDISCN_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_NDISCN_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_NDISCB */ -#define FSL_ESW_NDISCB_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_NDISCB_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_POQC */ -#define FSL_ESW_POQC_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_POQC_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_PMVID */ -#define FSL_ESW_PMVID_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_PMVID_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_PMVTAG */ -#define FSL_ESW_PMVTAG_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_PMVTAG_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_PBL */ -#define FSL_ESW_PBL_COUNT(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_PBL_COUNT(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_ISR */ #define FSL_ESW_ISR_EBERR (0x00000001) @@ -1067,13 +765,13 @@ struct switch_platform_private { #define FSL_ESW_IMR_LRN (0x00000200) /* Bit definitions and macros for FSL_ESW_RDSR */ -#define FSL_ESW_RDSR_ADDRESS(x) (((x)&0x3FFFFFFF)<<2) +#define FSL_ESW_RDSR_ADDRESS(x) (((x) & 0x3FFFFFFF) << 2) /* Bit definitions and macros for FSL_ESW_TDSR */ -#define FSL_ESW_TDSR_ADDRESS(x) (((x)&0x3FFFFFFF)<<2) +#define FSL_ESW_TDSR_ADDRESS(x) (((x) & 0x3FFFFFFF) << 2) /* Bit definitions and macros for FSL_ESW_MRBR */ -#define FSL_ESW_MRBR_SIZE(x) (((x)&0x000003FF)<<4) +#define FSL_ESW_MRBR_SIZE(x) (((x) & 0x000003FF) << 4) /* Bit definitions and macros for FSL_ESW_RDAR */ #define FSL_ESW_RDAR_R_DES_ACTIVE (0x01000000) @@ -1082,12 +780,12 @@ struct switch_platform_private { #define FSL_ESW_TDAR_X_DES_ACTIVE (0x01000000) /* Bit definitions and macros for FSL_ESW_LREC0 */ -#define FSL_ESW_LREC0_MACADDR0(x) (((x)&0xFFFFFFFF)<<0) +#define FSL_ESW_LREC0_MACADDR0(x) (((x) & 0xFFFFFFFF) << 0) /* Bit definitions and macros for FSL_ESW_LREC1 */ -#define FSL_ESW_LREC1_MACADDR1(x) (((x)&0x0000FFFF)<<0) -#define FSL_ESW_LREC1_HASH(x) (((x)&0x000000FF)<<16) -#define FSL_ESW_LREC1_SWPORT(x) (((x)&0x00000003)<<24) +#define FSL_ESW_LREC1_MACADDR1(x) (((x) & 0x0000FFFF) << 0) +#define FSL_ESW_LREC1_HASH(x) (((x) & 0x000000FF) << 16) +#define FSL_ESW_LREC1_SWPORT(x) (((x) & 0x00000003) << 24) /* Bit definitions and macros for FSL_ESW_LSR */ #define FSL_ESW_LSR_DA (0x00000001) |