[openwrt/openwrt] realtek: mdio: apply phy polling config for RTL931x

LEDE Commits lede-commits at lists.infradead.org
Sun Jan 25 03:12:20 PST 2026


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

commit 4fa27cb325817cf0e439fffc52895ad4104568b5
Author: Jonas Jelonek <jelonek.jonas at gmail.com>
AuthorDate: Sun Jan 11 10:59:54 2026 +0000

    realtek: mdio: apply phy polling config for RTL931x
    
    Apply the PHY polling configuration for RTL931x too, as previously
    implemented for RTL930x. This is needed for several PHYs on that
    platform to function properly.
    
    Add another flag called 'force_res' to the phy_info struct which is for
    RTL931x only. The SDK mentions this as a flag to force polling the
    Realtek proprietary PHY status resolution register. Effectively, this
    changes the polling to proprietary format instead of standard format,
    and sets an enable bit in another private polling register field.
    
    Signed-off-by: Jonas Jelonek <jelonek.jonas at gmail.com>
    Link: https://github.com/openwrt/openwrt/pull/21515
    Signed-off-by: Robert Marko <robert.marko at sartura.hr>
---
 .../drivers/net/mdio/mdio-realtek-otto.c           | 93 +++++++++++++++++++---
 1 file changed, 84 insertions(+), 9 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 8e97e21c3f..bcc8f2b775 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
@@ -95,6 +95,11 @@
 #define RTMDIO_931X_MAC_L2_GLOBAL_CTRL2		(0x1358)
 #define RTMDIO_931X_SMI_PORT_POLLING_SEL	(0x0C9C)
 #define RTMDIO_931X_SMI_PORT_ADDR		(0x0C74)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL0	(0x0CF0)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL1	(0x0CF4)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL2	(0x0CF8)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL3	(0x0CFC)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL4	(0x0D00)
 
 #define sw_r32(reg)				readl(RTMDIO_SW_BASE + reg)
 #define sw_w32(val, reg)			writel(val, RTMDIO_SW_BASE + reg)
@@ -193,6 +198,7 @@ struct rtmdio_phy_info {
 	int mac_type;
 	bool has_giga_lite;
 	bool has_res_reg;
+	bool force_res;
 	unsigned int poll_duplex;
 	unsigned int poll_adv_1000;
 	unsigned int poll_lpa_1000;
@@ -749,6 +755,7 @@ static int rtmdio_930x_reset(struct mii_bus *bus)
 static int rtmdio_931x_reset(struct mii_bus *bus)
 {
 	struct rtmdio_bus_priv *priv = bus->priv;
+	struct rtmdio_phy_info phyinfo;
 	u32 poll_sel[4] = { 0 };
 	u32 poll_ctrl = 0;
 	u32 c45_mask = 0;
@@ -779,22 +786,90 @@ static int rtmdio_931x_reset(struct mii_bus *bus)
 		sw_w32(poll_sel[i], RTMDIO_931X_SMI_PORT_POLLING_SEL + (i * 4));
 	}
 
-	/* Configure which SMI busses */
-	pr_info("c45_mask: %08x, RTMDIO_931X_SMI_GLB_CTRL0 was %X", c45_mask, sw_r32(RTMDIO_931X_SMI_GLB_CTRL0));
+	/* Configure c22/c45 polling (bit 1 of SMI_SETX_FMT_SEL)
+	 *
+	 * NOTE: this seems to be needed before accessing the bus though
+	 * it should only apply to the SMI polling. Not setting c22/c45 here
+	 * apparently causes garbage being read below.
+	 */
 	for (int i = 0; i < RTMDIO_MAX_SMI_BUS; i++) {
 		/* bus is polled in c45 */
 		if (priv->smi_bus_isc45[i])
 			c45_mask |= 0x2 << (i * 2);  /* Std. C45, non-standard is 0x3 */
 	}
+	pr_info("%s: c45_mask: %08x", __func__, c45_mask);
+	sw_w32_mask(GENMASK(7, 0), c45_mask, RTMDIO_931X_SMI_GLB_CTRL1);
 
-	pr_info("c45_mask: %08x, RTL931X_SMI_GLB_CTRL0 was %X", c45_mask, sw_r32(RTMDIO_931X_SMI_GLB_CTRL0));
-
-	/* We have a 10G PHY enable polling
-	 * sw_w32(0x01010000, RTL931X_SMI_10GPHY_POLLING_SEL2);
-	 * sw_w32(0x01E7C400, RTL931X_SMI_10GPHY_POLLING_SEL3);
-	 * sw_w32(0x01E7E820, RTL931X_SMI_10GPHY_POLLING_SEL4);
+	/* Define PHY specific polling parameters
+	 *
+	 * Those are applied per port here but the SoC only supports them
+	 * per SMI bus or for all GPHY/10GPHY. This should be guarded by
+	 * the existing hardware designs (i.e. only equally polled PHYs on
+	 * the same SMI bus or kind of PHYs).
 	 */
-	sw_w32_mask(GENMASK(7, 0), c45_mask, RTMDIO_931X_SMI_GLB_CTRL1);
+	for (int addr = 0; addr < priv->cfg->cpu_port; addr++) {
+		unsigned int mask, val;
+		int smi = priv->smi_bus[addr];
+		
+		if (smi < 0)
+			continue;
+
+		rtmdio_get_phy_info(bus, addr, &phyinfo);
+		if (phyinfo.phy_unknown) {
+			pr_warn("skip polling setup for unknown PHY %08x on port %d\n",
+				phyinfo.phy_id, addr);
+			continue;
+		}
+
+		mask = val = 0;
+
+		/* PRVTE0 polling */
+		mask |= BIT(20 + smi);
+		if (phyinfo.has_res_reg)
+			val |= BIT(20 + smi);
+
+		/* PRVTE1 polling */
+		mask |= BIT(24 + smi);
+		if (phyinfo.force_res)
+			val |= BIT(24 + smi);
+
+		sw_w32_mask(mask, val, RTMDIO_931X_SMI_GLB_CTRL0);
+
+		/* polling std. or proprietary format (bit 0 of SMI_SETX_FMT_SEL) */
+		mask = BIT(smi * 2);
+		val = phyinfo.force_res ? mask : 0;
+		sw_w32_mask(mask, val, RTMDIO_931X_SMI_GLB_CTRL1);
+
+		/* special polling registers */
+		if (phyinfo.poll_duplex || phyinfo.poll_adv_1000 || phyinfo.poll_lpa_1000) {
+			sw_w32(phyinfo.poll_duplex, RTMDIO_931X_SMI_10GPHY_POLLING_SEL2);
+			sw_w32(phyinfo.poll_adv_1000, RTMDIO_931X_SMI_10GPHY_POLLING_SEL3);
+			sw_w32(phyinfo.poll_lpa_1000, RTMDIO_931X_SMI_10GPHY_POLLING_SEL4);
+		}
+	}
+
+	pr_debug("%s: RTMDIO_931X_SMI_GLB_CTRL0 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_GLB_CTRL0));
+	pr_debug("%s: RTMDIO_931X_SMI_GLB_CTRL1 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_GLB_CTRL1));
+	pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_0_15 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL));
+	pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_16_27 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL + 4));
+	pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_28_43 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL + 8));
+	pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_44_55 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL + 12));
+	pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL0 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL0));
+	pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL1 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL1));
+	pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL2 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL2));
+	pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL3 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL3));
+	pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL4 %08x\n", __func__,
+		 sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL4));
 
 	return 0;
 }




More information about the lede-commits mailing list