net: bcm6368: fix restart flow issues
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Tue, 1 Jan 2019 18:44:46 +0000 (19:44 +0100)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Wed, 16 Jan 2019 12:56:43 +0000 (13:56 +0100)
Correctly enable/disable bcm6368-net controller to avoid flow issues.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
drivers/net/bcm6368-eth.c

index a31efba9d194595c2121cecbe20ab2ab6ac0a8bd..110985ed1dc247db4398ffeeb88da4c6aca26c3e 100644 (file)
@@ -309,6 +309,43 @@ static int bcm6368_eth_start(struct udevice *dev)
        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
        uint8_t i;
 
+       /* disable all ports */
+       for (i = 0; i < priv->num_ports; i++) {
+               setbits_8(priv->base + ETH_PORTOV_REG(i),
+                         ETH_PORTOV_ENABLE_MASK);
+               setbits_8(priv->base + ETH_PTCTRL_REG(i),
+                         ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
+               priv->sw_port_link[i] = 0;
+       }
+
+       /* enable external ports */
+       for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+               u8 rgmii_ctrl = ETH_RGMII_CTRL_GMII_CLK_EN;
+
+               if (!priv->used_ports[i].used)
+                       continue;
+
+               if (priv->rgmii_override)
+                       rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+               if (priv->rgmii_timing)
+                       rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+
+               setbits_8(priv->base + ETH_RGMII_CTRL_REG(i), rgmii_ctrl);
+       }
+
+       /* reset mib */
+       setbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
+       mdelay(1);
+       clrbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
+       mdelay(1);
+
+       /* force CPU port state */
+       setbits_8(priv->base + ETH_IMPOV_REG,
+                 ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
+
+       /* enable switch forward engine */
+       setbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
+
        /* prepare rx dma buffers */
        for (i = 0; i < ETH_RX_DESC; i++) {
                int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
@@ -368,6 +405,31 @@ static int bcm6368_eth_start(struct udevice *dev)
 static void bcm6368_eth_stop(struct udevice *dev)
 {
        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+       uint8_t i;
+
+       /* disable all ports */
+       for (i = 0; i < priv->num_ports; i++) {
+               setbits_8(priv->base + ETH_PORTOV_REG(i),
+                         ETH_PORTOV_ENABLE_MASK);
+               setbits_8(priv->base + ETH_PTCTRL_REG(i),
+                         ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
+       }
+
+       /* disable external ports */
+       for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+               if (!priv->used_ports[i].used)
+                       continue;
+
+               clrbits_8(priv->base + ETH_RGMII_CTRL_REG(i),
+                         ETH_RGMII_CTRL_GMII_CLK_EN);
+       }
+
+       /* disable CPU port */
+       clrbits_8(priv->base + ETH_IMPOV_REG,
+                 ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
+
+       /* disable switch forward engine */
+       clrbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
 
        /* disable dma rx channel */
        dma_disable(&priv->rx_dma);
@@ -444,7 +506,6 @@ static int bcm6368_eth_probe(struct udevice *dev)
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
        int num_ports, ret, i;
-       uint32_t val;
        ofnode node;
 
        /* get base address */
@@ -561,52 +622,6 @@ static int bcm6368_eth_probe(struct udevice *dev)
        if (ret)
                return ret;
 
-       /* disable all ports */
-       for (i = 0; i < priv->num_ports; i++) {
-               writeb_be(ETH_PORTOV_ENABLE_MASK,
-                             priv->base + ETH_PORTOV_REG(i));
-               writeb_be(ETH_PTCTRL_RXDIS_MASK |
-                             ETH_PTCTRL_TXDIS_MASK,
-                             priv->base + ETH_PTCTRL_REG(i));
-
-               priv->sw_port_link[i] = 0;
-       }
-
-       /* enable external ports */
-       for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
-               u8 rgmii_ctrl;
-
-               if (!priv->used_ports[i].used)
-                       continue;
-
-               rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
-               rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
-               if (priv->rgmii_override)
-                       rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
-               if (priv->rgmii_timing)
-                       rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
-               writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
-       }
-
-       /* reset mib */
-       val = readb_be(priv->base + ETH_GMCR_REG);
-       val |= ETH_GMCR_RST_MIB_MASK;
-       writeb_be(val, priv->base + ETH_GMCR_REG);
-       mdelay(1);
-       val &= ~ETH_GMCR_RST_MIB_MASK;
-       writeb_be(val, priv->base + ETH_GMCR_REG);
-       mdelay(1);
-
-       /* force CPU port state */
-       val = readb_be(priv->base + ETH_IMPOV_REG);
-       val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
-       writeb_be(val, priv->base + ETH_IMPOV_REG);
-
-       /* enable switch forward engine */
-       val = readb_be(priv->base + ETH_SWMODE_REG);
-       val |= ETH_SWMODE_FWD_EN_MASK;
-       writeb_be(val, priv->base + ETH_SWMODE_REG);
-
        /* enable jumbo on all ports */
        writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
        writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);