Skip to content

Commit cc59dbc

Browse files
committed
Merge branch 'net-bcmgenet-restore-internal-EPHY-support'
Doug Berger says: ==================== net: bcmgenet: restore internal EPHY support (part 2) This is a follow up to my previous submission (see [1]). The first commit provides what is intended to be a complete solution for the issues that can result from insufficient clocking of the MAC during reset of its state machines. It should be backported to the stable releases. It is intended to replace the partial solution of commit 1f51548 ("net: bcmgenet: soft reset 40nm EPHYs before MAC init") which is reverted by the second commit of this series and should not be back- ported as noted in [2]. The third commit corrects a timing hazard with a polled PHY that can occur when the MAC resumes and also when a v3 internal EPHY is reset by the change in commit 25382b9 ("net: bcmgenet: reset 40nm EPHY on energy detect"). It is expected that commit 25382b9 be back- ported to stable first before backporting this commit. [1] https://lkml.org/lkml/2019/10/16/1706 [2] https://lkml.org/lkml/2019/10/31/749 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 2836654 + 0686bd9 commit cc59dbc

File tree

3 files changed

+110
-72
lines changed

3 files changed

+110
-72
lines changed

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

Lines changed: 15 additions & 20 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)
@@ -2614,8 +2612,10 @@ static void bcmgenet_irq_task(struct work_struct *work)
26142612
spin_unlock_irq(&priv->lock);
26152613

26162614
if (status & UMAC_IRQ_PHY_DET_R &&
2617-
priv->dev->phydev->autoneg != AUTONEG_ENABLE)
2615+
priv->dev->phydev->autoneg != AUTONEG_ENABLE) {
26182616
phy_init_hw(priv->dev->phydev);
2617+
genphy_config_aneg(priv->dev->phydev);
2618+
}
26192619

26202620
/* Link UP/DOWN event */
26212621
if (status & UMAC_IRQ_LINK_EVENT)
@@ -2879,12 +2879,6 @@ static int bcmgenet_open(struct net_device *dev)
28792879
if (priv->internal_phy)
28802880
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
28812881

2882-
ret = bcmgenet_mii_connect(dev);
2883-
if (ret) {
2884-
netdev_err(dev, "failed to connect to PHY\n");
2885-
goto err_clk_disable;
2886-
}
2887-
28882882
/* take MAC out of reset */
28892883
bcmgenet_umac_reset(priv);
28902884

@@ -2894,12 +2888,6 @@ static int bcmgenet_open(struct net_device *dev)
28942888
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
28952889
priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
28962890

2897-
ret = bcmgenet_mii_config(dev, true);
2898-
if (ret) {
2899-
netdev_err(dev, "unsupported PHY\n");
2900-
goto err_disconnect_phy;
2901-
}
2902-
29032891
bcmgenet_set_hw_addr(priv, dev->dev_addr);
29042892

29052893
if (priv->internal_phy) {
@@ -2915,7 +2903,7 @@ static int bcmgenet_open(struct net_device *dev)
29152903
ret = bcmgenet_init_dma(priv);
29162904
if (ret) {
29172905
netdev_err(dev, "failed to initialize DMA\n");
2918-
goto err_disconnect_phy;
2906+
goto err_clk_disable;
29192907
}
29202908

29212909
/* Always enable ring 16 - descriptor ring */
@@ -2938,19 +2926,25 @@ static int bcmgenet_open(struct net_device *dev)
29382926
goto err_irq0;
29392927
}
29402928

2929+
ret = bcmgenet_mii_probe(dev);
2930+
if (ret) {
2931+
netdev_err(dev, "failed to connect to PHY\n");
2932+
goto err_irq1;
2933+
}
2934+
29412935
bcmgenet_netif_start(dev);
29422936

29432937
netif_tx_start_all_queues(dev);
29442938

29452939
return 0;
29462940

2941+
err_irq1:
2942+
free_irq(priv->irq1, priv);
29472943
err_irq0:
29482944
free_irq(priv->irq0, priv);
29492945
err_fini_dma:
29502946
bcmgenet_dma_teardown(priv);
29512947
bcmgenet_fini_dma(priv);
2952-
err_disconnect_phy:
2953-
phy_disconnect(dev->phydev);
29542948
err_clk_disable:
29552949
if (priv->internal_phy)
29562950
bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
@@ -3631,8 +3625,6 @@ static int bcmgenet_resume(struct device *d)
36313625
if (priv->internal_phy)
36323626
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
36333627

3634-
phy_init_hw(dev->phydev);
3635-
36363628
bcmgenet_umac_reset(priv);
36373629

36383630
init_umac(priv);
@@ -3641,7 +3633,10 @@ static int bcmgenet_resume(struct device *d)
36413633
if (priv->wolopts)
36423634
clk_disable_unprepare(priv->clk_wol);
36433635

