realtek: mdio/dsa: refactor mdio bus initialization

The mdio driver currently determines the smi bus and address from the
realtek,smi-address attribute of the phy. To better reflect the
topology and align with upstream, the phys should be relocated below
their associated bus. As an interim solution the following dts notation
is in focus.

mdio_ctrl: mdio-controller {
  mdio_bus0: mdio-bus@0 {
    reg = <0>;
    phy0: ethernet-phy@0 {
      reg = <0>;
      compatible = "ethernet-phy-ieee802.3-c45";
      realtek,smi-address = <8>;
    };

  &mdio_bus1 {
    reg = <1>;
    phy16: ethernet-phy@16 {
      reg = <16>;
      compatible = "ethernet-phy-ieee802.3-c45";
      realtek,smi-address = <2>;
  };
}

With this

- the phy reg property still denotes the port number
- the bus number can be derived from the parent bus node.
- the bus address is taken from realtek,smi-address

Refactor bus initialization so it can handle phy nodes below
multiple bus nodes.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/21438
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Markus Stockhausen 2026-01-12 16:43:40 +01:00 committed by Hauke Mehrtens
parent 3722b006a6
commit 3b73474f71

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/fwnode_mdio.h>
#include <linux/mutex.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
@ -149,6 +150,7 @@ struct rtmdio_bus_priv {
bool raw[RTMDIO_MAX_PORT];
int smi_bus[RTMDIO_MAX_PORT];
u8 smi_addr[RTMDIO_MAX_PORT];
struct device_node *dn[RTMDIO_MAX_PORT];
bool smi_bus_isc45[RTMDIO_MAX_SMI_BUS];
};
@ -1012,31 +1014,21 @@ static int rtmdio_reset(struct mii_bus *bus)
static int rtmdio_probe(struct platform_device *pdev)
{
struct device_node *dn;
struct device *dev = &pdev->dev;
struct rtmdio_bus_priv *priv;
struct device_node *dn;
struct mii_bus *bus;
int addr;
int ret, addr;
bus = devm_mdiobus_alloc_size(dev, sizeof(*priv));
if (!bus)
return -ENOMEM;
priv = bus->priv;
priv->cfg = (const struct rtmdio_config *)device_get_match_data(dev);
for (addr = 0; addr < RTMDIO_MAX_PORT; addr++)
priv->smi_bus[addr] = -1;
priv->cfg = (const struct rtmdio_config *)device_get_match_data(dev);
bus->name = "Realtek MDIO bus";
bus->reset = rtmdio_reset;
bus->read = rtmdio_read;
bus->write = rtmdio_write;
bus->read_c45 = rtmdio_read_c45;
bus->write_c45 = rtmdio_write_c45;
bus->parent = dev;
bus->phy_mask = ~(BIT_ULL(priv->cfg->cpu_port) - 1ULL);
for_each_node_by_name(dn, "ethernet-phy") {
u32 smi_addr[2];
@ -1063,17 +1055,34 @@ static int rtmdio_probe(struct platform_device *pdev)
if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45"))
priv->smi_bus_isc45[priv->smi_bus[addr]] = true;
priv->dn[addr] = dn;
}
dn = of_find_compatible_node(NULL, NULL, "realtek,rtl83xx-switch");
if (!dn) {
dev_err(dev, "No RTL switch node in DTS\n");
return -ENODEV;
}
bus->name = "Realtek MDIO bus";
bus->reset = rtmdio_reset;
bus->read = rtmdio_read;
bus->write = rtmdio_write;
bus->read_c45 = rtmdio_read_c45;
bus->write_c45 = rtmdio_write_c45;
bus->parent = dev;
bus->phy_mask = ~0;
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev));
return devm_of_mdiobus_register(dev, bus, dev->of_node);
device_set_node(&bus->dev, of_fwnode_handle(dev->of_node));
ret = devm_mdiobus_register(dev, bus);
if (ret)
return ret;
for (addr = 0; addr < priv->cfg->cpu_port; addr++) {
if (priv->dn[addr]) {
ret = fwnode_mdiobus_register_phy(bus, of_fwnode_handle(priv->dn[addr]), addr);
if (ret)
return ret;
}
}
return 0;
}
static const struct rtmdio_config rtmdio_838x_cfg = {