[openwrt/openwrt] realtek: phy: add basic RTL8218B setup

LEDE Commits lede-commits at lists.infradead.org
Wed Jul 23 15:45:04 PDT 2025


hauke pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/19bc6e8c7f86b197b7bccc45c6af4a3ff521e8ee

commit 19bc6e8c7f86b197b7bccc45c6af4a3ff521e8ee
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Tue Jul 22 03:14:59 2025 -0400

    realtek: phy: add basic RTL8218B setup
    
    On some devices (like ZyXEL GS1920) the phys are not initialized and patched
    by the bootloader. This is done through the vendor SDK when the software
    starts. To make these devices usable too, provide the most basic setup
    sequence for the RTL8218B.
    
    Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/19491
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 .../files-6.12/drivers/net/phy/rtl83xx-phy.c       | 52 +++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
index e794b1296d..439ba9aa37 100644
--- a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
+++ b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
@@ -38,6 +38,7 @@ extern int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnu
 #define RTL821X_PAGE_MAC		0x0a43
 #define RTL821X_PAGE_STATE		0x0b80
 #define RTL821X_PAGE_PATCH		0x0b82
+#define RTL821X_MAC_SDS_PAGE(sds, page)	(0x404 + (sds) * 0x20 + (page))
 
 /* Using the special page 0xfff with the MDIO controller found in
  * RealTek SoCs allows to access the PHY in RAW mode, ie. bypassing
@@ -3811,6 +3812,55 @@ static int rtl821x_config_init(struct phy_device *phydev)
 	return 0;
 }
 
+static void rtl8218b_cmu_reset(struct phy_device *phydev, int reset_id)
+{
+	int bitpos = reset_id * 2;
+
+	/* CMU seems to have 8 pairs of reset bits that always work the same way */
+	phy_modify_paged(phydev, 0x467, 0x14, 0, BIT(bitpos));
+	phy_modify_paged(phydev, 0x467, 0x14, 0, BIT(bitpos + 1));
+	phy_write_paged(phydev, 0x467, 0x14, 0x0);
+}
+
+static int rtl8218b_config_init(struct phy_device *phydev)
+{
+	int oldpage, oldxpage;
+
+	rtl821x_config_init(phydev);
+
+	if (phydev->mdio.addr % 8)
+		return 0;
+	/*
+	 * Realtek provides two ways of initializing the PHY package. Either by U-Boot or via
+	 * vendor software and SDK. In case U-Boot setup is missing, run basic configuration
+	 * so that ports at least get link up and pass traffic.
+	 */
+
+	oldpage = phy_read(phydev, RTL8XXX_PAGE_SELECT);
+	oldxpage = phy_read(phydev, RTL821XEXT_MEDIA_PAGE_SELECT);
+	phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, 0x8);
+
+	/* activate 32/40 bit redundancy algorithm for first MAC serdes */
+	phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(0, 1), 0x14, 0, BIT(3));
+	/* magic CMU setting for stable connectivity of first MAC serdes */
+	phy_write_paged(phydev, 0x462, 0x15, 0x6e58);
+	rtl8218b_cmu_reset(phydev, 0);
+
+	for (int sds = 0; sds < 2; sds++) {
+		/* force negative clock edge */
+		phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(sds, 0), 0x17, 0, BIT(14));
+		rtl8218b_cmu_reset(phydev, 5 + sds);
+		/* soft reset */
+		phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(sds, 0), 0x13, 0, BIT(6));
+		phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(sds, 0), 0x13, BIT(6), 0);
+	}
+
+	phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, oldxpage);
+	phy_write(phydev, RTL8XXX_PAGE_SELECT, oldpage);
+
+	return 0;
+}
+
 static int rtl838x_serdes_probe(struct phy_device *phydev)
 {
 	int addr = phydev->mdio.addr;
@@ -3898,7 +3948,7 @@ static struct phy_driver rtl83xx_phy_driver[] = {
 	{
 		.match_phy_device = rtl8218b_ext_match_phy_device,
 		.name		= "Realtek RTL8218B (external)",
-		.config_init	= rtl821x_config_init,
+		.config_init	= rtl8218b_config_init,
 		.features	= PHY_GBIT_FEATURES,
 		.probe		= rtl8218b_ext_phy_probe,
 		.read_mmd	= rtl821x_read_mmd,




More information about the lede-commits mailing list