[openwrt/openwrt] realtek: phy: add RTL8214x/RTL8218x patch helper

LEDE Commits lede-commits at lists.infradead.org
Fri Aug 29 15:20:47 PDT 2025


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

commit d5ad59ffb13e4bca44e9cc2ec137d2d54f40bc7f
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Wed Aug 20 02:25:44 2025 -0400

    realtek: phy: add RTL8214x/RTL8218x patch helper
    
    The patching sequence of the RTL8214x/8218x is very similar.
    Especially the preparation for readiness is always the same.
    Provide a common helper to improve readability.
    
    While we are here clean up the changed functions
    
    - Sort variable definitions according to upstream
    - simplify some messages
    
    Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/19810
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 .../files-6.12/drivers/net/phy/rtl83xx-phy.c       | 155 ++++++---------------
 1 file changed, 46 insertions(+), 109 deletions(-)

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 490352dfc6..b93c0fc522 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
@@ -635,20 +635,38 @@ static int rtl8390_configure_generic(struct phy_device *phydev)
 	return 0;
 }
 
+static int rtl821x_prepare_patch(struct phy_device *phydev, int ports)
+{
+	struct phy_device *patchphy;
+	int tries = 50;
+
+	for (int port = 0; port < ports; port++) {
+		patchphy = get_package_phy(phydev, port);
+		phy_write_paged(patchphy, RTL821X_PAGE_PATCH, 0x10, 0x10);
+	}
+
+	for (int port = 0; port < ports; port++) {
+		patchphy = get_package_phy(phydev, port);
+		while (tries && !(phy_read_paged(patchphy, RTL821X_PAGE_STATE, 0x10) & 0x40)) {
+			tries--;
+			usleep_range(10000, 25000);
+		};
+	}
+
+	if (!tries)
+		phydev_err(get_package_phy(phydev, 0), "package not ready for patch.\n");
+
+	return tries ? 0 : -EIO;
+}
+
 static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev)
 {
-	u32 val, phy_id;
-	int mac = phydev->mdio.addr;
-	struct fw_header *h;
 	u32 *rtl838x_6275B_intPhy_perport;
 	u32 *rtl8218b_6276B_hwEsd_perport;
 	struct phy_device *patchphy;
-
-	val = phy_read(phydev, 2);
-	phy_id = val << 16;
-	val = phy_read(phydev, 3);
-	phy_id |= val;
-	pr_debug("Phy on MAC %d: %x\n", mac, phy_id);
+	struct fw_header *h;
+	int ret;
+	u32 val;
 
 	/* Read internal PHY ID */
 	phy_write_paged(phydev, 31, 27, 0x0002);
@@ -658,9 +676,6 @@ static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev)
 		return -1;
 	}
 
-	/* Internal RTL8218B, version 2 */
-	phydev_info(phydev, "Detected internal RTL8218B\n");
-
 	h = rtl838x_request_fw(phydev, &rtl838x_8380_fw, FIRMWARE_838X_8380_1);
 	if (!h)
 		return -1;
@@ -673,10 +688,7 @@ static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev)
 	rtl838x_6275B_intPhy_perport = (void *)h + sizeof(struct fw_header) + h->parts[8].start;
 	rtl8218b_6276B_hwEsd_perport = (void *)h + sizeof(struct fw_header) + h->parts[9].start;
 
-	// Currently not used
-	// if (sw_r32(RTL838X_DMY_REG31) == 0x1) {
-	// 	int ipd_flag = 1;
-	// }
+	phydev_info(phydev, "patch\n");
 
 	val = phy_read(phydev, MII_BMCR);
 	if (val & BMCR_PDOWN)
@@ -685,27 +697,10 @@ static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev)
 		rtl8380_phy_reset(phydev);
 	msleep(100);
 
-	/* Ready PHY for patch */
-	for (int port = 0; port < 8; port++) {
-		patchphy = get_package_phy(phydev, port);
-		phy_write_paged(patchphy, RTL838X_PAGE_RAW, RTL8XXX_PAGE_SELECT, RTL821X_PAGE_PATCH);
-		phy_write_paged(patchphy, RTL838X_PAGE_RAW, 0x10, 0x0010);
-	}
-	msleep(500);
-	for (int port = 0; port < 8; port++) {
-		int i;
+	ret = rtl821x_prepare_patch(phydev, 8);
+	if (ret)
+		return ret;
 
-		patchphy = get_package_phy(phydev, port);
-		for (i = 0; i < 100 ; i++) {
-			val = phy_read_paged(patchphy, RTL821X_PAGE_STATE, 0x10);
-			if (val & 0x40)
-				break;
-		}
-		if (i >= 100) {
-			phydev_err(patchphy, "not ready for patch.\n");
-			return -1;
-		}
-	}
 	for (int port = 0; port < 8; port++) {
 		int i;
 
@@ -732,23 +727,13 @@ static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev)
 
 static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev)
 {
-	u32 val, ipd, phy_id;
-	int mac = phydev->mdio.addr;
-	struct fw_header *h;
-	u32 *rtl8380_rtl8218b_perchip;
 	u32 *rtl8218B_6276B_rtl8380_perport;
+	u32 *rtl8380_rtl8218b_perchip;
 	u32 *rtl8380_rtl8218b_perport;
 	struct phy_device *patchphy;
-
-	if (soc_info.family == RTL8380_FAMILY_ID && mac != 0 && mac != 16) {
-		phydev_err(phydev, "External RTL8218B must have PHY-IDs 0 or 16!\n");
-		return -1;
-	}
-	val = phy_read(phydev, 2);
-	phy_id = val << 16;
-	val = phy_read(phydev, 3);
-	phy_id |= val;
-	pr_info("Phy on MAC %d: %x\n", mac, phy_id);
+	struct fw_header *h;
+	u32 val, ipd;
+	int ret;
 
 	/* Read internal PHY ID */
 	phy_write_paged(phydev, 31, 27, 0x0002);
@@ -757,7 +742,6 @@ static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev)
 		phydev_err(phydev, "Expected external RTL8218B, found PHY-ID %x\n", val);
 		return -1;
 	}
