]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: phy: add RTL8218D initialization 21551/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Thu, 15 Jan 2026 17:25:31 +0000 (18:25 +0100)
committerRobert Marko <robimarko@gmail.com>
Fri, 23 Jan 2026 09:31:01 +0000 (10:31 +0100)
The RTL8218D currently relies on proper U-Boot configuration. In
case that is not possible, provide a basic setup sequence that can
bring the PHY "alive". The SDK provides multiple configuration
sequences for two operation modes (XSGMII or QSGMII) and the different
SoC families. Due to limited testing resources only provide a setup
for RTL93xx devices and both modes at the moment.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/21551
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c

index e1a60ce55e82917a9a1bc246a89dd8e470c6f1f1..fad43dd8aa047e766b0b779928533d06a94ff376 100644 (file)
@@ -738,6 +738,68 @@ static int rtl821x_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int rtl8218d_config_init(struct phy_device *phydev)
+{
+       int oldpage, oldxpage;
+       bool is_qsgmii;
+       int chip_info;
+
+       rtl821x_config_init(phydev);
+
+       if (phydev->mdio.addr % 8)
+               return 0;
+       /*
+        * The RTl8218D has two MAC (aka SoC side) operation modes. Either dual QSGMII
+        * or single XSGMII (Realtek proprietary) link. The mode is usually configured via
+        * strapping pins CHIP_MODE1/2. For the moment offer a configuration that at least
+        * works for RTL93xx devices. This sequence even "revives" a PHY that has been hard
+        * reset with
+        *
+        *      phy_write(phydev, 0x1e, 0x8);
+        *      phy_write_paged(phydev, 0x262, 0x10, 0x1);
+        */
+       oldpage = phy_read(phydev, RTL8XXX_PAGE_SELECT);
+       oldxpage = phy_read(phydev, RTL821XEXT_MEDIA_PAGE_SELECT);
+
+       phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, 0x8);
+       chip_info = phy_read_paged(phydev, 0x327, 0x15);
+       is_qsgmii = (phy_read_paged(phydev, 0x260, 0x12) & 0xf0) == 0xd0;
+
+       pr_info("RTL8218D (chip_id=%d, rev_id=%d) on port %d running in %s mode\n",
+               (chip_info >> 7) & 0x7, chip_info & 0x7f, phydev->mdio.addr,
+               is_qsgmii ? "QSGMII" : "XSGMII");
+
+       if (is_qsgmii) {
+               for (int sds = 0; sds < 2; sds++) {
+                       /* unknown amplification value */
+                       phy_modify_paged(phydev, 0x4a8 + sds * 0x100, 0x12, BIT(3), 0);
+                       /* main aplification */
+                       phy_modify_paged(phydev, 0x4ab + sds * 0x100, 0x16, 0x3e0, 0x1e0);
+                       /* unknown LCCMU value */
+                       phy_write_paged(phydev, 0x4ac + sds * 0x100, 0x15, 0x4380);
+               }
+       } else {
+               /* serdes 0/1 disable auto negotiation */
+               phy_modify_paged(phydev, 0x400, 0x12, 0, BIT(8));
+               phy_modify_paged(phydev, 0x500, 0x12, 0, BIT(8));
+               /* unknown eye configuration */
+               phy_modify_paged(phydev, 0x4b8, 0x12, BIT(3), 0);
+       }
+
+       /* reset serdes 0 */
+       phy_write_paged(phydev, 0x400, 0x10, 0x1700);
+       phy_write_paged(phydev, 0x400, 0x10, 0x1703);
+
+       /* reset serdes 1 */
+       phy_write_paged(phydev, 0x500, 0x10, 0x1400);
+       phy_write_paged(phydev, 0x500, 0x10, 0x1403);
+
+       phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, oldxpage);
+       phy_write(phydev, RTL8XXX_PAGE_SELECT, oldpage);
+
+       return 0;
+}
+
 static void rtl8218b_cmu_reset(struct phy_device *phydev, int reset_id)
 {
        int bitpos = reset_id * 2;
@@ -896,7 +958,7 @@ static struct phy_driver rtl83xx_phy_driver[] = {
        {
                PHY_ID_MATCH_EXACT(PHY_ID_RTL8218D),
                .name           = "REALTEK RTL8218D",
-               .config_init    = rtl821x_config_init,
+               .config_init    = rtl8218d_config_init,
                .features       = PHY_GBIT_FEATURES,
                .probe          = rtl8218x_phy_probe,
                .read_mmd       = rtl821x_read_mmd,