diff options
Diffstat (limited to 'drivers/of/of_mdio.c')
-rw-r--r-- | drivers/of/of_mdio.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 86829f8064a6..8453f08d2ef4 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -56,7 +56,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi phy = phy_device_create(mdio, addr, phy_id, 0, NULL); else phy = get_phy_device(mdio, addr, is_c45); - if (!phy || IS_ERR(phy)) + if (IS_ERR_OR_NULL(phy)) return 1; rc = irq_of_parse_and_map(child, 0); @@ -98,7 +98,7 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, int rc; mdiodev = mdio_device_create(mdio, addr); - if (!mdiodev || IS_ERR(mdiodev)) + if (IS_ERR(mdiodev)) return 1; /* Associate the OF node with the device structure so it @@ -143,11 +143,32 @@ int of_mdio_parse_addr(struct device *dev, const struct device_node *np) } EXPORT_SYMBOL(of_mdio_parse_addr); +/* The following is a list of PHY compatible strings which appear in + * some DTBs. The compatible string is never matched against a PHY + * driver, so is pointless. We only expect devices which are not PHYs + * to have a compatible string, so they can be matched to an MDIO + * driver. Encourage users to upgrade their DT blobs to remove these. + */ +static const struct of_device_id whitelist_phys[] = { + { .compatible = "brcm,40nm-ephy" }, + { .compatible = "marvell,88E1111", }, + { .compatible = "marvell,88e1116", }, + { .compatible = "marvell,88e1118", }, + { .compatible = "marvell,88e1145", }, + { .compatible = "marvell,88e1149r", }, + { .compatible = "marvell,88e1310", }, + { .compatible = "marvell,88E1510", }, + { .compatible = "marvell,88E1514", }, + { .compatible = "moxa,moxart-rtl8201cp", }, + {} +}; + /* * Return true if the child node is for a phy. It must either: * o Compatible string of "ethernet-phy-idX.X" * o Compatible string of "ethernet-phy-ieee802.3-c45" * o Compatible string of "ethernet-phy-ieee802.3-c22" + * o In the white list above (and issue a warning) * o No compatibility string * * A device which is not a phy is expected to have a compatible string @@ -166,6 +187,13 @@ static bool of_mdiobus_child_is_phy(struct device_node *child) if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22")) return true; + if (of_match_node(whitelist_phys, child)) { + pr_warn(FW_WARN + "%s: Whitelisted compatible string. Please remove\n", + child->full_name); + return true; + } + if (!of_find_property(child, "compatible", NULL)) return true; @@ -183,7 +211,6 @@ static bool of_mdiobus_child_is_phy(struct device_node *child) int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { struct device_node *child; - const __be32 *paddr; bool scanphys = false; int addr, rc; @@ -218,8 +245,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) /* auto scan for PHYs with empty reg property */ for_each_available_child_of_node(np, child) { /* Skip PHYs with reg property set */ - paddr = of_get_property(child, "reg", NULL); - if (paddr) + if (of_find_property(child, "reg", NULL)) continue; for (addr = 0; addr < PHY_MAX_ADDR; addr++) { @@ -256,11 +282,19 @@ static int of_phy_match(struct device *dev, void *phy_np) struct phy_device *of_phy_find_device(struct device_node *phy_np) { struct device *d; + struct mdio_device *mdiodev; + if (!phy_np) return NULL; d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match); - return d ? to_phy_device(d) : NULL; + if (d) { + mdiodev = to_mdio_device(d); + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) + return to_phy_device(d); + } + + return NULL; } EXPORT_SYMBOL(of_phy_find_device); @@ -269,6 +303,7 @@ EXPORT_SYMBOL(of_phy_find_device); * @dev: pointer to net_device claiming the phy * @phy_np: Pointer to device tree node for the PHY * @hndlr: Link state callback for the network device + * @flags: flags to pass to the PHY * @iface: PHY data interface type * * If successful, returns a pointer to the phy_device with the embedded @@ -377,7 +412,7 @@ int of_phy_register_fixed_link(struct device_node *np) if (strcmp(managed, "in-band-status") == 0) { /* status is zeroed, namely its .link member */ phy = fixed_phy_register(PHY_POLL, &status, -1, np); - return IS_ERR(phy) ? PTR_ERR(phy) : 0; + return PTR_ERR_OR_ZERO(phy); } } @@ -399,7 +434,7 @@ int of_phy_register_fixed_link(struct device_node *np) return -EPROBE_DEFER; phy = fixed_phy_register(PHY_POLL, &status, link_gpio, np); - return IS_ERR(phy) ? PTR_ERR(phy) : 0; + return PTR_ERR_OR_ZERO(phy); } /* Old binding */ @@ -411,7 +446,7 @@ int of_phy_register_fixed_link(struct device_node *np) 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 IS_ERR(phy) ? PTR_ERR(phy) : 0; + return PTR_ERR_OR_ZERO(phy); } return -ENODEV; |