3636+
phy_init_hw(dev->phydev);
3637+
36443638
/* Speed settings must be restored */
3639+
genphy_config_aneg(dev->phydev);
36453640
bcmgenet_mii_config(priv->dev, false);
36463641

36473642
bcmgenet_set_hw_addr(priv, dev->dev_addr);

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);
724723
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: 94 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -173,46 +173,6 @@ 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-
216176
int bcmgenet_mii_config(struct net_device *dev, bool init)
217177
{
218178
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -221,8 +181,38 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
221181
const char *phy_name = NULL;
222182
u32 id_mode_dis = 0;
223183
u32 port_ctrl;
184+
int bmcr = -1;
185+
int ret;
224186
u32 reg;
225187

188+
/* MAC clocking workaround during reset of umac state machines */
189+
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
190+
if (reg & CMD_SW_RESET) {
191+
/* An MII PHY must be isolated to prevent TXC contention */
192+
if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
193+
ret = phy_read(phydev, MII_BMCR);
194+
if (ret >= 0) {
195+
bmcr = ret;
196+
ret = phy_write(phydev, MII_BMCR,
197+
bmcr | BMCR_ISOLATE);
198+
}
199+
if (ret) {
200+
netdev_err(dev, "failed to isolate PHY\n");
201+
return ret;
202+
}
203+
}
204+
/* Switch MAC clocking to RGMII generated clock */
205+
bcmgenet_sys_writel(priv, PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
206+
/* Ensure 5 clks with Rx disabled
207+
* followed by 5 clks with Reset asserted
208+
*/
209+
udelay(4);
210+
reg &= ~(CMD_SW_RESET | CMD_LCL_LOOP_EN);
211+
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
212+
/* Ensure 5 more clocks before Rx is enabled */
213+
udelay(2);
214+
}
215+
226216
priv->ext_phy = !priv->internal_phy &&
227217
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
228218

@@ -254,6 +244,9 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
254244
phy_set_max_speed(phydev, SPEED_100);
255245
bcmgenet_sys_writel(priv,
256246
PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
247+
/* Restore the MII PHY after isolation */
248+
if (bmcr >= 0)
249+
phy_write(phydev, MII_BMCR, bmcr);
257250
break;
258251

259252
case PHY_INTERFACE_MODE_REVMII:
@@ -306,21 +299,71 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
306299
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
307300
}
308301

309-
if (init) {
310-
linkmode_copy(phydev->advertising, phydev->supported);
302+
if (init)
303+
dev_info(kdev, "configuring instance for %s\n", phy_name);
311304

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;
305+
return 0;
306+
}
320307

321-
dev_info(kdev, "configuring instance for %s\n", phy_name);
308+
int bcmgenet_mii_probe(struct net_device *dev)
309+
{
310+
struct bcmgenet_priv *priv = netdev_priv(dev);
311+
struct device_node *dn = priv->pdev->dev.of_node;
312+
struct phy_device *phydev;
313+
u32 phy_flags = 0;
314+
int ret;
315+
316+
/* Communicate the integrated PHY revision */
317+
if (priv->internal_phy)
318+
phy_flags = priv->gphy_rev;
319+
320+
/* Initialize link state variables that bcmgenet_mii_setup() uses */
321+
priv->old_link = -1;
322+
priv->old_speed = -1;
323+
priv->old_duplex = -1;
324+
priv->old_pause = -1;
325+
326+
if (dn) {
327+
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
328+
phy_flags, priv->phy_interface);
329+
if (!phydev) {
330+
pr_err("could not attach to PHY\n");
331+
return -ENODEV;
332+
}
333+
} else {
334+
phydev = dev->phydev;
335+
phydev->dev_flags = phy_flags;
336+
337+
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
338+
priv->phy_interface);
339+
if (ret) {
340+
pr_err("could not attach to PHY\n");
341+
return -ENODEV;
342+
}
322343
}
323344

345+
/* Configure port multiplexer based on what the probed PHY device since
346+
* reading the 'max-speed' property determines the maximum supported
347+
* PHY speed which is needed for bcmgenet_mii_config() to configure
348+
* things appropriately.
349+
*/
350+
ret = bcmgenet_mii_config(dev, true);
351+
if (ret) {
352+
phy_disconnect(dev->phydev);
353+
return ret;
354+
}
355+
356+
linkmode_copy(phydev->advertising, phydev->supported);
357+
358+
/* The internal PHY has its link interrupts routed to the
359+
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
360+
* that prevents the signaling of link UP interrupts when
361+
* the link operates at 10Mbps, so fallback to polling for
362+
* those versions of GENET.
363+
*/
364+
if (priv->internal_phy && !GENET_IS_V5(priv))
365+
dev->phydev->irq = PHY_IGNORE_INTERRUPT;
366+
324367
return 0;
325368
}
326369

0 commit comments

Comments
 (0)