[PATCH v3] net: airoha_eth: fix mt7531 mdio related initialization bug

Mikhail Kshevetskiy mikhail.kshevetskiy at iopsys.eu
Thu Jun 4 03:08:37 CEST 2026


Private data isn't ready during bind time. The call of dev_get_priv()
function will return NULL. Thus we can't save mdio device pointer and
use it later during probe.

To solve an issue, we will move mt7531 mdio device binding to the probing
function of 'airoha-eth' driver.

All GDM ports (except of GDM1) are connected directly to their PHYs, so
corresponding mdio bus will be automatically probed during PHY setup.

GDM1 ports differ from other GDM ports. It connected to the airoha switch
device. The mt7531 mdio bus is used to manage link state of airoha switch
device ports (LAN ports 1-4 corresponds to PHYs 0x09-0x0C). Therefore,
manual probing of mt7531 mdio bus is required to be able set/query states
of corresponding LAN ports.

Fixes: 96d9e7c46425 ("net: airoha: use mt7531 mdio for GDM1")
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy at iopsys.eu>
---
Changes v2:
 * small refactoring

Changes v3:
 * Move mt7531 mdio bus initialization function before it's first usage.
 * Probe mt7531 mdio bus for GDM1 port, but not for other GDM port.
 * Add an explanation why mt7531 mdio bus must be probed for GDM1 only
---
 drivers/net/airoha_eth.c | 78 ++++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 30 deletions(-)

diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c
index 84ee9b2ad76..e5d39b95cc5 100644
--- a/drivers/net/airoha_eth.c
+++ b/drivers/net/airoha_eth.c
@@ -845,11 +845,45 @@ static int airoha_alloc_gdm_port(struct udevice *dev, ofnode node)
 					    (ulong)eth, node, &gdm_dev);
 }
 
+static struct udevice *airoha_switch_mdio_init(struct udevice *dev)
+{
+	struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
+	ofnode switch_node, mdio_node;
+	struct udevice *mdio_dev;
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(MDIO_MT7531_MMIO))
+		return NULL;
+
+	switch_node = ofnode_by_compatible(ofnode_null(),
+					   data->switch_compatible);
+	if (!ofnode_valid(switch_node)) {
+		debug("Warning: missing airoha switch node\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mdio_node = ofnode_find_subnode(switch_node, "mdio");
+	if (!ofnode_valid(mdio_node)) {
+		debug("Warning: missing airoha switch mdio subnode\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	ret = device_bind_driver_to_node(dev, "mt7531-mdio-mmio", "mt7531-mdio",
+					 mdio_node, &mdio_dev);
+	if (ret) {
+		debug("Warning: failed to bind airoha switch mdio\n");
+		return ERR_PTR(ret);
+	}
+
+	return mdio_dev;
+}
+
 static int airoha_eth_probe(struct udevice *dev)
 {
 	struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
 	struct airoha_eth *eth = dev_get_priv(dev);
 	struct regmap *scu_regmap;
+	struct udevice *mdio_dev;
 	ofnode node;
 	int i, ret;
 
@@ -908,10 +942,10 @@ static int airoha_eth_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	if (eth->switch_mdio_dev) {
-		if (!device_probe(eth->switch_mdio_dev))
-			debug("Warning: failed to probe airoha switch mdio\n");
-	}
+	/* Airoha switch mdio PHYs maybe used by several GDM devices */
+	mdio_dev = airoha_switch_mdio_init(dev);
+	if (!IS_ERR_OR_NULL(mdio_dev))
+		eth->switch_mdio_dev = mdio_dev;
 
 	ofnode_for_each_subnode(node, dev_ofnode(dev)) {
 		if (!ofnode_device_is_compatible(node, "airoha,eth-mac"))
@@ -957,6 +991,16 @@ static int airoha_eth_port_probe(struct udevice *dev)
 #else
 		return -EINVAL;
 #endif
+	} else {
+		/*
+		 * GDM1 device connected to airoha switch. Probe airoha switch
+		 * mdio to be able set/query states of corresponding LAN ports.
+		 */
+		ret = device_probe(eth->switch_mdio_dev);
+		if (ret) {
+			debug("Warning: failed to probe airoha switch mdio\n");
+			eth->switch_mdio_dev = NULL;
+		}
 	}
 
 	return 0;
@@ -1202,38 +1246,12 @@ static int arht_eth_write_hwaddr(struct udevice *dev)
 
 static int airoha_eth_bind(struct udevice *dev)
 {
-	struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
-	struct airoha_eth *eth = dev_get_priv(dev);
-	ofnode switch_node, mdio_node;
-	int ret;
-
 	/*
 	 * Force Probe as we set the Main ETH driver as misc
 	 * to register multiple eth port for each GDM
 	 */
 	dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
 
-	if (!CONFIG_IS_ENABLED(MDIO_MT7531_MMIO))
-		return 0;
-
-	switch_node = ofnode_by_compatible(ofnode_null(),
-					   data->switch_compatible);
-	if (!ofnode_valid(switch_node)) {
-		debug("Warning: missing switch node\n");
-		return 0;
-	}
-
-	mdio_node = ofnode_find_subnode(switch_node, "mdio");
-	if (!ofnode_valid(mdio_node)) {
-		debug("Warning: missing mdio node\n");
-		return 0;
-	}
-
-	ret = device_bind_driver_to_node(dev, "mt7531-mdio-mmio", "mt7531-mdio",
-					 mdio_node, &eth->switch_mdio_dev);
-	if (ret)
-		debug("Warning: failed to bind mdio controller\n");
-
 	return 0;
 }
 
-- 
2.53.0



More information about the U-Boot mailing list