aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/genet/bcmmii.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/broadcom/genet/bcmmii.c')
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c111
1 files changed, 57 insertions, 54 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index adf23d2ac488..b3679ad1c1c7 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -163,14 +163,13 @@ void bcmgenet_mii_setup(struct net_device *dev)
163 phy_print_status(phydev); 163 phy_print_status(phydev);
164} 164}
165 165
166void bcmgenet_mii_reset(struct net_device *dev) 166static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
167 struct fixed_phy_status *status)
167{ 168{
168 struct bcmgenet_priv *priv = netdev_priv(dev); 169 if (dev && dev->phydev && status)
170 status->link = dev->phydev->link;
169 171
170 if (priv->phydev) { 172 return 0;
171 phy_init_hw(priv->phydev);
172 phy_start_aneg(priv->phydev);
173 }
174} 173}
175 174
176void bcmgenet_phy_power_set(struct net_device *dev, bool enable) 175void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
@@ -215,7 +214,6 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev)
215 reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); 214 reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
216 reg |= EXT_PWR_DN_EN_LD; 215 reg |= EXT_PWR_DN_EN_LD;
217 bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); 216 bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
218 bcmgenet_mii_reset(dev);
219} 217}
220 218
221static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) 219static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
@@ -226,9 +224,13 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
226 reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL); 224 reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
227 reg |= LED_ACT_SOURCE_MAC; 225 reg |= LED_ACT_SOURCE_MAC;
228 bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL); 226 bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
227
228 if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
229 fixed_phy_set_link_update(priv->phydev,
230 bcmgenet_fixed_phy_link_update);
229} 231}
230 232
231int bcmgenet_mii_config(struct net_device *dev, bool init) 233int bcmgenet_mii_config(struct net_device *dev)
232{ 234{
233 struct bcmgenet_priv *priv = netdev_priv(dev); 235 struct bcmgenet_priv *priv = netdev_priv(dev);
234 struct phy_device *phydev = priv->phydev; 236 struct phy_device *phydev = priv->phydev;
@@ -238,10 +240,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
238 u32 port_ctrl; 240 u32 port_ctrl;
239 u32 reg; 241 u32 reg;
240 242
241 priv->ext_phy = !phy_is_internal(priv->phydev) && 243 priv->ext_phy = !priv->internal_phy &&
242 (priv->phy_interface != PHY_INTERFACE_MODE_MOCA); 244 (priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
243 245
244 if (phy_is_internal(priv->phydev)) 246 if (priv->internal_phy)
245 priv->phy_interface = PHY_INTERFACE_MODE_NA; 247 priv->phy_interface = PHY_INTERFACE_MODE_NA;
246 248
247 switch (priv->phy_interface) { 249 switch (priv->phy_interface) {
@@ -259,7 +261,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
259 261
260 bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); 262 bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
261 263
262 if (phy_is_internal(priv->phydev)) { 264 if (priv->internal_phy) {
263 phy_name = "internal PHY"; 265 phy_name = "internal PHY";
264 bcmgenet_internal_phy_setup(dev); 266 bcmgenet_internal_phy_setup(dev);
265 } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { 267 } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
@@ -321,13 +323,12 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
321 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); 323 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
322 } 324 }
323 325
324 if (init) 326 dev_info_once(kdev, "configuring instance for %s\n", phy_name);
325 dev_info(kdev, "configuring instance for %s\n", phy_name);
326 327
327 return 0; 328 return 0;
328} 329}
329 330
330static int bcmgenet_mii_probe(struct net_device *dev) 331int bcmgenet_mii_probe(struct net_device *dev)
331{ 332{
332 struct bcmgenet_priv *priv = netdev_priv(dev); 333 struct bcmgenet_priv *priv = netdev_priv(dev);
333 struct device_node *dn = priv->pdev->dev.of_node; 334 struct device_node *dn = priv->pdev->dev.of_node;
@@ -345,22 +346,6 @@ static int bcmgenet_mii_probe(struct net_device *dev)
345 priv->old_pause = -1; 346 priv->old_pause = -1;
346 347
347 if (dn) { 348 if (dn) {
348 if (priv->phydev) {
349 pr_info("PHY already attached\n");
350 return 0;
351 }
352
353 /* In the case of a fixed PHY, the DT node associated
354 * to the PHY is the Ethernet MAC DT node.
355 */
356 if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
357 ret = of_phy_register_fixed_link(dn);
358 if (ret)
359 return ret;
360
361 priv->phy_dn = of_node_get(dn);
362 }
363
364 phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 349 phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
365 phy_flags, priv->phy_interface); 350 phy_flags, priv->phy_interface);
366 if (!phydev) { 351 if (!phydev) {
@@ -386,7 +371,7 @@ static int bcmgenet_mii_probe(struct net_device *dev)
386 * PHY speed which is needed for bcmgenet_mii_config() to configure 371 * PHY speed which is needed for bcmgenet_mii_config() to configure
387 * things appropriately. 372 * things appropriately.
388 */ 373 */
389 ret = bcmgenet_mii_config(dev, true); 374 ret = bcmgenet_mii_config(dev);
390 if (ret) { 375 if (ret) {
391 phy_disconnect(priv->phydev); 376 phy_disconnect(priv->phydev);
392 return ret; 377 return ret;
@@ -397,14 +382,11 @@ static int bcmgenet_mii_probe(struct net_device *dev)
397 /* The internal PHY has its link interrupts routed to the 382 /* The internal PHY has its link interrupts routed to the
398 * Ethernet MAC ISRs 383 * Ethernet MAC ISRs
399 */ 384 */
400 if (phy_is_internal(priv->phydev)) 385 if (priv->internal_phy)
401 priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT; 386 priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT;
402 else 387 else
403 priv->mii_bus->irq[phydev->addr] = PHY_POLL; 388 priv->mii_bus->irq[phydev->addr] = PHY_POLL;
404 389
405 pr_info("attached PHY at address %d [%s]\n",
406 phydev->addr, phydev->drv->name);
407
408 return 0; 390 return 0;
409} 391}
410 392
@@ -490,7 +472,10 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
490{ 472{
491 struct device_node *dn = priv->pdev->dev.of_node; 473 struct device_node *dn = priv->pdev->dev.of_node;
492 struct device *kdev = &priv->pdev->dev; 474 struct device *kdev = &priv->pdev->dev;
475 const char *phy_mode_str = NULL;
476 struct phy_device *phydev = NULL;
493 char *compat; 477 char *compat;
478 int phy_mode;
494 int ret; 479 int ret;
495 480
496 compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version); 481 compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
@@ -513,17 +498,43 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
513 /* Fetch the PHY phandle */ 498 /* Fetch the PHY phandle */
514 priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0); 499 priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
515 500
501 /* In the case of a fixed PHY, the DT node associated
502 * to the PHY is the Ethernet MAC DT node.
503 */
504 if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
505 ret = of_phy_register_fixed_link(dn);
506 if (ret)
507 return ret;
508
509 priv->phy_dn = of_node_get(dn);
510 }
511
516 /* Get the link mode */ 512 /* Get the link mode */
517 priv->phy_interface = of_get_phy_mode(dn); 513 phy_mode = of_get_phy_mode(dn);
514 priv->phy_interface = phy_mode;
518 515
519 return 0; 516 /* We need to specifically look up whether this PHY interface is internal
520} 517 * or not *before* we even try to probe the PHY driver over MDIO as we
518 * may have shut down the internal PHY for power saving purposes.
519 */
520 if (phy_mode < 0) {
521 ret = of_property_read_string(dn, "phy-mode", &phy_mode_str);
522 if (ret < 0) {
523 dev_err(kdev, "invalid PHY mode property\n");
524 return ret;
525 }
521 526
522static int bcmgenet_fixed_phy_link_update(struct net_device *dev, 527 priv->phy_interface = PHY_INTERFACE_MODE_NA;
523 struct fixed_phy_status *status) 528 if (!strcasecmp(phy_mode_str, "internal"))
524{ 529 priv->internal_phy = true;
525 if (dev && dev->phydev && status) 530 }
526 status->link = dev->phydev->link; 531
532 /* Make sure we initialize MoCA PHYs with a link down */
533 if (phy_mode == PHY_INTERFACE_MODE_MOCA) {
534 phydev = of_phy_find_device(dn);
535 if (phydev)
536 phydev->link = 0;
537 }
527 538
528 return 0; 539 return 0;
529} 540}
@@ -580,12 +591,9 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
580 return -ENODEV; 591 return -ENODEV;
581 } 592 }
582 593
583 if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET) { 594 /* Make sure we initialize MoCA PHYs with a link down */
584 ret = fixed_phy_set_link_update( 595 phydev->link = 0;
585 phydev, bcmgenet_fixed_phy_link_update); 596
586 if (!ret)
587 phydev->link = 0;
588 }
589 } 597 }
590 598
591 priv->phydev = phydev; 599 priv->phydev = phydev;
@@ -615,10 +623,6 @@ int bcmgenet_mii_init(struct net_device *dev)
615 623
616 ret = bcmgenet_mii_bus_init(priv); 624 ret = bcmgenet_mii_bus_init(priv);
617 if (ret) 625 if (ret)
618 goto out_free;
619
620 ret = bcmgenet_mii_probe(dev);
621 if (ret)
622 goto out; 626 goto out;
623 627
624 return 0; 628 return 0;
@@ -626,7 +630,6 @@ int bcmgenet_mii_init(struct net_device *dev)
626out: 630out:
627 of_node_put(priv->phy_dn); 631 of_node_put(priv->phy_dn);
628 mdiobus_unregister(priv->mii_bus); 632 mdiobus_unregister(priv->mii_bus);
629out_free:
630 kfree(priv->mii_bus->irq); 633 kfree(priv->mii_bus->irq);
631 mdiobus_free(priv->mii_bus); 634 mdiobus_free(priv->mii_bus);
632 return ret; 635 return ret;