You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/target/linux/bcm63xx/patches-5.4/423-bcm63xx_enet_add_b53_su...

170 lines
4.5 KiB
Diff

--- 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
@@ -17,6 +17,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"
@@ -1909,7 +1910,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 = {
@@ -1918,6 +1920,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
*/
@@ -2174,29 +2212,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));
@@ -2652,6 +2667,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;
@@ -2731,6 +2749,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:
@@ -2752,6 +2807,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);