From 945a335f662086145969816297a233d1a280ba95 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sun, 15 Sep 2024 13:01:41 -0400 Subject: [PATCH] realtek: ethernet: Improve SMI polling configuration based on DTS Although Zyxel XGS1210 devices are not yet officially supported there are several patches floating around to enable them. This is a very imporant one because it fixes a SMI misconfiguration. In the known DTS the SFP+ port settings are set as follows. phy26: ethernet-phy@26 { compatible = "ethernet-phy-ieee802.3-c45"; phy-is-integrated; reg = <26>; sds = < 8 >; }; phy27: ethernet-phy@27 { compatible = "ethernet-phy-ieee802.3-c45"; phy-is-integrated; reg = <27>; sds = < 9 >; }; So these are PHYs linked to an internal SerDes. During initialization rtl838x_mdio_init() generates smi_bus=0 & smi_addr=27/28 for these ports. Although this seems like a valid configuration integrated PHYs attached to an SerDes do not have an SMI bus. Later on the mdio reset wrongly feeds the SMI registers and as a result the PHYs on SMI bus 0 do not work. Without patch (loaded with rtk network on & initramfs): ... mdio_bus mdio-bus: MDIO device at address 0 is missing. mdio_bus mdio-bus: MDIO device at address 1 is missing. mdio_bus mdio-bus: MDIO device at address 2 is missing. mdio_bus mdio-bus: MDIO device at address 3 is missing. mdio_bus mdio-bus: MDIO device at address 4 is missing. mdio_bus mdio-bus: MDIO device at address 5 is missing. mdio_bus mdio-bus: MDIO device at address 6 is missing. mdio_bus mdio-bus: MDIO device at address 7 is missing. ... rtl83xx-switch ... : no phy at 0 rtl83xx-switch ... : failed to connect to PHY: -ENODEV rtl83xx-switch ... : error -19 setting up PHY for tree 0, switch 0, port 0 rtl83xx-switch ... : no phy at 1 rtl83xx-switch ... : failed to connect to PHY: -ENODEV rtl83xx-switch ... : error -19 setting up PHY for tree 0, switch 0, port 1 ... With patch (loaded with rtk network on & initramfs): ... rtl83xx-switch ... : PHY [mdio-bus:00] driver [REALTEK RTL8218D] (irq=POLL) rtl83xx-switch ... : PHY [mdio-bus:01] driver [REALTEK RTL8218D] (irq=POLL) ... Signed-off-by: Birger Koblitz Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/16457 Signed-off-by: Robert Marko --- .../drivers/net/ethernet/rtl838x_eth.c | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c index 710c65bc11..4b79090696 100644 --- a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c @@ -195,7 +195,7 @@ struct rtl838x_eth_priv { u32 lastEvent; u16 rxrings; u16 rxringlen; - u8 smi_bus[MAX_PORTS]; + int smi_bus[MAX_PORTS]; u8 smi_addr[MAX_PORTS]; u32 sds_id[MAX_PORTS]; bool smi_bus_isc45[MAX_SMI_BUSSES]; @@ -2008,8 +2008,9 @@ static int rtmdio_930x_reset(struct mii_bus *bus) for (int i = 0; i < RTL930X_CPU_PORT; i++) { int pos; - if (priv->smi_bus[i] > 3) + if (priv->smi_bus[i] < 0) continue; + pos = (i % 6) * 5; sw_w32_mask(0x1f << pos, priv->smi_addr[i] << pos, RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4); @@ -2114,9 +2115,12 @@ static int rtmdio_931x_reset(struct mii_bus *bus) mdc_on[0] = mdc_on[1] = mdc_on[2] = mdc_on[3] = false; /* Mapping of port to phy-addresses on an SMI bus */ poll_sel[0] = poll_sel[1] = poll_sel[2] = poll_sel[3] = 0; - for (int i = 0; i < 56; i++) { + for (int i = 0; i < RTL931X_CPU_PORT; i++) { u32 pos; + if (priv->smi_bus[i] < 0) + continue; + pos = (i % 6) * 5; sw_w32_mask(0x1f << pos, priv->smi_addr[i] << pos, RTL931X_SMI_PORT_ADDR + (i / 6) * 4); pos = (i * 2) % 32; @@ -2282,30 +2286,35 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) if (of_property_read_u32(dn, "reg", &pn)) continue; - if (of_property_read_u32_array(dn, "rtl9300,smi-address", &smi_addr[0], 2)) { - smi_addr[0] = 0; - smi_addr[1] = pn; + if (pn >= MAX_PORTS) { + pr_err("%s: illegal port number %d\n", __func__, pn); + return -ENODEV; } if (of_property_read_u32(dn, "sds", &priv->sds_id[pn])) priv->sds_id[pn] = -1; - else { + else pr_info("set sds port %d to %d\n", pn, priv->sds_id[pn]); - } - if (pn < MAX_PORTS) { + if (of_property_read_u32_array(dn, "rtl9300,smi-address", &smi_addr[0], 2)) { + priv->smi_bus[pn] = 0; + priv->smi_addr[pn] = pn; + } else { priv->smi_bus[pn] = smi_addr[0]; priv->smi_addr[pn] = smi_addr[1]; - } else { - pr_err("%s: illegal port number %d\n", __func__, pn); } - if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45")) - priv->smi_bus_isc45[smi_addr[0]] = true; - - if (of_property_read_bool(dn, "phy-is-integrated")) { - priv->phy_is_internal[pn] = true; + if (priv->smi_bus[pn] >= MAX_SMI_BUSSES) { + pr_err("%s: illegal SMI bus number %d\n", __func__, priv->smi_bus[pn]); + return -ENODEV; } + + priv->phy_is_internal[pn] = of_property_read_bool(dn, "phy-is-integrated"); + + if (priv->phy_is_internal[pn] && priv->sds_id[pn] >= 0) + priv->smi_bus[pn]= -1; + else if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45")) + priv->smi_bus_isc45[priv->smi_bus[pn]] = true; } dn = of_find_compatible_node(NULL, NULL, "realtek,rtl83xx-switch");