Skip to content

Commit 19bc6e8

Browse files
plappermaulhauke
authored andcommitted
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@gmx.de> Link: openwrt/openwrt#19491 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
1 parent 9533e2e commit 19bc6e8

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnu
3838
#define RTL821X_PAGE_MAC 0x0a43
3939
#define RTL821X_PAGE_STATE 0x0b80
4040
#define RTL821X_PAGE_PATCH 0x0b82
41+
#define RTL821X_MAC_SDS_PAGE(sds, page) (0x404 + (sds) * 0x20 + (page))
4142

4243
/* Using the special page 0xfff with the MDIO controller found in
4344
* 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)
38113812
return 0;
38123813
}
38133814

3815+
static void rtl8218b_cmu_reset(struct phy_device *phydev, int reset_id)
3816+
{
3817+
int bitpos = reset_id * 2;
3818+
3819+
/* CMU seems to have 8 pairs of reset bits that always work the same way */
3820+
phy_modify_paged(phydev, 0x467, 0x14, 0, BIT(bitpos));
3821+
phy_modify_paged(phydev, 0x467, 0x14, 0, BIT(bitpos + 1));
3822+
phy_write_paged(phydev, 0x467, 0x14, 0x0);
3823+
}
3824+
3825+
static int rtl8218b_config_init(struct phy_device *phydev)
3826+
{
3827+
int oldpage, oldxpage;
3828+
3829+
rtl821x_config_init(phydev);
3830+
3831+
if (phydev->mdio.addr % 8)
3832+
return 0;
3833+
/*
3834+
* Realtek provides two ways of initializing the PHY package. Either by U-Boot or via
3835+
* vendor software and SDK. In case U-Boot setup is missing, run basic configuration
3836+
* so that ports at least get link up and pass traffic.
3837+
*/
3838+
3839+
oldpage = phy_read(phydev, RTL8XXX_PAGE_SELECT);
3840+
oldxpage = phy_read(phydev, RTL821XEXT_MEDIA_PAGE_SELECT);
3841+
phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, 0x8);
3842+
3843+
/* activate 32/40 bit redundancy algorithm for first MAC serdes */
3844+
phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(0, 1), 0x14, 0, BIT(3));
3845+
/* magic CMU setting for stable connectivity of first MAC serdes */
3846+
phy_write_paged(phydev, 0x462, 0x15, 0x6e58);
3847+
rtl8218b_cmu_reset(phydev, 0);
3848+
3849+
for (int sds = 0; sds < 2; sds++) {
3850+
/* force negative clock edge */
3851+
phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(sds, 0), 0x17, 0, BIT(14));
3852+
rtl8218b_cmu_reset(phydev, 5 + sds);
3853+
/* soft reset */
3854+
phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(sds, 0), 0x13, 0, BIT(6));
3855+
phy_modify_paged(phydev, RTL821X_MAC_SDS_PAGE(sds, 0), 0x13, BIT(6), 0);
3856+
}
3857+
3858+
phy_write(phydev, RTL821XEXT_MEDIA_PAGE_SELECT, oldxpage);
3859+
phy_write(phydev, RTL8XXX_PAGE_SELECT, oldpage);
3860+
3861+
return 0;
3862+
}
3863+
38143864
static int rtl838x_serdes_probe(struct phy_device *phydev)
38153865
{
38163866
int addr = phydev->mdio.addr;
@@ -3898,7 +3948,7 @@ static struct phy_driver rtl83xx_phy_driver[] = {
38983948
{
38993949
.match_phy_device = rtl8218b_ext_match_phy_device,
39003950
.name = "Realtek RTL8218B (external)",
3901-
.config_init = rtl821x_config_init,
3951+
.config_init = rtl8218b_config_init,
39023952
.features = PHY_GBIT_FEATURES,
39033953
.probe = rtl8218b_ext_phy_probe,
39043954
.read_mmd = rtl821x_read_mmd,

0 commit comments

Comments
 (0)