[openwrt/openwrt] realtek: mdio: register PHYs via fwnode for PSE support

LEDE Commits lede-commits at lists.infradead.org
Thu Feb 19 01:46:48 PST 2026


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/a36ab12454e401bdc581e9f96458fa860ddfce73

commit a36ab12454e401bdc581e9f96458fa860ddfce73
Author: Carlo Szelinsky <github at szelinsky.de>
AuthorDate: Sat Feb 14 16:11:59 2026 +0100

    realtek: mdio: register PHYs via fwnode for PSE support
    
    Switch from auto-scan PHY discovery to explicit DT-based registration
    using fwnode_mdiobus_register_phy(). This is the standard approach used
    by of_mdiobus_register() and most MDIO drivers.
    
    Auto-scan (phy_mask-based) registration does not attach DT fwnode data
    to PHY devices, which means DT properties like "pses" are never parsed.
    As a result, PSE controllers referenced from PHY nodes are not linked,
    and ethtool PSE commands (--show-pse, --set-pse) do not work.
    
    Store the device_node for each PHY found during DT parsing, suppress
    auto-scan by setting phy_mask to ~0, and register each PHY explicitly
    after devm_mdiobus_register(). This allows fwnode_find_pse_control() to
    resolve PSE references and also establishes proper fw_devlink supplier
    relationships.
    
    Additionally this fixes a bug where the RTL8221B is limited to
    1G and below due to missing DTS references.
    
    Fixes: 4e00306 ("realtek: mdio: use bus auto registration")
    
    Signed-off-by: Carlo Szelinsky <github at szelinsky.de>
    Link: https://github.com/openwrt/openwrt/pull/22019
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 .../drivers/net/mdio/mdio-realtek-otto.c           | 37 ++++++++++++----------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c b/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c
index bd5ad65a32..f008c59b4f 100644
--- a/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c
+++ b/target/linux/realtek/files-6.12/drivers/net/mdio/mdio-realtek-otto.c
@@ -508,10 +508,6 @@ static int rtmdio_read(struct mii_bus *bus, int addr, int regnum)
 	if (addr >= ctrl->cfg->cpu_port)
 		return -ENODEV;
 
-	/* prevent WARN_ONCE() during scan */
-	if (ctrl->smi_bus[addr] >=0 && ctrl->smi_bus_isc45[ctrl->smi_bus[addr]] && regnum == 2)
-		return -EIO;
-
 	if (regnum == RTMDIO_PAGE_SELECT && ctrl->page[addr] != ctrl->cfg->raw_page)
 		return ctrl->page[addr];
 
@@ -868,10 +864,9 @@ static int rtmdio_reset(struct mii_bus *bus)
 static int rtmdio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct device_node *dn[RTMDIO_MAX_PORT] = {}, *np;
 	struct rtmdio_ctrl *ctrl;
-	struct device_node *dn;
 	struct mii_bus *bus;
-	u64 mask = 0ULL;
 	int ret, addr;
 
 	bus = devm_mdiobus_alloc_size(dev, sizeof(*ctrl));
@@ -887,30 +882,30 @@ static int rtmdio_probe(struct platform_device *pdev)
 	for (addr = 0; addr < RTMDIO_MAX_PORT; addr++)
 		ctrl->smi_bus[addr] = -1;
 
-	for_each_node_by_name(dn, "ethernet-phy") {
-		if (of_property_read_u32(dn, "reg", &addr))
+	for_each_node_by_name(np, "ethernet-phy") {
+		if (of_property_read_u32(np, "reg", &addr))
 			continue;
 
 		if (addr < 0 || addr >= ctrl->cfg->cpu_port) {
 			dev_err(dev, "illegal port number %d\n", addr);
-			of_node_put(dn);
+			of_node_put(np);
 			return -EINVAL;
 		}
 
-		of_property_read_u32(dn->parent, "reg", &ctrl->smi_bus[addr]);
-		if (of_property_read_u32(dn, "realtek,smi-address", &ctrl->smi_addr[addr]))
+		of_property_read_u32(np->parent, "reg", &ctrl->smi_bus[addr]);
+		if (of_property_read_u32(np, "realtek,smi-address", &ctrl->smi_addr[addr]))
 			ctrl->smi_addr[addr] = addr;
-		
+
 		if (ctrl->smi_bus[addr] < 0 || ctrl->smi_bus[addr] >= RTMDIO_MAX_SMI_BUS) {
 			dev_err(dev, "illegal SMI bus number %d\n", ctrl->smi_bus[addr]);
-			of_node_put(dn);
+			of_node_put(np);
 			return -EINVAL;
 		}
 
-		if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45"))
+		if (of_device_is_compatible(np, "ethernet-phy-ieee802.3-c45"))
 			ctrl->smi_bus_isc45[ctrl->smi_bus[addr]] = true;
 
-		mask |= BIT_ULL(addr);
+		dn[addr] = of_node_get(np);
 	}
 
 	bus->name = "Realtek MDIO bus";
@@ -920,7 +915,7 @@ static int rtmdio_probe(struct platform_device *pdev)
 	bus->read_c45 = rtmdio_read_c45;
 	bus->write_c45 = rtmdio_write_c45;
 	bus->parent = dev;
-	bus->phy_mask = ~mask;
+	bus->phy_mask = ~0;
 	snprintf(bus->id, MII_BUS_ID_SIZE, "realtek-mdio");
 
 	device_set_node(&bus->dev, of_fwnode_handle(dev->of_node));
@@ -930,6 +925,16 @@ static int rtmdio_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	for (addr = 0; addr < ctrl->cfg->cpu_port; addr++) {
+		if (ctrl->smi_bus[addr] < 0)
+			continue;
+
+		ret = fwnode_mdiobus_register_phy(bus, of_fwnode_handle(dn[addr]), addr);
+		of_node_put(dn[addr]);
+		if (ret)
+			return ret;
+	}
+
 	if (ctrl->cfg->setup_polling)
 		ctrl->cfg->setup_polling(bus);
 




More information about the lede-commits mailing list