mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-01-28 03:37:17 +01:00
kernel: net: phy: realtek: replace in-band AN hack
Replace downstream hack for RealTek PHYs with a more clean solution which could make it upstream. As SGMII in-band AN is broken on some platforms, or simply expected to be disabled by default in phy/sgmii mode (ie. on-board PHYs with MDIO for out-of-band configuration and status), a hack for the RealTek PHY driver was introduced to unconditionally disable SGMII in-band autonegotiation. Meanwhile the kernel has gained a proper interface for PHY and PCS to report in-band AN capabilities and enable/disable in-band, matching PHY and PCS capabilities. Thanks to Bevan Weiss' knowledge about how RealTek PHY SerDes registers are being handled in RealTek's SDK this can now be greatly improved: - report in-band capabilties - let phylink set in-band matching PCS and PHY capabilities - properly abstracted indirect access of SerDes registers Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
5652b98952
commit
dfce21df96
7 changed files with 160 additions and 91 deletions
|
|
@ -1,79 +0,0 @@
|
|||
From d54ef6aea00e7a6ace439baade6ad0aa38ee4b04 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Mon, 3 Apr 2023 01:21:57 +0300
|
||||
Subject: [PATCH 287/326] net: phy: realtek: disable SGMII in-band AN for 2.5G
|
||||
PHYs
|
||||
|
||||
MAC drivers don't use SGMII in-band autonegotiation unless told to do so
|
||||
in device tree using 'managed = "in-band-status"'. When using MDIO to
|
||||
access a PHY, in-band-status is unneeded as we have link-status via
|
||||
MDIO. Switch off SGMII in-band autonegotiation using magic values.
|
||||
|
||||
Reported-by: Chen Minqiang <ptpt52@gmail.com>
|
||||
Reported-by: Chukun Pan <amadeus@jmu.edu.cn>
|
||||
Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Tested-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++++++++++--
|
||||
1 file changed, 25 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -1345,8 +1345,8 @@ static int rtl822xb_write_mmd(struct phy
|
||||
static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1)
|
||||
{
|
||||
bool has_2500, has_sgmii;
|
||||
+ int ret, val;
|
||||
u16 mode;
|
||||
- int ret;
|
||||
|
||||
has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
|
||||
phydev->host_interfaces) ||
|
||||
@@ -1388,18 +1388,42 @@ static int rtl822x_set_serdes_option_mod
|
||||
RTL822X_VND1_SERDES_OPTION,
|
||||
RTL822X_VND1_SERDES_OPTION_MODE_MASK,
|
||||
mode);
|
||||
- if (gen1 || ret < 0)
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!gen1) {
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Disable SGMII AN */
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7588, 0x2);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7589, 0x71d0);
|
||||
+ if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503);
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7587, 0x3);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455);
|
||||
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 0x7587,
|
||||
+ val, !(val & BIT(0)), 500, 100000, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int rtl822x_config_init(struct phy_device *phydev)
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
From 43a4dfb71e2d23bae10ae13b7314d0641321d35e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sat, 3 Jan 2026 02:53:59 +0000
|
||||
Subject: [PATCH 2/2] net: phy: realtek: implement configuring in-band an
|
||||
|
||||
Implement the inband_caps() and config_inband() PHY driver methods to
|
||||
allow configuring the use of in-band-status with SGMII and 2500Base-X on
|
||||
RTL8226 and RTL8221B 2.5GE PHYs.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek/realtek_main.c | 67 ++++++++++++++++++++++++++
|
||||
1 file changed, 67 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -135,6 +135,15 @@
|
||||
#define RTL822X_VND2_TO_PAGE_REG(reg) (16 + (((reg) & GENMASK(3, 0)) >> 1))
|
||||
#define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg))
|
||||
|
||||
+#define RTL822X_VND1_SERDES_CMD 0x7587
|
||||
+#define RTL822X_VND1_SERDES_CMD_WRITE BIT(1)
|
||||
+#define RTL822X_VND1_SERDES_CMD_BUSY BIT(0)
|
||||
+#define RTL822X_VND1_SERDES_ADDR 0x7588
|
||||
+#define RTL822X_VND1_SERDES_ADDR_AUTONEG 0x2
|
||||
+#define RTL822X_VND1_SERDES_INBAND_DISABLE 0x71d0
|
||||
+#define RTL822X_VND1_SERDES_INBAND_ENABLE 0x70d0
|
||||
+#define RTL822X_VND1_SERDES_DATA 0x7589
|
||||
+
|
||||
#define RTL8221B_VND2_INER 0xa4d2
|
||||
#define RTL8221B_VND2_INER_LINK_STATUS BIT(4)
|
||||
|
||||
@@ -1381,6 +1390,50 @@ static int rtl822xb_config_init(struct p
|
||||
return rtl822x_set_serdes_option_mode(phydev, false);
|
||||
}
|
||||
|
||||
+static int rtl822x_serdes_write(struct phy_device *phydev, u16 reg, u16 val)
|
||||
+{
|
||||
+ int ret, poll;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_ADDR, reg);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_DATA, val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CMD,
|
||||
+ RTL822X_VND1_SERDES_CMD_WRITE |
|
||||
+ RTL822X_VND1_SERDES_CMD_BUSY);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
|
||||
+ RTL822X_VND1_SERDES_CMD, poll,
|
||||
+ !(poll & RTL822X_VND1_SERDES_CMD_BUSY),
|
||||
+ 500, 100000, false);
|
||||
+}
|
||||
+
|
||||
+static int rtl822x_config_inband(struct phy_device *phydev, unsigned int modes)
|
||||
+{
|
||||
+ return rtl822x_serdes_write(phydev, RTL822X_VND1_SERDES_ADDR_AUTONEG,
|
||||
+ (modes != LINK_INBAND_DISABLE) ?
|
||||
+ RTL822X_VND1_SERDES_INBAND_ENABLE :
|
||||
+ RTL822X_VND1_SERDES_INBAND_DISABLE);
|
||||
+}
|
||||
+
|
||||
+static unsigned int rtl822x_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int rtl822xb_get_rate_matching(struct phy_device *phydev,
|
||||
phy_interface_t iface)
|
||||
{
|
||||
@@ -2180,6 +2233,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
@@ -2195,6 +2250,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.get_features = rtl822x_c45_get_features,
|
||||
.config_aneg = rtl822x_c45_config_aneg,
|
||||
.config_init = rtl822x_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.read_status = rtl822xb_c45_read_status,
|
||||
.suspend = genphy_c45_pma_suspend,
|
||||
.resume = rtlgen_c45_resume,
|
||||
@@ -2207,6 +2264,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
@@ -2223,6 +2282,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
@@ -2239,6 +2300,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.soft_reset = rtl822x_c45_soft_reset,
|
||||
.probe = rtl822x_probe,
|
||||
.config_init = rtl822xb_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.get_features = rtl822x_c45_get_features,
|
||||
.config_aneg = rtl822x_c45_config_aneg,
|
||||
@@ -2253,6 +2316,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
@@ -2269,6 +2334,8 @@ static struct phy_driver realtek_drvs[]
|
||||
.soft_reset = rtl822x_c45_soft_reset,
|
||||
.probe = rtl822x_probe,
|
||||
.config_init = rtl822xb_config_init,
|
||||
+ .inband_caps = rtl822x_inband_caps,
|
||||
+ .config_inband = rtl822x_config_inband,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.get_features = rtl822x_c45_get_features,
|
||||
.config_aneg = rtl822x_c45_config_aneg,
|
||||
|
|
@ -18,7 +18,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -1815,9 +1815,11 @@ static bool rtlgen_supports_2_5gbps(stru
|
||||
@@ -1813,9 +1813,11 @@ static bool rtlgen_supports_2_5gbps(stru
|
||||
{
|
||||
int val;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -162,6 +162,10 @@
|
||||
@@ -170,6 +170,10 @@
|
||||
|
||||
#define RTL8224_SRAM_RTCT_LEN(pair) (0x8028 + (pair) * 4)
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
#define RTL8366RB_POWER_SAVE 0x15
|
||||
#define RTL8366RB_POWER_SAVE_ON BIT(12)
|
||||
|
||||
@@ -208,6 +212,10 @@ struct rtl821x_priv {
|
||||
@@ -216,6 +220,10 @@ struct rtl821x_priv {
|
||||
u16 iner;
|
||||
};
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
static int rtl821x_read_page(struct phy_device *phydev)
|
||||
{
|
||||
return __phy_read(phydev, RTL821x_PAGE_SELECT);
|
||||
@@ -1231,6 +1239,18 @@ static int rtl822x_write_mmd(struct phy_
|
||||
@@ -1239,6 +1247,18 @@ static int rtl822x_write_mmd(struct phy_
|
||||
|
||||
static int rtl822x_probe(struct phy_device *phydev)
|
||||
{
|
||||
|
|
@ -54,10 +54,10 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) &&
|
||||
phydev->phy_id != RTL_GENERIC_PHYID)
|
||||
return rtl822x_hwmon_init(phydev);
|
||||
@@ -1342,6 +1362,19 @@ static int rtl822xb_write_mmd(struct phy
|
||||
return write_ret;
|
||||
@@ -1320,6 +1340,19 @@ static int rtl822xb_write_mmd(struct phy
|
||||
}
|
||||
|
||||
|
||||
+static int rtl822x_init_phycr1(struct phy_device *phydev, bool no_aldps)
|
||||
+{
|
||||
+ struct rtl822x_priv *priv = phydev->priv;
|
||||
|
|
@ -74,10 +74,11 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1)
|
||||
{
|
||||
bool has_2500, has_sgmii;
|
||||
@@ -1423,6 +1456,14 @@ static int rtl822x_set_serdes_option_mod
|
||||
@@ -1377,7 +1410,15 @@ static int rtl822x_set_serdes_option_mod
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
|
@ -86,6 +87,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
return 0;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int rtl822x_config_init(struct phy_device *phydev)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -1900,10 +1900,32 @@ static int rtl8226_match_phy_device(stru
|
||||
@@ -1898,10 +1898,32 @@ static int rtl8226_match_phy_device(stru
|
||||
static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
|
||||
bool is_c45)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -1597,6 +1597,9 @@ static int rtl822x_c45_get_features(stru
|
||||
@@ -1626,6 +1626,9 @@ static int rtl822x_c45_get_features(stru
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
|
||||
phydev->supported);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
---
|
||||
--- a/drivers/net/phy/realtek/realtek_main.c
|
||||
+++ b/drivers/net/phy/realtek/realtek_main.c
|
||||
@@ -165,6 +165,7 @@
|
||||
@@ -174,6 +174,7 @@
|
||||
#define RTL8221B_PHYCR1 0xa430
|
||||
#define RTL8221B_PHYCR1_ALDPS_EN BIT(2)
|
||||
#define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12)
|
||||
|
|
@ -21,7 +21,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
#define RTL8366RB_POWER_SAVE 0x15
|
||||
#define RTL8366RB_POWER_SAVE_ON BIT(12)
|
||||
@@ -1372,7 +1373,8 @@ static int rtl822x_init_phycr1(struct ph
|
||||
@@ -1381,7 +1382,8 @@ static int rtl822x_init_phycr1(struct ph
|
||||
|
||||
return phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL8221B_PHYCR1,
|
||||
RTL8221B_PHYCR1_ALDPS_EN |
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue