Commit af4e6671 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-bcmgenet-revisit-MAC-reset'

Doug Berger says:

====================
net: bcmgenet: revisit MAC reset

Commit 3a55402c ("net: bcmgenet: use RGMII loopback for MAC
reset") was intended to resolve issues with reseting the UniMAC
core within the GENET block by providing better control over the
clocks used by the UniMAC core. Unfortunately, it is not
compatible with all of the supported system configurations so an
alternative method must be applied.

This commit set provides such an alternative. The first commit
reverts the previous change and the second commit provides the
alternative reset sequence that addresses the concerns observed
with the previous implementation.

This replacement implementation should be applied to the stable
branches wherever commit 3a55402c ("net: bcmgenet: use RGMII
loopback for MAC reset") has been applied.

Unfortunately, reverting that commit may conflict with some
restructuring changes introduced by commit 4f8d81b7 ("net:
bcmgenet: Refactor register access in bcmgenet_mii_config").
The first commit in this set has been manually edited to
resolve the conflict on net/master. I would be happy to help
stable maintainers with resolving any such conflicts if they
occur. However, I do not expect that commit to have been
backported to stable branch so hopefully the revert can be
applied cleanly.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d36963b8 88f6c8bf
...@@ -1965,6 +1965,8 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable) ...@@ -1965,6 +1965,8 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
u32 reg; u32 reg;
reg = bcmgenet_umac_readl(priv, UMAC_CMD); reg = bcmgenet_umac_readl(priv, UMAC_CMD);
if (reg & CMD_SW_RESET)
return;
if (enable) if (enable)
reg |= mask; reg |= mask;
else else
...@@ -1984,11 +1986,9 @@ static void reset_umac(struct bcmgenet_priv *priv) ...@@ -1984,11 +1986,9 @@ static void reset_umac(struct bcmgenet_priv *priv)
bcmgenet_rbuf_ctrl_set(priv, 0); bcmgenet_rbuf_ctrl_set(priv, 0);
udelay(10); udelay(10);
/* disable MAC while updating its registers */ /* issue soft reset and disable MAC while updating its registers */
bcmgenet_umac_writel(priv, 0, UMAC_CMD); bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
udelay(2);
/* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
bcmgenet_umac_writel(priv, CMD_SW_RESET | CMD_LCL_LOOP_EN, UMAC_CMD);
} }
static void bcmgenet_intr_disable(struct bcmgenet_priv *priv) static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
......
...@@ -132,8 +132,12 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, ...@@ -132,8 +132,12 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
return -EINVAL; return -EINVAL;
} }
/* disable RX */ /* Can't suspend with WoL if MAC is still in reset */
reg = bcmgenet_umac_readl(priv, UMAC_CMD); reg = bcmgenet_umac_readl(priv, UMAC_CMD);
if (reg & CMD_SW_RESET)
reg &= ~CMD_SW_RESET;
/* disable RX */
reg &= ~CMD_RX_EN; reg &= ~CMD_RX_EN;
bcmgenet_umac_writel(priv, reg, UMAC_CMD); bcmgenet_umac_writel(priv, reg, UMAC_CMD);
mdelay(10); mdelay(10);
......
...@@ -95,6 +95,12 @@ void bcmgenet_mii_setup(struct net_device *dev) ...@@ -95,6 +95,12 @@ void bcmgenet_mii_setup(struct net_device *dev)
CMD_HD_EN | CMD_HD_EN |
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE); CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
reg |= cmd_bits; reg |= cmd_bits;
if (reg & CMD_SW_RESET) {
reg &= ~CMD_SW_RESET;
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
udelay(2);
reg |= CMD_TX_EN | CMD_RX_EN;
}
bcmgenet_umac_writel(priv, reg, UMAC_CMD); bcmgenet_umac_writel(priv, reg, UMAC_CMD);
} else { } else {
/* done if nothing has changed */ /* done if nothing has changed */
...@@ -181,38 +187,8 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -181,38 +187,8 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
const char *phy_name = NULL; const char *phy_name = NULL;
u32 id_mode_dis = 0; u32 id_mode_dis = 0;
u32 port_ctrl; u32 port_ctrl;
int bmcr = -1;
int ret;
u32 reg; u32 reg;
/* MAC clocking workaround during reset of umac state machines */
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
if (reg & CMD_SW_RESET) {
/* An MII PHY must be isolated to prevent TXC contention */
if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
ret = phy_read(phydev, MII_BMCR);
if (ret >= 0) {
bmcr = ret;
ret = phy_write(phydev, MII_BMCR,
bmcr | BMCR_ISOLATE);
}
if (ret) {
netdev_err(dev, "failed to isolate PHY\n");
return ret;
}
}
/* Switch MAC clocking to RGMII generated clock */
bcmgenet_sys_writel(priv, PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
/* Ensure 5 clks with Rx disabled
* followed by 5 clks with Reset asserted
*/
udelay(4);
reg &= ~(CMD_SW_RESET | CMD_LCL_LOOP_EN);
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
/* Ensure 5 more clocks before Rx is enabled */
udelay(2);
}
switch (priv->phy_interface) { switch (priv->phy_interface) {
case PHY_INTERFACE_MODE_INTERNAL: case PHY_INTERFACE_MODE_INTERNAL:
phy_name = "internal PHY"; phy_name = "internal PHY";
...@@ -282,10 +258,6 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -282,10 +258,6 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
/* Restore the MII PHY after isolation */
if (bmcr >= 0)
phy_write(phydev, MII_BMCR, bmcr);
priv->ext_phy = !priv->internal_phy && priv->ext_phy = !priv->internal_phy &&
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA); (priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment