Просмотр исходного кода

bcm63xx: expose the internal switch to b53

Allow b53 access to the internal switch of BCM6328, BCM6362 and BCM6368.

Signed-off-by: Jonas Gorski <[email protected]>

SVN-Revision: 35306
Jonas Gorski 13 лет назад
Родитель
Сommit
17d51121a6

+ 169 - 0
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 <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"
+@@ -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);