]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
dsa: Move switch drivers to new directory drivers/net/dsa
authorBen Hutchings <ben@decadent.org.uk>
Sun, 27 Nov 2011 17:08:33 +0000 (17:08 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Nov 2011 05:21:36 +0000 (00:21 -0500)
Support for specific hardware belongs under drivers/net/ not net/.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Acked-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
16 files changed:
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/dsa/Kconfig [new file with mode: 0644]
drivers/net/dsa/Makefile [new file with mode: 0644]
drivers/net/dsa/mv88e6060.c [new file with mode: 0644]
drivers/net/dsa/mv88e6123_61_65.c [new file with mode: 0644]
drivers/net/dsa/mv88e6131.c [new file with mode: 0644]
drivers/net/dsa/mv88e6xxx.c [new file with mode: 0644]
drivers/net/dsa/mv88e6xxx.h [new file with mode: 0644]
net/dsa/Kconfig
net/dsa/Makefile
net/dsa/mv88e6060.c [deleted file]
net/dsa/mv88e6123_61_65.c [deleted file]
net/dsa/mv88e6131.c [deleted file]
net/dsa/mv88e6xxx.c [deleted file]
net/dsa/mv88e6xxx.h [deleted file]

index debdf1c07c5b8b8c484e020507d902cbc60246b2..9845afb37cc80a785cc3fe137ed6d0e729ccb589 100644 (file)
@@ -243,6 +243,8 @@ source "drivers/atm/Kconfig"
 
 source "drivers/net/caif/Kconfig"
 
+source "drivers/net/dsa/Kconfig"
+
 source "drivers/net/ethernet/Kconfig"
 
 source "drivers/net/fddi/Kconfig"
index 4e4ebfe1aa535367b15b3e480c657215b163a5d2..1988881853ab8437b7776493df00e063588e5f59 100644 (file)
@@ -30,6 +30,7 @@ obj-$(CONFIG_DEV_APPLETALK) += appletalk/
 obj-$(CONFIG_CAIF) += caif/
 obj-$(CONFIG_CAN) += can/
 obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+obj-$(CONFIG_NET_DSA) += dsa/
 obj-$(CONFIG_ETHERNET) += ethernet/
 obj-$(CONFIG_FDDI) += fddi/
 obj-$(CONFIG_HIPPI) += hippi/
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
new file mode 100644 (file)
index 0000000..dd151d5
--- /dev/null
@@ -0,0 +1,36 @@
+menu "Distributed Switch Architecture drivers"
+       depends on NET_DSA
+
+config NET_DSA_MV88E6XXX
+       tristate
+       default n
+
+config NET_DSA_MV88E6060
+       tristate "Marvell 88E6060 ethernet switch chip support"
+       select NET_DSA_TAG_TRAILER
+       ---help---
+         This enables support for the Marvell 88E6060 ethernet switch
+         chip.
+
+config NET_DSA_MV88E6XXX_NEED_PPU
+       bool
+       default n
+
+config NET_DSA_MV88E6131
+       tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
+       select NET_DSA_MV88E6XXX
+       select NET_DSA_MV88E6XXX_NEED_PPU
+       select NET_DSA_TAG_DSA
+       ---help---
+         This enables support for the Marvell 88E6085/6095/6095F/6131
+         ethernet switch chips.
+
+config NET_DSA_MV88E6123_61_65
+       tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
+       select NET_DSA_MV88E6XXX
+       select NET_DSA_TAG_EDSA
+       ---help---
+         This enables support for the Marvell 88E6123/6161/6165
+         ethernet switch chips.
+
+endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
new file mode 100644 (file)
index 0000000..f3bda05
--- /dev/null
@@ -0,0 +1,9 @@
+obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
+obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
+mv88e6xxx_drv-y += mv88e6xxx.o
+ifdef CONFIG_NET_DSA_MV88E6123_61_65
+mv88e6xxx_drv-y += mv88e6123_61_65.o
+endif
+ifdef CONFIG_NET_DSA_MV88E6131
+mv88e6xxx_drv-y += mv88e6131.o
+endif
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
new file mode 100644 (file)
index 0000000..7fc4e81
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * net/dsa/mv88e6060.c - Driver for Marvell 88e6060 switch chips
+ * Copyright (c) 2008-2009 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <net/dsa.h>
+
+#define REG_PORT(p)            (8 + (p))
+#define REG_GLOBAL             0x0f
+
+static int reg_read(struct dsa_switch *ds, int addr, int reg)
+{
+       return mdiobus_read(ds->master_mii_bus, ds->pd->sw_addr + addr, reg);
+}
+
+#define REG_READ(addr, reg)                                    \
+       ({                                                      \
+               int __ret;                                      \
+                                                               \
+               __ret = reg_read(ds, addr, reg);                \
+               if (__ret < 0)                                  \
+                       return __ret;                           \
+               __ret;                                          \
+       })
+
+
+static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
+{
+       return mdiobus_write(ds->master_mii_bus, ds->pd->sw_addr + addr,
+                            reg, val);
+}
+
+#define REG_WRITE(addr, reg, val)                              \
+       ({                                                      \
+               int __ret;                                      \
+                                                               \
+               __ret = reg_write(ds, addr, reg, val);          \
+               if (__ret < 0)                                  \
+                       return __ret;                           \
+       })
+
+static char *mv88e6060_probe(struct mii_bus *bus, int sw_addr)
+{
+       int ret;
+
+       ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03);
+       if (ret >= 0) {
+               ret &= 0xfff0;
+               if (ret == 0x0600)
+                       return "Marvell 88E6060";
+       }
+
+       return NULL;
+}
+
+static int mv88e6060_switch_reset(struct dsa_switch *ds)
+{
+       int i;
+       int ret;
+
+       /*
+        * Set all ports to the disabled state.
+        */
+       for (i = 0; i < 6; i++) {
+               ret = REG_READ(REG_PORT(i), 0x04);
+               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
+       }
+
+       /*
+        * Wait for transmit queues to drain.
+        */
+       msleep(2);
+
+       /*
+        * Reset the switch.
+        */
+       REG_WRITE(REG_GLOBAL, 0x0a, 0xa130);
+
+       /*
+        * Wait up to one second for reset to complete.
+        */
+       for (i = 0; i < 1000; i++) {
+               ret = REG_READ(REG_GLOBAL, 0x00);
+               if ((ret & 0x8000) == 0x0000)
+                       break;
+
+               msleep(1);
+       }
+       if (i == 1000)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int mv88e6060_setup_global(struct dsa_switch *ds)
+{
+       /*
+        * Disable discarding of frames with excessive collisions,
+        * set the maximum frame size to 1536 bytes, and mask all
+        * interrupt sources.
+        */
+       REG_WRITE(REG_GLOBAL, 0x04, 0x0800);
+
+       /*
+        * Enable automatic address learning, set the address
+        * database size to 1024 entries, and set the default aging
+        * time to 5 minutes.
+        */
+       REG_WRITE(REG_GLOBAL, 0x0a, 0x2130);
+
+       return 0;
+}
+
+static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
+{
+       int addr = REG_PORT(p);
+
+       /*
+        * Do not force flow control, disable Ingress and Egress
+        * Header tagging, disable VLAN tunneling, and set the port
+        * state to Forwarding.  Additionally, if this is the CPU
+        * port, enable Ingress and Egress Trailer tagging mode.
+        */
+       REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ?  0x4103 : 0x0003);
+
+       /*
+        * Port based VLAN map: give each port its own address
+        * database, allow the CPU port to talk to each of the 'real'
+        * ports, and allow each of the 'real' ports to only talk to
+        * the CPU port.
+        */
+       REG_WRITE(addr, 0x06,
+                       ((p & 0xf) << 12) |
+                        (dsa_is_cpu_port(ds, p) ?
+                               ds->phys_port_mask :
+                               (1 << ds->dst->cpu_port)));
+
+       /*
+        * Port Association Vector: when learning source addresses
+        * of packets, add the address to the address database using
+        * a port bitmap that has only the bit for this port set and
+        * the other bits clear.
+        */
+       REG_WRITE(addr, 0x0b, 1 << p);
+
+       return 0;
+}
+
+static int mv88e6060_setup(struct dsa_switch *ds)
+{
+       int i;
+       int ret;
+
+       ret = mv88e6060_switch_reset(ds);
+       if (ret < 0)
+               return ret;
+
+       /* @@@ initialise atu */
+
+       ret = mv88e6060_setup_global(ds);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < 6; i++) {
+               ret = mv88e6060_setup_port(ds, i);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr)
+{
+       REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
+       REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
+       REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
+
+       return 0;
+}
+
+static int mv88e6060_port_to_phy_addr(int port)
+{
+       if (port >= 0 && port <= 5)
+               return port;
+       return -1;
+}
+
+static int mv88e6060_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+       int addr;
+
+       addr = mv88e6060_port_to_phy_addr(port);
+       if (addr == -1)
+               return 0xffff;
+
+       return reg_read(ds, addr, regnum);
+}
+
+static int
+mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
+{
+       int addr;
+
+       addr = mv88e6060_port_to_phy_addr(port);
+       if (addr == -1)
+               return 0xffff;
+
+       return reg_write(ds, addr, regnum, val);
+}
+
+static void mv88e6060_poll_link(struct dsa_switch *ds)
+{
+       int i;
+
+       for (i = 0; i < DSA_MAX_PORTS; i++) {
+               struct net_device *dev;
+               int uninitialized_var(port_status);
+               int link;
+               int speed;
+               int duplex;
+               int fc;
+
+               dev = ds->ports[i];
+               if (dev == NULL)
+                       continue;
+
+               link = 0;
+               if (dev->flags & IFF_UP) {
+                       port_status = reg_read(ds, REG_PORT(i), 0x00);
+                       if (port_status < 0)
+                               continue;
+
+                       link = !!(port_status & 0x1000);
+               }
+
+               if (!link) {
+                       if (netif_carrier_ok(dev)) {
+                               printk(KERN_INFO "%s: link down\n", dev->name);
+                               netif_carrier_off(dev);
+                       }
+                       continue;
+               }
+
+               speed = (port_status & 0x0100) ? 100 : 10;
+               duplex = (port_status & 0x0200) ? 1 : 0;
+               fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0;
+
+               if (!netif_carrier_ok(dev)) {
+                       printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
+                                        "flow control %sabled\n", dev->name,
+                                        speed, duplex ? "full" : "half",
+                                        fc ? "en" : "dis");
+                       netif_carrier_on(dev);
+               }
+       }
+}
+
+static struct dsa_switch_driver mv88e6060_switch_driver = {
+       .tag_protocol   = htons(ETH_P_TRAILER),
+       .probe          = mv88e6060_probe,
+       .setup          = mv88e6060_setup,
+       .set_addr       = mv88e6060_set_addr,
+       .phy_read       = mv88e6060_phy_read,
+       .phy_write      = mv88e6060_phy_write,
+       .poll_link      = mv88e6060_poll_link,
+};
+
+static int __init mv88e6060_init(void)
+{
+       register_switch_driver(&mv88e6060_switch_driver);
+       return 0;
+}
+module_init(mv88e6060_init);
+
+static void __exit mv88e6060_cleanup(void)
+{
+       unregister_switch_driver(&mv88e6060_switch_driver);
+}
+module_exit(mv88e6060_cleanup);
+
+MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
+MODULE_DESCRIPTION("Driver for Marvell 88E6060 ethernet switch chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mv88e6060");
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
new file mode 100644 (file)
index 0000000..c0a458f
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
+ * Copyright (c) 2008-2009 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <net/dsa.h>
+#include "mv88e6xxx.h"
+
+static char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr)
+{
+       int ret;
+
+       ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
+       if (ret >= 0) {
+               ret &= 0xfff0;
+               if (ret == 0x1210)
+                       return "Marvell 88E6123";
+               if (ret == 0x1610)
+                       return "Marvell 88E6161";
+               if (ret == 0x1650)
+                       return "Marvell 88E6165";
+       }
+
+       return NULL;
+}
+
+static int mv88e6123_61_65_switch_reset(struct dsa_switch *ds)
+{
+       int i;
+       int ret;
+
+       /*
+        * Set all ports to the disabled state.
+        */
+       for (i = 0; i < 8; i++) {
+               ret = REG_READ(REG_PORT(i), 0x04);
+               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
+       }
+
+       /*
+        * Wait for transmit queues to drain.
+        */
+       msleep(2);
+
+       /*
+        * Reset the switch.
+        */
+       REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
+
+       /*
+        * Wait up to one second for reset to complete.
+        */
+       for (i = 0; i < 1000; i++) {
+               ret = REG_READ(REG_GLOBAL, 0x00);
+               if ((ret & 0xc800) == 0xc800)
+                       break;
+
+               msleep(1);
+       }
+       if (i == 1000)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
+{
+       int ret;
+       int i;
+
+       /*
+        * Disable the PHY polling unit (since there won't be any
+        * external PHYs to poll), don't discard packets with
+        * excessive collisions, and mask all interrupt sources.
+        */
+       REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
+
+       /*
+        * Set the default address aging time to 5 minutes, and
+        * enable address learn messages to be sent to all message
+        * ports.
+        */
+       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
+
+       /*
+        * Configure the priority mapping registers.
+        */
+       ret = mv88e6xxx_config_prio(ds);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Configure the upstream port, and configure the upstream
+        * port as the port to which ingress and egress monitor frames
+        * are to be sent.
+        */
+       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
+
+       /*
+        * Disable remote management for now, and set the switch's
+        * DSA device number.
+        */
+       REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
+
+       /*
+        * Send all frames with destination addresses matching
+        * 01:80:c2:00:00:2x to the CPU port.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
+
+       /*
+        * Send all frames with destination addresses matching
+        * 01:80:c2:00:00:0x to the CPU port.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
+
+       /*
+        * Disable the loopback filter, disable flow control
+        * messages, disable flood broadcast override, disable
+        * removing of provider tags, disable ATU age violation
+        * interrupts, disable tag flow control, force flow
+        * control priority to the highest, and send all special
+        * multicast frames to the CPU at the highest priority.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
+
+       /*
+        * Program the DSA routing table.
+        */
+       for (i = 0; i < 32; i++) {
+               int nexthop;
+
+               nexthop = 0x1f;
+               if (i != ds->index && i < ds->dst->pd->nr_chips)
+                       nexthop = ds->pd->rtable[i] & 0x1f;
+
+               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
+       }
+
+       /*
+        * Clear all trunk masks.
+        */
+       for (i = 0; i < 8; i++)
+               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
+
+       /*
+        * Clear all trunk mappings.
+        */
+       for (i = 0; i < 16; i++)
+               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
+
+       /*
+        * Disable ingress rate limiting by resetting all ingress
+        * rate limit registers to their initial state.
+        */
+       for (i = 0; i < 6; i++)
+               REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
+
+       /*
+        * Initialise cross-chip port VLAN table to reset defaults.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
+
+       /*
+        * Clear the priority override table.
+        */
+       for (i = 0; i < 16; i++)
+               REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
+
+       /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
+
+       return 0;
+}
+
+static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
+{
+       int addr = REG_PORT(p);
+       u16 val;
+
+       /*
+        * MAC Forcing register: don't force link, speed, duplex
+        * or flow control state to any particular values on physical
+        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
+        * full duplex.
+        */
+       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
+               REG_WRITE(addr, 0x01, 0x003e);
+       else
+               REG_WRITE(addr, 0x01, 0x0003);
+
+       /*
+        * Do not limit the period of time that this port can be
+        * paused for by the remote end or the period of time that
+        * this port can pause the remote end.
+        */
+       REG_WRITE(addr, 0x02, 0x0000);
+
+       /*
+        * Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
+        * disable Header mode, enable IGMP/MLD snooping, disable VLAN
+        * tunneling, determine priority by looking at 802.1p and IP
+        * priority fields (IP prio has precedence), and set STP state
+        * to Forwarding.
+        *
+        * If this is the CPU link, use DSA or EDSA tagging depending
+        * on which tagging mode was configured.
+        *
+        * If this is a link to another switch, use DSA tagging mode.
+        *
+        * If this is the upstream port for this switch, enable
+        * forwarding of unknown unicasts and multicasts.
+        */
+       val = 0x0433;
+       if (dsa_is_cpu_port(ds, p)) {
+               if (ds->dst->tag_protocol == htons(ETH_P_EDSA))
+                       val |= 0x3300;
+               else
+                       val |= 0x0100;
+       }
+       if (ds->dsa_port_mask & (1 << p))
+               val |= 0x0100;
+       if (p == dsa_upstream_port(ds))
+               val |= 0x000c;
+       REG_WRITE(addr, 0x04, val);
+
+       /*
+        * Port Control 1: disable trunking.  Also, if this is the
+        * CPU port, enable learn messages to be sent to this port.
+        */
+       REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
+
+       /*
+        * Port based VLAN map: give each port its own address
+        * database, allow the CPU port to talk to each of the 'real'
+        * ports, and allow each of the 'real' ports to only talk to
+        * the upstream port.
+        */
+       val = (p & 0xf) << 12;
+       if (dsa_is_cpu_port(ds, p))
+               val |= ds->phys_port_mask;
+       else
+               val |= 1 << dsa_upstream_port(ds);
+       REG_WRITE(addr, 0x06, val);
+
+       /*
+        * Default VLAN ID and priority: don't set a default VLAN
+        * ID, and set the default packet priority to zero.
+        */
+       REG_WRITE(addr, 0x07, 0x0000);
+
+       /*
+        * Port Control 2: don't force a good FCS, set the maximum
+        * frame size to 10240 bytes, don't let the switch add or
+        * strip 802.1q tags, don't discard tagged or untagged frames
+        * on this port, do a destination address lookup on all
+        * received packets as usual, disable ARP mirroring and don't
+        * send a copy of all transmitted/received frames on this port
+        * to the CPU.
+        */
+       REG_WRITE(addr, 0x08, 0x2080);
+
+       /*
+        * Egress rate control: disable egress rate control.
+        */
+       REG_WRITE(addr, 0x09, 0x0001);
+
+       /*
+        * Egress rate control 2: disable egress rate control.
+        */
+       REG_WRITE(addr, 0x0a, 0x0000);
+
+       /*
+        * Port Association Vector: when learning source addresses
+        * of packets, add the address to the address database using
+        * a port bitmap that has only the bit for this port set and
+        * the other bits clear.
+        */
+       REG_WRITE(addr, 0x0b, 1 << p);
+
+       /*
+        * Port ATU control: disable limiting the number of address
+        * database entries that this port is allowed to use.
+        */
+       REG_WRITE(addr, 0x0c, 0x0000);
+
+       /*
+        * Priorit Override: disable DA, SA and VTU priority override.
+        */
+       REG_WRITE(addr, 0x0d, 0x0000);
+
+       /*
+        * Port Ethertype: use the Ethertype DSA Ethertype value.
+        */
+       REG_WRITE(addr, 0x0f, ETH_P_EDSA);
+
+       /*
+        * Tag Remap: use an identity 802.1p prio -> switch prio
+        * mapping.
+        */
+       REG_WRITE(addr, 0x18, 0x3210);
+
+       /*
+        * Tag Remap 2: use an identity 802.1p prio -> switch prio
+        * mapping.
+        */
+       REG_WRITE(addr, 0x19, 0x7654);
+
+       return 0;
+}
+
+static int mv88e6123_61_65_setup(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int i;
+       int ret;
+
+       mutex_init(&ps->smi_mutex);
+       mutex_init(&ps->stats_mutex);
+
+       ret = mv88e6123_61_65_switch_reset(ds);
+       if (ret < 0)
+               return ret;
+
+       /* @@@ initialise vtu and atu */
+
+       ret = mv88e6123_61_65_setup_global(ds);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < 6; i++) {
+               ret = mv88e6123_61_65_setup_port(ds, i);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int mv88e6123_61_65_port_to_phy_addr(int port)
+{
+       if (port >= 0 && port <= 4)
+               return port;
+       return -1;
+}
+
+static int
+mv88e6123_61_65_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+       int addr = mv88e6123_61_65_port_to_phy_addr(port);
+       return mv88e6xxx_phy_read(ds, addr, regnum);
+}
+
+static int
+mv88e6123_61_65_phy_write(struct dsa_switch *ds,
+                             int port, int regnum, u16 val)
+{
+       int addr = mv88e6123_61_65_port_to_phy_addr(port);
+       return mv88e6xxx_phy_write(ds, addr, regnum, val);
+}
+
+static struct mv88e6xxx_hw_stat mv88e6123_61_65_hw_stats[] = {
+       { "in_good_octets", 8, 0x00, },
+       { "in_bad_octets", 4, 0x02, },
+       { "in_unicast", 4, 0x04, },
+       { "in_broadcasts", 4, 0x06, },
+       { "in_multicasts", 4, 0x07, },
+       { "in_pause", 4, 0x16, },
+       { "in_undersize", 4, 0x18, },
+       { "in_fragments", 4, 0x19, },
+       { "in_oversize", 4, 0x1a, },
+       { "in_jabber", 4, 0x1b, },
+       { "in_rx_error", 4, 0x1c, },
+       { "in_fcs_error", 4, 0x1d, },
+       { "out_octets", 8, 0x0e, },
+       { "out_unicast", 4, 0x10, },
+       { "out_broadcasts", 4, 0x13, },
+       { "out_multicasts", 4, 0x12, },
+       { "out_pause", 4, 0x15, },
+       { "excessive", 4, 0x11, },
+       { "collisions", 4, 0x1e, },
+       { "deferred", 4, 0x05, },
+       { "single", 4, 0x14, },
+       { "multiple", 4, 0x17, },
+       { "out_fcs_error", 4, 0x03, },
+       { "late", 4, 0x1f, },
+       { "hist_64bytes", 4, 0x08, },
+       { "hist_65_127bytes", 4, 0x09, },
+       { "hist_128_255bytes", 4, 0x0a, },
+       { "hist_256_511bytes", 4, 0x0b, },
+       { "hist_512_1023bytes", 4, 0x0c, },
+       { "hist_1024_max_bytes", 4, 0x0d, },
+};
+
+static void
+mv88e6123_61_65_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
+{
+       mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats),
+                             mv88e6123_61_65_hw_stats, port, data);
+}
+
+static void
+mv88e6123_61_65_get_ethtool_stats(struct dsa_switch *ds,
+                                 int port, uint64_t *data)
+{
+       mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats),
+                                   mv88e6123_61_65_hw_stats, port, data);
+}
+
+static int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds)
+{
+       return ARRAY_SIZE(mv88e6123_61_65_hw_stats);
+}
+
+struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
+       .tag_protocol           = cpu_to_be16(ETH_P_EDSA),
+       .priv_size              = sizeof(struct mv88e6xxx_priv_state),
+       .probe                  = mv88e6123_61_65_probe,
+       .setup                  = mv88e6123_61_65_setup,
+       .set_addr               = mv88e6xxx_set_addr_indirect,
+       .phy_read               = mv88e6123_61_65_phy_read,
+       .phy_write              = mv88e6123_61_65_phy_write,
+       .poll_link              = mv88e6xxx_poll_link,
+       .get_strings            = mv88e6123_61_65_get_strings,
+       .get_ethtool_stats      = mv88e6123_61_65_get_ethtool_stats,
+       .get_sset_count         = mv88e6123_61_65_get_sset_count,
+};
+
+MODULE_ALIAS("platform:mv88e6123");
+MODULE_ALIAS("platform:mv88e6161");
+MODULE_ALIAS("platform:mv88e6165");
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
new file mode 100644 (file)
index 0000000..e0eb682
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support
+ * Copyright (c) 2008-2009 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <net/dsa.h>
+#include "mv88e6xxx.h"
+
+/*
+ * Switch product IDs
+ */
+#define ID_6085                0x04a0
+#define ID_6095                0x0950
+#define ID_6131                0x1060
+
+static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr)
+{
+       int ret;
+
+       ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
+       if (ret >= 0) {
+               ret &= 0xfff0;
+               if (ret == ID_6085)
+                       return "Marvell 88E6085";
+               if (ret == ID_6095)
+                       return "Marvell 88E6095/88E6095F";
+               if (ret == ID_6131)
+                       return "Marvell 88E6131";
+       }
+
+       return NULL;
+}
+
+static int mv88e6131_switch_reset(struct dsa_switch *ds)
+{
+       int i;
+       int ret;
+
+       /*
+        * Set all ports to the disabled state.
+        */
+       for (i = 0; i < 11; i++) {
+               ret = REG_READ(REG_PORT(i), 0x04);
+               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
+       }
+
+       /*
+        * Wait for transmit queues to drain.
+        */
+       msleep(2);
+
+       /*
+        * Reset the switch.
+        */
+       REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
+
+       /*
+        * Wait up to one second for reset to complete.
+        */
+       for (i = 0; i < 1000; i++) {
+               ret = REG_READ(REG_GLOBAL, 0x00);
+               if ((ret & 0xc800) == 0xc800)
+                       break;
+
+               msleep(1);
+       }
+       if (i == 1000)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int mv88e6131_setup_global(struct dsa_switch *ds)
+{
+       int ret;
+       int i;
+
+       /*
+        * Enable the PHY polling unit, don't discard packets with
+        * excessive collisions, use a weighted fair queueing scheme
+        * to arbitrate between packet queues, set the maximum frame
+        * size to 1632, and mask all interrupt sources.
+        */
+       REG_WRITE(REG_GLOBAL, 0x04, 0x4400);
+
+       /*
+        * Set the default address aging time to 5 minutes, and
+        * enable address learn messages to be sent to all message
+        * ports.
+        */
+       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
+
+       /*
+        * Configure the priority mapping registers.
+        */
+       ret = mv88e6xxx_config_prio(ds);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Set the VLAN ethertype to 0x8100.
+        */
+       REG_WRITE(REG_GLOBAL, 0x19, 0x8100);
+
+       /*
+        * Disable ARP mirroring, and configure the upstream port as
+        * the port to which ingress and egress monitor frames are to
+        * be sent.
+        */
+       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
+
+       /*
+        * Disable cascade port functionality unless this device
+        * is used in a cascade configuration, and set the switch's
+        * DSA device number.
+        */
+       if (ds->dst->pd->nr_chips > 1)
+               REG_WRITE(REG_GLOBAL, 0x1c, 0xf000 | (ds->index & 0x1f));
+       else
+               REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
+
+       /*
+        * Send all frames with destination addresses matching
+        * 01:80:c2:00:00:0x to the CPU port.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
+
+       /*
+        * Ignore removed tag data on doubly tagged packets, disable
+        * flow control messages, force flow control priority to the
+        * highest, and send all special multicast frames to the CPU
+        * port at the highest priority.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
+
+       /*
+        * Program the DSA routing table.
+        */
+       for (i = 0; i < 32; i++) {
+               int nexthop;
+
+               nexthop = 0x1f;
+               if (i != ds->index && i < ds->dst->pd->nr_chips)
+                       nexthop = ds->pd->rtable[i] & 0x1f;
+
+               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
+       }
+
+       /*
+        * Clear all trunk masks.
+        */
+       for (i = 0; i < 8; i++)
+               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff);
+
+       /*
+        * Clear all trunk mappings.
+        */
+       for (i = 0; i < 16; i++)
+               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
+
+       /*
+        * Force the priority of IGMP/MLD snoop frames and ARP frames
+        * to the highest setting.
+        */
+       REG_WRITE(REG_GLOBAL2, 0x0f, 0x00ff);
+
+       return 0;
+}
+
+static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int addr = REG_PORT(p);
+       u16 val;
+
+       /*
+        * MAC Forcing register: don't force link, speed, duplex
+        * or flow control state to any particular values on physical
+        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
+        * (100 Mb/s on 6085) full duplex.
+        */
+       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
+               if (ps->id == ID_6085)
+                       REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */
+               else
+                       REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */
+       else
+               REG_WRITE(addr, 0x01, 0x0003);
+
+       /*
+        * Port Control: disable Core Tag, disable Drop-on-Lock,
+        * transmit frames unmodified, disable Header mode,
+        * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN
+        * tunneling, determine priority by looking at 802.1p and
+        * IP priority fields (IP prio has precedence), and set STP
+        * state to Forwarding.
+        *
+        * If this is the upstream port for this switch, enable
+        * forwarding of unknown unicasts, and enable DSA tagging
+        * mode.
+        *
+        * If this is the link to another switch, use DSA tagging
+        * mode, but do not enable forwarding of unknown unicasts.
+        */
+       val = 0x0433;
+       if (p == dsa_upstream_port(ds)) {
+               val |= 0x0104;
+               /*
+                * On 6085, unknown multicast forward is controlled
+                * here rather than in Port Control 2 register.
+                */
+               if (ps->id == ID_6085)
+                       val |= 0x0008;
+       }
+       if (ds->dsa_port_mask & (1 << p))
+               val |= 0x0100;
+       REG_WRITE(addr, 0x04, val);
+
+       /*
+        * Port Control 1: disable trunking.  Also, if this is the
+        * CPU port, enable learn messages to be sent to this port.
+        */
+       REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
+
+       /*
+        * Port based VLAN map: give each port its own address
+        * database, allow the CPU port to talk to each of the 'real'
+        * ports, and allow each of the 'real' ports to only talk to
+        * the upstream port.
+        */
+       val = (p & 0xf) << 12;
+       if (dsa_is_cpu_port(ds, p))
+               val |= ds->phys_port_mask;
+       else
+               val |= 1 << dsa_upstream_port(ds);
+       REG_WRITE(addr, 0x06, val);
+
+       /*
+        * Default VLAN ID and priority: don't set a default VLAN
+        * ID, and set the default packet priority to zero.
+        */
+       REG_WRITE(addr, 0x07, 0x0000);
+
+       /*
+        * Port Control 2: don't force a good FCS, don't use
+        * VLAN-based, source address-based or destination
+        * address-based priority overrides, don't let the switch
+        * add or strip 802.1q tags, don't discard tagged or
+        * untagged frames on this port, do a destination address
+        * lookup on received packets as usual, don't send a copy
+        * of all transmitted/received frames on this port to the
+        * CPU, and configure the upstream port number.
+        *
+        * If this is the upstream port for this switch, enable
+        * forwarding of unknown multicast addresses.
+        */
+       if (ps->id == ID_6085)
+               /*
+                * on 6085, bits 3:0 are reserved, bit 6 control ARP
+                * mirroring, and multicast forward is handled in
+                * Port Control register.
+                */
+               REG_WRITE(addr, 0x08, 0x0080);
+       else {
+               val = 0x0080 | dsa_upstream_port(ds);
+               if (p == dsa_upstream_port(ds))
+                       val |= 0x0040;
+               REG_WRITE(addr, 0x08, val);
+       }
+
+       /*
+        * Rate Control: disable ingress rate limiting.
+        */
+       REG_WRITE(addr, 0x09, 0x0000);
+
+       /*
+        * Rate Control 2: disable egress rate limiting.
+        */
+       REG_WRITE(addr, 0x0a, 0x0000);
+
+       /*
+        * Port Association Vector: when learning source addresses
+        * of packets, add the address to the address database using
+        * a port bitmap that has only the bit for this port set and
+        * the other bits clear.
+        */
+       REG_WRITE(addr, 0x0b, 1 << p);
+
+       /*
+        * Tag Remap: use an identity 802.1p prio -> switch prio
+        * mapping.
+        */
+       REG_WRITE(addr, 0x18, 0x3210);
+
+       /*
+        * Tag Remap 2: use an identity 802.1p prio -> switch prio
+        * mapping.
+        */
+       REG_WRITE(addr, 0x19, 0x7654);
+
+       return 0;
+}
+
+static int mv88e6131_setup(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int i;
+       int ret;
+
+       mutex_init(&ps->smi_mutex);
+       mv88e6xxx_ppu_state_init(ds);
+       mutex_init(&ps->stats_mutex);
+
+       ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
+
+       ret = mv88e6131_switch_reset(ds);
+       if (ret < 0)
+               return ret;
+
+       /* @@@ initialise vtu and atu */
+
+       ret = mv88e6131_setup_global(ds);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < 11; i++) {
+               ret = mv88e6131_setup_port(ds, i);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int mv88e6131_port_to_phy_addr(int port)
+{
+       if (port >= 0 && port <= 11)
+               return port;
+       return -1;
+}
+
+static int
+mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+       int addr = mv88e6131_port_to_phy_addr(port);
+       return mv88e6xxx_phy_read_ppu(ds, addr, regnum);
+}
+
+static int
+mv88e6131_phy_write(struct dsa_switch *ds,
+                             int port, int regnum, u16 val)
+{
+       int addr = mv88e6131_port_to_phy_addr(port);
+       return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val);
+}
+
+static struct mv88e6xxx_hw_stat mv88e6131_hw_stats[] = {
+       { "in_good_octets", 8, 0x00, },
+       { "in_bad_octets", 4, 0x02, },
+       { "in_unicast", 4, 0x04, },
+       { "in_broadcasts", 4, 0x06, },
+       { "in_multicasts", 4, 0x07, },
+       { "in_pause", 4, 0x16, },
+       { "in_undersize", 4, 0x18, },
+       { "in_fragments", 4, 0x19, },
+       { "in_oversize", 4, 0x1a, },
+       { "in_jabber", 4, 0x1b, },
+       { "in_rx_error", 4, 0x1c, },
+       { "in_fcs_error", 4, 0x1d, },
+       { "out_octets", 8, 0x0e, },
+       { "out_unicast", 4, 0x10, },
+       { "out_broadcasts", 4, 0x13, },
+       { "out_multicasts", 4, 0x12, },
+       { "out_pause", 4, 0x15, },
+       { "excessive", 4, 0x11, },
+       { "collisions", 4, 0x1e, },
+       { "deferred", 4, 0x05, },
+       { "single", 4, 0x14, },
+       { "multiple", 4, 0x17, },
+       { "out_fcs_error", 4, 0x03, },
+       { "late", 4, 0x1f, },
+       { "hist_64bytes", 4, 0x08, },
+       { "hist_65_127bytes", 4, 0x09, },
+       { "hist_128_255bytes", 4, 0x0a, },
+       { "hist_256_511bytes", 4, 0x0b, },
+       { "hist_512_1023bytes", 4, 0x0c, },
+       { "hist_1024_max_bytes", 4, 0x0d, },
+};
+
+static void
+mv88e6131_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
+{
+       mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6131_hw_stats),
+                             mv88e6131_hw_stats, port, data);
+}
+
+static void
+mv88e6131_get_ethtool_stats(struct dsa_switch *ds,
+                                 int port, uint64_t *data)
+{
+       mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6131_hw_stats),
+                                   mv88e6131_hw_stats, port, data);
+}
+
+static int mv88e6131_get_sset_count(struct dsa_switch *ds)
+{
+       return ARRAY_SIZE(mv88e6131_hw_stats);
+}
+
+struct dsa_switch_driver mv88e6131_switch_driver = {
+       .tag_protocol           = cpu_to_be16(ETH_P_DSA),
+       .priv_size              = sizeof(struct mv88e6xxx_priv_state),
+       .probe                  = mv88e6131_probe,
+       .setup                  = mv88e6131_setup,
+       .set_addr               = mv88e6xxx_set_addr_direct,
+       .phy_read               = mv88e6131_phy_read,
+       .phy_write              = mv88e6131_phy_write,
+       .poll_link              = mv88e6xxx_poll_link,
+       .get_strings            = mv88e6131_get_strings,
+       .get_ethtool_stats      = mv88e6131_get_ethtool_stats,
+       .get_sset_count         = mv88e6131_get_sset_count,
+};
+
+MODULE_ALIAS("platform:mv88e6085");
+MODULE_ALIAS("platform:mv88e6095");
+MODULE_ALIAS("platform:mv88e6095f");
+MODULE_ALIAS("platform:mv88e6131");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
new file mode 100644 (file)
index 0000000..5467c04
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+ * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <net/dsa.h>
+#include "mv88e6xxx.h"
+
+/*
+ * If the switch's ADDR[4:0] strap pins are strapped to zero, it will
+ * use all 32 SMI bus addresses on its SMI bus, and all switch registers
+ * will be directly accessible on some {device address,register address}
+ * pair.  If the ADDR[4:0] pins are not strapped to zero, the switch
+ * will only respond to SMI transactions to that specific address, and
+ * an indirect addressing mechanism needs to be used to access its
+ * registers.
+ */
+static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               ret = mdiobus_read(bus, sw_addr, 0);
+               if (ret < 0)
+                       return ret;
+
+               if ((ret & 0x8000) == 0)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
+{
+       int ret;
+
+       if (sw_addr == 0)
+               return mdiobus_read(bus, addr, reg);
+
+       /*
+        * Wait for the bus to become free.
+        */
+       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Transmit the read command.
+        */
+       ret = mdiobus_write(bus, sw_addr, 0, 0x9800 | (addr << 5) | reg);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Wait for the read command to complete.
+        */
+       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Read the data.
+        */
+       ret = mdiobus_read(bus, sw_addr, 1);
+       if (ret < 0)
+               return ret;
+
+       return ret & 0xffff;
+}
+
+int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int ret;
+
+       mutex_lock(&ps->smi_mutex);
+       ret = __mv88e6xxx_reg_read(ds->master_mii_bus,
+                                  ds->pd->sw_addr, addr, reg);
+       mutex_unlock(&ps->smi_mutex);
+
+       return ret;
+}
+
+int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
+                         int reg, u16 val)
+{
+       int ret;
+
+       if (sw_addr == 0)
+               return mdiobus_write(bus, addr, reg, val);
+
+       /*
+        * Wait for the bus to become free.
+        */
+       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Transmit the data to write.
+        */
+       ret = mdiobus_write(bus, sw_addr, 1, val);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Transmit the write command.
+        */
+       ret = mdiobus_write(bus, sw_addr, 0, 0x9400 | (addr << 5) | reg);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Wait for the write command to complete.
+        */
+       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int ret;
+
+       mutex_lock(&ps->smi_mutex);
+       ret = __mv88e6xxx_reg_write(ds->master_mii_bus,
+                                   ds->pd->sw_addr, addr, reg, val);
+       mutex_unlock(&ps->smi_mutex);
+
+       return ret;
+}
+
+int mv88e6xxx_config_prio(struct dsa_switch *ds)
+{
+       /*
+        * Configure the IP ToS mapping registers.
+        */
+       REG_WRITE(REG_GLOBAL, 0x10, 0x0000);
+       REG_WRITE(REG_GLOBAL, 0x11, 0x0000);
+       REG_WRITE(REG_GLOBAL, 0x12, 0x5555);
+       REG_WRITE(REG_GLOBAL, 0x13, 0x5555);
+       REG_WRITE(REG_GLOBAL, 0x14, 0xaaaa);
+       REG_WRITE(REG_GLOBAL, 0x15, 0xaaaa);
+       REG_WRITE(REG_GLOBAL, 0x16, 0xffff);
+       REG_WRITE(REG_GLOBAL, 0x17, 0xffff);
+
+       /*
+        * Configure the IEEE 802.1p priority mapping register.
+        */
+       REG_WRITE(REG_GLOBAL, 0x18, 0xfa41);
+
+       return 0;
+}
+
+int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
+{
+       REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
+       REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
+       REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
+
+       return 0;
+}
+
+int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < 6; i++) {
+               int j;
+
+               /*
+                * Write the MAC address byte.
+                */
+               REG_WRITE(REG_GLOBAL2, 0x0d, 0x8000 | (i << 8) | addr[i]);
+
+               /*
+                * Wait for the write to complete.
+                */
+               for (j = 0; j < 16; j++) {
+                       ret = REG_READ(REG_GLOBAL2, 0x0d);
+                       if ((ret & 0x8000) == 0)
+                               break;
+               }
+               if (j == 16)
+                       return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
+{
+       if (addr >= 0)
+               return mv88e6xxx_reg_read(ds, addr, regnum);
+       return 0xffff;
+}
+
+int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val)
+{
+       if (addr >= 0)
+               return mv88e6xxx_reg_write(ds, addr, regnum, val);
+       return 0;
+}
+
+#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
+static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
+{
+       int ret;
+       int i;
+
+       ret = REG_READ(REG_GLOBAL, 0x04);
+       REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000);
+
+       for (i = 0; i < 1000; i++) {
+               ret = REG_READ(REG_GLOBAL, 0x00);
+               msleep(1);
+               if ((ret & 0xc000) != 0xc000)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
+{
+       int ret;
+       int i;
+
+       ret = REG_READ(REG_GLOBAL, 0x04);
+       REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000);
+
+       for (i = 0; i < 1000; i++) {
+               ret = REG_READ(REG_GLOBAL, 0x00);
+               msleep(1);
+               if ((ret & 0xc000) == 0xc000)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
+{
+       struct mv88e6xxx_priv_state *ps;
+
+       ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
+       if (mutex_trylock(&ps->ppu_mutex)) {
+               struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
+
+               if (mv88e6xxx_ppu_enable(ds) == 0)
+                       ps->ppu_disabled = 0;
+               mutex_unlock(&ps->ppu_mutex);
+       }
+}
+
+static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)_ps;
+
+       schedule_work(&ps->ppu_work);
+}
+
+static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int ret;
+
+       mutex_lock(&ps->ppu_mutex);
+
+       /*
+        * If the PHY polling unit is enabled, disable it so that
+        * we can access the PHY registers.  If it was already
+        * disabled, cancel the timer that is going to re-enable
+        * it.
+        */
+       if (!ps->ppu_disabled) {
+               ret = mv88e6xxx_ppu_disable(ds);
+               if (ret < 0) {
+                       mutex_unlock(&ps->ppu_mutex);
+                       return ret;
+               }
+               ps->ppu_disabled = 1;
+       } else {
+               del_timer(&ps->ppu_timer);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+
+       /*
+        * Schedule a timer to re-enable the PHY polling unit.
+        */
+       mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
+       mutex_unlock(&ps->ppu_mutex);
+}
+
+void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+
+       mutex_init(&ps->ppu_mutex);
+       INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
+       init_timer(&ps->ppu_timer);
+       ps->ppu_timer.data = (unsigned long)ps;
+       ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
+}
+
+int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
+{
+       int ret;
+
+       ret = mv88e6xxx_ppu_access_get(ds);
+       if (ret >= 0) {
+               ret = mv88e6xxx_reg_read(ds, addr, regnum);
+               mv88e6xxx_ppu_access_put(ds);
+       }
+
+       return ret;
+}
+
+int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
+                           int regnum, u16 val)
+{
+       int ret;
+
+       ret = mv88e6xxx_ppu_access_get(ds);
+       if (ret >= 0) {
+               ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
+               mv88e6xxx_ppu_access_put(ds);
+       }
+
+       return ret;
+}
+#endif
+
+void mv88e6xxx_poll_link(struct dsa_switch *ds)
+{
+       int i;
+
+       for (i = 0; i < DSA_MAX_PORTS; i++) {
+               struct net_device *dev;
+               int uninitialized_var(port_status);
+               int link;
+               int speed;
+               int duplex;
+               int fc;
+
+               dev = ds->ports[i];
+               if (dev == NULL)
+                       continue;
+
+               link = 0;
+               if (dev->flags & IFF_UP) {
+                       port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00);
+                       if (port_status < 0)
+                               continue;
+
+                       link = !!(port_status & 0x0800);
+               }
+
+               if (!link) {
+                       if (netif_carrier_ok(dev)) {
+                               printk(KERN_INFO "%s: link down\n", dev->name);
+                               netif_carrier_off(dev);
+                       }
+                       continue;
+               }
+
+               switch (port_status & 0x0300) {
+               case 0x0000:
+                       speed = 10;
+                       break;
+               case 0x0100:
+                       speed = 100;
+                       break;
+               case 0x0200:
+                       speed = 1000;
+                       break;
+               default:
+                       speed = -1;
+                       break;
+               }
+               duplex = (port_status & 0x0400) ? 1 : 0;
+               fc = (port_status & 0x8000) ? 1 : 0;
+
+               if (!netif_carrier_ok(dev)) {
+                       printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
+                                        "flow control %sabled\n", dev->name,
+                                        speed, duplex ? "full" : "half",
+                                        fc ? "en" : "dis");
+                       netif_carrier_on(dev);
+               }
+       }
+}
+
+static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < 10; i++) {
+               ret = REG_READ(REG_GLOBAL, 0x1d);
+               if ((ret & 0x8000) == 0)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
+{
+       int ret;
+
+       /*
+        * Snapshot the hardware statistics counters for this port.
+        */
+       REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port);
+
+       /*
+        * Wait for the snapshotting to complete.
+        */
+       ret = mv88e6xxx_stats_wait(ds);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
+{
+       u32 _val;
+       int ret;
+
+       *val = 0;
+
+       ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat);
+       if (ret < 0)
+               return;
+
+       ret = mv88e6xxx_stats_wait(ds);
+       if (ret < 0)
+               return;
+
+       ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e);
+       if (ret < 0)
+               return;
+
+       _val = ret << 16;
+
+       ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f);
+       if (ret < 0)
+               return;
+
+       *val = _val | ret;
+}
+
+void mv88e6xxx_get_strings(struct dsa_switch *ds,
+                          int nr_stats, struct mv88e6xxx_hw_stat *stats,
+                          int port, uint8_t *data)
+{
+       int i;
+
+       for (i = 0; i < nr_stats; i++) {
+               memcpy(data + i * ETH_GSTRING_LEN,
+                      stats[i].string, ETH_GSTRING_LEN);
+       }
+}
+
+void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
+                                int nr_stats, struct mv88e6xxx_hw_stat *stats,
+                                int port, uint64_t *data)
+{
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+       int ret;
+       int i;
+
+       mutex_lock(&ps->stats_mutex);
+
+       ret = mv88e6xxx_stats_snapshot(ds, port);
+       if (ret < 0) {
+               mutex_unlock(&ps->stats_mutex);
+               return;
+       }
+
+       /*
+        * Read each of the counters.
+        */
+       for (i = 0; i < nr_stats; i++) {
+               struct mv88e6xxx_hw_stat *s = stats + i;
+               u32 low;
+               u32 high;
+
+               mv88e6xxx_stats_read(ds, s->reg, &low);
+               if (s->sizeof_stat == 8)
+                       mv88e6xxx_stats_read(ds, s->reg + 1, &high);
+               else
+                       high = 0;
+
+               data[i] = (((u64)high) << 32) | low;
+       }
+
+       mutex_unlock(&ps->stats_mutex);
+}
+
+static int __init mv88e6xxx_init(void)
+{
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
+       register_switch_driver(&mv88e6131_switch_driver);
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
+       register_switch_driver(&mv88e6123_61_65_switch_driver);
+#endif
+       return 0;
+}
+module_init(mv88e6xxx_init);
+
+static void __exit mv88e6xxx_cleanup(void)
+{
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
+       unregister_switch_driver(&mv88e6123_61_65_switch_driver);
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
+       unregister_switch_driver(&mv88e6131_switch_driver);
+#endif
+}
+module_exit(mv88e6xxx_cleanup);
+
+MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
+MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
new file mode 100644 (file)
index 0000000..fc2cd7b
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * net/dsa/mv88e6xxx.h - Marvell 88e6xxx switch chip support
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MV88E6XXX_H
+#define __MV88E6XXX_H
+
+#define REG_PORT(p)            (0x10 + (p))
+#define REG_GLOBAL             0x1b
+#define REG_GLOBAL2            0x1c
+
+struct mv88e6xxx_priv_state {
+       /*
+        * When using multi-chip addressing, this mutex protects
+        * access to the indirect access registers.  (In single-chip
+        * mode, this mutex is effectively useless.)
+        */
+       struct mutex    smi_mutex;
+
+#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
+       /*
+        * Handles automatic disabling and re-enabling of the PHY
+        * polling unit.
+        */
+       struct mutex            ppu_mutex;
+       int                     ppu_disabled;
+       struct work_struct      ppu_work;
+       struct timer_list       ppu_timer;
+#endif
+
+       /*
+        * This mutex serialises access to the statistics unit.
+        * Hold this mutex over snapshot + dump sequences.
+        */
+       struct mutex    stats_mutex;
+
+       int             id; /* switch product id */
+};
+
+struct mv88e6xxx_hw_stat {
+       char string[ETH_GSTRING_LEN];
+       int sizeof_stat;
+       int reg;
+};
+
+int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
+int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
+int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
+                          int reg, u16 val);
+int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
+int mv88e6xxx_config_prio(struct dsa_switch *ds);
+int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
+int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
+int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum);
+int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val);
+void mv88e6xxx_ppu_state_init(struct dsa_switch *ds);
+int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
+int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
+                           int regnum, u16 val);
+void mv88e6xxx_poll_link(struct dsa_switch *ds);
+void mv88e6xxx_get_strings(struct dsa_switch *ds,
+                          int nr_stats, struct mv88e6xxx_hw_stat *stats,
+                          int port, uint8_t *data);
+void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
+                                int nr_stats, struct mv88e6xxx_hw_stat *stats,
+                                int port, uint64_t *data);
+
+extern struct dsa_switch_driver mv88e6131_switch_driver;
+extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
+
+#define REG_READ(addr, reg)                                            \
+       ({                                                              \
+               int __ret;                                              \
+                                                                       \
+               __ret = mv88e6xxx_reg_read(ds, addr, reg);              \
+               if (__ret < 0)                                          \
+                       return __ret;                                   \
+               __ret;                                                  \
+       })
+
+#define REG_WRITE(addr, reg, val)                                      \
+       ({                                                              \
+               int __ret;                                              \
+                                                                       \
+               __ret = mv88e6xxx_reg_write(ds, addr, reg, val);        \
+               if (__ret < 0)                                          \
+                       return __ret;                                   \
+       })
+
+
+
+#endif
index 7e12303827e8e9e163548c912c3ead3d9afb9cf9..274791cd7a35df1274e9120d199af84ea9f60dd0 100644 (file)
@@ -1,4 +1,4 @@
-menuconfig NET_DSA
+config NET_DSA
        tristate "Distributed Switch Architecture support"
        default n
        depends on EXPERIMENTAL && NETDEVICES && !S390
