Skip to content

Commit 1f51548

Browse files
Doug Bergerdavem330
authored andcommitted
net: bcmgenet: soft reset 40nm EPHYs before MAC init
It turns out that the "Workaround for putting the PHY in IDDQ mode" used by the internal EPHYs on 40nm Set-Top Box chips when powering down puts the interface to the GENET MAC in a state that can cause subsequent MAC resets to be incomplete. Rather than restore the forced soft reset when powering up internal PHYs, this commit moves the invocation of phy_init_hw earlier in the MAC initialization sequence to just before the MAC reset in the open and resume functions. This allows the interface to be stable and allows the MAC resets to be successful. The bcmgenet_mii_probe() function is split in two to accommodate this. The new function bcmgenet_mii_connect() handles the first half of the functionality before the MAC initialization, and the bcmgenet_mii_config() function is extended to provide the remaining PHY configuration following the MAC initialization. Fixes: 484bfa1 ("Revert "net: bcmgenet: Software reset EPHY after power on"") Signed-off-by: Doug Berger <opendmb@gmail.com> Acked-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent fe586b8 commit 1f51548

File tree

3 files changed

+69
-73
lines changed

3 files changed

+69
-73
lines changed

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2872,6 +2872,12 @@ static int bcmgenet_open(struct net_device *dev)
28722872
if (priv->internal_phy)
28732873
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
28742874

2875+
ret = bcmgenet_mii_connect(dev);
2876+
if (ret) {
2877+
netdev_err(dev, "failed to connect to PHY\n");
2878+
goto err_clk_disable;
2879+
}
2880+
28752881
/* take MAC out of reset */
28762882
bcmgenet_umac_reset(priv);
28772883

@@ -2881,6 +2887,12 @@ static int bcmgenet_open(struct net_device *dev)
28812887
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
28822888
priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
28832889

2890+
ret = bcmgenet_mii_config(dev, true);
2891+
if (ret) {
2892+
netdev_err(dev, "unsupported PHY\n");
2893+
goto err_disconnect_phy;
2894+
}
2895+
28842896
bcmgenet_set_hw_addr(priv, dev->dev_addr);
28852897

28862898
if (priv->internal_phy) {
@@ -2896,7 +2908,7 @@ static int bcmgenet_open(struct net_device *dev)
28962908
ret = bcmgenet_init_dma(priv);
28972909
if (ret) {
28982910
netdev_err(dev, "failed to initialize DMA\n");
2899-
goto err_clk_disable;
2911+
goto err_disconnect_phy;
29002912
}
29012913

29022914
/* Always enable ring 16 - descriptor ring */
@@ -2919,25 +2931,19 @@ static int bcmgenet_open(struct net_device *dev)
29192931
goto err_irq0;
29202932
}
29212933

2922-
ret = bcmgenet_mii_probe(dev);
2923-
if (ret) {
2924-
netdev_err(dev, "failed to connect to PHY\n");
2925-
goto err_irq1;
2926-
}
2927-
29282934
bcmgenet_netif_start(dev);
29292935

29302936
netif_tx_start_all_queues(dev);
29312937

29322938
return 0;
29332939

2934-
err_irq1:
2935-
free_irq(priv->irq1, priv);
29362940
err_irq0:
29372941
free_irq(priv->irq0, priv);
29382942
err_fini_dma:
29392943
bcmgenet_dma_teardown(priv);
29402944
bcmgenet_fini_dma(priv);
2945+
err_disconnect_phy:
2946+
phy_disconnect(dev->phydev);
29412947
err_clk_disable:
29422948
if (priv->internal_phy)
29432949
bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
@@ -3618,6 +3624,8 @@ static int bcmgenet_resume(struct device *d)
36183624
if (priv->internal_phy)
36193625
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
36203626

3627+
phy_init_hw(dev->phydev);
3628+
36213629
bcmgenet_umac_reset(priv);
36223630

36233631
init_umac(priv);
@@ -3626,8 +3634,6 @@ static int bcmgenet_resume(struct device *d)
36263634
if (priv->wolopts)
36273635
clk_disable_unprepare(priv->clk_wol);
36283636

3629-
phy_init_hw(dev->phydev);
3630-
36313637
/* Speed settings must be restored */
36323638
bcmgenet_mii_config(priv->dev, false);
36333639

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,8 @@ GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
720720

721721
/* MDIO routines */
722722
int bcmgenet_mii_init(struct net_device *dev);
723+
int bcmgenet_mii_connect(struct net_device *dev);
723724
int bcmgenet_mii_config(struct net_device *dev, bool init);
724-
int bcmgenet_mii_probe(struct net_device *dev);
725725
void bcmgenet_mii_exit(struct net_device *dev);
726726
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
727727
void bcmgenet_mii_setup(struct net_device *dev);

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

