[net-next PATCH v1 7/7] net/fsl: Use _ADR ACPI object to register PHYs

From: Calvin Johnson
Date: Wed Sep 30 2020 - 12:06:40 EST


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