diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/genet/bcmmii.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmmii.c | 111 |
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 | ||
166 | void bcmgenet_mii_reset(struct net_device *dev) | 166 | static 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 | ||
176 | void bcmgenet_phy_power_set(struct net_device *dev, bool enable) | 175 | void 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 | ||
221 | static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) | 219 | static 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 | ||
231 | int bcmgenet_mii_config(struct net_device *dev, bool init) | 233 | int 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 | ||
330 | static int bcmgenet_mii_probe(struct net_device *dev) | 331 | int 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 | ||
522 | static 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) | |||
626 | out: | 630 | out: |
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); |
629 | out_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; |