summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2015-06-26 13:39:05 -0400
committerDavid S. Miller <davem@davemloft.net>2015-06-28 23:28:20 -0400
commit7b635da86821005cd131369b7a4268df8067cc6c (patch)
tree80e2c8d5e756a9d632cd4b1ca0cb6d9927376dad /drivers/net
parent8e346e1594bab6c06b6b4d2938c881729b03041d (diff)
net: bcmgenet: workaround initial read failures for integrated PHYs
All BCM7xxx integrated Gigabit PHYs have an issue in their MDIO management controller which will make the initial read or write to them to fail and return 0xffff. This is a real issue as the typical first thing we do is read from MII_PHYSID1 and MII_PHYSID2 from get_phy_id() to register a driver for these PHYs. Coupled with the workaround in drivers/net/phy/bcm7xxx.c, this workaround for the MDIO bus controller consists in scanning the list of PHYs to do this initial read workaround for as part of the MDIO bus reset routine which is invoked prior to mdiobus_scan(). Once we have a proper PHY driver/device registered, all workarounds are located there (e.g: power management suspend/resume calls). Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h1
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c54
2 files changed, 51 insertions, 4 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index 6f2887a5e0be..6159deab8c98 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -594,6 +594,7 @@ struct bcmgenet_priv {
594 wait_queue_head_t wq; 594 wait_queue_head_t wq;
595 struct phy_device *phydev; 595 struct phy_device *phydev;
596 struct device_node *phy_dn; 596 struct device_node *phy_dn;
597 struct device_node *mdio_dn;
597 struct mii_bus *mii_bus; 598 struct mii_bus *mii_bus;
598 u16 gphy_rev; 599 u16 gphy_rev;
599 struct clk *clk_eee; 600 struct clk *clk_eee;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 6bef04e2f735..adf23d2ac488 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -408,6 +408,52 @@ static int bcmgenet_mii_probe(struct net_device *dev)
408 return 0; 408 return 0;
409} 409}
410 410
411/* Workaround for integrated BCM7xxx Gigabit PHYs which have a problem with
412 * their internal MDIO management controller making them fail to successfully
413 * be read from or written to for the first transaction. We insert a dummy
414 * BMSR read here to make sure that phy_get_device() and get_phy_id() can
415 * correctly read the PHY MII_PHYSID1/2 registers and successfully register a
416 * PHY device for this peripheral.
417 *
418 * Once the PHY driver is registered, we can workaround subsequent reads from
419 * there (e.g: during system-wide power management).
420 *
421 * bus->reset is invoked before mdiobus_scan during mdiobus_register and is
422 * therefore the right location to stick that workaround. Since we do not want
423 * to read from non-existing PHYs, we either use bus->phy_mask or do a manual
424 * Device Tree scan to limit the search area.
425 */
426static int bcmgenet_mii_bus_reset(struct mii_bus *bus)
427{
428 struct net_device *dev = bus->priv;
429 struct bcmgenet_priv *priv = netdev_priv(dev);
430 struct device_node *np = priv->mdio_dn;
431 struct device_node *child = NULL;
432 u32 read_mask = 0;
433 int addr = 0;
434
435 if (!np) {
436 read_mask = 1 << priv->phy_addr;
437 } else {
438 for_each_available_child_of_node(np, child) {
439 addr = of_mdio_parse_addr(&dev->dev, child);
440 if (addr < 0)
441 continue;
442
443 read_mask |= 1 << addr;
444 }
445 }
446
447 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
448 if (read_mask & 1 << addr) {
449 dev_dbg(&dev->dev, "Workaround for PHY @ %d\n", addr);
450 mdiobus_read(bus, addr, MII_BMSR);
451 }
452 }
453
454 return 0;
455}
456
411static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv) 457static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv)
412{ 458{
413 struct mii_bus *bus; 459 struct mii_bus *bus;
@@ -427,6 +473,7 @@ static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv)
427 bus->parent = &priv->pdev->dev; 473 bus->parent = &priv->pdev->dev;
428 bus->read = bcmgenet_mii_read; 474 bus->read = bcmgenet_mii_read;
429 bus->write = bcmgenet_mii_write; 475 bus->write = bcmgenet_mii_write;
476 bus->reset = bcmgenet_mii_bus_reset;
430 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", 477 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d",
431 priv->pdev->name, priv->pdev->id); 478 priv->pdev->name, priv->pdev->id);
432 479
@@ -443,7 +490,6 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
443{ 490{
444 struct device_node *dn = priv->pdev->dev.of_node; 491 struct device_node *dn = priv->pdev->dev.of_node;
445 struct device *kdev = &priv->pdev->dev; 492 struct device *kdev = &priv->pdev->dev;
446 struct device_node *mdio_dn;
447 char *compat; 493 char *compat;
448 int ret; 494 int ret;
449 495
@@ -451,14 +497,14 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
451 if (!compat) 497 if (!compat)
452 return -ENOMEM; 498 return -ENOMEM;
453 499
454 mdio_dn = of_find_compatible_node(dn, NULL, compat); 500 priv->mdio_dn = of_find_compatible_node(dn, NULL, compat);
455 kfree(compat); 501 kfree(compat);
456 if (!mdio_dn) { 502 if (!priv->mdio_dn) {
457 dev_err(kdev, "unable to find MDIO bus node\n"); 503 dev_err(kdev, "unable to find MDIO bus node\n");
458 return -ENODEV; 504 return -ENODEV;
459 } 505 }
460 506
461 ret = of_mdiobus_register(priv->mii_bus, mdio_dn); 507 ret = of_mdiobus_register(priv->mii_bus, priv->mdio_dn);
462 if (ret) { 508 if (ret) {
463 dev_err(kdev, "failed to register MDIO bus\n"); 509 dev_err(kdev, "failed to register MDIO bus\n");
464 return ret; 510 return ret;