From: Carlo Szelinsky Date: Sat, 14 Feb 2026 15:11:59 +0000 (+0100) Subject: realtek: mdio: register PHYs via fwnode for PSE support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a36ab12454e401bdc581e9f96458fa860ddfce73;p=thirdparty%2Fopenwrt.git 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 Link: https://github.com/openwrt/openwrt/pull/22019 Signed-off-by: Robert Marko --- 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 bd5ad65a322..f008c59b4fd 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);