diff options
Diffstat (limited to 'drivers/of/of_mdio.c')
| -rw-r--r-- | drivers/of/of_mdio.c | 82 |
1 files changed, 47 insertions, 35 deletions
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index e0dbd6e48a98..98258583abb0 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -44,7 +44,7 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id) return -EINVAL; } -static void of_mdiobus_register_phy(struct mii_bus *mdio, +static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child, u32 addr) { struct phy_device *phy; @@ -60,9 +60,13 @@ static void of_mdiobus_register_phy(struct mii_bus *mdio, else phy = get_phy_device(mdio, addr, is_c45); if (IS_ERR(phy)) - return; + return PTR_ERR(phy); - rc = irq_of_parse_and_map(child, 0); + rc = of_irq_get(child, 0); + if (rc == -EPROBE_DEFER) { + phy_device_free(phy); + return rc; + } if (rc > 0) { phy->irq = rc; mdio->irq[addr] = rc; @@ -84,22 +88,23 @@ static void of_mdiobus_register_phy(struct mii_bus *mdio, if (rc) { phy_device_free(phy); of_node_put(child); - return; + return rc; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); + return 0; } -static void of_mdiobus_register_device(struct mii_bus *mdio, - struct device_node *child, u32 addr) +static int of_mdiobus_register_device(struct mii_bus *mdio, + struct device_node *child, u32 addr) { struct mdio_device *mdiodev; int rc; mdiodev = mdio_device_create(mdio, addr); if (IS_ERR(mdiodev)) - return; + return PTR_ERR(mdiodev); /* Associate the OF node with the device structure so it * can be looked up later. @@ -112,11 +117,12 @@ static void of_mdiobus_register_device(struct mii_bus *mdio, if (rc) { mdio_device_free(mdiodev); of_node_put(child); - return; + return rc; } dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n", child->name, addr); + return 0; } /* The following is a list of PHY compatible strings which appear in @@ -166,8 +172,8 @@ static bool of_mdiobus_child_is_phy(struct device_node *child) if (of_match_node(whitelist_phys, child)) { pr_warn(FW_WARN - "%s: Whitelisted compatible string. Please remove\n", - child->full_name); + "%pOF: Whitelisted compatible string. Please remove\n", + child); return true; } @@ -219,9 +225,11 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) } if (of_mdiobus_child_is_phy(child)) - of_mdiobus_register_phy(mdio, child, addr); + rc = of_mdiobus_register_phy(mdio, child, addr); else - of_mdiobus_register_device(mdio, child, addr); + rc = of_mdiobus_register_device(mdio, child, addr); + if (rc) + goto unregister; } if (!scanphys) @@ -242,12 +250,19 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) dev_info(&mdio->dev, "scan phy %s at address %i\n", child->name, addr); - if (of_mdiobus_child_is_phy(child)) - of_mdiobus_register_phy(mdio, child, addr); + if (of_mdiobus_child_is_phy(child)) { + rc = of_mdiobus_register_phy(mdio, child, addr); + if (rc) + goto unregister; + } } } return 0; + +unregister: + mdiobus_unregister(mdio); + return rc; } EXPORT_SYMBOL(of_mdiobus_register); @@ -421,19 +436,14 @@ int of_phy_register_fixed_link(struct device_node *np) { struct fixed_phy_status status = {}; struct device_node *fixed_link_node; - const __be32 *fixed_link_prop; - int link_gpio; - int len, err; - struct phy_device *phy; + u32 fixed_link_prop[5]; const char *managed; + int link_gpio = -1; - err = of_property_read_string(np, "managed", &managed); - if (err == 0) { - if (strcmp(managed, "in-band-status") == 0) { - /* status is zeroed, namely its .link member */ - phy = fixed_phy_register(PHY_POLL, &status, -1, np); - return PTR_ERR_OR_ZERO(phy); - } + if (of_property_read_string(np, "managed", &managed) == 0 && + strcmp(managed, "in-band-status") == 0) { + /* status is zeroed, namely its .link member */ + goto register_phy; } /* New binding */ @@ -456,23 +466,25 @@ int of_phy_register_fixed_link(struct device_node *np) if (link_gpio == -EPROBE_DEFER) return -EPROBE_DEFER; - phy = fixed_phy_register(PHY_POLL, &status, link_gpio, np); - return PTR_ERR_OR_ZERO(phy); + goto register_phy; } /* Old binding */ - fixed_link_prop = of_get_property(np, "fixed-link", &len); - if (fixed_link_prop && len == (5 * sizeof(__be32))) { + if (of_property_read_u32_array(np, "fixed-link", fixed_link_prop, + ARRAY_SIZE(fixed_link_prop)) == 0) { status.link = 1; - status.duplex = be32_to_cpu(fixed_link_prop[1]); - status.speed = be32_to_cpu(fixed_link_prop[2]); - status.pause = be32_to_cpu(fixed_link_prop[3]); - status.asym_pause = be32_to_cpu(fixed_link_prop[4]); - phy = fixed_phy_register(PHY_POLL, &status, -1, np); - return PTR_ERR_OR_ZERO(phy); + status.duplex = fixed_link_prop[1]; + status.speed = fixed_link_prop[2]; + status.pause = fixed_link_prop[3]; + status.asym_pause = fixed_link_prop[4]; + goto register_phy; } return -ENODEV; + +register_phy: + return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, link_gpio, + np)); } EXPORT_SYMBOL(of_phy_register_fixed_link); |