* [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching
@ 2024-03-03 10:28 Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs Eric Woudstra
` (6 more replies)
0 siblings, 7 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
Based on the comments in [PATCH net-next]
"Realtek RTL822x PHY rework to c45 and SerDes interface switching"
Adds SerDes switching interface between 2500base-x and sgmii for
rtl822x and rtl8251b.
Add get_rate_matching() for rtl822x and rtl8251b, reading the serdes
mode from phy.
Driver instances are added for rtl8221b and rtl8251b for Clause 45
access only. The existing code is not touched, they use newly added
functions. They also use the same rtl822x_config_init() and
rtl822x_get_rate_matching() as these functions also can be used for
direct Clause 45 access. Also Adds definition of MMC 31 registers,
which cannot be used through C45-over-C22, only when phydev->is_c45
is set.
Change rtlgen_get_speed() so the register value is passed as argument.
Using Clause 45 access, this value is retrieved differently.
Rename it to rtlgen_decode_speed() and add a call to it in
rtl822x_c45_read_status().
Add rtl822x_c45_get_features() to set supported ports.
Then 2 quirks are added for sfp modules known to have a rtl8221b
behind RollBall, Clause 45 only, protocol.
Changed in PATCH v2:
* Set author to Marek for the commit of the new C45 instances
* Separate commit for setting supported ports
* Renamed rtlgen_get_speed to rtlgen_decode_speed
* Always fill in possible interfaces
* Renamed sfp_fixup_oem_2_5g to sfp_fixup_oem_2_5gbaset
* Only update phydev->interface when link is up
Alexander Couzens (1):
net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
Eric Woudstra (4):
net: phy: realtek: add get_rate_matching() for rtl822x/8251b PHYs
net: phy: realtek: Change rtlgen_get_speed() to rtlgen_decode_speed()
net: phy: realtek: add rtl822x_c45_get_features() to set supported
ports
net: sfp: Fixup for OEM SFP-2.5G-T module
Marek Behún (2):
net: phy: realtek: Add driver instances for rtl8221b/8251b via Clause
45
net: sfp: add quirk for another multigig RollBall transceiver
drivers/net/phy/realtek.c | 325 +++++++++++++++++++++++++++++++++++---
drivers/net/phy/sfp.c | 10 +-
2 files changed, 312 insertions(+), 23 deletions(-)
--
2.42.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
2024-03-03 13:29 ` Daniel Golle
2024-03-03 20:42 ` Heiner Kallweit
2024-03-03 10:28 ` [PATCH v2 net-next 2/7] net: phy: realtek: add get_rate_matching() " Eric Woudstra
` (5 subsequent siblings)
6 siblings, 2 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Alexander Couzens, Eric Woudstra
From: Alexander Couzens <lynxis@fe80.eu>
The rtl822x series and rtl8251b support switching SerDes mode between
2500base-x and sgmii based on the negotiated copper speed.
Configure this switching mode according to SerDes modes supported by
host.
There is an additional datasheet for RTL8226B/RTL8221B called
"SERDES MODE SETTING FLOW APPLICATION NOTE" where this sequence to
setup interface and rate adapter mode.
However, there is no documentation about the meaning of registers
and bits, it's literally just magic numbers and pseudo-code.
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
[ refactored, dropped HiSGMII mode and changed commit message ]
Signed-off-by: Marek Behún <kabel@kernel.org>
[ changed rtl822x_update_interface() to use vendor register ]
[ always fill in possible interfaces ]
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/realtek.c | 99 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 1fa70427b2a2..8a876e003774 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -54,6 +54,16 @@
RTL8201F_ISR_LINK)
#define RTL8201F_IER 0x13
+#define RTL822X_VND1_SERDES_OPTION 0x697a
+#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
+#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0
+#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2
+
+#define RTL822X_VND1_SERDES_CTRL3 0x7580
+#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0)
+#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
+#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
+
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -659,6 +669,60 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
return ret;
}
+static int rtl822x_config_init(struct phy_device *phydev)
+{
+ bool has_2500, has_sgmii;
+ u16 mode;
+ int ret;
+
+ has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
+ phydev->host_interfaces) ||
+ phydev->interface == PHY_INTERFACE_MODE_2500BASEX;
+
+ has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII,
+ phydev->host_interfaces) ||
+ phydev->interface == PHY_INTERFACE_MODE_SGMII;
+
+ /* fill in possible interfaces */
+ __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces,
+ has_2500);
+ __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces,
+ has_sgmii);
+
+ if (!has_2500 && !has_sgmii)
+ return 0;
+
+ /* determine SerDes option mode */
+ if (has_2500 && !has_sgmii)
+ mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX;
+ else
+ mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII;
+
+ /* the following sequence with magic numbers sets up the SerDes
+ * option mode
+ */
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1,
+ RTL822X_VND1_SERDES_OPTION,
+ RTL822X_VND1_SERDES_OPTION_MODE_MASK,
+ mode);
+ if (ret < 0)
+ return ret;
+
+ 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;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
+}
+
static int rtl822x_get_features(struct phy_device *phydev)
{
int val;
@@ -695,6 +759,28 @@ static int rtl822x_config_aneg(struct phy_device *phydev)
return __genphy_config_aneg(phydev, ret);
}
+static void rtl822x_update_interface(struct phy_device *phydev)
+{
+ int val;
+
+ if (!phydev->link)
+ return;
+
+ /* Change interface according to serdes mode */
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3);
+ if (val < 0)
+ return;
+
+ switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) {
+ case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX:
+ phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
+ break;
+ case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII:
+ phydev->interface = PHY_INTERFACE_MODE_SGMII;
+ break;
+ }
+}
+
static int rtl822x_read_status(struct phy_device *phydev)
{
int ret;
@@ -709,11 +795,13 @@ static int rtl822x_read_status(struct phy_device *phydev)
lpadv);
}
- ret = genphy_read_status(phydev);
+ ret = rtlgen_read_status(phydev);
if (ret < 0)
return ret;
- return rtlgen_get_speed(phydev);
+ rtl822x_update_interface(phydev);
+
+ return 0;
}
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
@@ -976,6 +1064,7 @@ static struct phy_driver realtek_drvs[] = {
.match_phy_device = rtl8226_match_phy_device,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
+ .config_init = rtl822x_config_init,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -988,6 +1077,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
+ .config_init = rtl822x_config_init,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1000,6 +1090,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8226-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
+ .config_init = rtl822x_config_init,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1010,6 +1101,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
+ .config_init = rtl822x_config_init,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1019,6 +1111,7 @@ static struct phy_driver realtek_drvs[] = {
PHY_ID_MATCH_EXACT(0x001cc849),
.name = "RTL8221B-VB-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
+ .config_init = rtl822x_config_init,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
@@ -1030,6 +1123,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8221B-VM-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
+ .config_init = rtl822x_config_init,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1040,6 +1134,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8251B 5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
+ .config_init = rtl822x_config_init,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 2/7] net: phy: realtek: add get_rate_matching() for rtl822x/8251b PHYs
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 3/7] net: phy: realtek: Add driver instances for rtl8221b/8251b via Clause 45 Eric Woudstra
` (4 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
Uses vendor register to determine if SerDes is setup in rate-matching mode.
Rate-matching only supported when SerDes is set to 2500base-x.
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/realtek.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 8a876e003774..d7a47edd529e 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -723,6 +723,28 @@ static int rtl822x_config_init(struct phy_device *phydev)
return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
}
+static int rtl822x_get_rate_matching(struct phy_device *phydev,
+ phy_interface_t iface)
+{
+ int val;
+
+ /* Only rate matching at 2500base-x */
+ if (iface != PHY_INTERFACE_MODE_2500BASEX)
+ return RATE_MATCH_NONE;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_OPTION);
+ if (val < 0)
+ return val;
+
+ switch (val & RTL822X_VND1_SERDES_OPTION_MODE_MASK) {
+ case RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX:
+ return RATE_MATCH_PAUSE;
+ /* case RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII: */
+ default:
+ return RATE_MATCH_NONE;
+ }
+}
+
static int rtl822x_get_features(struct phy_device *phydev)
{
int val;
@@ -1065,6 +1087,7 @@ static struct phy_driver realtek_drvs[] = {
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1078,6 +1101,7 @@ static struct phy_driver realtek_drvs[] = {
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1091,6 +1115,7 @@ static struct phy_driver realtek_drvs[] = {
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1102,6 +1127,7 @@ static struct phy_driver realtek_drvs[] = {
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1112,6 +1138,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8221B-VB-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
@@ -1124,6 +1151,7 @@ static struct phy_driver realtek_drvs[] = {
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
@@ -1135,6 +1163,7 @@ static struct phy_driver realtek_drvs[] = {
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
.read_status = rtl822x_read_status,
.suspend = genphy_suspend,
.resume = rtlgen_resume,
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 3/7] net: phy: realtek: Add driver instances for rtl8221b/8251b via Clause 45
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 2/7] net: phy: realtek: add get_rate_matching() " Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 4/7] net: phy: realtek: Change rtlgen_get_speed() to rtlgen_decode_speed() Eric Woudstra
` (3 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
From: Marek Behún <kabel@kernel.org>
Collected from several commits in [PATCH net-next]
"Realtek RTL822x PHY rework to c45 and SerDes interface switching"
The instances are used by Clause 45 only accessible PHY's on several sfp
modules, which are using RollBall protocol.
Signed-off-by: Marek Behún <kabel@kernel.org>
[ Added matching functions to differentiate C45 instances ]
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/realtek.c | 146 ++++++++++++++++++++++++++++++++++++--
1 file changed, 140 insertions(+), 6 deletions(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index d7a47edd529e..f9a67761878e 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -64,6 +64,13 @@
#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
+/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45
+ * is set, they cannot be accessed by C45-over-C22.
+ */
+#define RTL822X_VND2_GBCR 0xa412
+
+#define RTL822X_VND2_GANLPAR 0xa414
+
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -74,6 +81,9 @@
#define RTL_GENERIC_PHYID 0x001cc800
#define RTL_8211FVD_PHYID 0x001cc878
+#define RTL_8221B_VB_CG 0x001cc849
+#define RTL_8221B_VN_CG 0x001cc84a
+#define RTL_8251B 0x001cc862
MODULE_DESCRIPTION("Realtek PHY driver");
MODULE_AUTHOR("Johnson Leung");
@@ -826,6 +836,56 @@ static int rtl822x_read_status(struct phy_device *phydev)
return 0;
}
+static int rtl822x_c45_config_aneg(struct phy_device *phydev)
+{
+ bool changed = false;
+ int ret, val;
+
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ return genphy_c45_pma_setup_forced(phydev);
+
+ ret = genphy_c45_an_config_aneg(phydev);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
+
+ /* Vendor register as C45 has no standardized support for 1000BaseT */
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR,
+ ADVERTISE_1000FULL, val);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ return genphy_c45_check_and_restart_aneg(phydev, changed);
+}
+
+static int rtl822x_c45_read_status(struct phy_device *phydev)
+{
+ int ret, val;
+
+ ret = genphy_c45_read_status(phydev);
+ if (ret < 0)
+ return ret;
+
+ /* Vendor register as C45 has no standardized support for 1000BaseT */
+ if (phydev->autoneg == AUTONEG_ENABLE) {
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ RTL822X_VND2_GANLPAR);
+ if (val < 0)
+ return val;
+
+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
+ }
+
+ rtl822x_update_interface(phydev);
+
+ return 0;
+}
+
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
{
int val;
@@ -849,6 +909,44 @@ static int rtl8226_match_phy_device(struct phy_device *phydev)
rtlgen_supports_2_5gbps(phydev);
}
+static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, bool is_c45)
+{
+ if (phydev->is_c45)
+ return is_c45 && (id == phydev->c45_ids.device_ids[1]);
+ else
+ return !is_c45 && (id == phydev->phy_id);
+}
+
+static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
+{
+ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
+}
+
+static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev)
+{
+ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
+}
+
+static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev)
+{
+ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
+}
+
+static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
+{
+ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
+}
+
+static int rtl8251b_c22_match_phy_device(struct phy_device *phydev)
+{
+ return rtlgen_is_c45_match(phydev, RTL_8251B, false);
+}
+
+static int rtl8251b_c45_match_phy_device(struct phy_device *phydev)
+{
+ return rtlgen_is_c45_match(phydev, RTL_8251B, true);
+}
+
static int rtlgen_resume(struct phy_device *phydev)
{
int ret = genphy_resume(phydev);
@@ -859,6 +957,15 @@ static int rtlgen_resume(struct phy_device *phydev)
return ret;
}
+static int rtlgen_c45_resume(struct phy_device *phydev)
+{
+ int ret = genphy_c45_pma_resume(phydev);
+
+ msleep(20);
+
+ return ret;
+}
+
static int rtl9000a_config_init(struct phy_device *phydev)
{
phydev->autoneg = AUTONEG_DISABLE;
@@ -1134,8 +1241,8 @@ static struct phy_driver realtek_drvs[] = {
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
- PHY_ID_MATCH_EXACT(0x001cc849),
- .name = "RTL8221B-VB-CG 2.5Gbps PHY",
+ .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
+ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
.get_features = rtl822x_get_features,
.config_init = rtl822x_config_init,
.get_rate_matching = rtl822x_get_rate_matching,
@@ -1146,8 +1253,17 @@ static struct phy_driver realtek_drvs[] = {
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
- PHY_ID_MATCH_EXACT(0x001cc84a),
- .name = "RTL8221B-VM-CG 2.5Gbps PHY",
+ .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
+ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
+ .config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
+ .config_aneg = rtl822x_c45_config_aneg,
+ .read_status = rtl822x_c45_read_status,
+ .suspend = genphy_c45_pma_suspend,
+ .resume = rtlgen_c45_resume,
+ }, {
+ .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
+ .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
@@ -1158,8 +1274,17 @@ static struct phy_driver realtek_drvs[] = {
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
- PHY_ID_MATCH_EXACT(0x001cc862),
- .name = "RTL8251B 5Gbps PHY",
+ .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
+ .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
+ .config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
+ .config_aneg = rtl822x_c45_config_aneg,
+ .read_status = rtl822x_c45_read_status,
+ .suspend = genphy_c45_pma_suspend,
+ .resume = rtlgen_c45_resume,
+ }, {
+ .match_phy_device = rtl8251b_c22_match_phy_device,
+ .name = "RTL8251B 5Gbps PHY (C22)",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822x_config_init,
@@ -1169,6 +1294,15 @@ static struct phy_driver realtek_drvs[] = {
.resume = rtlgen_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
+ }, {
+ .match_phy_device = rtl8251b_c45_match_phy_device,
+ .name = "RTL8251B 5Gbps PHY (C45)",
+ .config_init = rtl822x_config_init,
+ .get_rate_matching = rtl822x_get_rate_matching,
+ .config_aneg = rtl822x_c45_config_aneg,
+ .read_status = rtl822x_c45_read_status,
+ .suspend = genphy_c45_pma_suspend,
+ .resume = rtlgen_c45_resume,
}, {
PHY_ID_MATCH_EXACT(0x001cc961),
.name = "RTL8366RB Gigabit Ethernet",
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 4/7] net: phy: realtek: Change rtlgen_get_speed() to rtlgen_decode_speed()
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
` (2 preceding siblings ...)
2024-03-03 10:28 ` [PATCH v2 net-next 3/7] net: phy: realtek: Add driver instances for rtl8221b/8251b via Clause 45 Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 5/7] net: phy: realtek: add rtl822x_c45_get_features() to set supported ports Eric Woudstra
` (2 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
The value of the register to determine the speed, is retrieved
differently when using Clause 45 only. To use the rtlgen_get_speed()
function in this case, pass the value of the register as argument to
rtlgen_get_speed(). The function would then always return 0, so change it
to void. A better name for this function now is rtlgen_decode_speed().
Add reading speed to rtl822x_c45_read_status().
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/realtek.c | 38 ++++++++++++++++++++++++--------------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index f9a67761878e..6449d8e0842c 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -71,6 +71,8 @@
#define RTL822X_VND2_GANLPAR 0xa414
+#define RTL822X_VND2_PHYSR 0xa434
+
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -551,17 +553,8 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
}
/* get actual speed to cover the downshift case */
-static int rtlgen_get_speed(struct phy_device *phydev)
+static void rtlgen_decode_speed(struct phy_device *phydev, int val)
{
- int val;
-
- if (!phydev->link)
- return 0;
-
- val = phy_read_paged(phydev, 0xa43, 0x12);
- if (val < 0)
- return val;
-
switch (val & RTLGEN_SPEED_MASK) {
case 0x0000:
phydev->speed = SPEED_10;
@@ -584,19 +577,26 @@ static int rtlgen_get_speed(struct phy_device *phydev)
default:
break;
}
-
- return 0;
}
static int rtlgen_read_status(struct phy_device *phydev)
{
- int ret;
+ int ret, val;
ret = genphy_read_status(phydev);
if (ret < 0)
return ret;
- return rtlgen_get_speed(phydev);
+ if (!phydev->link)
+ return 0;
+
+ val = phy_read_paged(phydev, 0xa43, 0x12);
+ if (val < 0)
+ return val;
+
+ rtlgen_decode_speed(phydev, val);
+
+ return 0;
}
static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
@@ -881,6 +881,16 @@ static int rtl822x_c45_read_status(struct phy_device *phydev)
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
}
+ if (!phydev->link)
+ return 0;
+
+ /* Read actual speed from vendor register. */
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_PHYSR);
+ if (val < 0)
+ return val;
+
+ rtlgen_decode_speed(phydev, val);
+
rtl822x_update_interface(phydev);
return 0;
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 5/7] net: phy: realtek: add rtl822x_c45_get_features() to set supported ports
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
` (3 preceding siblings ...)
2024-03-03 10:28 ` [PATCH v2 net-next 4/7] net: phy: realtek: Change rtlgen_get_speed() to rtlgen_decode_speed() Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 6/7] net: sfp: Fixup for OEM SFP-2.5G-T module Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 7/7] net: sfp: add quirk for another multigig RollBall transceiver Eric Woudstra
6 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
Sets ETHTOOL_LINK_MODE_TP_BIT and ETHTOOL_LINK_MODE_MII_BIT in
phydev->supported.
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/realtek.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 6449d8e0842c..3dc27a4f2c88 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -836,6 +836,16 @@ static int rtl822x_read_status(struct phy_device *phydev)
return 0;
}
+static int rtl822x_c45_get_features(struct phy_device *phydev)
+{
+ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
+ phydev->supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT,
+ phydev->supported);
+
+ return genphy_c45_pma_read_abilities(phydev);
+}
+
static int rtl822x_c45_config_aneg(struct phy_device *phydev)
{
bool changed = false;
@@ -1267,6 +1277,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
.config_init = rtl822x_config_init,
.get_rate_matching = rtl822x_get_rate_matching,
+ .get_features = rtl822x_c45_get_features,
.config_aneg = rtl822x_c45_config_aneg,
.read_status = rtl822x_c45_read_status,
.suspend = genphy_c45_pma_suspend,
@@ -1288,6 +1299,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
.config_init = rtl822x_config_init,
.get_rate_matching = rtl822x_get_rate_matching,
+ .get_features = rtl822x_c45_get_features,
.config_aneg = rtl822x_c45_config_aneg,
.read_status = rtl822x_c45_read_status,
.suspend = genphy_c45_pma_suspend,
@@ -1309,6 +1321,7 @@ static struct phy_driver realtek_drvs[] = {
.name = "RTL8251B 5Gbps PHY (C45)",
.config_init = rtl822x_config_init,
.get_rate_matching = rtl822x_get_rate_matching,
+ .get_features = rtl822x_c45_get_features,
.config_aneg = rtl822x_c45_config_aneg,
.read_status = rtl822x_c45_read_status,
.suspend = genphy_c45_pma_suspend,
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 6/7] net: sfp: Fixup for OEM SFP-2.5G-T module
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
` (4 preceding siblings ...)
2024-03-03 10:28 ` [PATCH v2 net-next 5/7] net: phy: realtek: add rtl822x_c45_get_features() to set supported ports Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 7/7] net: sfp: add quirk for another multigig RollBall transceiver Eric Woudstra
6 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
Change from quirk to fixup for the OEM SFP-2.5G-T module.
Implementing this fixup, the rtl8221b phy is attached and the quirk is no
longer used.
The module is re-branded to different brands, the one I have that applies
to this patch is branded LuLeey.
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/sfp.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index f75c9eb3958e..191a6d5dc925 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -385,6 +385,13 @@ static void sfp_fixup_rollball(struct sfp *sfp)
sfp->phy_t_retry = msecs_to_jiffies(1000);
}
+// For 2.5GBASE-T short-reach modules
+static void sfp_fixup_oem_2_5gbaset(struct sfp *sfp)
+{
+ sfp_fixup_rollball(sfp);
+ sfp->id.base.extended_cc = SFF8024_ECC_2_5GBASE_T;
+}
+
static void sfp_fixup_fs_10gt(struct sfp *sfp)
{
sfp_fixup_10gbaset_30m(sfp);
@@ -503,7 +510,7 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt),
SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
- SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
+ SFP_QUIRK_F("OEM", "SFP-2.5G-T", sfp_fixup_oem_2_5gbaset),
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
SFP_QUIRK_F("Turris", "RTSFP-10", sfp_fixup_rollball),
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 net-next 7/7] net: sfp: add quirk for another multigig RollBall transceiver
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
` (5 preceding siblings ...)
2024-03-03 10:28 ` [PATCH v2 net-next 6/7] net: sfp: Fixup for OEM SFP-2.5G-T module Eric Woudstra
@ 2024-03-03 10:28 ` Eric Woudstra
6 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 10:28 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Eric Woudstra
From: Marek Behún <kabel@kernel.org>
Add quirk for another RollBall copper transceiver: Turris RTSFP-2.5G,
containing 2.5g capable RTL8221B PHY.
Signed-off-by: Marek Behún <kabel@kernel.org>
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
drivers/net/phy/sfp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 191a6d5dc925..0476624bbca6 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -513,6 +513,7 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK_F("OEM", "SFP-2.5G-T", sfp_fixup_oem_2_5gbaset),
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
+ SFP_QUIRK_F("Turris", "RTSFP-2.5G", sfp_fixup_rollball),
SFP_QUIRK_F("Turris", "RTSFP-10", sfp_fixup_rollball),
SFP_QUIRK_F("Turris", "RTSFP-10G", sfp_fixup_rollball),
};
--
2.42.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 10:28 ` [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs Eric Woudstra
@ 2024-03-03 13:29 ` Daniel Golle
2024-03-03 14:33 ` Eric Woudstra
2024-03-03 20:42 ` Heiner Kallweit
1 sibling, 1 reply; 15+ messages in thread
From: Daniel Golle @ 2024-03-03 13:29 UTC (permalink / raw)
To: Eric Woudstra
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, netdev, Alexander Couzens
On Sun, Mar 03, 2024 at 11:28:42AM +0100, Eric Woudstra wrote:
> From: Alexander Couzens <lynxis@fe80.eu>
>
> The rtl822x series and rtl8251b support switching SerDes mode between
> 2500base-x and sgmii based on the negotiated copper speed.
>
> Configure this switching mode according to SerDes modes supported by
> host.
>
> There is an additional datasheet for RTL8226B/RTL8221B called
> "SERDES MODE SETTING FLOW APPLICATION NOTE" where this sequence to
> setup interface and rate adapter mode.
Gramar doesn't parse, missing verb.
>
> However, there is no documentation about the meaning of registers
> and bits, it's literally just magic numbers and pseudo-code.
>
> Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
> [ refactored, dropped HiSGMII mode and changed commit message ]
> Signed-off-by: Marek Behún <kabel@kernel.org>
> [ changed rtl822x_update_interface() to use vendor register ]
> [ always fill in possible interfaces ]
> Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
> ---
> drivers/net/phy/realtek.c | 99 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 97 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
> index 1fa70427b2a2..8a876e003774 100644
> --- a/drivers/net/phy/realtek.c
> +++ b/drivers/net/phy/realtek.c
> @@ -54,6 +54,16 @@
> RTL8201F_ISR_LINK)
> #define RTL8201F_IER 0x13
>
> +#define RTL822X_VND1_SERDES_OPTION 0x697a
> +#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
> +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0
> +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2
> +
> +#define RTL822X_VND1_SERDES_CTRL3 0x7580
> +#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0)
> +#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
> +#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
> +
> #define RTL8366RB_POWER_SAVE 0x15
> #define RTL8366RB_POWER_SAVE_ON BIT(12)
>
> @@ -659,6 +669,60 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
> return ret;
> }
>
> +static int rtl822x_config_init(struct phy_device *phydev)
> +{
> + bool has_2500, has_sgmii;
> + u16 mode;
> + int ret;
> +
> + has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
> + phydev->host_interfaces) ||
> + phydev->interface == PHY_INTERFACE_MODE_2500BASEX;
> +
> + has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII,
> + phydev->host_interfaces) ||
> + phydev->interface == PHY_INTERFACE_MODE_SGMII;
> +
> + /* fill in possible interfaces */
> + __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces,
> + has_2500);
> + __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces,
> + has_sgmii);
> +
> + if (!has_2500 && !has_sgmii)
> + return 0;
> +
> + /* determine SerDes option mode */
> + if (has_2500 && !has_sgmii)
> + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX;
> + else
> + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII;
> +
> + /* the following sequence with magic numbers sets up the SerDes
> + * option mode
> + */
> + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0);
> + if (ret < 0)
> + return ret;
> +
> + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1,
> + RTL822X_VND1_SERDES_OPTION,
> + RTL822X_VND1_SERDES_OPTION_MODE_MASK,
> + mode);
> + if (ret < 0)
> + return ret;
> +
> + 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;
> +
> + return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
> +}
> +
> static int rtl822x_get_features(struct phy_device *phydev)
> {
> int val;
> @@ -695,6 +759,28 @@ static int rtl822x_config_aneg(struct phy_device *phydev)
> return __genphy_config_aneg(phydev, ret);
> }
>
> +static void rtl822x_update_interface(struct phy_device *phydev)
> +{
> + int val;
> +
> + if (!phydev->link)
> + return;
> +
> + /* Change interface according to serdes mode */
> + val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3);
> + if (val < 0)
> + return;
> +
> + switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) {
> + case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX:
> + phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
> + break;
> + case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII:
> + phydev->interface = PHY_INTERFACE_MODE_SGMII;
> + break;
> + }
> +}
> +
> static int rtl822x_read_status(struct phy_device *phydev)
> {
> int ret;
> @@ -709,11 +795,13 @@ static int rtl822x_read_status(struct phy_device *phydev)
> lpadv);
> }
>
> - ret = genphy_read_status(phydev);
> + ret = rtlgen_read_status(phydev);
> if (ret < 0)
> return ret;
>
> - return rtlgen_get_speed(phydev);
> + rtl822x_update_interface(phydev);
> +
> + return 0;
> }
>
> static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
> @@ -976,6 +1064,7 @@ static struct phy_driver realtek_drvs[] = {
> .match_phy_device = rtl8226_match_phy_device,
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -988,6 +1077,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8226B_RTL8221B 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1000,6 +1090,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8226-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1010,6 +1101,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1019,6 +1111,7 @@ static struct phy_driver realtek_drvs[] = {
> PHY_ID_MATCH_EXACT(0x001cc849),
> .name = "RTL8221B-VB-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> + .config_init = rtl822x_config_init,
> .config_aneg = rtl822x_config_aneg,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> @@ -1030,6 +1123,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8221B-VM-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1040,6 +1134,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8251B 5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
Have you tested this on RTL8251B?
This PHY usually uses 5GBase-R link mode with rate-adapter mode for
lower speeds. Hence I'm pretty sure that also setting up SerDes mode
register will be a bit different.
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> --
> 2.42.1
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 13:29 ` Daniel Golle
@ 2024-03-03 14:33 ` Eric Woudstra
0 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-03 14:33 UTC (permalink / raw)
To: Daniel Golle
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, netdev, Alexander Couzens
On 3/3/24 14:29, Daniel Golle wrote:
>> There is an additional datasheet for RTL8226B/RTL8221B called
>> "SERDES MODE SETTING FLOW APPLICATION NOTE" where this sequence to
>> setup interface and rate adapter mode.
>
> Gramar doesn't parse, missing verb.
Thanks, I'll correct it.
>> + .config_init = rtl822x_config_init,
>
> Have you tested this on RTL8251B?
> This PHY usually uses 5GBase-R link mode with rate-adapter mode for
> lower speeds. Hence I'm pretty sure that also setting up SerDes mode
> register will be a bit different.
Thanks, I'd better not add following lines for the rtl8251b (2x):
.config_init = rtl822x_config_init,
.get_rate_matching = rtl822x_get_rate_matching,
Until someone with the hardware can test it.
Perhaps we can find a RollBall sfp module that has one on it and use it
on a BPI-R4...
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 10:28 ` [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs Eric Woudstra
2024-03-03 13:29 ` Daniel Golle
@ 2024-03-03 20:42 ` Heiner Kallweit
2024-03-03 21:08 ` Daniel Golle
1 sibling, 1 reply; 15+ messages in thread
From: Heiner Kallweit @ 2024-03-03 20:42 UTC (permalink / raw)
To: Eric Woudstra, Andrew Lunn, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, Daniel Golle
Cc: netdev, Alexander Couzens
On 03.03.2024 11:28, Eric Woudstra wrote:
> From: Alexander Couzens <lynxis@fe80.eu>
>
> The rtl822x series and rtl8251b support switching SerDes mode between
> 2500base-x and sgmii based on the negotiated copper speed.
>
> Configure this switching mode according to SerDes modes supported by
> host.
>
> There is an additional datasheet for RTL8226B/RTL8221B called
> "SERDES MODE SETTING FLOW APPLICATION NOTE" where this sequence to
> setup interface and rate adapter mode.
>
> However, there is no documentation about the meaning of registers
> and bits, it's literally just magic numbers and pseudo-code.
>
> Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
> [ refactored, dropped HiSGMII mode and changed commit message ]
> Signed-off-by: Marek Behún <kabel@kernel.org>
> [ changed rtl822x_update_interface() to use vendor register ]
> [ always fill in possible interfaces ]
> Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
> ---
> drivers/net/phy/realtek.c | 99 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 97 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
> index 1fa70427b2a2..8a876e003774 100644
> --- a/drivers/net/phy/realtek.c
> +++ b/drivers/net/phy/realtek.c
> @@ -54,6 +54,16 @@
> RTL8201F_ISR_LINK)
> #define RTL8201F_IER 0x13
>
> +#define RTL822X_VND1_SERDES_OPTION 0x697a
> +#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
> +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0
> +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2
> +
> +#define RTL822X_VND1_SERDES_CTRL3 0x7580
> +#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0)
> +#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
> +#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
> +
> #define RTL8366RB_POWER_SAVE 0x15
> #define RTL8366RB_POWER_SAVE_ON BIT(12)
>
> @@ -659,6 +669,60 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
> return ret;
> }
>
> +static int rtl822x_config_init(struct phy_device *phydev)
> +{
> + bool has_2500, has_sgmii;
> + u16 mode;
> + int ret;
> +
> + has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
> + phydev->host_interfaces) ||
> + phydev->interface == PHY_INTERFACE_MODE_2500BASEX;
> +
> + has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII,
> + phydev->host_interfaces) ||
> + phydev->interface == PHY_INTERFACE_MODE_SGMII;
> +
> + /* fill in possible interfaces */
> + __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces,
> + has_2500);
> + __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces,
> + has_sgmii);
> +
> + if (!has_2500 && !has_sgmii)
> + return 0;
> +
> + /* determine SerDes option mode */
> + if (has_2500 && !has_sgmii)
> + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX;
> + else
> + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII;
> +
> + /* the following sequence with magic numbers sets up the SerDes
> + * option mode
> + */
> + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0);
> + if (ret < 0)
> + return ret;
> +
> + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1,
> + RTL822X_VND1_SERDES_OPTION,
> + RTL822X_VND1_SERDES_OPTION_MODE_MASK,
> + mode);
> + if (ret < 0)
> + return ret;
> +
> + 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;
> +
> + return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
> +}
> +
> static int rtl822x_get_features(struct phy_device *phydev)
> {
> int val;
> @@ -695,6 +759,28 @@ static int rtl822x_config_aneg(struct phy_device *phydev)
> return __genphy_config_aneg(phydev, ret);
> }
>
> +static void rtl822x_update_interface(struct phy_device *phydev)
> +{
> + int val;
> +
> + if (!phydev->link)
> + return;
> +
> + /* Change interface according to serdes mode */
> + val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3);
> + if (val < 0)
> + return;
> +
> + switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) {
> + case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX:
> + phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
> + break;
> + case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII:
> + phydev->interface = PHY_INTERFACE_MODE_SGMII;
> + break;
> + }
> +}
> +
> static int rtl822x_read_status(struct phy_device *phydev)
> {
> int ret;
> @@ -709,11 +795,13 @@ static int rtl822x_read_status(struct phy_device *phydev)
> lpadv);
> }
>
> - ret = genphy_read_status(phydev);
> + ret = rtlgen_read_status(phydev);
> if (ret < 0)
> return ret;
>
> - return rtlgen_get_speed(phydev);
> + rtl822x_update_interface(phydev);
> +
> + return 0;
> }
>
> static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
> @@ -976,6 +1064,7 @@ static struct phy_driver realtek_drvs[] = {
> .match_phy_device = rtl8226_match_phy_device,
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
Did you test this (and the rest of the series) on RTL8125A, where
MMD register access for the integrated 2.5G PHY isn't supported?
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -988,6 +1077,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8226B_RTL8221B 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1000,6 +1090,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8226-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1010,6 +1101,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1019,6 +1111,7 @@ static struct phy_driver realtek_drvs[] = {
> PHY_ID_MATCH_EXACT(0x001cc849),
> .name = "RTL8221B-VB-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> + .config_init = rtl822x_config_init,
> .config_aneg = rtl822x_config_aneg,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> @@ -1030,6 +1123,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8221B-VM-CG 2.5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
> @@ -1040,6 +1134,7 @@ static struct phy_driver realtek_drvs[] = {
> .name = "RTL8251B 5Gbps PHY",
> .get_features = rtl822x_get_features,
> .config_aneg = rtl822x_config_aneg,
> + .config_init = rtl822x_config_init,
> .read_status = rtl822x_read_status,
> .suspend = genphy_suspend,
> .resume = rtlgen_resume,
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 20:42 ` Heiner Kallweit
@ 2024-03-03 21:08 ` Daniel Golle
2024-03-03 21:14 ` Heiner Kallweit
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Daniel Golle @ 2024-03-03 21:08 UTC (permalink / raw)
To: Heiner Kallweit
Cc: Eric Woudstra, Andrew Lunn, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, netdev, Alexander Couzens
On Sun, Mar 03, 2024 at 09:42:31PM +0100, Heiner Kallweit wrote:
> On 03.03.2024 11:28, Eric Woudstra wrote:
> > From: Alexander Couzens <lynxis@fe80.eu>
> >
> > The rtl822x series and rtl8251b support switching SerDes mode between
> > 2500base-x and sgmii based on the negotiated copper speed.
> >
> > Configure this switching mode according to SerDes modes supported by
> > host.
> >
> > There is an additional datasheet for RTL8226B/RTL8221B called
> > "SERDES MODE SETTING FLOW APPLICATION NOTE" where this sequence to
> > setup interface and rate adapter mode.
> >
> > However, there is no documentation about the meaning of registers
> > and bits, it's literally just magic numbers and pseudo-code.
> >
> > Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
> > [ refactored, dropped HiSGMII mode and changed commit message ]
> > Signed-off-by: Marek Behún <kabel@kernel.org>
> > [ changed rtl822x_update_interface() to use vendor register ]
> > [ always fill in possible interfaces ]
> > Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
> > ---
> > drivers/net/phy/realtek.c | 99 ++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 97 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
> > index 1fa70427b2a2..8a876e003774 100644
> > --- a/drivers/net/phy/realtek.c
> > +++ b/drivers/net/phy/realtek.c
> > @@ -54,6 +54,16 @@
> > RTL8201F_ISR_LINK)
> > #define RTL8201F_IER 0x13
> >
> > +#define RTL822X_VND1_SERDES_OPTION 0x697a
> > +#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
> > +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0
> > +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2
> > +
> > +#define RTL822X_VND1_SERDES_CTRL3 0x7580
> > +#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0)
> > +#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
> > +#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
> > +
> > #define RTL8366RB_POWER_SAVE 0x15
> > #define RTL8366RB_POWER_SAVE_ON BIT(12)
> >
> > @@ -659,6 +669,60 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
> > return ret;
> > }
> >
> > +static int rtl822x_config_init(struct phy_device *phydev)
> > +{
> > + bool has_2500, has_sgmii;
> > + u16 mode;
> > + int ret;
> > +
> > + has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
> > + phydev->host_interfaces) ||
> > + phydev->interface == PHY_INTERFACE_MODE_2500BASEX;
> > +
> > + has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII,
> > + phydev->host_interfaces) ||
> > + phydev->interface == PHY_INTERFACE_MODE_SGMII;
> > +
> > + /* fill in possible interfaces */
> > + __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces,
> > + has_2500);
> > + __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces,
> > + has_sgmii);
> > +
> > + if (!has_2500 && !has_sgmii)
> > + return 0;
> > +
> > + /* determine SerDes option mode */
> > + if (has_2500 && !has_sgmii)
> > + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX;
> > + else
> > + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII;
> > +
> > + /* the following sequence with magic numbers sets up the SerDes
> > + * option mode
> > + */
> > + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1,
> > + RTL822X_VND1_SERDES_OPTION,
> > + RTL822X_VND1_SERDES_OPTION_MODE_MASK,
> > + mode);
> > + if (ret < 0)
> > + return ret;
> > +
> > + 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;
> > +
> > + return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
> > +}
> > +
> > static int rtl822x_get_features(struct phy_device *phydev)
> > {
> > int val;
> > @@ -695,6 +759,28 @@ static int rtl822x_config_aneg(struct phy_device *phydev)
> > return __genphy_config_aneg(phydev, ret);
> > }
> >
> > +static void rtl822x_update_interface(struct phy_device *phydev)
> > +{
> > + int val;
> > +
> > + if (!phydev->link)
> > + return;
> > +
> > + /* Change interface according to serdes mode */
> > + val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3);
> > + if (val < 0)
> > + return;
> > +
> > + switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) {
> > + case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX:
> > + phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
> > + break;
> > + case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII:
> > + phydev->interface = PHY_INTERFACE_MODE_SGMII;
> > + break;
> > + }
> > +}
> > +
> > static int rtl822x_read_status(struct phy_device *phydev)
> > {
> > int ret;
> > @@ -709,11 +795,13 @@ static int rtl822x_read_status(struct phy_device *phydev)
> > lpadv);
> > }
> >
> > - ret = genphy_read_status(phydev);
> > + ret = rtlgen_read_status(phydev);
> > if (ret < 0)
> > return ret;
> >
> > - return rtlgen_get_speed(phydev);
> > + rtl822x_update_interface(phydev);
> > +
> > + return 0;
> > }
> >
> > static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
> > @@ -976,6 +1064,7 @@ static struct phy_driver realtek_drvs[] = {
> > .match_phy_device = rtl8226_match_phy_device,
> > .get_features = rtl822x_get_features,
> > .config_aneg = rtl822x_config_aneg,
> > + .config_init = rtl822x_config_init,
>
> Did you test this (and the rest of the series) on RTL8125A, where
> MMD register access for the integrated 2.5G PHY isn't supported?
None of this should be done on RealTek NICs, and the easiest way to
prevent that is to test if phydev->phylink is NULL or not (as the NIC
driver doesn't use phylink but rather just calls phy_connect_direct()).
Also note that the datasheet with the magic SerDes config sequences
lists only 2nd generation 2.5G PHYs as supported:
RTL8226B
RTL8221B(I)
RTL8221B(I)-VB
RTL8221B(I)-VM
So RTL8226 and RTL8226-CG are **not** listed there and being from the
1st generation of RealTek 2.5G PHYs I would assume that it won't
support setting up the SerDes mode in this way.
Afaik those anyway were only used in early RealTek-based 2.5G switches
and maybe NICs, I'm pretty sure you won't find them inside SFP modules
or as part non-RealTek-based routers or switches -- hence switching
SerDes mode most likely anyway will never be required for those.
>
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > .resume = rtlgen_resume,
> > @@ -988,6 +1077,7 @@ static struct phy_driver realtek_drvs[] = {
> > .name = "RTL8226B_RTL8221B 2.5Gbps PHY",
> > .get_features = rtl822x_get_features,
> > .config_aneg = rtl822x_config_aneg,
> > + .config_init = rtl822x_config_init,
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > .resume = rtlgen_resume,
> > @@ -1000,6 +1090,7 @@ static struct phy_driver realtek_drvs[] = {
> > .name = "RTL8226-CG 2.5Gbps PHY",
> > .get_features = rtl822x_get_features,
> > .config_aneg = rtl822x_config_aneg,
> > + .config_init = rtl822x_config_init,
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > .resume = rtlgen_resume,
> > @@ -1010,6 +1101,7 @@ static struct phy_driver realtek_drvs[] = {
> > .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
> > .get_features = rtl822x_get_features,
> > .config_aneg = rtl822x_config_aneg,
> > + .config_init = rtl822x_config_init,
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > .resume = rtlgen_resume,
> > @@ -1019,6 +1111,7 @@ static struct phy_driver realtek_drvs[] = {
> > PHY_ID_MATCH_EXACT(0x001cc849),
> > .name = "RTL8221B-VB-CG 2.5Gbps PHY",
> > .get_features = rtl822x_get_features,
> > + .config_init = rtl822x_config_init,
> > .config_aneg = rtl822x_config_aneg,
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > @@ -1030,6 +1123,7 @@ static struct phy_driver realtek_drvs[] = {
> > .name = "RTL8221B-VM-CG 2.5Gbps PHY",
> > .get_features = rtl822x_get_features,
> > .config_aneg = rtl822x_config_aneg,
> > + .config_init = rtl822x_config_init,
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > .resume = rtlgen_resume,
> > @@ -1040,6 +1134,7 @@ static struct phy_driver realtek_drvs[] = {
> > .name = "RTL8251B 5Gbps PHY",
> > .get_features = rtl822x_get_features,
> > .config_aneg = rtl822x_config_aneg,
> > + .config_init = rtl822x_config_init,
> > .read_status = rtl822x_read_status,
> > .suspend = genphy_suspend,
> > .resume = rtlgen_resume,
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 21:08 ` Daniel Golle
@ 2024-03-03 21:14 ` Heiner Kallweit
2024-03-04 0:04 ` Russell King (Oracle)
2024-03-05 8:44 ` Eric Woudstra
2 siblings, 0 replies; 15+ messages in thread
From: Heiner Kallweit @ 2024-03-03 21:14 UTC (permalink / raw)
To: Daniel Golle
Cc: Eric Woudstra, Andrew Lunn, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, netdev, Alexander Couzens
On 03.03.2024 22:08, Daniel Golle wrote:
> On Sun, Mar 03, 2024 at 09:42:31PM +0100, Heiner Kallweit wrote:
>> On 03.03.2024 11:28, Eric Woudstra wrote:
>>> From: Alexander Couzens <lynxis@fe80.eu>
>>>
>>> The rtl822x series and rtl8251b support switching SerDes mode between
>>> 2500base-x and sgmii based on the negotiated copper speed.
>>>
>>> Configure this switching mode according to SerDes modes supported by
>>> host.
>>>
>>> There is an additional datasheet for RTL8226B/RTL8221B called
>>> "SERDES MODE SETTING FLOW APPLICATION NOTE" where this sequence to
>>> setup interface and rate adapter mode.
>>>
>>> However, there is no documentation about the meaning of registers
>>> and bits, it's literally just magic numbers and pseudo-code.
>>>
>>> Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
>>> [ refactored, dropped HiSGMII mode and changed commit message ]
>>> Signed-off-by: Marek Behún <kabel@kernel.org>
>>> [ changed rtl822x_update_interface() to use vendor register ]
>>> [ always fill in possible interfaces ]
>>> Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
>>> ---
>>> drivers/net/phy/realtek.c | 99 ++++++++++++++++++++++++++++++++++++++-
>>> 1 file changed, 97 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
>>> index 1fa70427b2a2..8a876e003774 100644
>>> --- a/drivers/net/phy/realtek.c
>>> +++ b/drivers/net/phy/realtek.c
>>> @@ -54,6 +54,16 @@
>>> RTL8201F_ISR_LINK)
>>> #define RTL8201F_IER 0x13
>>>
>>> +#define RTL822X_VND1_SERDES_OPTION 0x697a
>>> +#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
>>> +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0
>>> +#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2
>>> +
>>> +#define RTL822X_VND1_SERDES_CTRL3 0x7580
>>> +#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0)
>>> +#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
>>> +#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
>>> +
>>> #define RTL8366RB_POWER_SAVE 0x15
>>> #define RTL8366RB_POWER_SAVE_ON BIT(12)
>>>
>>> @@ -659,6 +669,60 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
>>> return ret;
>>> }
>>>
>>> +static int rtl822x_config_init(struct phy_device *phydev)
>>> +{
>>> + bool has_2500, has_sgmii;
>>> + u16 mode;
>>> + int ret;
>>> +
>>> + has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
>>> + phydev->host_interfaces) ||
>>> + phydev->interface == PHY_INTERFACE_MODE_2500BASEX;
>>> +
>>> + has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII,
>>> + phydev->host_interfaces) ||
>>> + phydev->interface == PHY_INTERFACE_MODE_SGMII;
>>> +
>>> + /* fill in possible interfaces */
>>> + __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces,
>>> + has_2500);
>>> + __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces,
>>> + has_sgmii);
>>> +
>>> + if (!has_2500 && !has_sgmii)
>>> + return 0;
>>> +
>>> + /* determine SerDes option mode */
>>> + if (has_2500 && !has_sgmii)
>>> + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX;
>>> + else
>>> + mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII;
>>> +
>>> + /* the following sequence with magic numbers sets up the SerDes
>>> + * option mode
>>> + */
>>> + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1,
>>> + RTL822X_VND1_SERDES_OPTION,
>>> + RTL822X_VND1_SERDES_OPTION_MODE_MASK,
>>> + mode);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + 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;
>>> +
>>> + return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
>>> +}
>>> +
>>> static int rtl822x_get_features(struct phy_device *phydev)
>>> {
>>> int val;
>>> @@ -695,6 +759,28 @@ static int rtl822x_config_aneg(struct phy_device *phydev)
>>> return __genphy_config_aneg(phydev, ret);
>>> }
>>>
>>> +static void rtl822x_update_interface(struct phy_device *phydev)
>>> +{
>>> + int val;
>>> +
>>> + if (!phydev->link)
>>> + return;
>>> +
>>> + /* Change interface according to serdes mode */
>>> + val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3);
>>> + if (val < 0)
>>> + return;
>>> +
>>> + switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) {
>>> + case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX:
>>> + phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
>>> + break;
>>> + case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII:
>>> + phydev->interface = PHY_INTERFACE_MODE_SGMII;
>>> + break;
>>> + }
>>> +}
>>> +
>>> static int rtl822x_read_status(struct phy_device *phydev)
>>> {
>>> int ret;
>>> @@ -709,11 +795,13 @@ static int rtl822x_read_status(struct phy_device *phydev)
>>> lpadv);
>>> }
>>>
>>> - ret = genphy_read_status(phydev);
>>> + ret = rtlgen_read_status(phydev);
>>> if (ret < 0)
>>> return ret;
>>>
>>> - return rtlgen_get_speed(phydev);
>>> + rtl822x_update_interface(phydev);
>>> +
>>> + return 0;
>>> }
>>>
>>> static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
>>> @@ -976,6 +1064,7 @@ static struct phy_driver realtek_drvs[] = {
>>> .match_phy_device = rtl8226_match_phy_device,
>>> .get_features = rtl822x_get_features,
>>> .config_aneg = rtl822x_config_aneg,
>>> + .config_init = rtl822x_config_init,
>>
>> Did you test this (and the rest of the series) on RTL8125A, where
>> MMD register access for the integrated 2.5G PHY isn't supported?
>
> None of this should be done on RealTek NICs, and the easiest way to
> prevent that is to test if phydev->phylink is NULL or not (as the NIC
> driver doesn't use phylink but rather just calls phy_connect_direct()).
>
Right. I'm asking because this PHY driver entry is used on RTL8125A.
> Also note that the datasheet with the magic SerDes config sequences
> lists only 2nd generation 2.5G PHYs as supported:
> RTL8226B
> RTL8221B(I)
> RTL8221B(I)-VB
> RTL8221B(I)-VM
>
> So RTL8226 and RTL8226-CG are **not** listed there and being from the
> 1st generation of RealTek 2.5G PHYs I would assume that it won't
> support setting up the SerDes mode in this way.
>
> Afaik those anyway were only used in early RealTek-based 2.5G switches
> and maybe NICs, I'm pretty sure you won't find them inside SFP modules
> or as part non-RealTek-based routers or switches -- hence switching
> SerDes mode most likely anyway will never be required for those.
>
>>
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> .resume = rtlgen_resume,
>>> @@ -988,6 +1077,7 @@ static struct phy_driver realtek_drvs[] = {
>>> .name = "RTL8226B_RTL8221B 2.5Gbps PHY",
>>> .get_features = rtl822x_get_features,
>>> .config_aneg = rtl822x_config_aneg,
>>> + .config_init = rtl822x_config_init,
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> .resume = rtlgen_resume,
>>> @@ -1000,6 +1090,7 @@ static struct phy_driver realtek_drvs[] = {
>>> .name = "RTL8226-CG 2.5Gbps PHY",
>>> .get_features = rtl822x_get_features,
>>> .config_aneg = rtl822x_config_aneg,
>>> + .config_init = rtl822x_config_init,
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> .resume = rtlgen_resume,
>>> @@ -1010,6 +1101,7 @@ static struct phy_driver realtek_drvs[] = {
>>> .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
>>> .get_features = rtl822x_get_features,
>>> .config_aneg = rtl822x_config_aneg,
>>> + .config_init = rtl822x_config_init,
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> .resume = rtlgen_resume,
>>> @@ -1019,6 +1111,7 @@ static struct phy_driver realtek_drvs[] = {
>>> PHY_ID_MATCH_EXACT(0x001cc849),
>>> .name = "RTL8221B-VB-CG 2.5Gbps PHY",
>>> .get_features = rtl822x_get_features,
>>> + .config_init = rtl822x_config_init,
>>> .config_aneg = rtl822x_config_aneg,
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> @@ -1030,6 +1123,7 @@ static struct phy_driver realtek_drvs[] = {
>>> .name = "RTL8221B-VM-CG 2.5Gbps PHY",
>>> .get_features = rtl822x_get_features,
>>> .config_aneg = rtl822x_config_aneg,
>>> + .config_init = rtl822x_config_init,
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> .resume = rtlgen_resume,
>>> @@ -1040,6 +1134,7 @@ static struct phy_driver realtek_drvs[] = {
>>> .name = "RTL8251B 5Gbps PHY",
>>> .get_features = rtl822x_get_features,
>>> .config_aneg = rtl822x_config_aneg,
>>> + .config_init = rtl822x_config_init,
>>> .read_status = rtl822x_read_status,
>>> .suspend = genphy_suspend,
>>> .resume = rtlgen_resume,
>>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 21:08 ` Daniel Golle
2024-03-03 21:14 ` Heiner Kallweit
@ 2024-03-04 0:04 ` Russell King (Oracle)
2024-03-05 8:44 ` Eric Woudstra
2 siblings, 0 replies; 15+ messages in thread
From: Russell King (Oracle) @ 2024-03-04 0:04 UTC (permalink / raw)
To: Daniel Golle
Cc: Heiner Kallweit, Eric Woudstra, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Behún,
Frank Wunderlich, netdev, Alexander Couzens
On Sun, Mar 03, 2024 at 09:08:15PM +0000, Daniel Golle wrote:
> On Sun, Mar 03, 2024 at 09:42:31PM +0100, Heiner Kallweit wrote:
> > Did you test this (and the rest of the series) on RTL8125A, where
> > MMD register access for the integrated 2.5G PHY isn't supported?
>
> None of this should be done on RealTek NICs, and the easiest way to
> prevent that is to test if phydev->phylink is NULL or not (as the NIC
> driver doesn't use phylink but rather just calls phy_connect_direct()).
Ewwwwwwwwwwwwwwwww. Please do not use the presence of phydev->phylink to
change driver behaviour. That's just... disgusting.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs
2024-03-03 21:08 ` Daniel Golle
2024-03-03 21:14 ` Heiner Kallweit
2024-03-04 0:04 ` Russell King (Oracle)
@ 2024-03-05 8:44 ` Eric Woudstra
2 siblings, 0 replies; 15+ messages in thread
From: Eric Woudstra @ 2024-03-05 8:44 UTC (permalink / raw)
To: Daniel Golle, Heiner Kallweit
Cc: Andrew Lunn, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Marek Behún, Frank Wunderlich,
netdev, Alexander Couzens
On 3/3/24 22:08, Daniel Golle wrote:
> None of this should be done on RealTek NICs, and the easiest way to
> prevent that is to test if phydev->phylink is NULL or not (as the NIC
> driver doesn't use phylink but rather just calls phy_connect_direct()).
>
> Also note that the datasheet with the magic SerDes config sequences
> lists only 2nd generation 2.5G PHYs as supported:
> RTL8226B
> RTL8221B(I)
> RTL8221B(I)-VB
> RTL8221B(I)-VM
>
> So RTL8226 and RTL8226-CG are **not** listed there and being from the
> 1st generation of RealTek 2.5G PHYs I would assume that it won't
> support setting up the SerDes mode in this way.
>
> Afaik those anyway were only used in early RealTek-based 2.5G switches
> and maybe NICs, I'm pretty sure you won't find them inside SFP modules
> or as part non-RealTek-based routers or switches -- hence switching
> SerDes mode most likely anyway will never be required for those.
Then it would be best to change all patches in this patch-set to only
modify the driver instances of:
"RTL8226B_RTL8221B 2.5Gbps PHY"
"RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY"
"RTL8221B-VB-CG 2.5Gbps PHY"
"RTL8221B-VM-CG 2.5Gbps PHY"
And NOT to modify:
"RTL8226 2.5Gbps PHY
"RTL8226-CG 2.5Gbps PHY"
"RTL8251B 5Gbps PHY"
Or are there more restrictions? If so, why is it a restriction?
Perhaps this can help me find an expression to use as match.
Best regards,
Eric Woudstra
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2024-03-05 8:44 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-03 10:28 [PATCH v2 net-next 0/7] rtl8221b/8251b add C45 instances and SerDes switching Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 1/7] net: phy: realtek: configure SerDes mode for rtl822x/8251b PHYs Eric Woudstra
2024-03-03 13:29 ` Daniel Golle
2024-03-03 14:33 ` Eric Woudstra
2024-03-03 20:42 ` Heiner Kallweit
2024-03-03 21:08 ` Daniel Golle
2024-03-03 21:14 ` Heiner Kallweit
2024-03-04 0:04 ` Russell King (Oracle)
2024-03-05 8:44 ` Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 2/7] net: phy: realtek: add get_rate_matching() " Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 3/7] net: phy: realtek: Add driver instances for rtl8221b/8251b via Clause 45 Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 4/7] net: phy: realtek: Change rtlgen_get_speed() to rtlgen_decode_speed() Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 5/7] net: phy: realtek: add rtl822x_c45_get_features() to set supported ports Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 6/7] net: sfp: Fixup for OEM SFP-2.5G-T module Eric Woudstra
2024-03-03 10:28 ` [PATCH v2 net-next 7/7] net: sfp: add quirk for another multigig RollBall transceiver Eric Woudstra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).