PHYs on an mdio bus has address which can be obtained from ACPI DSDT table using the _ADR object. DSDT Eg: PHYs connected to MDI0 bus. ------------------------- Scope(\_SB.MDI0) { Device(PHY1) { Name (_ADR, 0x1) } // end of PHY1 Device(PHY2) { Name (_ADR, 0x2) } // end of PHY2 } // end of MDI0 ------------------------- Signed-off-by: Calvin Johnson <calvin.johnson@xxxxxxxxxxx> --- drivers/net/ethernet/freescale/xgmac_mdio.c | 48 +++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index 98be51d8b08c..fb272564855e 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -2,6 +2,7 @@ * QorIQ 10G MDIO Controller * * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2020 NXP * * Authors: Andy Fleming <afleming@xxxxxxxxxxxxx> * Timur Tabi <timur@xxxxxxxxxxxxx> @@ -11,6 +12,7 @@ * kind, whether express or implied. */ +#include <linux/acpi.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/interrupt.h> @@ -248,6 +250,10 @@ static int xgmac_mdio_probe(struct platform_device *pdev) struct resource *res; struct mdio_fsl_priv *priv; int ret; + struct fwnode_handle *fwnode; + struct fwnode_handle *child; + unsigned long long addr; + acpi_status status; /* In DPAA-1, MDIO is one of the many FMan sub-devices. The FMan * defines a register space that spans a large area, covering all the @@ -284,10 +290,44 @@ static int xgmac_mdio_probe(struct platform_device *pdev) priv->has_a011043 = device_property_read_bool(&pdev->dev, "fsl,erratum-a011043"); - - ret = of_mdiobus_register(bus, np); - if (ret) { - dev_err(&pdev->dev, "cannot register MDIO bus\n"); + if (is_of_node(pdev->dev.fwnode)) { + ret = of_mdiobus_register(bus, np); + if (ret) { + dev_err(&pdev->dev, "cannot register MDIO bus\n"); + goto err_registration; + } + } else if (is_acpi_node(pdev->dev.fwnode)) { + priv->is_little_endian = true; + /* Mask out all PHYs from auto probing. */ + bus->phy_mask = ~0; + ret = mdiobus_register(bus); + if (ret) { + dev_err(&pdev->dev, "mdiobus register err(%d)\n", ret); + return ret; + } + + fwnode = pdev->dev.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(bus, child, addr); + if (ret == -ENODEV) + dev_err(&bus->dev, + "MDIO device at address %lld is missing.\n", + addr); + } + } else { + dev_err(&pdev->dev, "Cannot get cfg data from DT or ACPI\n"); + ret = -ENXIO; goto err_registration; } -- 2.17.1