diff options
Diffstat (limited to 'drivers/net/mdio/of_mdio.c')
| -rw-r--r-- | drivers/net/mdio/of_mdio.c | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c index 510822d6d0d9..b8d298c04d3f 100644 --- a/drivers/net/mdio/of_mdio.c +++ b/drivers/net/mdio/of_mdio.c @@ -25,6 +25,7 @@ MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("OpenFirmware MDIO bus (Ethernet PHY) accessors"); /* Extract the clause 22 phy ID from the compatible string of the form * ethernet-phy-idAAAA.BBBB */ @@ -62,14 +63,11 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, /* Associate the OF node with the device structure so it * can be looked up later. */ - fwnode_handle_get(fwnode); - device_set_node(&mdiodev->dev, fwnode); + device_set_node(&mdiodev->dev, fwnode_handle_get(fwnode)); /* All data is now stored in the mdiodev struct; register it. */ rc = mdio_device_register(mdiodev); if (rc) { - device_set_node(&mdiodev->dev, NULL); - fwnode_handle_put(fwnode); mdio_device_free(mdiodev); return rc; } @@ -131,29 +129,78 @@ bool of_mdiobus_child_is_phy(struct device_node *child) return true; } - if (!of_find_property(child, "compatible", NULL)) + if (!of_property_present(child, "compatible")) return true; return false; } EXPORT_SYMBOL(of_mdiobus_child_is_phy); +static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, + bool *scanphys) +{ + struct device_node *child; + int addr, rc = 0; + + /* Loop over the child nodes and register a phy_device for each phy */ + for_each_available_child_of_node(np, child) { + if (of_node_name_eq(child, "ethernet-phy-package")) { + /* Ignore invalid ethernet-phy-package node */ + if (!of_property_present(child, "reg")) + continue; + + rc = __of_mdiobus_parse_phys(mdio, child, NULL); + if (rc && rc != -ENODEV) + goto exit; + + continue; + } + + addr = of_mdio_parse_addr(&mdio->dev, child); + if (addr < 0) { + /* Skip scanning for invalid ethernet-phy-package node */ + if (scanphys) + *scanphys = true; + continue; + } + + if (of_mdiobus_child_is_phy(child)) + rc = of_mdiobus_register_phy(mdio, child, addr); + else + rc = of_mdiobus_register_device(mdio, child, addr); + + if (rc == -ENODEV) + dev_err(&mdio->dev, + "MDIO device at address %d is missing.\n", + addr); + else if (rc) + goto exit; + } + + return 0; +exit: + of_node_put(child); + return rc; +} + /** - * of_mdiobus_register - Register mii_bus and create PHYs from the device tree + * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree * @mdio: pointer to mii_bus structure * @np: pointer to device_node of MDIO bus. + * @owner: module owning the @mdio object. * * This function registers the mii_bus structure and registers a phy_device * for each child node of @np. */ -int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, + struct module *owner) { struct device_node *child; bool scanphys = false; int addr, rc; if (!np) - return mdiobus_register(mdio); + return __mdiobus_register(mdio, owner); /* Do not continue if the node is disabled */ if (!of_device_is_available(np)) @@ -172,38 +219,23 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) of_property_read_u32(np, "reset-post-delay-us", &mdio->reset_post_delay_us); /* Register the MDIO bus */ - rc = mdiobus_register(mdio); + rc = __mdiobus_register(mdio, owner); if (rc) return rc; /* Loop over the child nodes and register a phy_device for each phy */ - for_each_available_child_of_node(np, child) { - addr = of_mdio_parse_addr(&mdio->dev, child); - if (addr < 0) { - scanphys = true; - continue; - } - - if (of_mdiobus_child_is_phy(child)) - rc = of_mdiobus_register_phy(mdio, child, addr); - else - rc = of_mdiobus_register_device(mdio, child, addr); - - if (rc == -ENODEV) - dev_err(&mdio->dev, - "MDIO device at address %d is missing.\n", - addr); - else if (rc) - goto unregister; - } + rc = __of_mdiobus_parse_phys(mdio, np, &scanphys); + if (rc) + goto unregister; if (!scanphys) return 0; /* auto scan for PHYs with empty reg property */ for_each_available_child_of_node(np, child) { - /* Skip PHYs with reg property set */ - if (of_find_property(child, "reg", NULL)) + /* Skip PHYs with reg property set or ethernet-phy-package node */ + if (of_property_present(child, "reg") || + of_node_name_eq(child, "ethernet-phy-package")) continue; for (addr = 0; addr < PHY_MAX_ADDR; addr++) { @@ -224,19 +256,20 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) if (!rc) break; if (rc != -ENODEV) - goto unregister; + goto put_unregister; } } } return 0; -unregister: +put_unregister: of_node_put(child); +unregister: mdiobus_unregister(mdio); return rc; } -EXPORT_SYMBOL(of_mdiobus_register); +EXPORT_SYMBOL(__of_mdiobus_register); /** * of_mdio_find_device - Given a device tree node, find the mdio_device @@ -354,7 +387,7 @@ EXPORT_SYMBOL(of_phy_get_and_connect); bool of_phy_is_fixed_link(struct device_node *np) { struct device_node *dn; - int len, err; + int err; const char *managed; /* New binding */ @@ -369,8 +402,7 @@ bool of_phy_is_fixed_link(struct device_node *np) return true; /* Old binding */ - if (of_get_property(np, "fixed-link", &len) && - len == (5 * sizeof(__be32))) + if (of_property_count_u32_elems(np, "fixed-link") == 5) return true; return false; @@ -412,6 +444,8 @@ int of_phy_register_fixed_link(struct device_node *np) /* Old binding */ if (of_property_read_u32_array(np, "fixed-link", fixed_link_prop, ARRAY_SIZE(fixed_link_prop)) == 0) { + pr_warn_once("%pOF uses deprecated array-style fixed-link binding!\n", + np); status.link = 1; status.duplex = fixed_link_prop[1]; status.speed = fixed_link_prop[2]; @@ -423,7 +457,7 @@ int of_phy_register_fixed_link(struct device_node *np) return -ENODEV; register_phy: - return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, np)); + return PTR_ERR_OR_ZERO(fixed_phy_register(&status, np)); } EXPORT_SYMBOL(of_phy_register_fixed_link); @@ -438,6 +472,5 @@ void of_phy_deregister_fixed_link(struct device_node *np) fixed_phy_unregister(phydev); put_device(&phydev->mdio.dev); /* of_phy_find_device() */ - phy_device_free(phydev); /* fixed_phy_register() */ } EXPORT_SYMBOL(of_phy_deregister_fixed_link); |
