OpenWrt – Rev 1

Subversion Repositories:
Rev:
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
@@ -332,6 +332,9 @@ struct bcm_enet_priv {
        struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
        int sw_port_link[ENETSW_MAX_PORT];
 
+       /* platform device for associated switch */
+       struct platform_device *b53_device;
+
        /* used to poll switch port state */
        struct timer_list swphy_poll;
        spinlock_t enetsw_mdio_lock;
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -30,6 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/if_vlan.h>
+#include <linux/platform_data/b53.h>
 
 #include <bcm63xx_dev_enet.h>
 #include "bcm63xx_enet.h"
@@ -1936,7 +1937,8 @@ static int bcm_enet_remove(struct platfo
        return 0;
 }
 
-struct platform_driver bcm63xx_enet_driver = {
+
+static struct platform_driver bcm63xx_enet_driver = {
        .probe  = bcm_enet_probe,
        .remove = bcm_enet_remove,
        .driver = {
@@ -1945,6 +1947,42 @@ struct platform_driver bcm63xx_enet_driv
        },
 };
 
+struct b53_platform_data bcm63xx_b53_pdata = {
+       .chip_id = 0x6300,
+       .big_endian = 1,
+};
+
+struct platform_device bcm63xx_b53_dev = {
+       .name           = "b53-switch",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &bcm63xx_b53_pdata,
+       },
+};
+
+static int bcmenet_switch_register(struct bcm_enet_priv *priv, u16 port_mask)
+{
+       int ret;
+
+       bcm63xx_b53_pdata.regs = priv->base;
+       bcm63xx_b53_pdata.enabled_ports = port_mask;
+       bcm63xx_b53_pdata.alias = priv->net_dev->name;
+
+       ret = platform_device_register(&bcm63xx_b53_dev);
+       if (!ret)
+               priv->b53_device = &bcm63xx_b53_dev;
+
+       return ret;
+}
+
+static void bcmenet_switch_unregister(struct bcm_enet_priv *priv)
+{
+       if (priv->b53_device)
+               platform_device_unregister(&bcm63xx_b53_dev);
+
+       priv->b53_device = NULL;
+}
+
 /*
  * switch mii access callbacks
  */
@@ -2203,29 +2241,6 @@ static int bcm_enetsw_open(struct net_de
                enetsw_writeb(priv, rgmii_ctrl, ENETSW_RGMII_CTRL_REG(i));
        }
 
-       /* reset mib */
-       val = enetsw_readb(priv, ENETSW_GMCR_REG);
-       val |= ENETSW_GMCR_RST_MIB_MASK;
-       enetsw_writeb(priv, val, ENETSW_GMCR_REG);
-       mdelay(1);
-       val &= ~ENETSW_GMCR_RST_MIB_MASK;
-       enetsw_writeb(priv, val, ENETSW_GMCR_REG);
-       mdelay(1);
-
-       /* force CPU port state */
-       val = enetsw_readb(priv, ENETSW_IMPOV_REG);
-       val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK;
-       enetsw_writeb(priv, val, ENETSW_IMPOV_REG);
-
-       /* enable switch forward engine */
-       val = enetsw_readb(priv, ENETSW_SWMODE_REG);
-       val |= ENETSW_SWMODE_FWD_EN_MASK;
-       enetsw_writeb(priv, val, ENETSW_SWMODE_REG);
-
-       /* enable jumbo on all ports */
-       enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG);
-       enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG);
-
        /* initialize flow control buffer allocation */
        enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
                        ENETDMA_BUFALLOC_REG(priv->rx_chan));
@@ -2684,6 +2699,9 @@ static int bcm_enetsw_probe(struct platf
        struct bcm63xx_enetsw_platform_data *pd;
        struct resource *res_mem;
        int ret, irq_rx, irq_tx;
+       unsigned i, num_ports = 0;
+       u16 port_mask = BIT(8);
+       u8 val;
 
        if (!bcm_enet_shared_base[0])
                return -EPROBE_DEFER;
@@ -2766,6 +2784,43 @@ static int bcm_enetsw_probe(struct platf
        priv->pdev = pdev;
        priv->net_dev = dev;
 
+       /* reset mib */
+       val = enetsw_readb(priv, ENETSW_GMCR_REG);
+       val |= ENETSW_GMCR_RST_MIB_MASK;
+       enetsw_writeb(priv, val, ENETSW_GMCR_REG);
+       mdelay(1);
+       val &= ~ENETSW_GMCR_RST_MIB_MASK;
+       enetsw_writeb(priv, val, ENETSW_GMCR_REG);
+       mdelay(1);
+
+       /* force CPU port state */
+       val = enetsw_readb(priv, ENETSW_IMPOV_REG);
+       val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK;
+       enetsw_writeb(priv, val, ENETSW_IMPOV_REG);
+
+       /* enable switch forward engine */
+       val = enetsw_readb(priv, ENETSW_SWMODE_REG);
+       val |= ENETSW_SWMODE_FWD_EN_MASK;
+       enetsw_writeb(priv, val, ENETSW_SWMODE_REG);
+
+       /* enable jumbo on all ports */
+       enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG);
+       enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG);
+
+       for (i = 0; i < priv->num_ports; i++) {
+               struct bcm63xx_enetsw_port *port = &priv->used_ports[i];
+
+               if (!port->used)
+                       continue;
+
+               num_ports++;
+               port_mask |= BIT(i);
+       }
+
+       /* only register if there is more than one external port */
+       if (num_ports > 1)
+               bcmenet_switch_register(priv, port_mask);
+
        return 0;
 
 out_disable_clk:
@@ -2787,6 +2842,9 @@ static int bcm_enetsw_remove(struct plat
        priv = netdev_priv(dev);
        unregister_netdev(dev);
 
+       /* remove switch */
+       bcmenet_switch_unregister(priv);
+
        clk_disable_unprepare(priv->mac_clk);
 
        free_netdev(dev);