Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bcm7xxx_workaround'

Florian Fainelli says:

====================
net: phy: bcm7xxx initial read/write workaround

This patch series fixes occasional BCM7xxx PHY driver binding failure due
to a harware bug where the first read or write does not come out of the PHY
MDIO management controller.

Since we have two different MDIO controllers using this PHY, a similar
need to be replicated in GENET and UniMAC MDIO.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+101 -4
+1
drivers/net/ethernet/broadcom/genet/bcmgenet.h
··· 594 594 wait_queue_head_t wq; 595 595 struct phy_device *phydev; 596 596 struct device_node *phy_dn; 597 + struct device_node *mdio_dn; 597 598 struct mii_bus *mii_bus; 598 599 u16 gphy_rev; 599 600 struct clk *clk_eee;
+50 -4
drivers/net/ethernet/broadcom/genet/bcmmii.c
··· 408 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 + */ 426 + static 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 + 411 457 static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv) 412 458 { 413 459 struct mii_bus *bus; ··· 473 427 bus->parent = &priv->pdev->dev; 474 428 bus->read = bcmgenet_mii_read; 475 429 bus->write = bcmgenet_mii_write; 430 + bus->reset = bcmgenet_mii_bus_reset; 476 431 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", 477 432 priv->pdev->name, priv->pdev->id); 478 433 ··· 490 443 { 491 444 struct device_node *dn = priv->pdev->dev.of_node; 492 445 struct device *kdev = &priv->pdev->dev; 493 - struct device_node *mdio_dn; 494 446 char *compat; 495 447 int ret; 496 448 ··· 497 451 if (!compat) 498 452 return -ENOMEM; 499 453 500 - mdio_dn = of_find_compatible_node(dn, NULL, compat); 454 + priv->mdio_dn = of_find_compatible_node(dn, NULL, compat); 501 455 kfree(compat); 502 - if (!mdio_dn) { 456 + if (!priv->mdio_dn) { 503 457 dev_err(kdev, "unable to find MDIO bus node\n"); 504 458 return -ENODEV; 505 459 } 506 460 507 - ret = of_mdiobus_register(priv->mii_bus, mdio_dn); 461 + ret = of_mdiobus_register(priv->mii_bus, priv->mdio_dn); 508 462 if (ret) { 509 463 dev_err(kdev, "failed to register MDIO bus\n"); 510 464 return ret;
+7
drivers/net/phy/bcm7xxx.c
··· 246 246 pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n", 247 247 dev_name(&phydev->dev), phydev->drv->name, rev, patch); 248 248 249 + /* Dummy read to a register to workaround an issue upon reset where the 250 + * internal inverter may not allow the first MDIO transaction to pass 251 + * the MDIO management controller and make us return 0xffff for such 252 + * reads. 253 + */ 254 + phy_read(phydev, MII_BMSR); 255 + 249 256 switch (rev) { 250 257 case 0xb0: 251 258 ret = bcm7xxx_28nm_b0_afe_config_init(phydev);
+43
drivers/net/phy/mdio-bcm-unimac.c
··· 120 120 return 0; 121 121 } 122 122 123 + /* Workaround for integrated BCM7xxx Gigabit PHYs which have a problem with 124 + * their internal MDIO management controller making them fail to successfully 125 + * be read from or written to for the first transaction. We insert a dummy 126 + * BMSR read here to make sure that phy_get_device() and get_phy_id() can 127 + * correctly read the PHY MII_PHYSID1/2 registers and successfully register a 128 + * PHY device for this peripheral. 129 + * 130 + * Once the PHY driver is registered, we can workaround subsequent reads from 131 + * there (e.g: during system-wide power management). 132 + * 133 + * bus->reset is invoked before mdiobus_scan during mdiobus_register and is 134 + * therefore the right location to stick that workaround. Since we do not want 135 + * to read from non-existing PHYs, we either use bus->phy_mask or do a manual 136 + * Device Tree scan to limit the search area. 137 + */ 138 + static int unimac_mdio_reset(struct mii_bus *bus) 139 + { 140 + struct device_node *np = bus->dev.of_node; 141 + struct device_node *child; 142 + u32 read_mask = 0; 143 + int addr; 144 + 145 + if (!np) { 146 + read_mask = ~bus->phy_mask; 147 + } else { 148 + for_each_available_child_of_node(np, child) { 149 + addr = of_mdio_parse_addr(&bus->dev, child); 150 + if (addr < 0) 151 + continue; 152 + 153 + read_mask |= 1 << addr; 154 + } 155 + } 156 + 157 + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { 158 + if (read_mask & 1 << addr) 159 + mdiobus_read(bus, addr, MII_BMSR); 160 + } 161 + 162 + return 0; 163 + } 164 + 123 165 static int unimac_mdio_probe(struct platform_device *pdev) 124 166 { 125 167 struct unimac_mdio_priv *priv; ··· 197 155 bus->parent = &pdev->dev; 198 156 bus->read = unimac_mdio_read; 199 157 bus->write = unimac_mdio_write; 158 + bus->reset = unimac_mdio_reset; 200 159 snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); 201 160 202 161 bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);