mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-13 21:58:06 +04:00
realtek: phy: fix RTL8218E XSGMII initialization
Commitc8c187f0f0("realtek: add support for RTL8218E") added the PHY identifier and reused the generic RTL821x callbacks. This is enough when the bootloader has already configured the package, but it leaves the MAC-side SerDes uninitialized without that setup. As a result, the XSGMII link is not established after a cold boot and/or without any pre-established PHY setup. Add package-level initialization on the base PHY address and gate it on the strapped XSGMII mode. Apply the minimal required subset of the vendor configuration, reset the active SerDes block, and force XSGMII mode by disabling SerDes autonegotiation. QSGMII remains unsupported. This completes RTL8218E support without relying on bootloader PHY setup while avoiding the large, mostly unnecessary vendor register table. This minimal sequence has been established through various testing iterations on two devices. Fixes:c8c187f0f0("realtek: add support for RTL8218E") Assisted-by: ChatGPT (OpenAI GPT-5.6 Sol) Link: https://github.com/openwrt/openwrt/pull/25255 Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
This commit is contained in:
1 file changed
+43
-1
@@ -449,6 +449,48 @@ static int rtl821x_config_init(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8218e_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int oldpage, oldxpage;
|
||||
bool is_xsgmii;
|
||||
|
||||
rtl821x_config_init(phydev);
|
||||
|
||||
if (phydev->mdio.addr % 8)
|
||||
return 0;
|
||||
|
||||
oldpage = phy_read(phydev, RTL821x_PAGE_SELECT);
|
||||
oldxpage = phy_read(phydev, RTL821x_EXT_PAGE_SELECT);
|
||||
|
||||
phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0x8);
|
||||
is_xsgmii = (phy_read_paged(phydev, 0x260, 0x12) & 0xf0) == 0xb0;
|
||||
|
||||
/* QSGMII configuration is not currently supported. */
|
||||
if (!is_xsgmii)
|
||||
goto restore;
|
||||
|
||||
/* Apply the minimal vendor XSGMII configuration, undocumented magic. */
|
||||
phy_write_paged(phydev, 0x4b8, 0x10, 0x8714);
|
||||
phy_write_paged(phydev, 0x4b8, 0x12, 0x7230);
|
||||
phy_write_paged(phydev, 0x4be, 0x16, 0x1000);
|
||||
phy_write_paged(phydev, 0x4bf, 0x11, 0x7000);
|
||||
phy_write_paged(phydev, 0x4bf, 0x16, 0x0042);
|
||||
phy_write_paged(phydev, 0x4ba, 0x14, 0x9d04);
|
||||
|
||||
/* Reset SerDes 0. */
|
||||
phy_write_paged(phydev, 0x400, 0x10, 0x1700);
|
||||
phy_write_paged(phydev, 0x400, 0x10, 0x1703);
|
||||
|
||||
/* Disable SerDes 0 XSGMII autonegotiation. */
|
||||
phy_modify_paged(phydev, 0x400, 0x12, GENMASK(9, 8), BIT(8));
|
||||
|
||||
restore:
|
||||
phy_write(phydev, RTL821x_EXT_PAGE_SELECT, oldxpage);
|
||||
phy_write(phydev, RTL821x_PAGE_SELECT, oldpage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8218d_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int oldpage, oldxpage;
|
||||
@@ -681,7 +723,7 @@ static struct phy_driver rtl83xx_phy_driver[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(PHY_ID_RTL8218E),
|
||||
.name = "REALTEK RTL8218E",
|
||||
.config_init = rtl821x_config_init,
|
||||
.config_init = rtl8218e_config_init,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.probe = rtl8218x_phy_probe,
|
||||
.read_mmd = rtl821x_read_mmd,
|
||||
|
||||
Reference in new issue
Block a user