Skip to content

Commit 28c2d1a

Browse files
Doug Bergerdavem330
authored andcommitted
net: bcmgenet: enable loopback during UniMAC sw_reset
It is necessary for the UniMAC to be clocked at least 5 cycles while the sw_reset is asserted to ensure a clean reset. It was discovered that this condition was not being met when connected to an external RGMII PHY that disabled the Rx clock in the Power Save state. This commit modifies the reset_umac function to place the (RG)MII interface into a local loopback mode where the Rx clock comes from the GENET sourced Tx clk during the sw_reset to ensure the presence and stability of the clock. In addition, it turns out that the sw_reset of the UniMAC is not self clearing, but this was masked by a bug in the timeout code. The sw_reset is now explicitly cleared by zeroing the UMAC_CMD register before returning from reset_umac which makes it no longer necessary to do so in init_umac and makes the clearing of CMD_TX_EN and CMD_RX_EN by umac_enable_set redundant. The timeout code (and its associated bug) are removed so reset_umac no longer needs to return a result, and that means init_umac that calls reset_umac does not need to as well. Fixes: 1c1008c ("net: bcmgenet: add main driver file") Signed-off-by: Doug Berger <opendmb@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4fd6dc9 commit 28c2d1a

File tree

1 file changed

+10
-45
lines changed

1 file changed

+10
-45
lines changed

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

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,36 +1935,19 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
19351935
usleep_range(1000, 2000);
19361936
}
19371937

1938-
static int reset_umac(struct bcmgenet_priv *priv)
1938+
static void reset_umac(struct bcmgenet_priv *priv)
19391939
{
1940-
struct device *kdev = &priv->pdev->dev;
1941-
unsigned int timeout = 0;
1942-
u32 reg;
1943-
19441940
/* 7358a0/7552a0: bad default in RBUF_FLUSH_CTRL.umac_sw_rst */
19451941
bcmgenet_rbuf_ctrl_set(priv, 0);
19461942
udelay(10);
19471943

19481944
/* disable MAC while updating its registers */
19491945
bcmgenet_umac_writel(priv, 0, UMAC_CMD);
19501946

1951-
/* issue soft reset, wait for it to complete */
1952-
bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
1953-
while (timeout++ < 1000) {
1954-
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
1955-
if (!(reg & CMD_SW_RESET))
1956-
return 0;
1957-
1958-
udelay(1);
1959-
}
1960-
1961-
if (timeout == 1000) {
1962-
dev_err(kdev,
1963-
"timeout waiting for MAC to come out of reset\n");
1964-
return -ETIMEDOUT;
1965-
}
1966-
1967-
return 0;
1947+
/* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
1948+
bcmgenet_umac_writel(priv, CMD_SW_RESET | CMD_LCL_LOOP_EN, UMAC_CMD);
1949+
udelay(2);
1950+
bcmgenet_umac_writel(priv, 0, UMAC_CMD);
19681951
}
19691952

19701953
static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
@@ -1994,20 +1977,16 @@ static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
19941977
bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
19951978
}
19961979

1997-
static int init_umac(struct bcmgenet_priv *priv)
1980+
static void init_umac(struct bcmgenet_priv *priv)
19981981
{
19991982
struct device *kdev = &priv->pdev->dev;
2000-
int ret;
20011983
u32 reg;
20021984
u32 int0_enable = 0;
20031985

20041986
dev_dbg(&priv->pdev->dev, "bcmgenet: init_umac\n");
20051987

2006-
ret = reset_umac(priv);
2007-
if (ret)
2008-
return ret;
1988+
reset_umac(priv);
20091989

2010-
bcmgenet_umac_writel(priv, 0, UMAC_CMD);
20111990
/* clear tx/rx counter */
20121991
bcmgenet_umac_writel(priv,
20131992
MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT,
@@ -2046,8 +2025,6 @@ static int init_umac(struct bcmgenet_priv *priv)
20462025
bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
20472026

20482027
dev_dbg(kdev, "done init umac\n");
2049-
2050-
return 0;
20512028
}
20522029

20532030
/* Initialize a Tx ring along with corresponding hardware registers */
@@ -2863,12 +2840,7 @@ static int bcmgenet_open(struct net_device *dev)
28632840
/* take MAC out of reset */
28642841
bcmgenet_umac_reset(priv);
28652842

2866-
ret = init_umac(priv);
2867-
if (ret)
2868-
goto err_clk_disable;
2869-
2870-
/* disable ethernet MAC while updating its registers */
2871-
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
2843+
init_umac(priv);
28722844

28732845
/* Make sure we reflect the value of CRC_CMD_FWD */
28742846
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
@@ -3546,9 +3518,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
35463518
!strcasecmp(phy_mode_str, "internal"))
35473519
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
35483520

3549-
err = reset_umac(priv);
3550-
if (err)
3551-
goto err_clk_disable;
3521+
reset_umac(priv);
35523522

35533523
err = bcmgenet_mii_init(dev);
35543524
if (err)
@@ -3660,9 +3630,7 @@ static int bcmgenet_resume(struct device *d)
36603630

36613631
bcmgenet_umac_reset(priv);
36623632

3663-
ret = init_umac(priv);
3664-
if (ret)
3665-
goto out_clk_disable;
3633+
init_umac(priv);
36663634

36673635
/* From WOL-enabled suspend, switch to regular clock */
36683636
if (priv->wolopts)
@@ -3672,9 +3640,6 @@ static int bcmgenet_resume(struct device *d)
36723640
/* Speed settings must be restored */
36733641
bcmgenet_mii_config(priv->dev, false);
36743642

3675-
/* disable ethernet MAC while updating its registers */
3676-
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
3677-
36783643
bcmgenet_set_hw_addr(priv, dev->dev_addr);
36793644

36803645
if (priv->internal_phy) {

0 commit comments

Comments
 (0)