Introduce fwnode_mdiobus_register() to register PHYs on the mdiobus. If the fwnode is DT node, then call of_mdiobus_register(). If it is an ACPI node, then: - disable auto probing of mdiobus - register mdiobus - save fwnode to mdio structure - loop over child nodes & register a phy_device for each PHY Signed-off-by: Calvin Johnson <calvin.johnson@xxxxxxxxxxx> --- Changes in v2: None drivers/net/phy/mdio_bus.c | 50 ++++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 1 + 2 files changed, 51 insertions(+) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 3361a1a86e97..e7ad34908936 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/acpi.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/errno.h> @@ -567,6 +568,55 @@ static int mdiobus_create_device(struct mii_bus *bus, return ret; } +/** + * fwnode_mdiobus_register - Register mii_bus and create PHYs from fwnode + * @mdio: pointer to mii_bus structure + * @fwnode: pointer to fwnode of MDIO bus. + * + * This function registers the mii_bus structure and registers a phy_device + * for each child node of @fwnode. + */ +int fwnode_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode) +{ + struct fwnode_handle *child; + unsigned long long addr; + acpi_status status; + int ret; + + if (is_of_node(fwnode)) { + return of_mdiobus_register(mdio, to_of_node(fwnode)); + } else if (is_acpi_node(fwnode)) { + /* Mask out all PHYs from auto probing. */ + mdio->phy_mask = ~0; + ret = mdiobus_register(mdio); + if (ret) + return ret; + + mdio->dev.fwnode = fwnode; + /* Loop over the child nodes and register a phy_device for each PHY */ + fwnode_for_each_child_node(fwnode, child) { + status = acpi_evaluate_integer(ACPI_HANDLE_FWNODE(child), + "_ADR", NULL, &addr); + if (ACPI_FAILURE(status)) { + pr_debug("_ADR returned %d\n", status); + continue; + } + + if (addr < 0 || addr >= PHY_MAX_ADDR) + continue; + + ret = fwnode_mdiobus_register_phy(mdio, child, addr); + if (ret == -ENODEV) + dev_err(&mdio->dev, + "MDIO device at address %lld is missing.\n", + addr); + } + return 0; + } + return -EINVAL; +} +EXPORT_SYMBOL(fwnode_mdiobus_register); + /** * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus * @bus: target mii_bus diff --git a/include/linux/phy.h b/include/linux/phy.h index 10a66b65a008..67ea4ca6f76f 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -383,6 +383,7 @@ static inline struct mii_bus *mdiobus_alloc(void) return mdiobus_alloc_size(0); } +int fwnode_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode); int __mdiobus_register(struct mii_bus *bus, struct module *owner); int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus, struct module *owner); -- 2.17.1