5366c72f9c1edaf22935f34a3c637764cc89f455
[openwrt/staging/wigyori.git] /
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
5 Clause 45
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 Collected from several commits in [PATCH net-next]
11 "Realtek RTL822x PHY rework to c45 and SerDes interface switching"
12
13 The instances are used by Clause 45 only accessible PHY's on several sfp
14 modules, which are using RollBall protocol.
15
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>
19
20 Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
21 Signed-off-by: David S. Miller <davem@davemloft.net>
22 ---
23 drivers/net/phy/realtek.c | 135 ++++++++++++++++++++++++++++++++++++--
24 1 file changed, 131 insertions(+), 4 deletions(-)
25
26 --- a/drivers/net/phy/realtek.c
27 +++ b/drivers/net/phy/realtek.c
28 @@ -64,6 +64,13 @@
29 #define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
30 #define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
31
32 +/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45
33 + * is set, they cannot be accessed by C45-over-C22.
34 + */
35 +#define RTL822X_VND2_GBCR 0xa412
36 +
37 +#define RTL822X_VND2_GANLPAR 0xa414
38 +
39 #define RTL8366RB_POWER_SAVE 0x15
40 #define RTL8366RB_POWER_SAVE_ON BIT(12)
41
42 @@ -74,6 +81,9 @@
43
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
49
50 MODULE_DESCRIPTION("Realtek PHY driver");
51 MODULE_AUTHOR("Johnson Leung");
52 @@ -839,6 +849,67 @@ static int rtl822xb_read_status(struct p
53 return 0;
54 }
55
56 +static int rtl822x_c45_config_aneg(struct phy_device *phydev)
57 +{
58 + bool changed = false;
59 + int ret, val;
60 +
61 + if (phydev->autoneg == AUTONEG_DISABLE)
62 + return genphy_c45_pma_setup_forced(phydev);
63 +
64 + ret = genphy_c45_an_config_aneg(phydev);
65 + if (ret < 0)
66 + return ret;
67 + if (ret > 0)
68 + changed = true;
69 +
70 + val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
71 +
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);
75 + if (ret < 0)
76 + return ret;
77 + if (ret > 0)
78 + changed = true;
79 +
80 + return genphy_c45_check_and_restart_aneg(phydev, changed);
81 +}
82 +
83 +static int rtl822x_c45_read_status(struct phy_device *phydev)
84 +{
85 + int ret, val;
86 +
87 + ret = genphy_c45_read_status(phydev);
88 + if (ret < 0)
89 + return ret;
90 +
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);
95 + if (val < 0)
96 + return val;
97 +
98 + mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
99 + }
100 +
101 + return 0;
102 +}
103 +
104 +static int rtl822xb_c45_read_status(struct phy_device *phydev)
105 +{
106 + int ret;
107 +
108 + ret = rtl822x_c45_read_status(phydev);
109 + if (ret < 0)
110 + return ret;
111 +
112 + rtl822xb_update_interface(phydev);
113 +
114 + return 0;
115 +}
116 +
117 static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
118 {
119 int val;
120 @@ -862,6 +933,35 @@ static int rtl8226_match_phy_device(stru
121 rtlgen_supports_2_5gbps(phydev);
122 }
123
124 +static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
125 + bool is_c45)
126 +{
127 + if (phydev->is_c45)
128 + return is_c45 && (id == phydev->c45_ids.device_ids[1]);
129 + else
130 + return !is_c45 && (id == phydev->phy_id);
131 +}
132 +
133 +static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
134 +{
135 + return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
136 +}
137 +
138 +static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev)
139 +{
140 + return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
141 +}
142 +
143 +static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev)
144 +{
145 + return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
146 +}
147 +
148 +static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
149 +{
150 + return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
151 +}
152 +
153 static int rtlgen_resume(struct phy_device *phydev)
154 {
155 int ret = genphy_resume(phydev);
156 @@ -872,6 +972,15 @@ static int rtlgen_resume(struct phy_devi
157 return ret;
158 }
159
160 +static int rtlgen_c45_resume(struct phy_device *phydev)
161 +{
162 + int ret = genphy_c45_pma_resume(phydev);
163 +
164 + msleep(20);
165 +
166 + return ret;
167 +}
168 +
169 static int rtl9000a_config_init(struct phy_device *phydev)
170 {
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,
175 }, {
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,
186 }, {
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,
197 + }, {
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,
206 }, {
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,
215 + }, {
216 PHY_ID_MATCH_EXACT(0x001cc862),
217 .name = "RTL8251B 5Gbps PHY",
218 .get_features = rtl822x_get_features,