@@ -23,38 +23,4 @@ config NET_DSA_TAG_TRAILER
        bool
        default n
 
-
-# switch drivers
-config NET_DSA_MV88E6XXX
-       tristate
-       default n
-
-config NET_DSA_MV88E6060
-       tristate "Marvell 88E6060 ethernet switch chip support"
-       select NET_DSA_TAG_TRAILER
-       ---help---
-         This enables support for the Marvell 88E6060 ethernet switch
-         chip.
-
-config NET_DSA_MV88E6XXX_NEED_PPU
-       bool
-       default n
-
-config NET_DSA_MV88E6131
-       tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
-       select NET_DSA_MV88E6XXX
-       select NET_DSA_MV88E6XXX_NEED_PPU
-       select NET_DSA_TAG_DSA
-       ---help---
-         This enables support for the Marvell 88E6085/6095/6095F/6131
-         ethernet switch chips.
-
-config NET_DSA_MV88E6123_61_65
-       tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
-       select NET_DSA_MV88E6XXX
-       select NET_DSA_TAG_EDSA
-       ---help---
-         This enables support for the Marvell 88E6123/6161/6165
-         ethernet switch chips.
-
 endif
index 191dd482e557172b018a37468a18bf67a608b0ee..7b9fcbbeda5d0d80678ba909f76b0b30d8436a2d 100644 (file)
@@ -6,14 +6,3 @@ dsa_core-y += dsa.o slave.o
 dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