Lines changed: 51 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,46 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
173173
bcmgenet_fixed_phy_link_update);
174174
}
175175

176+
int bcmgenet_mii_connect(struct net_device *dev)
177+
{
178+
struct bcmgenet_priv *priv = netdev_priv(dev);
179+
struct device_node *dn = priv->pdev->dev.of_node;
180+
struct phy_device *phydev;
181+
u32 phy_flags = 0;
182+
int ret;
183+
184+
/* Communicate the integrated PHY revision */
185+
if (priv->internal_phy)
186+
phy_flags = priv->gphy_rev;
187+
188+
/* Initialize link state variables that bcmgenet_mii_setup() uses */
189+
priv->old_link = -1;
190+
priv->old_speed = -1;
191+
priv->old_duplex = -1;
192+
priv->old_pause = -1;
193+
194+
if (dn) {
195+
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
196+
phy_flags, priv->phy_interface);
197+
if (!phydev) {
198+
pr_err("could not attach to PHY\n");
199+
return -ENODEV;
200+
}
201+
} else {
202+
phydev = dev->phydev;
203+
phydev->dev_flags = phy_flags;
204+
205+
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
206+
priv->phy_interface);
207+
if (ret) {
208+
pr_err("could not attach to PHY\n");
209+
return -ENODEV;
210+
}
211+
}
212+
213+
return 0;
214+
}
215+
176216
int bcmgenet_mii_config(struct net_device *dev, bool init)
177217
{
178218
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -266,71 +306,21 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
266306
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
267307
}
268308

269-
if (init)
270-
dev_info(kdev, "configuring instance for %s\n", phy_name);
271-
272-
return 0;
273-
}
309+
if (init) {
310+
linkmode_copy(phydev->advertising, phydev->supported);
274311

275-
int bcmgenet_mii_probe(struct net_device *dev)
276-
{
277-
struct bcmgenet_priv *priv = netdev_priv(dev);
278-
struct device_node *dn = priv->pdev->dev.of_node;
279-
struct phy_device *phydev;
280-
u32 phy_flags = 0;
281-
int ret;
282-
283-
/* Communicate the integrated PHY revision */
284-
if (priv->internal_phy)
285-
phy_flags = priv->gphy_rev;
286-
287-
/* Initialize link state variables that bcmgenet_mii_setup() uses */
288-
priv->old_link = -1;
289-
priv->old_speed = -1;
290-
priv->old_duplex = -1;
291-
priv->old_pause = -1;
292-
293-
if (dn) {
294-
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
295-
phy_flags, priv->phy_interface);
296-
if (!phydev) {
297-
pr_err("could not attach to PHY\n");
298-
return -ENODEV;
299-
}
300-
} else {
301-
phydev = dev->phydev;
302-
phydev->dev_flags = phy_flags;
303-
304-
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
305-
priv->phy_interface);
306-
if (ret) {
307-
pr_err("could not attach to PHY\n");
308-
return -ENODEV;
309-
}
310-
}
312+
/* The internal PHY has its link interrupts routed to the
313+
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
314+
* that prevents the signaling of link UP interrupts when
315+
* the link operates at 10Mbps, so fallback to polling for
316+
* those versions of GENET.
317+
*/
318+
if (priv->internal_phy && !GENET_IS_V5(priv))
319+
phydev->irq = PHY_IGNORE_INTERRUPT;
311320

312-
/* Configure port multiplexer based on what the probed PHY device since
313-
* reading the 'max-speed' property determines the maximum supported
314-
* PHY speed which is needed for bcmgenet_mii_config() to configure
315-
* things appropriately.
316-
*/
317-
ret = bcmgenet_mii_config(dev, true);
318-
if (ret) {
319-
phy_disconnect(dev->phydev);
320-
return ret;
321+
dev_info(kdev, "configuring instance for %s\n", phy_name);
321322
}
322323

323-
linkmode_copy(phydev->advertising, phydev->supported);
324-
325-
/* The internal PHY has its link interrupts routed to the
326-
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
327-
* that prevents the signaling of link UP interrupts when
328-
* the link operates at 10Mbps, so fallback to polling for
329-
* those versions of GENET.
330-
*/
331-
if (priv->internal_phy && !GENET_IS_V5(priv))
332-
dev->phydev->irq = PHY_IGNORE_INTERRUPT;
333-
334324
return 0;
335325
}
336326

0 commit comments

Comments
 (0)