summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2019-02-08 15:35:43 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-05 22:33:09 +0200
commita78aae93ba9c8e00a2055ebf5644cca8666f9805 (patch)
tree844c72193baaf87f9e1e3df4b4c7428476d036df
parent1f3694865d5600bb23938f26a6effa843dc7cbca (diff)
net: marvell: mvpp2: fix stuck in-band SGMII negotiation
[ Upstream commit 316734fdcf70900a83065360cff11a5826919067 ] It appears that the mvpp22 can get stuck with SGMII negotiation. The symptoms are that in-band negotiation never completes and the partner (eg, PHY) never reports SGMII link up, or if it supports negotiation bypass, goes into negotiation bypass mode (which will happen when the PHY sees that the MAC is alive but gets no response.) Triggering the PHY end of the link to re-negotiate results in the bypass bit clearing on the PHY, and then re-setting - indicating that the problem is at the mvpp22 GMAC end. Asserting the GMAC reset and de-asserting it resolves the issue. Arrange to assert the GMAC reset at probe time, and deassert it only after we have configured the GMAC for the appropriate mode. This resolves the issue. Tested-by: Sven Auhagen <sven.auhagen@voleatech.de> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index f8e4808a8317..9988c89ed9fd 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1372,13 +1372,9 @@ static void mvpp2_port_reset(struct mvpp2_port *port)
for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
mvpp2_read_count(port, &mvpp2_ethtool_regs[i]);
- val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
- ~MVPP2_GMAC_PORT_RESET_MASK;
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) |
+ MVPP2_GMAC_PORT_RESET_MASK;
writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
-
- while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
- MVPP2_GMAC_PORT_RESET_MASK)
- continue;
}
/* Change maximum receive size of the port */
@@ -4445,12 +4441,15 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
const struct phylink_link_state *state)
{
u32 an, ctrl0, ctrl2, ctrl4;
+ u32 old_ctrl2;
an = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
ctrl0 = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+ old_ctrl2 = ctrl2;
+
/* Force link down */
an &= ~MVPP2_GMAC_FORCE_LINK_PASS;
an |= MVPP2_GMAC_FORCE_LINK_DOWN;
@@ -4523,6 +4522,12 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG);
writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG);
writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+
+ if (old_ctrl2 & MVPP2_GMAC_PORT_RESET_MASK) {
+ while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+ MVPP2_GMAC_PORT_RESET_MASK)
+ continue;
+ }
}
static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,