From: Markus Stockhausen Date: Wed, 7 Jan 2026 07:32:58 +0000 (+0100) Subject: realtek: phy: add RTL8214FC initialization for RTL839x X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bab65dfa7c8ab27d0b2c76126e4d1114a92aa10;p=thirdparty%2Fopenwrt.git realtek: phy: add RTL8214FC initialization for RTL839x Until now the RTL8214FC is initialized either by U-Boot (all devices) or by some magic firmware file (RTL838x). On RTL839x devices without U-Boot (e.g. ZyXEL GS1920) this PHY cannot be used. Provide the most basic setup sequence for RTL839x so that copper/fiber work. Later it can be taken over for all devices and the firmware helpers can be dropped. Remark! This should not (but might) break RTL839x devices with RTL8214FC U-Boot setup. Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/21435 Signed-off-by: Stijn Tintel --- 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 8ac3024439d..046b9cc0d47 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 @@ -811,20 +811,6 @@ static const struct sfp_upstream_ops rtl8214fc_sfp_ops = { .module_remove = rtl8214fc_sfp_remove, }; -static int rtl8214fc_phy_probe(struct phy_device *phydev) -{ - int ret = 0; - - if (rtl821x_package_join(phydev, 4) == RTL821X_JOIN_LAST) { - if (soc_info.family == RTL8380_FAMILY_ID) - ret = rtl8380_configure_rtl8214fc(get_base_phy(phydev)); - if (ret) - return ret; - } - - return phy_sfp_probe(phydev, &rtl8214fc_sfp_ops); -} - static int rtl8214c_phy_probe(struct phy_device *phydev) { if (rtl821x_package_join(phydev, 4) == RTL821X_JOIN_LAST) @@ -931,6 +917,58 @@ static int rtl8218b_config_init(struct phy_device *phydev) return 0; } +static int rtl8214fc_config_init(struct phy_device *phydev) +{ + static int regs[] = {16, 19, 20, 21}; + struct phy_device *portphy; + int port; + + /* Hardware is similar to RTL8218B reuse coding for serdes and copper init */ + rtl8218b_config_init(phydev); + + if (phydev->mdio.addr % 8) + return 0; + + for (port = 0; port < 4; port++) { + portphy = get_package_phy(phydev, port); + + phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, 0x8); + /* setup basic fiber control in base phy and default to copper */ + phy_write_paged(phydev, 0x266, regs[port], 0x0f95); + phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, 0x0); + + phy_write(portphy, RTL821XEXT_MEDIA_PAGE_SELECT, 0x3); + /* set fiber SerDes RX to negative edge */ + phy_modify_paged(portphy, 0x8, 0x17, 0, BIT(14)); + /* auto negotiation disable link on */ + phy_modify_paged(portphy, 0x8, 0x14, 0, BIT(2)); + /* disable fiber 100MBit */ + phy_modify_paged(portphy, 0x8, 0x11, BIT(5), 0); + phy_write(portphy, RTL821XEXT_MEDIA_PAGE_SELECT, 0x0); + + /* Disable EEE. 0xa5d/0x10 is the same as MDIO_MMD_AN / MDIO_AN_EEE_ADV */ + phy_write_paged(portphy, 0xa5d, 0x10, 0x0000); + } + + return 0; +} + +static int rtl8214fc_phy_probe(struct phy_device *phydev) +{ + int ret = 0; + + if (rtl821x_package_join(phydev, 4) == RTL821X_JOIN_LAST) { + if (soc_info.family == RTL8380_FAMILY_ID) + ret = rtl8380_configure_rtl8214fc(get_base_phy(phydev)); + else if (soc_info.family == RTL8390_FAMILY_ID) + ret = rtl8214fc_config_init(get_base_phy(phydev)); + if (ret) + return ret; + } + + return phy_sfp_probe(phydev, &rtl8214fc_sfp_ops); +} + static struct phy_driver rtl83xx_phy_driver[] = { { PHY_ID_MATCH_EXACT(PHY_ID_RTL8214C),