-
-# switch drivers
-obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
-obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
-mv88e6xxx_drv-y += mv88e6xxx.o
-ifdef CONFIG_NET_DSA_MV88E6123_61_65
-mv88e6xxx_drv-y += mv88e6123_61_65.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6131
-mv88e6xxx_drv-y += mv88e6131.o
-endif
diff --git a/net/dsa/mv88e6060.c b/net/dsa/mv88e6060.c
deleted file mode 100644 (file)
index 7fc4e81..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * net/dsa/mv88e6060.c - Driver for Marvell 88e6060 switch chips
- * Copyright (c) 2008-2009 Marvell Semiconductor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <net/dsa.h>
-
-#define REG_PORT(p)            (8 + (p))
-#define REG_GLOBAL             0x0f
-
-static int reg_read(struct dsa_switch *ds, int addr, int reg)
-{
-       return mdiobus_read(ds->master_mii_bus, ds->pd->sw_addr + addr, reg);
-}
-
-#define REG_READ(addr, reg)                                    \
-       ({                                                      \
-               int __ret;                                      \
-                                                               \
-               __ret = reg_read(ds, addr, reg);                \
-               if (__ret < 0)                                  \
-                       return __ret;                           \
-               __ret;                                          \
-       })
-
-
-static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
-{
-       return mdiobus_write(ds->master_mii_bus, ds->pd->sw_addr + addr,
-                            reg, val);
-}
-
-#define REG_WRITE(addr, reg, val)                              \
-       ({                                                      \
-               int __ret;                                      \
-                                                               \
-               __ret = reg_write(ds, addr, reg, val);          \
-               if (__ret < 0)                                  \
-                       return __ret;                           \
-       })
-
-static char *mv88e6060_probe(struct mii_bus *bus, int sw_addr)
-{
-       int ret;
-
-       ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03);
-       if (ret >= 0) {
-               ret &= 0xfff0;
-               if (ret == 0x0600)
-                       return "Marvell 88E6060";
-       }
-
-       return NULL;
-}
-
-static int mv88e6060_switch_reset(struct dsa_switch *ds)
-{
-       int i;
-       int ret;
-
-       /*
-        * Set all ports to the disabled state.
-        */
-       for (i = 0; i < 6; i++) {
-               ret = REG_READ(REG_PORT(i), 0x04);
-               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
-       }
-
-       /*
-        * Wait for transmit queues to drain.
-        */
-       msleep(2);
-
-       /*
-        * Reset the switch.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0xa130);
-
-       /*
-        * Wait up to one second for reset to complete.
-        */
-       for (i = 0; i < 1000; i++) {
-               ret = REG_READ(REG_GLOBAL, 0x00);
-               if ((ret & 0x8000) == 0x0000)
-                       break;
-
-               msleep(1);
-       }
-       if (i == 1000)
-               return -ETIMEDOUT;
-
-       return 0;
-}
-
-static int mv88e6060_setup_global(struct dsa_switch *ds)
-{
-       /*
-        * Disable discarding of frames with excessive collisions,
-        * set the maximum frame size to 1536 bytes, and mask all
-        * interrupt sources.
-        */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x0800);
-
-       /*
-        * Enable automatic address learning, set the address
-        * database size to 1024 entries, and set the default aging
-        * time to 5 minutes.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x2130);
-
-       return 0;
-}
-
-static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
-{
-       int addr = REG_PORT(p);
-
-       /*
-        * Do not force flow control, disable Ingress and Egress
-        * Header tagging, disable VLAN tunneling, and set the port
-        * state to Forwarding.  Additionally, if this is the CPU
-        * port, enable Ingress and Egress Trailer tagging mode.
-        */
-       REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ?  0x4103 : 0x0003);
-
-       /*
-        * Port based VLAN map: give each port its own address
-        * database, allow the CPU port to talk to each of the 'real'
-        * ports, and allow each of the 'real' ports to only talk to
-        * the CPU port.
-        */
-       REG_WRITE(addr, 0x06,
-                       ((p & 0xf) << 12) |
-                        (dsa_is_cpu_port(ds, p) ?
-                               ds->phys_port_mask :
-                               (1 << ds->dst->cpu_port)));
-
-       /*
-        * Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       return 0;
-}
-
-static int mv88e6060_setup(struct dsa_switch *ds)
-{
-       int i;
-       int ret;
-
-       ret = mv88e6060_switch_reset(ds);
-       if (ret < 0)
-               return ret;
-
-       /* @@@ initialise atu */
-
-       ret = mv88e6060_setup_global(ds);
-       if (ret < 0)
-               return ret;
-
-       for (i = 0; i < 6; i++) {
-               ret = mv88e6060_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr)
-{
-       REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
-       REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
-       REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
-
-       return 0;
-}
-
-static int mv88e6060_port_to_phy_addr(int port)
-{
-       if (port >= 0 && port <= 5)
-               return port;
-       return -1;
-}
-
-static int mv88e6060_phy_read(struct dsa_switch *ds, int port, int regnum)
-{
-       int addr;
-
-       addr = mv88e6060_port_to_phy_addr(port);
-       if (addr == -1)
-               return 0xffff;
-
-       return reg_read(ds, addr, regnum);
-}
-
-static int
-mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
-{
-       int addr;
-
-       addr = mv88e6060_port_to_phy_addr(port);
-       if (addr == -1)
-               return 0xffff;
-
-       return reg_write(ds, addr, regnum, val);
-}
-
-static void mv88e6060_poll_link(struct dsa_switch *ds)
-{
-       int i;
-
-       for (i = 0; i < DSA_MAX_PORTS; i++) {
-               struct net_device *dev;
-               int uninitialized_var(port_status);
-               int link;
-               int speed;
-               int duplex;
-               int fc;
-
-               dev = ds->ports[i];
-               if (dev == NULL)
-                       continue;
-
-               link = 0;
-               if (dev->flags & IFF_UP) {
-                       port_status = reg_read(ds, REG_PORT(i), 0x00);
-                       if (port_status < 0)
-                               continue;
-
-                       link = !!(port_status & 0x1000);
-               }
-
-               if (!link) {
-                       if (netif_carrier_ok(dev)) {
-                               printk(KERN_INFO "%s: link down\n", dev->name);
-                               netif_carrier_off(dev);
-                       }
-                       continue;
-               }
-
-               speed = (port_status & 0x0100) ? 100 : 10;
-               duplex = (port_status & 0x0200) ? 1 : 0;
-               fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0;
-
-               if (!netif_carrier_ok(dev)) {
-                       printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
-                                        "flow control %sabled\n", dev->name,
-                                        speed, duplex ? "full" : "half",
-                                        fc ? "en" : "dis");
-                       netif_carrier_on(dev);
-               }
-       }
-}
-
-static struct dsa_switch_driver mv88e6060_switch_driver = {
-       .tag_protocol   = htons(ETH_P_TRAILER),
-       .probe          = mv88e6060_probe,
-       .setup          = mv88e6060_setup,
-       .set_addr       = mv88e6060_set_addr,
-       .phy_read       = mv88e6060_phy_read,
-       .phy_write      = mv88e6060_phy_write,
-       .poll_link      = mv88e6060_poll_link,
-};
-
-static int __init mv88e6060_init(void)
-{
-       register_switch_driver(&mv88e6060_switch_driver);
-       return 0;
-}
-module_init(mv88e6060_init);
-
-static void __exit mv88e6060_cleanup(void)
-{
-       unregister_switch_driver(&mv88e6060_switch_driver);
-}
-module_exit(mv88e6060_cleanup);
-
-MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
-MODULE_DESCRIPTION("Driver for Marvell 88E6060 ethernet switch chip");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mv88e6060");
diff --git a/net/dsa/mv88e6123_61_65.c b/net/dsa/mv88e6123_61_65.c
deleted file mode 100644 (file)
index c0a458f..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
- * Copyright (c) 2008-2009 Marvell Semiconductor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <net/dsa.h>
-#include "mv88e6xxx.h"
-
-static char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr)
-{
-       int ret;
-
-       ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
-       if (ret >= 0) {
-               ret &= 0xfff0;
-               if (ret == 0x1210)
-                       return "Marvell 88E6123";
-               if (ret == 0x1610)
-                       return "Marvell 88E6161";
-               if (ret == 0x1650)
-                       return "Marvell 88E6165";
-       }
-
-       return NULL;
-}
-
-static int mv88e6123_61_65_switch_reset(struct dsa_switch *ds)
-{
-       int i;
-       int ret;
-
-       /*
-        * Set all ports to the disabled state.
-        */
-       for (i = 0; i < 8; i++) {
-               ret = REG_READ(REG_PORT(i), 0x04);
-               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
-       }
-
-       /*
-        * Wait for transmit queues to drain.
-        */
-       msleep(2);
-
-       /*
-        * Reset the switch.
-        */
-       REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
-
-       /*
-        * Wait up to one second for reset to complete.
-        */
-       for (i = 0; i < 1000; i++) {
-               ret = REG_READ(REG_GLOBAL, 0x00);
-               if ((ret & 0xc800) == 0xc800)
-                       break;
-
-               msleep(1);
-       }
-       if (i == 1000)
-               return -ETIMEDOUT;
-
-       return 0;
-}
-
-static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
-{
-       int ret;
-       int i;
-
-       /*
-        * Disable the PHY polling unit (since there won't be any
-        * external PHYs to poll), don't discard packets with
-        * excessive collisions, and mask all interrupt sources.
-        */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
-
-       /*
-        * Set the default address aging time to 5 minutes, and
-        * enable address learn messages to be sent to all message
-        * ports.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
-
-       /*
-        * Configure the priority mapping registers.
-        */
-       ret = mv88e6xxx_config_prio(ds);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Configure the upstream port, and configure the upstream
-        * port as the port to which ingress and egress monitor frames
-        * are to be sent.
-        */
-       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
-
-       /*
-        * Disable remote management for now, and set the switch's
-        * DSA device number.
-        */
-       REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
-
-       /*
-        * Send all frames with destination addresses matching
-        * 01:80:c2:00:00:2x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
-
-       /*
-        * Send all frames with destination addresses matching
-        * 01:80:c2:00:00:0x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
-
-       /*
-        * Disable the loopback filter, disable flow control
-        * messages, disable flood broadcast override, disable
-        * removing of provider tags, disable ATU age violation
-        * interrupts, disable tag flow control, force flow
-        * control priority to the highest, and send all special
-        * multicast frames to the CPU at the highest priority.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
-
-       /*
-        * Program the DSA routing table.
-        */
-       for (i = 0; i < 32; i++) {
-               int nexthop;
-
-               nexthop = 0x1f;
-               if (i != ds->index && i < ds->dst->pd->nr_chips)
-                       nexthop = ds->pd->rtable[i] & 0x1f;
-
-               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
-       }
-
-       /*
-        * Clear all trunk masks.
-        */
-       for (i = 0; i < 8; i++)
-               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
-
-       /*
-        * Clear all trunk mappings.
-        */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
-
-       /*
-        * Disable ingress rate limiting by resetting all ingress
-        * rate limit registers to their initial state.
-        */
-       for (i = 0; i < 6; i++)
-               REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
-
-       /*
-        * Initialise cross-chip port VLAN table to reset defaults.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
-
-       /*
-        * Clear the priority override table.
-        */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
-
-       /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
-
-       return 0;
-}
-
-static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
-{
-       int addr = REG_PORT(p);
-       u16 val;
-
-       /*
-        * MAC Forcing register: don't force link, speed, duplex
-        * or flow control state to any particular values on physical
-        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * full duplex.
-        */
-       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               REG_WRITE(addr, 0x01, 0x003e);
-       else
-               REG_WRITE(addr, 0x01, 0x0003);
-
-       /*
-        * Do not limit the period of time that this port can be
-        * paused for by the remote end or the period of time that
-        * this port can pause the remote end.
-        */
-       REG_WRITE(addr, 0x02, 0x0000);
-
-       /*
-        * Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
-        * disable Header mode, enable IGMP/MLD snooping, disable VLAN
-        * tunneling, determine priority by looking at 802.1p and IP
-        * priority fields (IP prio has precedence), and set STP state
-        * to Forwarding.
-        *
-        * If this is the CPU link, use DSA or EDSA tagging depending
-        * on which tagging mode was configured.
-        *
-        * If this is a link to another switch, use DSA tagging mode.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown unicasts and multicasts.
-        */
-       val = 0x0433;
-       if (dsa_is_cpu_port(ds, p)) {
-               if (ds->dst->tag_protocol == htons(ETH_P_EDSA))
-                       val |= 0x3300;
-               else
-                       val |= 0x0100;
-       }
-       if (ds->dsa_port_mask & (1 << p))
-               val |= 0x0100;
-       if (p == dsa_upstream_port(ds))
-               val |= 0x000c;
-       REG_WRITE(addr, 0x04, val);
-
-       /*
-        * Port Control 1: disable trunking.  Also, if this is the
-        * CPU port, enable learn messages to be sent to this port.
-        */
-       REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
-
-       /*
-        * Port based VLAN map: give each port its own address
-        * database, allow the CPU port to talk to each of the 'real'
-        * ports, and allow each of the 'real' ports to only talk to
-        * the upstream port.
-        */
-       val = (p & 0xf) << 12;
-       if (dsa_is_cpu_port(ds, p))
-               val |= ds->phys_port_mask;
-       else
-               val |= 1 << dsa_upstream_port(ds);
-       REG_WRITE(addr, 0x06, val);
-
-       /*
-        * Default VLAN ID and priority: don't set a default VLAN
-        * ID, and set the default packet priority to zero.
-        */
-       REG_WRITE(addr, 0x07, 0x0000);
-
-       /*
-        * Port Control 2: don't force a good FCS, set the maximum
-        * frame size to 10240 bytes, don't let the switch add or
-        * strip 802.1q tags, don't discard tagged or untagged frames
-        * on this port, do a destination address lookup on all
-        * received packets as usual, disable ARP mirroring and don't
-        * send a copy of all transmitted/received frames on this port
-        * to the CPU.
-        */
-       REG_WRITE(addr, 0x08, 0x2080);
-
-       /*
-        * Egress rate control: disable egress rate control.
-        */
-       REG_WRITE(addr, 0x09, 0x0001);
-
-       /*
-        * Egress rate control 2: disable egress rate control.
-        */
-       REG_WRITE(addr, 0x0a, 0x0000);
-
-       /*
-        * Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       /*
-        * Port ATU control: disable limiting the number of address
-        * database entries that this port is allowed to use.
-        */
-       REG_WRITE(addr, 0x0c, 0x0000);
-
-       /*
-        * Priorit Override: disable DA, SA and VTU priority override.
-        */
-       REG_WRITE(addr, 0x0d, 0x0000);
-
-       /*
-        * Port Ethertype: use the Ethertype DSA Ethertype value.
-        */
-       REG_WRITE(addr, 0x0f, ETH_P_EDSA);
-
-       /*
-        * Tag Remap: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x18, 0x3210);
-
-       /*
-        * Tag Remap 2: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x19, 0x7654);
-
-       return 0;
-}
-
-static int mv88e6123_61_65_setup(struct dsa_switch *ds)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int i;
-       int ret;
-
-       mutex_init(&ps->smi_mutex);
-       mutex_init(&ps->stats_mutex);
-
-       ret = mv88e6123_61_65_switch_reset(ds);
-       if (ret < 0)
-               return ret;
-
-       /* @@@ initialise vtu and atu */
-
-       ret = mv88e6123_61_65_setup_global(ds);
-       if (ret < 0)
-               return ret;
-
-       for (i = 0; i < 6; i++) {
-               ret = mv88e6123_61_65_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int mv88e6123_61_65_port_to_phy_addr(int port)
-{
-       if (port >= 0 && port <= 4)
-               return port;
-       return -1;
-}
-
-static int
-mv88e6123_61_65_phy_read(struct dsa_switch *ds, int port, int regnum)
-{
-       int addr = mv88e6123_61_65_port_to_phy_addr(port);
-       return mv88e6xxx_phy_read(ds, addr, regnum);
-}
-
-static int
-mv88e6123_61_65_phy_write(struct dsa_switch *ds,
-                             int port, int regnum, u16 val)
-{
-       int addr = mv88e6123_61_65_port_to_phy_addr(port);
-       return mv88e6xxx_phy_write(ds, addr, regnum, val);
-}
-
-static struct mv88e6xxx_hw_stat mv88e6123_61_65_hw_stats[] = {
-       { "in_good_octets", 8, 0x00, },
-       { "in_bad_octets", 4, 0x02, },
-       { "in_unicast", 4, 0x04, },
-       { "in_broadcasts", 4, 0x06, },
-       { "in_multicasts", 4, 0x07, },
-       { "in_pause", 4, 0x16, },
-       { "in_undersize", 4, 0x18, },
-       { "in_fragments", 4, 0x19, },
-       { "in_oversize", 4, 0x1a, },
-       { "in_jabber", 4, 0x1b, },
-       { "in_rx_error", 4, 0x1c, },
-       { "in_fcs_error", 4, 0x1d, },
-       { "out_octets", 8, 0x0e, },
-       { "out_unicast", 4, 0x10, },
-       { "out_broadcasts", 4, 0x13, },
-       { "out_multicasts", 4, 0x12, },
-       { "out_pause", 4, 0x15, },
-       { "excessive", 4, 0x11, },
-       { "collisions", 4, 0x1e, },
-       { "deferred", 4, 0x05, },
-       { "single", 4, 0x14, },
-       { "multiple", 4, 0x17, },
-       { "out_fcs_error", 4, 0x03, },
-       { "late", 4, 0x1f, },
-       { "hist_64bytes", 4, 0x08, },
-       { "hist_65_127bytes", 4, 0x09, },
-       { "hist_128_255bytes", 4, 0x0a, },
-       { "hist_256_511bytes", 4, 0x0b, },
-       { "hist_512_1023bytes", 4, 0x0c, },
-       { "hist_1024_max_bytes", 4, 0x0d, },
-};
-
-static void
-mv88e6123_61_65_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
-{
-       mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats),
-                             mv88e6123_61_65_hw_stats, port, data);
-}
-
-static void
-mv88e6123_61_65_get_ethtool_stats(struct dsa_switch *ds,
-                                 int port, uint64_t *data)
-{
-       mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats),
-                                   mv88e6123_61_65_hw_stats, port, data);
-}
-
-static int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds)
-{
-       return ARRAY_SIZE(mv88e6123_61_65_hw_stats);
-}
-
-struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
-       .tag_protocol           = cpu_to_be16(ETH_P_EDSA),
-       .priv_size              = sizeof(struct mv88e6xxx_priv_state),
-       .probe                  = mv88e6123_61_65_probe,
-       .setup                  = mv88e6123_61_65_setup,
-       .set_addr               = mv88e6xxx_set_addr_indirect,
-       .phy_read               = mv88e6123_61_65_phy_read,
-       .phy_write              = mv88e6123_61_65_phy_write,
-       .poll_link              = mv88e6xxx_poll_link,
-       .get_strings            = mv88e6123_61_65_get_strings,
-       .get_ethtool_stats      = mv88e6123_61_65_get_ethtool_stats,
-       .get_sset_count         = mv88e6123_61_65_get_sset_count,
-};
-
-MODULE_ALIAS("platform:mv88e6123");
-MODULE_ALIAS("platform:mv88e6161");
-MODULE_ALIAS("platform:mv88e6165");
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c
deleted file mode 100644 (file)
index e0eb682..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support
- * Copyright (c) 2008-2009 Marvell Semiconductor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <net/dsa.h>
-#include "mv88e6xxx.h"
-
-/*
- * Switch product IDs
- */
-#define ID_6085                0x04a0
-#define ID_6095                0x0950
-#define ID_6131                0x1060
-
-static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr)
-{
-       int ret;
-
-       ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
-       if (ret >= 0) {
-               ret &= 0xfff0;
-               if (ret == ID_6085)
-                       return "Marvell 88E6085";
-               if (ret == ID_6095)
-                       return "Marvell 88E6095/88E6095F";
-               if (ret == ID_6131)
-                       return "Marvell 88E6131";
-       }
-
-       return NULL;
-}
-
-static int mv88e6131_switch_reset(struct dsa_switch *ds)
-{
-       int i;
-       int ret;
-
-       /*
-        * Set all ports to the disabled state.
-        */
-       for (i = 0; i < 11; i++) {
-               ret = REG_READ(REG_PORT(i), 0x04);
-               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
-       }
-
-       /*
-        * Wait for transmit queues to drain.
-        */
-       msleep(2);
-
-       /*
-        * Reset the switch.
-        */
-       REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
-
-       /*
-        * Wait up to one second for reset to complete.
-        */
-       for (i = 0; i < 1000; i++) {
-               ret = REG_READ(REG_GLOBAL, 0x00);
-               if ((ret & 0xc800) == 0xc800)
-                       break;
-
-               msleep(1);
-       }
-       if (i == 1000)
-               return -ETIMEDOUT;
-
-       return 0;
-}
-
-static int mv88e6131_setup_global(struct dsa_switch *ds)
-{
-       int ret;
-       int i;
-
-       /*
-        * Enable the PHY polling unit, don't discard packets with
-        * excessive collisions, use a weighted fair queueing scheme
-        * to arbitrate between packet queues, set the maximum frame
-        * size to 1632, and mask all interrupt sources.
-        */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x4400);
-
-       /*
-        * Set the default address aging time to 5 minutes, and
-        * enable address learn messages to be sent to all message
-        * ports.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
-
-       /*
-        * Configure the priority mapping registers.
-        */
-       ret = mv88e6xxx_config_prio(ds);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Set the VLAN ethertype to 0x8100.
-        */
-       REG_WRITE(REG_GLOBAL, 0x19, 0x8100);
-
-       /*
-        * Disable ARP mirroring, and configure the upstream port as
-        * the port to which ingress and egress monitor frames are to
-        * be sent.
-        */
-       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
-
-       /*
-        * Disable cascade port functionality unless this device
-        * is used in a cascade configuration, and set the switch's
-        * DSA device number.
-        */
-       if (ds->dst->pd->nr_chips > 1)
-               REG_WRITE(REG_GLOBAL, 0x1c, 0xf000 | (ds->index & 0x1f));
-       else
-               REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
-
-       /*
-        * Send all frames with destination addresses matching
-        * 01:80:c2:00:00:0x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
-
-       /*
-        * Ignore removed tag data on doubly tagged packets, disable
-        * flow control messages, force flow control priority to the
-        * highest, and send all special multicast frames to the CPU
-        * port at the highest priority.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
-
-       /*
-        * Program the DSA routing table.
-        */
-       for (i = 0; i < 32; i++) {
-               int nexthop;
-
-               nexthop = 0x1f;
-               if (i != ds->index && i < ds->dst->pd->nr_chips)
-                       nexthop = ds->pd->rtable[i] & 0x1f;
-
-               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
-       }
-
-       /*
-        * Clear all trunk masks.
-        */
-       for (i = 0; i < 8; i++)
-               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff);
-
-       /*
-        * Clear all trunk mappings.
-        */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
-
-       /*
-        * Force the priority of IGMP/MLD snoop frames and ARP frames
-        * to the highest setting.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x0f, 0x00ff);
-
-       return 0;
-}
-
-static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int addr = REG_PORT(p);
-       u16 val;
-
-       /*
-        * MAC Forcing register: don't force link, speed, duplex
-        * or flow control state to any particular values on physical
-        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * (100 Mb/s on 6085) full duplex.
-        */
-       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               if (ps->id == ID_6085)
-                       REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */
-               else
-                       REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */
-       else
-               REG_WRITE(addr, 0x01, 0x0003);
-
-       /*
-        * Port Control: disable Core Tag, disable Drop-on-Lock,
-        * transmit frames unmodified, disable Header mode,
-        * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN
-        * tunneling, determine priority by looking at 802.1p and
-        * IP priority fields (IP prio has precedence), and set STP
-        * state to Forwarding.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown unicasts, and enable DSA tagging
-        * mode.
-        *
-        * If this is the link to another switch, use DSA tagging
-        * mode, but do not enable forwarding of unknown unicasts.
-        */
-       val = 0x0433;
-       if (p == dsa_upstream_port(ds)) {
-               val |= 0x0104;
-               /*
-                * On 6085, unknown multicast forward is controlled
-                * here rather than in Port Control 2 register.
-                */
-               if (ps->id == ID_6085)
-                       val |= 0x0008;
-       }
-       if (ds->dsa_port_mask & (1 << p))
-               val |= 0x0100;
-       REG_WRITE(addr, 0x04, val);
-
-       /*
-        * Port Control 1: disable trunking.  Also, if this is the
-        * CPU port, enable learn messages to be sent to this port.
-        */
-       REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
-
-       /*
-        * Port based VLAN map: give each port its own address
-        * database, allow the CPU port to talk to each of the 'real'
-        * ports, and allow each of the 'real' ports to only talk to
-        * the upstream port.
-        */
-       val = (p & 0xf) << 12;
-       if (dsa_is_cpu_port(ds, p))
-               val |= ds->phys_port_mask;
-       else
-               val |= 1 << dsa_upstream_port(ds);
-       REG_WRITE(addr, 0x06, val);
-
-       /*
-        * Default VLAN ID and priority: don't set a default VLAN
-        * ID, and set the default packet priority to zero.
-        */
-       REG_WRITE(addr, 0x07, 0x0000);
-
-       /*
-        * Port Control 2: don't force a good FCS, don't use
-        * VLAN-based, source address-based or destination
-        * address-based priority overrides, don't let the switch
-        * add or strip 802.1q tags, don't discard tagged or
-        * untagged frames on this port, do a destination address
-        * lookup on received packets as usual, don't send a copy
-        * of all transmitted/received frames on this port to the
-        * CPU, and configure the upstream port number.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown multicast addresses.
-        */
-       if (ps->id == ID_6085)
-               /*
-                * on 6085, bits 3:0 are reserved, bit 6 control ARP
-                * mirroring, and multicast forward is handled in
-                * Port Control register.
-                */
-               REG_WRITE(addr, 0x08, 0x0080);
-       else {
-               val = 0x0080 | dsa_upstream_port(ds);
-               if (p == dsa_upstream_port(ds))
-                       val |= 0x0040;
-               REG_WRITE(addr, 0x08, val);
-       }
-
-       /*
-        * Rate Control: disable ingress rate limiting.
-        */
-       REG_WRITE(addr, 0x09, 0x0000);
-
-       /*
-        * Rate Control 2: disable egress rate limiting.
-        */
-       REG_WRITE(addr, 0x0a, 0x0000);
-
-       /*
-        * Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       /*
-        * Tag Remap: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x18, 0x3210);
-
-       /*
-        * Tag Remap 2: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x19, 0x7654);
-
-       return 0;
-}
-
-static int mv88e6131_setup(struct dsa_switch *ds)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int i;
-       int ret;
-
-       mutex_init(&ps->smi_mutex);
-       mv88e6xxx_ppu_state_init(ds);
-       mutex_init(&ps->stats_mutex);
-
-       ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
-
-       ret = mv88e6131_switch_reset(ds);
-       if (ret < 0)
-               return ret;
-
-       /* @@@ initialise vtu and atu */
-
-       ret = mv88e6131_setup_global(ds);
-       if (ret < 0)
-               return ret;
-
-       for (i = 0; i < 11; i++) {
-               ret = mv88e6131_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int mv88e6131_port_to_phy_addr(int port)
-{
-       if (port >= 0 && port <= 11)
-               return port;
-       return -1;
-}
-
-static int
-mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum)
-{
-       int addr = mv88e6131_port_to_phy_addr(port);
-       return mv88e6xxx_phy_read_ppu(ds, addr, regnum);
-}
-
-static int
-mv88e6131_phy_write(struct dsa_switch *ds,
-                             int port, int regnum, u16 val)
-{
-       int addr = mv88e6131_port_to_phy_addr(port);
-       return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val);
-}
-
-static struct mv88e6xxx_hw_stat mv88e6131_hw_stats[] = {
-       { "in_good_octets", 8, 0x00, },
-       { "in_bad_octets", 4, 0x02, },
-       { "in_unicast", 4, 0x04, },
-       { "in_broadcasts", 4, 0x06, },
-       { "in_multicasts", 4, 0x07, },
-       { "in_pause", 4, 0x16, },
-       { "in_undersize", 4, 0x18, },
-       { "in_fragments", 4, 0x19, },
-       { "in_oversize", 4, 0x1a, },
-       { "in_jabber", 4, 0x1b, },
-       { "in_rx_error", 4, 0x1c, },
-       { "in_fcs_error", 4, 0x1d, },
-       { "out_octets", 8, 0x0e, },
-       { "out_unicast", 4, 0x10, },
-       { "out_broadcasts", 4, 0x13, },
-       { "out_multicasts", 4, 0x12, },
-       { "out_pause", 4, 0x15, },
-       { "excessive", 4, 0x11, },
-       { "collisions", 4, 0x1e, },
-       { "deferred", 4, 0x05, },
-       { "single", 4, 0x14, },
-       { "multiple", 4, 0x17, },
-       { "out_fcs_error", 4, 0x03, },
-       { "late", 4, 0x1f, },
-       { "hist_64bytes", 4, 0x08, },
-       { "hist_65_127bytes", 4, 0x09, },
-       { "hist_128_255bytes", 4, 0x0a, },
-       { "hist_256_511bytes", 4, 0x0b, },
-       { "hist_512_1023bytes", 4, 0x0c, },
-       { "hist_1024_max_bytes", 4, 0x0d, },
-};
-
-static void
-mv88e6131_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
-{
-       mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6131_hw_stats),
-                             mv88e6131_hw_stats, port, data);
-}
-
-static void
-mv88e6131_get_ethtool_stats(struct dsa_switch *ds,
-                                 int port, uint64_t *data)
-{
-       mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6131_hw_stats),
-                                   mv88e6131_hw_stats, port, data);
-}
-
-static int mv88e6131_get_sset_count(struct dsa_switch *ds)
-{
-       return ARRAY_SIZE(mv88e6131_hw_stats);
-}
-
-struct dsa_switch_driver mv88e6131_switch_driver = {
-       .tag_protocol           = cpu_to_be16(ETH_P_DSA),
-       .priv_size              = sizeof(struct mv88e6xxx_priv_state),
-       .probe                  = mv88e6131_probe,
-       .setup                  = mv88e6131_setup,
-       .set_addr               = mv88e6xxx_set_addr_direct,
-       .phy_read               = mv88e6131_phy_read,
-       .phy_write              = mv88e6131_phy_write,
-       .poll_link              = mv88e6xxx_poll_link,
-       .get_strings            = mv88e6131_get_strings,
-       .get_ethtool_stats      = mv88e6131_get_ethtool_stats,
-       .get_sset_count         = mv88e6131_get_sset_count,
-};
-
-MODULE_ALIAS("platform:mv88e6085");
-MODULE_ALIAS("platform:mv88e6095");
-MODULE_ALIAS("platform:mv88e6095f");
-MODULE_ALIAS("platform:mv88e6131");
diff --git a/net/dsa/mv88e6xxx.c b/net/dsa/mv88e6xxx.c
deleted file mode 100644 (file)
index 5467c04..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support
- * Copyright (c) 2008 Marvell Semiconductor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <net/dsa.h>
-#include "mv88e6xxx.h"
-
-/*
- * If the switch's ADDR[4:0] strap pins are strapped to zero, it will
- * use all 32 SMI bus addresses on its SMI bus, and all switch registers
- * will be directly accessible on some {device address,register address}
- * pair.  If the ADDR[4:0] pins are not strapped to zero, the switch
- * will only respond to SMI transactions to that specific address, and
- * an indirect addressing mechanism needs to be used to access its
- * registers.
- */
-static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
-{
-       int ret;
-       int i;
-
-       for (i = 0; i < 16; i++) {
-               ret = mdiobus_read(bus, sw_addr, 0);
-               if (ret < 0)
-                       return ret;
-
-               if ((ret & 0x8000) == 0)
-                       return 0;
-       }
-
-       return -ETIMEDOUT;
-}
-
-int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
-{
-       int ret;
-
-       if (sw_addr == 0)
-               return mdiobus_read(bus, addr, reg);
-
-       /*
-        * Wait for the bus to become free.
-        */
-       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Transmit the read command.
-        */
-       ret = mdiobus_write(bus, sw_addr, 0, 0x9800 | (addr << 5) | reg);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Wait for the read command to complete.
-        */
-       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Read the data.
-        */
-       ret = mdiobus_read(bus, sw_addr, 1);
-       if (ret < 0)
-               return ret;
-
-       return ret & 0xffff;
-}
-
-int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int ret;
-
-       mutex_lock(&ps->smi_mutex);
-       ret = __mv88e6xxx_reg_read(ds->master_mii_bus,
-                                  ds->pd->sw_addr, addr, reg);
-       mutex_unlock(&ps->smi_mutex);
-
-       return ret;
-}
-
-int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
-                         int reg, u16 val)
-{
-       int ret;
-
-       if (sw_addr == 0)
-               return mdiobus_write(bus, addr, reg, val);
-
-       /*
-        * Wait for the bus to become free.
-        */
-       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Transmit the data to write.
-        */
-       ret = mdiobus_write(bus, sw_addr, 1, val);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Transmit the write command.
-        */
-       ret = mdiobus_write(bus, sw_addr, 0, 0x9400 | (addr << 5) | reg);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Wait for the write command to complete.
-        */
-       ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int ret;
-
-       mutex_lock(&ps->smi_mutex);
-       ret = __mv88e6xxx_reg_write(ds->master_mii_bus,
-                                   ds->pd->sw_addr, addr, reg, val);
-       mutex_unlock(&ps->smi_mutex);
-
-       return ret;
-}
-
-int mv88e6xxx_config_prio(struct dsa_switch *ds)
-{
-       /*
-        * Configure the IP ToS mapping registers.
-        */
-       REG_WRITE(REG_GLOBAL, 0x10, 0x0000);
-       REG_WRITE(REG_GLOBAL, 0x11, 0x0000);
-       REG_WRITE(REG_GLOBAL, 0x12, 0x5555);
-       REG_WRITE(REG_GLOBAL, 0x13, 0x5555);
-       REG_WRITE(REG_GLOBAL, 0x14, 0xaaaa);
-       REG_WRITE(REG_GLOBAL, 0x15, 0xaaaa);
-       REG_WRITE(REG_GLOBAL, 0x16, 0xffff);
-       REG_WRITE(REG_GLOBAL, 0x17, 0xffff);
-
-       /*
-        * Configure the IEEE 802.1p priority mapping register.
-        */
-       REG_WRITE(REG_GLOBAL, 0x18, 0xfa41);
-
-       return 0;
-}
-
-int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
-{
-       REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
-       REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
-       REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
-
-       return 0;
-}
-
-int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < 6; i++) {
-               int j;
-
-               /*
-                * Write the MAC address byte.
-                */
-               REG_WRITE(REG_GLOBAL2, 0x0d, 0x8000 | (i << 8) | addr[i]);
-
-               /*
-                * Wait for the write to complete.
-                */
-               for (j = 0; j < 16; j++) {
-                       ret = REG_READ(REG_GLOBAL2, 0x0d);
-                       if ((ret & 0x8000) == 0)
-                               break;
-               }
-               if (j == 16)
-                       return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
-{
-       if (addr >= 0)
-               return mv88e6xxx_reg_read(ds, addr, regnum);
-       return 0xffff;
-}
-
-int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val)
-{
-       if (addr >= 0)
-               return mv88e6xxx_reg_write(ds, addr, regnum, val);
-       return 0;
-}
-
-#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
-static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
-{
-       int ret;
-       int i;
-
-       ret = REG_READ(REG_GLOBAL, 0x04);
-       REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000);
-
-       for (i = 0; i < 1000; i++) {
-               ret = REG_READ(REG_GLOBAL, 0x00);
-               msleep(1);
-               if ((ret & 0xc000) != 0xc000)
-                       return 0;
-       }
-
-       return -ETIMEDOUT;
-}
-
-static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
-{
-       int ret;
-       int i;
-
-       ret = REG_READ(REG_GLOBAL, 0x04);
-       REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000);
-
-       for (i = 0; i < 1000; i++) {
-               ret = REG_READ(REG_GLOBAL, 0x00);
-               msleep(1);
-               if ((ret & 0xc000) == 0xc000)
-                       return 0;
-       }
-
-       return -ETIMEDOUT;
-}
-
-static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
-{
-       struct mv88e6xxx_priv_state *ps;
-
-       ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
-       if (mutex_trylock(&ps->ppu_mutex)) {
-               struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
-
-               if (mv88e6xxx_ppu_enable(ds) == 0)
-                       ps->ppu_disabled = 0;
-               mutex_unlock(&ps->ppu_mutex);
-       }
-}
-
-static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)_ps;
-
-       schedule_work(&ps->ppu_work);
-}
-
-static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int ret;
-
-       mutex_lock(&ps->ppu_mutex);
-
-       /*
-        * If the PHY polling unit is enabled, disable it so that
-        * we can access the PHY registers.  If it was already
-        * disabled, cancel the timer that is going to re-enable
-        * it.
-        */
-       if (!ps->ppu_disabled) {
-               ret = mv88e6xxx_ppu_disable(ds);
-               if (ret < 0) {
-                       mutex_unlock(&ps->ppu_mutex);
-                       return ret;
-               }
-               ps->ppu_disabled = 1;
-       } else {
-               del_timer(&ps->ppu_timer);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-
-       /*
-        * Schedule a timer to re-enable the PHY polling unit.
-        */
-       mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
-       mutex_unlock(&ps->ppu_mutex);
-}
-
-void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-
-       mutex_init(&ps->ppu_mutex);
-       INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
-       init_timer(&ps->ppu_timer);
-       ps->ppu_timer.data = (unsigned long)ps;
-       ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
-}
-
-int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
-{
-       int ret;
-
-       ret = mv88e6xxx_ppu_access_get(ds);
-       if (ret >= 0) {
-               ret = mv88e6xxx_reg_read(ds, addr, regnum);
-               mv88e6xxx_ppu_access_put(ds);
-       }
-
-       return ret;
-}
-
-int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
-                           int regnum, u16 val)
-{
-       int ret;
-
-       ret = mv88e6xxx_ppu_access_get(ds);
-       if (ret >= 0) {
-               ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
-               mv88e6xxx_ppu_access_put(ds);
-       }
-
-       return ret;
-}
-#endif
-
-void mv88e6xxx_poll_link(struct dsa_switch *ds)
-{
-       int i;
-
-       for (i = 0; i < DSA_MAX_PORTS; i++) {
-               struct net_device *dev;
-               int uninitialized_var(port_status);
-               int link;
-               int speed;
-               int duplex;
-               int fc;
-
-               dev = ds->ports[i];
-               if (dev == NULL)
-                       continue;
-
-               link = 0;
-               if (dev->flags & IFF_UP) {
-                       port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00);
-                       if (port_status < 0)
-                               continue;
-
-                       link = !!(port_status & 0x0800);
-               }
-
-               if (!link) {
-                       if (netif_carrier_ok(dev)) {
-                               printk(KERN_INFO "%s: link down\n", dev->name);
-                               netif_carrier_off(dev);
-                       }
-                       continue;
-               }
-
-               switch (port_status & 0x0300) {
-               case 0x0000:
-                       speed = 10;
-                       break;
-               case 0x0100:
-                       speed = 100;
-                       break;
-               case 0x0200:
-                       speed = 1000;
-                       break;
-               default:
-                       speed = -1;
-                       break;
-               }
-               duplex = (port_status & 0x0400) ? 1 : 0;
-               fc = (port_status & 0x8000) ? 1 : 0;
-
-               if (!netif_carrier_ok(dev)) {
-                       printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
-                                        "flow control %sabled\n", dev->name,
-                                        speed, duplex ? "full" : "half",
-                                        fc ? "en" : "dis");
-                       netif_carrier_on(dev);
-               }
-       }
-}
-
-static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
-{
-       int ret;
-       int i;
-
-       for (i = 0; i < 10; i++) {
-               ret = REG_READ(REG_GLOBAL, 0x1d);
-               if ((ret & 0x8000) == 0)
-                       return 0;
-       }
-
-       return -ETIMEDOUT;
-}
-
-static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
-{
-       int ret;
-
-       /*
-        * Snapshot the hardware statistics counters for this port.
-        */
-       REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port);
-
-       /*
-        * Wait for the snapshotting to complete.
-        */
-       ret = mv88e6xxx_stats_wait(ds);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
-{
-       u32 _val;
-       int ret;
-
-       *val = 0;
-
-       ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat);
-       if (ret < 0)
-               return;
-
-       ret = mv88e6xxx_stats_wait(ds);
-       if (ret < 0)
-               return;
-
-       ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e);
-       if (ret < 0)
-               return;
-
-       _val = ret << 16;
-
-       ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f);
-       if (ret < 0)
-               return;
-
-       *val = _val | ret;
-}
-
-void mv88e6xxx_get_strings(struct dsa_switch *ds,
-                          int nr_stats, struct mv88e6xxx_hw_stat *stats,
-                          int port, uint8_t *data)
-{
-       int i;
-
-       for (i = 0; i < nr_stats; i++) {
-               memcpy(data + i * ETH_GSTRING_LEN,
-                      stats[i].string, ETH_GSTRING_LEN);
-       }
-}
-
-void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
-                                int nr_stats, struct mv88e6xxx_hw_stat *stats,
-                                int port, uint64_t *data)
-{
-       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
-       int ret;
-       int i;
-
-       mutex_lock(&ps->stats_mutex);
-
-       ret = mv88e6xxx_stats_snapshot(ds, port);
-       if (ret < 0) {
-               mutex_unlock(&ps->stats_mutex);
-               return;
-       }
-
-       /*
-        * Read each of the counters.
-        */
-       for (i = 0; i < nr_stats; i++) {
-               struct mv88e6xxx_hw_stat *s = stats + i;
-               u32 low;
-               u32 high;
-
-               mv88e6xxx_stats_read(ds, s->reg, &low);
-               if (s->sizeof_stat == 8)
-                       mv88e6xxx_stats_read(ds, s->reg + 1, &high);
-               else
-                       high = 0;
-
-               data[i] = (((u64)high) << 32) | low;
-       }
-
-       mutex_unlock(&ps->stats_mutex);
-}
-
-static int __init mv88e6xxx_init(void)
-{
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
-       register_switch_driver(&mv88e6131_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
-       register_switch_driver(&mv88e6123_61_65_switch_driver);
-#endif
-       return 0;
-}
-module_init(mv88e6xxx_init);
-
-static void __exit mv88e6xxx_cleanup(void)
-{
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
-       unregister_switch_driver(&mv88e6123_61_65_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
-       unregister_switch_driver(&mv88e6131_switch_driver);
-#endif
-}
-module_exit(mv88e6xxx_cleanup);
-
-MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
-MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
-MODULE_LICENSE("GPL");
diff --git a/net/dsa/mv88e6xxx.h b/net/dsa/mv88e6xxx.h
deleted file mode 100644 (file)
index fc2cd7b..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * net/dsa/mv88e6xxx.h - Marvell 88e6xxx switch chip support
- * Copyright (c) 2008 Marvell Semiconductor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MV88E6XXX_H
-#define __MV88E6XXX_H
-
-#define REG_PORT(p)            (0x10 + (p))
-#define REG_GLOBAL             0x1b
-#define REG_GLOBAL2            0x1c
-
-struct mv88e6xxx_priv_state {
-       /*
-        * When using multi-chip addressing, this mutex protects
-        * access to the indirect access registers.  (In single-chip
-        * mode, this mutex is effectively useless.)
-        */
-       struct mutex    smi_mutex;
-
-#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
-       /*
-        * Handles automatic disabling and re-enabling of the PHY
-        * polling unit.
-        */
-       struct mutex            ppu_mutex;
-       int                     ppu_disabled;
-       struct work_struct      ppu_work;
-       struct timer_list       ppu_timer;
-#endif
-
-       /*
-        * This mutex serialises access to the statistics unit.
-        * Hold this mutex over snapshot + dump sequences.
-        */
-       struct mutex    stats_mutex;
-
-       int             id; /* switch product id */
-};
-
-struct mv88e6xxx_hw_stat {
-       char string[ETH_GSTRING_LEN];
-       int sizeof_stat;
-       int reg;
-};
-
-int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
-int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
-int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
-                          int reg, u16 val);
-int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
-int mv88e6xxx_config_prio(struct dsa_switch *ds);
-int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
-int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
-int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum);
-int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val);
-void mv88e6xxx_ppu_state_init(struct dsa_switch *ds);
-int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
-int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
-                           int regnum, u16 val);
-void mv88e6xxx_poll_link(struct dsa_switch *ds);
-void mv88e6xxx_get_strings(struct dsa_switch *ds,
-                          int nr_stats, struct mv88e6xxx_hw_stat *stats,
-                          int port, uint8_t *data);
-void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
-                                int nr_stats, struct mv88e6xxx_hw_stat *stats,
-                                int port, uint64_t *data);
-
-extern struct dsa_switch_driver mv88e6131_switch_driver;
-extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
-
-#define REG_READ(addr, reg)                                            \
-       ({                                                              \
-               int __ret;                                              \
-                                                                       \
-               __ret = mv88e6xxx_reg_read(ds, addr, reg);              \
-               if (__ret < 0)                                          \
-                       return __ret;                                   \
-               __ret;                                                  \
-       })
-
-#define REG_WRITE(addr, reg, val)                                      \
-       ({                                                              \
-               int __ret;                                              \
-                                                                       \
-               __ret = mv88e6xxx_reg_write(ds, addr, reg, val);        \
-               if (__ret < 0)                                          \
-                       return __ret;                                   \
-       })
-
-
-
-#endif