Skip to content

Commit 3a55402

Browse files
Doug Bergerdavem330
authored andcommitted
net: bcmgenet: use RGMII loopback for MAC reset
As noted in commit 28c2d1a ("net: bcmgenet: enable loopback during UniMAC sw_reset") the UniMAC must be clocked while sw_reset is asserted for its state machines to reset cleanly. The transmit and receive clocks used by the UniMAC are derived from the signals used on its PHY interface. The bcmgenet MAC can be configured to work with different PHY interfaces including MII, GMII, RGMII, and Reverse MII on internal and external interfaces. Unfortunately for the UniMAC, when configured for MII the Tx clock is always driven from the PHY which places it outside of the direct control of the MAC. The earlier commit enabled a local loopback mode within the UniMAC so that the receive clock would be derived from the transmit clock which addressed the observed issue with an external GPHY disabling it's Rx clock. However, when a Tx clock is not available this loopback is insufficient. This commit implements a workaround that leverages the fact that the MAC can reliably generate all of its necessary clocking by enterring the external GPHY RGMII interface mode with the UniMAC in local loopback during the sw_reset interval. Unfortunately, this has the undesirable side efect of the RGMII GTXCLK signal being driven during the same window. In most configurations this is a benign side effect as the signal is either not routed to a pin or is already expected to drive the pin. The one exception is when an external MII PHY is expected to drive the same pin with its TX_CLK output creating output driver contention. This commit exploits the IEEE 802.3 clause 22 standard defined isolate mode to force an external MII PHY to present a high impedance on its TX_CLK output during the window to prevent any contention at the pin. The MII interface is used internally with the 40nm internal EPHY which agressively disables its clocks for power savings leading to incomplete resets of the UniMAC and many instabilities observed over the years. The workaround of this commit is expected to put an end to those problems. Fixes: 1c1008c ("net: bcmgenet: add main driver file") Signed-off-by: Doug Berger <[email protected]> Acked-by: Florian Fainelli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2836654 commit 3a55402

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

drivers/net/ethernet/broadcom/genet/bcmgenet.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,8 +1996,6 @@ static void reset_umac(struct bcmgenet_priv *priv)
19961996

19971997
/* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
19981998
bcmgenet_umac_writel(priv, CMD_SW_RESET | CMD_LCL_LOOP_EN, UMAC_CMD);
1999-
udelay(2);
2000-
bcmgenet_umac_writel(priv, 0, UMAC_CMD);
20011999
}
20022000

20032001
static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)

drivers/net/ethernet/broadcom/genet/bcmmii.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,38 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
221221
const char *phy_name = NULL;
222222
u32 id_mode_dis = 0;
223223
u32 port_ctrl;
224+
int bmcr = -1;
225+
int ret;
224226
u32 reg;
225227

228+
/* MAC clocking workaround during reset of umac state machines */
229+
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
230+
if (reg & CMD_SW_RESET) {
231+
/* An MII PHY must be isolated to prevent TXC contention */
232+
if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
233+
ret = phy_read(phydev, MII_BMCR);
234+
if (ret >= 0) {
235+
bmcr = ret;
236+
ret = phy_write(phydev, MII_BMCR,
237+
bmcr | BMCR_ISOLATE);
238+
}
239+
if (ret) {
240+
netdev_err(dev, "failed to isolate PHY\n");
241+
return ret;
242+
}
243+
}
244+
/* Switch MAC clocking to RGMII generated clock */
245+
bcmgenet_sys_writel(priv, PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
246+
/* Ensure 5 clks with Rx disabled
247+
* followed by 5 clks with Reset asserted
248+
*/
249+
udelay(4);
250+
reg &= ~(CMD_SW_RESET | CMD_LCL_LOOP_EN);
251+
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
252+
/* Ensure 5 more clocks before Rx is enabled */
253+
udelay(2);
254+
}
255+
226256
priv->ext_phy = !priv->internal_phy &&
227257
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
228258

@@ -254,6 +284,9 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
254284
phy_set_max_speed(phydev, SPEED_100);
255285
bcmgenet_sys_writel(priv,
256286
PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
287+
/* Restore the MII PHY after isolation */
288+
if (bmcr >= 0)
289+
phy_write(phydev, MII_BMCR, bmcr);
257290
break;
258291

259292
case PHY_INTERFACE_MODE_REVMII:

0 commit comments

Comments
 (0)