net: bcm6368: fix restart flow issues
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>
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
index a31efba..110985e 100644
--- a/drivers/net/bcm6368-eth.c
+++ b/drivers/net/bcm6368-eth.c
@@ -309,6 +309,43 @@
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 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 @@
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 @@
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);