From 9cd6b274ba27af06094d7efbfa78a7a7ba28f1e0 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Wed, 23 Jan 2013 10:12:37 +0000 Subject: bcm63xx: expose the internal switch to b53 Allow b53 access to the internal switch of BCM6328, BCM6362 and BCM6368. Signed-off-by: Jonas Gorski git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35306 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../447-bcm63xx_enet_add_b53_support.patch | 169 +++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 target/linux/brcm63xx/patches-3.6/447-bcm63xx_enet_add_b53_support.patch diff --git a/target/linux/brcm63xx/patches-3.6/447-bcm63xx_enet_add_b53_support.patch b/target/linux/brcm63xx/patches-3.6/447-bcm63xx_enet_add_b53_support.patch new file mode 100644 index 0000000000..93ef40945a --- /dev/null +++ b/target/linux/brcm63xx/patches-3.6/447-bcm63xx_enet_add_b53_support.patch @@ -0,0 +1,169 @@ +--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h ++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h +@@ -364,6 +364,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 + #include + #include ++#include + + #include + #include "bcm63xx_enet.h" +@@ -2013,7 +2014,8 @@ static int __devexit bcm_enet_remove(str + return 0; + } + +-struct platform_driver bcm63xx_enet_driver = { ++ ++static struct platform_driver bcm63xx_enet_driver = { + .probe = bcm_enet_probe, + .remove = __devexit_p(bcm_enet_remove), + .driver = { +@@ -2022,6 +2024,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 + */ +@@ -2270,29 +2308,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)); +@@ -2760,6 +2775,9 @@ static int __devinit bcm_enetsw_probe(st + 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; + + /* stop if shared driver failed, assume driver->probe will be + * called in the same order we register devices (correct ?) */ +@@ -2847,6 +2865,43 @@ static int __devinit bcm_enetsw_probe(st + 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_put_clk: +@@ -2877,6 +2932,9 @@ static int __devexit bcm_enetsw_remove(s + priv = netdev_priv(dev); + unregister_netdev(dev); + ++ /* remove switch */ ++ bcmenet_switch_unregister(priv); ++ + /* release device resources */ + iounmap(priv->base); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3