-	phydev_info(phydev, "Detected external RTL8218B\n");
 
 	h = rtl838x_request_fw(phydev, &rtl838x_8218b_fw, FIRMWARE_838X_8218b_1);
 	if (!h)
@@ -785,7 +769,7 @@ static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev)
 	phy_write_paged(phydev, RTL838X_PAGE_RAW, 0x1b, 0x4);
 	val = phy_read_paged(phydev, RTL838X_PAGE_RAW, 0x1c);
 
-	phydev_info(phydev, "Detected chip revision %04x\n", val);
+	phydev_info(phydev, "patch chip revision %d\n", val);
 
 	for (int i = 0; rtl8380_rtl8218b_perchip[i * 3] &&
 	                rtl8380_rtl8218b_perchip[i * 3 + 1]; i++) {
@@ -803,30 +787,9 @@ static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev)
 	}
 	mdelay(100);
 
-	/* Request patch */
-	for (int port = 0; port < 8; port++) {
-		patchphy = get_package_phy(phydev, port);
-		phy_write_paged(patchphy, RTL838X_PAGE_RAW, RTL8XXX_PAGE_SELECT, RTL821X_PAGE_PATCH);
-		phy_write_paged(patchphy, RTL838X_PAGE_RAW, 0x10, 0x0010);
-	}
-
-	mdelay(300);
-
-	/* Verify patch readiness */
-	for (int port = 0; port < 8; port++) {
-		int i;
-
-		patchphy = get_package_phy(phydev, port);
-		for (i = 0; i < 100; i++) {
-			val = phy_read_paged(patchphy, RTL821X_PAGE_STATE, 0x10);
-			if (val & 0x40)
-				break;
-		}
-		if (i >= 100) {
-			phydev_err(patchphy, "not ready for patch.\n");
-			return -1;
-		}
-	}
+	ret = rtl821x_prepare_patch(phydev, 8);
+	if (ret)
+		return ret;
 
 	/* Use Broadcast ID method for patching */
 	rtl821x_phy_setup_package_broadcast(phydev, true);
@@ -1081,19 +1044,12 @@ static int rtl8380_configure_rtl8214c(struct phy_device *phydev)
 
 static int rtl8380_configure_rtl8214fc(struct phy_device *phydev)
 {
-	int mac = phydev->mdio.addr;
-	struct fw_header *h;
 	u32 *rtl8380_rtl8214fc_perchip;
 	u32 *rtl8380_rtl8214fc_perport;
 	struct phy_device *patchphy;
-	u32 phy_id;
+	struct fw_header *h;
 	u32 val;
-
-	val = phy_read(phydev, 2);
-	phy_id = val << 16;
-	val = phy_read(phydev, 3);
-	phy_id |= val;
-	pr_debug("Phy on MAC %d: %x\n", mac, phy_id);
+	int ret;
 
 	/* Read internal PHY id */
 	phy_write_paged(phydev, 0, RTL821XEXT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_COPPER);
@@ -1103,7 +1059,6 @@ static int rtl8380_configure_rtl8214fc(struct phy_device *phydev)
 		phydev_err(phydev, "Expected external RTL8214FC, found PHY-ID %x\n", val);
 		return -1;
 	}
-	phydev_info(phydev, "Detected external RTL8214FC\n");
 
 	h = rtl838x_request_fw(phydev, &rtl838x_8214fc_fw, FIRMWARE_838X_8214FC_1);
 	if (!h)
@@ -1114,8 +1069,9 @@ static int rtl8380_configure_rtl8214fc(struct phy_device *phydev)
 		return -1;
 	}
 
-	rtl8380_rtl8214fc_perchip = (void *)h + sizeof(struct fw_header) + h->parts[0].start;
+	phydev_info(phydev, "patch\n");
 
+	rtl8380_rtl8214fc_perchip = (void *)h + sizeof(struct fw_header) + h->parts[0].start;
 	rtl8380_rtl8214fc_perport = (void *)h + sizeof(struct fw_header) + h->parts[1].start;
 
 	/* detect phy version */
@@ -1181,29 +1137,10 @@ static int rtl8380_configure_rtl8214fc(struct phy_device *phydev)
 		}
 	}
 
-	/* Request patch */
-	for (int port = 0; port < 4; port++) {
-		patchphy = get_package_phy(phydev, port);
-		phy_write_paged(patchphy, RTL838X_PAGE_RAW, RTL8XXX_PAGE_SELECT, RTL821X_PAGE_PATCH);
-		phy_write_paged(patchphy, RTL838X_PAGE_RAW, 0x10, 0x0010);
-	}
-	mdelay(300);
-
-	/* Verify patch readiness */
-	for (int port = 0; port < 4; port++) {
-		int i;
+	ret = rtl821x_prepare_patch(phydev, 4);
+	if (ret)
+		return ret;
 
-		patchphy = get_package_phy(phydev, port);
-		for (i = 0; i < 100; i++) {
-			val = phy_read_paged(patchphy, RTL821X_PAGE_STATE, 0x10);
-			if (val & 0x40)
-				break;
-		}
-		if (i >= 100) {
-			phydev_err(patchphy, "Could not patch PHY\n");
-			return -1;
-		}
-	}
 	/* Use Broadcast ID method for patching */
 	rtl821x_phy_setup_package_broadcast(phydev, true);
 




More information about the lede-commits mailing list