1 From ad5ce743a6b0329f642d80be50ef7b534e908fba Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
3 Date: Tue, 9 Apr 2024 09:30:13 +0200
4 Subject: [PATCH] net: phy: realtek: Add driver instances for rtl8221b via
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
10 Collected from several commits in [PATCH net-next]
11 "Realtek RTL822x PHY rework to c45 and SerDes interface switching"
13 The instances are used by Clause 45 only accessible PHY's on several sfp
14 modules, which are using RollBall protocol.
16 Signed-off-by: Marek BehĂșn <kabel@kernel.org>
17 [ Added matching functions to differentiate C45 instances ]
18 Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
20 Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
21 Signed-off-by: David S. Miller <davem@davemloft.net>
23 drivers/net/phy/realtek.c | 135 ++++++++++++++++++++++++++++++++++++--
24 1 file changed, 131 insertions(+), 4 deletions(-)
26 --- a/drivers/net/phy/realtek.c
27 +++ b/drivers/net/phy/realtek.c
29 #define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
30 #define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
32 +/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45
33 + * is set, they cannot be accessed by C45-over-C22.
35 +#define RTL822X_VND2_GBCR 0xa412
37 +#define RTL822X_VND2_GANLPAR 0xa414
39 #define RTL8366RB_POWER_SAVE 0x15
40 #define RTL8366RB_POWER_SAVE_ON BIT(12)
44 #define RTL_GENERIC_PHYID 0x001cc800
45 #define RTL_8211FVD_PHYID 0x001cc878
46 +#define RTL_8221B_VB_CG 0x001cc849
47 +#define RTL_8221B_VN_CG 0x001cc84a
48 +#define RTL_8251B 0x001cc862
50 MODULE_DESCRIPTION("Realtek PHY driver");
51 MODULE_AUTHOR("Johnson Leung");
52 @@ -839,6 +849,67 @@ static int rtl822xb_read_status(struct p
56 +static int rtl822x_c45_config_aneg(struct phy_device *phydev)
58 + bool changed = false;
61 + if (phydev->autoneg == AUTONEG_DISABLE)
62 + return genphy_c45_pma_setup_forced(phydev);
64 + ret = genphy_c45_an_config_aneg(phydev);
70 + val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
72 + /* Vendor register as C45 has no standardized support for 1000BaseT */
73 + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR,
74 + ADVERTISE_1000FULL, val);
80 + return genphy_c45_check_and_restart_aneg(phydev, changed);
83 +static int rtl822x_c45_read_status(struct phy_device *phydev)
87 + ret = genphy_c45_read_status(phydev);
91 + /* Vendor register as C45 has no standardized support for 1000BaseT */
92 + if (phydev->autoneg == AUTONEG_ENABLE) {
93 + val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
94 + RTL822X_VND2_GANLPAR);
98 + mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
104 +static int rtl822xb_c45_read_status(struct phy_device *phydev)
108 + ret = rtl822x_c45_read_status(phydev);
112 + rtl822xb_update_interface(phydev);
117 static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
120 @@ -862,6 +933,35 @@ static int rtl8226_match_phy_device(stru
121 rtlgen_supports_2_5gbps(phydev);
124 +static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
127 + if (phydev->is_c45)
128 + return is_c45 && (id == phydev->c45_ids.device_ids[1]);
130 + return !is_c45 && (id == phydev->phy_id);
133 +static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
135 + return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
138 +static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev)
140 + return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
143 +static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev)
145 + return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
148 +static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
150 + return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
153 static int rtlgen_resume(struct phy_device *phydev)
155 int ret = genphy_resume(phydev);
156 @@ -872,6 +972,15 @@ static int rtlgen_resume(struct phy_devi
160 +static int rtlgen_c45_resume(struct phy_device *phydev)
162 + int ret = genphy_c45_pma_resume(phydev);
169 static int rtl9000a_config_init(struct phy_device *phydev)
171 phydev->autoneg = AUTONEG_DISABLE;
172 @@ -1143,8 +1252,8 @@ static struct phy_driver realtek_drvs[]
173 .read_page = rtl821x_read_page,
174 .write_page = rtl821x_write_page,
176 - PHY_ID_MATCH_EXACT(0x001cc849),
177 - .name = "RTL8221B-VB-CG 2.5Gbps PHY",
178 + .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
179 + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
180 .get_features = rtl822x_get_features,
181 .config_aneg = rtl822x_config_aneg,
182 .config_init = rtl822xb_config_init,
183 @@ -1155,8 +1264,17 @@ static struct phy_driver realtek_drvs[]
184 .read_page = rtl821x_read_page,
185 .write_page = rtl821x_write_page,
187 - PHY_ID_MATCH_EXACT(0x001cc84a),
188 - .name = "RTL8221B-VM-CG 2.5Gbps PHY",
189 + .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
190 + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
191 + .config_init = rtl822xb_config_init,
192 + .get_rate_matching = rtl822xb_get_rate_matching,
193 + .config_aneg = rtl822x_c45_config_aneg,
194 + .read_status = rtl822xb_c45_read_status,
195 + .suspend = genphy_c45_pma_suspend,
196 + .resume = rtlgen_c45_resume,
198 + .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
199 + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
200 .get_features = rtl822x_get_features,
201 .config_aneg = rtl822x_config_aneg,
202 .config_init = rtl822xb_config_init,
203 @@ -1167,6 +1285,15 @@ static struct phy_driver realtek_drvs[]
204 .read_page = rtl821x_read_page,
205 .write_page = rtl821x_write_page,
207 + .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
208 + .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
209 + .config_init = rtl822xb_config_init,
210 + .get_rate_matching = rtl822xb_get_rate_matching,
211 + .config_aneg = rtl822x_c45_config_aneg,
212 + .read_status = rtl822xb_c45_read_status,
213 + .suspend = genphy_c45_pma_suspend,
214 + .resume = rtlgen_c45_resume,
216 PHY_ID_MATCH_EXACT(0x001cc862),
217 .name = "RTL8251B 5Gbps PHY",
218 .get_features = rtl822x_get_features,