Commit | Line | Data |
---|---|---|
457c8996 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
5acde34a RK |
2 | /* |
3 | * Clause 45 PHY support | |
4 | */ | |
5 | #include <linux/ethtool.h> | |
6 | #include <linux/export.h> | |
7 | #include <linux/mdio.h> | |
8 | #include <linux/mii.h> | |
9 | #include <linux/phy.h> | |
10 | ||
11 | /** | |
12 | * genphy_c45_setup_forced - configures a forced speed | |
13 | * @phydev: target phy_device struct | |
14 | */ | |
15 | int genphy_c45_pma_setup_forced(struct phy_device *phydev) | |
16 | { | |
17 | int ctrl1, ctrl2, ret; | |
18 | ||
19 | /* Half duplex is not supported */ | |
20 | if (phydev->duplex != DUPLEX_FULL) | |
21 | return -EINVAL; | |
22 | ||
23 | ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1); | |
24 | if (ctrl1 < 0) | |
25 | return ctrl1; | |
26 | ||
27 | ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2); | |
28 | if (ctrl2 < 0) | |
29 | return ctrl2; | |
30 | ||
31 | ctrl1 &= ~MDIO_CTRL1_SPEEDSEL; | |
32 | /* | |
33 | * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0. See 45.2.1.6.1 | |
34 | * in 802.3-2012 and 802.3-2015. | |
35 | */ | |
36 | ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30); | |
37 | ||
38 | switch (phydev->speed) { | |
39 | case SPEED_10: | |
40 | ctrl2 |= MDIO_PMA_CTRL2_10BT; | |
41 | break; | |
42 | case SPEED_100: | |
43 | ctrl1 |= MDIO_PMA_CTRL1_SPEED100; | |
44 | ctrl2 |= MDIO_PMA_CTRL2_100BTX; | |
45 | break; | |
46 | case SPEED_1000: | |
47 | ctrl1 |= MDIO_PMA_CTRL1_SPEED1000; | |
48 | /* Assume 1000base-T */ | |
49 | ctrl2 |= MDIO_PMA_CTRL2_1000BT; | |
50 | break; | |
7fd8afa8 MC |
51 | case SPEED_2500: |
52 | ctrl1 |= MDIO_CTRL1_SPEED2_5G; | |
53 | /* Assume 2.5Gbase-T */ | |
54 | ctrl2 |= MDIO_PMA_CTRL2_2_5GBT; | |
55 | break; | |
56 | case SPEED_5000: | |
57 | ctrl1 |= MDIO_CTRL1_SPEED5G; | |
58 | /* Assume 5Gbase-T */ | |
59 | ctrl2 |= MDIO_PMA_CTRL2_5GBT; | |
60 | break; | |
5acde34a RK |
61 | case SPEED_10000: |
62 | ctrl1 |= MDIO_CTRL1_SPEED10G; | |
63 | /* Assume 10Gbase-T */ | |
64 | ctrl2 |= MDIO_PMA_CTRL2_10GBT; | |
65 | break; | |
66 | default: | |
67 | return -EINVAL; | |
68 | } | |
69 | ||
70 | ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1); | |
71 | if (ret < 0) | |
72 | return ret; | |
73 | ||
29f000f7 HK |
74 | ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2); |
75 | if (ret < 0) | |
76 | return ret; | |
77 | ||
78 | return genphy_c45_an_disable_aneg(phydev); | |
5acde34a RK |
79 | } |
80 | EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced); | |
81 | ||
9a5dc8af AL |
82 | /** |
83 | * genphy_c45_an_config_aneg - configure advertisement registers | |
84 | * @phydev: target phy_device struct | |
85 | * | |
86 | * Configure advertisement registers based on modes set in phydev->advertising | |
87 | * | |
88 | * Returns negative errno code on failure, 0 if advertisement didn't change, | |
89 | * or 1 if advertised modes changed. | |
90 | */ | |
91 | int genphy_c45_an_config_aneg(struct phy_device *phydev) | |
92 | { | |
cc429d52 | 93 | int changed, ret; |
9a5dc8af AL |
94 | u32 adv; |
95 | ||
96 | linkmode_and(phydev->advertising, phydev->advertising, | |
97 | phydev->supported); | |
98 | ||
cc429d52 HK |
99 | changed = genphy_config_eee_advert(phydev); |
100 | ||
9a5dc8af AL |
101 | adv = linkmode_adv_to_mii_adv_t(phydev->advertising); |
102 | ||
9731ea06 HK |
103 | ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, |
104 | ADVERTISE_ALL | ADVERTISE_100BASE4 | | |
105 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, | |
106 | adv); | |
9a5dc8af AL |
107 | if (ret < 0) |
108 | return ret; | |
109 | if (ret > 0) | |
110 | changed = 1; | |
111 | ||
112 | adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); | |
113 | ||
9731ea06 HK |
114 | ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, |
115 | MDIO_AN_10GBT_CTRL_ADV10G | | |
116 | MDIO_AN_10GBT_CTRL_ADV5G | | |
117 | MDIO_AN_10GBT_CTRL_ADV2_5G, adv); | |
9a5dc8af AL |
118 | if (ret < 0) |
119 | return ret; | |
120 | if (ret > 0) | |
121 | changed = 1; | |
122 | ||
123 | return changed; | |
124 | } | |
125 | EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg); | |
126 | ||
5acde34a RK |
127 | /** |
128 | * genphy_c45_an_disable_aneg - disable auto-negotiation | |
129 | * @phydev: target phy_device struct | |
130 | * | |
131 | * Disable auto-negotiation in the Clause 45 PHY. The link parameters | |
132 | * parameters are controlled through the PMA/PMD MMD registers. | |
133 | * | |
134 | * Returns zero on success, negative errno code on failure. | |
135 | */ | |
136 | int genphy_c45_an_disable_aneg(struct phy_device *phydev) | |
137 | { | |
5acde34a | 138 | |
b52c018d HK |
139 | return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, |
140 | MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART); | |
5acde34a RK |
141 | } |
142 | EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg); | |
143 | ||
144 | /** | |
145 | * genphy_c45_restart_aneg - Enable and restart auto-negotiation | |
146 | * @phydev: target phy_device struct | |
147 | * | |
148 | * This assumes that the auto-negotiation MMD is present. | |
149 | * | |
150 | * Enable and restart auto-negotiation. | |
151 | */ | |
152 | int genphy_c45_restart_aneg(struct phy_device *phydev) | |
153 | { | |
b52c018d HK |
154 | return phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, |
155 | MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART); | |
5acde34a RK |
156 | } |
157 | EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg); | |
158 | ||
1af9f168 HK |
159 | /** |
160 | * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation | |
161 | * @phydev: target phy_device struct | |
162 | * @restart: whether aneg restart is requested | |
163 | * | |
164 | * This assumes that the auto-negotiation MMD is present. | |
165 | * | |
166 | * Check, and restart auto-negotiation if needed. | |
167 | */ | |
168 | int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart) | |
169 | { | |
170 | int ret = 0; | |
171 | ||
172 | if (!restart) { | |
173 | /* Configure and restart aneg if it wasn't set before */ | |
174 | ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); | |
175 | if (ret < 0) | |
176 | return ret; | |
177 | ||
178 | if (!(ret & MDIO_AN_CTRL1_ENABLE)) | |
179 | restart = true; | |
180 | } | |
181 | ||
182 | if (restart) | |
183 | ret = genphy_c45_restart_aneg(phydev); | |
184 | ||
185 | return ret; | |
186 | } | |
187 | EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg); | |
188 | ||
5acde34a RK |
189 | /** |
190 | * genphy_c45_aneg_done - return auto-negotiation complete status | |
191 | * @phydev: target phy_device struct | |
192 | * | |
193 | * This assumes that the auto-negotiation MMD is present. | |
194 | * | |
195 | * Reads the status register from the auto-negotiation MMD, returning: | |
196 | * - positive if auto-negotiation is complete | |
197 | * - negative errno code on error | |
198 | * - zero otherwise | |
199 | */ | |
200 | int genphy_c45_aneg_done(struct phy_device *phydev) | |
201 | { | |
202 | int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); | |
203 | ||
204 | return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0; | |
205 | } | |
206 | EXPORT_SYMBOL_GPL(genphy_c45_aneg_done); | |
207 | ||
208 | /** | |
209 | * genphy_c45_read_link - read the overall link status from the MMDs | |
210 | * @phydev: target phy_device struct | |
5acde34a RK |
211 | * |
212 | * Read the link status from the specified MMDs, and if they all indicate | |
a6e11f6b | 213 | * that the link is up, set phydev->link to 1. If an error is encountered, |
5acde34a RK |
214 | * a negative errno will be returned, otherwise zero. |
215 | */ | |
998a8a83 | 216 | int genphy_c45_read_link(struct phy_device *phydev) |
5acde34a | 217 | { |
c1164bb1 | 218 | u32 mmd_mask = MDIO_DEVS_PMAPMD; |
5acde34a RK |
219 | int val, devad; |
220 | bool link = true; | |
221 | ||
c36757eb HK |
222 | if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { |
223 | val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); | |
224 | if (val < 0) | |
225 | return val; | |
226 | ||
227 | /* Autoneg is being started, therefore disregard current | |
228 | * link status and report link as down. | |
229 | */ | |
230 | if (val & MDIO_AN_CTRL1_RESTART) { | |
231 | phydev->link = 0; | |
232 | return 0; | |
233 | } | |
234 | } | |
235 | ||
a6e11f6b | 236 | while (mmd_mask && link) { |
5acde34a RK |
237 | devad = __ffs(mmd_mask); |
238 | mmd_mask &= ~BIT(devad); | |
239 | ||
240 | /* The link state is latched low so that momentary link | |
93c09704 HK |
241 | * drops can be detected. Do not double-read the status |
242 | * in polling mode to detect such short link drops. | |
5acde34a | 243 | */ |
93c09704 HK |
244 | if (!phy_polling_mode(phydev)) { |
245 | val = phy_read_mmd(phydev, devad, MDIO_STAT1); | |
246 | if (val < 0) | |
247 | return val; | |
c397ab21 HK |
248 | else if (val & MDIO_STAT1_LSTATUS) |
249 | continue; | |
93c09704 HK |
250 | } |
251 | ||
5acde34a RK |
252 | val = phy_read_mmd(phydev, devad, MDIO_STAT1); |
253 | if (val < 0) | |
254 | return val; | |
255 | ||
256 | if (!(val & MDIO_STAT1_LSTATUS)) | |
257 | link = false; | |
258 | } | |
259 | ||
a6e11f6b HK |
260 | phydev->link = link; |
261 | ||
262 | return 0; | |
5acde34a RK |
263 | } |
264 | EXPORT_SYMBOL_GPL(genphy_c45_read_link); | |
265 | ||
266 | /** | |
cc1122b0 | 267 | * genphy_c45_read_lpa - read the link partner advertisement and pause |
5acde34a RK |
268 | * @phydev: target phy_device struct |
269 | * | |
270 | * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers, | |
cc1122b0 | 271 | * filling in the link partner advertisement, pause and asym_pause members |
5acde34a RK |
272 | * in @phydev. This assumes that the auto-negotiation MMD is present, and |
273 | * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected | |
274 | * to fill in the remainder of the link partner advert from vendor registers. | |
275 | */ | |
276 | int genphy_c45_read_lpa(struct phy_device *phydev) | |
277 | { | |
278 | int val; | |
279 | ||
5d237a07 HK |
280 | val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); |
281 | if (val < 0) | |
282 | return val; | |
283 | ||
372fcc1b HK |
284 | if (!(val & MDIO_AN_STAT1_COMPLETE)) { |
285 | linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, | |
286 | phydev->lp_advertising); | |
287 | mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); | |
288 | mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, 0); | |
289 | phydev->pause = 0; | |
290 | phydev->asym_pause = 0; | |
291 | ||
292 | return 0; | |
293 | } | |
294 | ||
5d237a07 HK |
295 | linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->lp_advertising, |
296 | val & MDIO_AN_STAT1_LPABLE); | |
297 | ||
cc1122b0 | 298 | /* Read the link partner's base page advertisement */ |
5acde34a RK |
299 | val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA); |
300 | if (val < 0) | |
301 | return val; | |
302 | ||
5d237a07 | 303 | mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, val); |
5acde34a RK |
304 | phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0; |
305 | phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0; | |
306 | ||
cc1122b0 | 307 | /* Read the link partner's 10G advertisement */ |
5acde34a RK |
308 | val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); |
309 | if (val < 0) | |
310 | return val; | |
311 | ||
96c2be34 | 312 | mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, val); |
5acde34a RK |
313 | |
314 | return 0; | |
315 | } | |
316 | EXPORT_SYMBOL_GPL(genphy_c45_read_lpa); | |
317 | ||
318 | /** | |
319 | * genphy_c45_read_pma - read link speed etc from PMA | |
320 | * @phydev: target phy_device struct | |
321 | */ | |
322 | int genphy_c45_read_pma(struct phy_device *phydev) | |
323 | { | |
324 | int val; | |
325 | ||
326 | val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1); | |
327 | if (val < 0) | |
328 | return val; | |
329 | ||
330 | switch (val & MDIO_CTRL1_SPEEDSEL) { | |
331 | case 0: | |
332 | phydev->speed = SPEED_10; | |
333 | break; | |
334 | case MDIO_PMA_CTRL1_SPEED100: | |
335 | phydev->speed = SPEED_100; | |
336 | break; | |
337 | case MDIO_PMA_CTRL1_SPEED1000: | |
338 | phydev->speed = SPEED_1000; | |
339 | break; | |
7fd8afa8 MC |
340 | case MDIO_CTRL1_SPEED2_5G: |
341 | phydev->speed = SPEED_2500; | |
342 | break; | |
343 | case MDIO_CTRL1_SPEED5G: | |
344 | phydev->speed = SPEED_5000; | |
345 | break; | |
5acde34a RK |
346 | case MDIO_CTRL1_SPEED10G: |
347 | phydev->speed = SPEED_10000; | |
348 | break; | |
349 | default: | |
350 | phydev->speed = SPEED_UNKNOWN; | |
351 | break; | |
352 | } | |
353 | ||
354 | phydev->duplex = DUPLEX_FULL; | |
355 | ||
356 | return 0; | |
357 | } | |
358 | EXPORT_SYMBOL_GPL(genphy_c45_read_pma); | |
921690f2 | 359 | |
ea4efe25 RK |
360 | /** |
361 | * genphy_c45_read_mdix - read mdix status from PMA | |
362 | * @phydev: target phy_device struct | |
363 | */ | |
364 | int genphy_c45_read_mdix(struct phy_device *phydev) | |
365 | { | |
366 | int val; | |
367 | ||
368 | if (phydev->speed == SPEED_10000) { | |
369 | val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, | |
370 | MDIO_PMA_10GBT_SWAPPOL); | |
371 | if (val < 0) | |
372 | return val; | |
373 | ||
374 | switch (val) { | |
375 | case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX: | |
376 | phydev->mdix = ETH_TP_MDI; | |
377 | break; | |
378 | ||
379 | case 0: | |
380 | phydev->mdix = ETH_TP_MDI_X; | |
381 | break; | |
382 | ||
383 | default: | |
384 | phydev->mdix = ETH_TP_MDI_INVALID; | |
385 | break; | |
386 | } | |
387 | } | |
388 | ||
389 | return 0; | |
390 | } | |
391 | EXPORT_SYMBOL_GPL(genphy_c45_read_mdix); | |
392 | ||
ac3f5533 MC |
393 | /** |
394 | * genphy_c45_pma_read_abilities - read supported link modes from PMA | |
395 | * @phydev: target phy_device struct | |
396 | * | |
397 | * Read the supported link modes from the PMA Status 2 (1.8) register. If bit | |
398 | * 1.8.9 is set, the list of supported modes is build using the values in the | |
399 | * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related | |
400 | * modes. If bit 1.11.14 is set, then the list is also extended with the modes | |
401 | * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and | |
402 | * 5GBASET are supported. | |
403 | */ | |
404 | int genphy_c45_pma_read_abilities(struct phy_device *phydev) | |
405 | { | |
406 | int val; | |
407 | ||
b6a4119d HK |
408 | linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); |
409 | if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { | |
410 | val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); | |
411 | if (val < 0) | |
412 | return val; | |
413 | ||
414 | if (val & MDIO_AN_STAT1_ABLE) | |
415 | linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, | |
416 | phydev->supported); | |
417 | } | |
418 | ||
ac3f5533 MC |
419 | val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2); |
420 | if (val < 0) | |
421 | return val; | |
422 | ||
423 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, | |
424 | phydev->supported, | |
425 | val & MDIO_PMA_STAT2_10GBSR); | |
426 | ||
427 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, | |
428 | phydev->supported, | |
429 | val & MDIO_PMA_STAT2_10GBLR); | |
430 | ||
431 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, | |
432 | phydev->supported, | |
433 | val & MDIO_PMA_STAT2_10GBER); | |
434 | ||
435 | if (val & MDIO_PMA_STAT2_EXTABLE) { | |
436 | val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE); | |
437 | if (val < 0) | |
438 | return val; | |
439 | ||
440 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, | |
441 | phydev->supported, | |
442 | val & MDIO_PMA_EXTABLE_10GBLRM); | |
443 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, | |
444 | phydev->supported, | |
445 | val & MDIO_PMA_EXTABLE_10GBT); | |
446 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, | |
447 | phydev->supported, | |
448 | val & MDIO_PMA_EXTABLE_10GBKX4); | |
449 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, | |
450 | phydev->supported, | |
451 | val & MDIO_PMA_EXTABLE_10GBKR); | |
452 | linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, | |
453 | phydev->supported, | |
454 | val & MDIO_PMA_EXTABLE_1000BT); | |
455 | linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, | |
456 | phydev->supported, | |
457 | val & MDIO_PMA_EXTABLE_1000BKX); | |
458 | ||
459 | linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, | |
460 | phydev->supported, | |
461 | val & MDIO_PMA_EXTABLE_100BTX); | |
462 | linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, | |
463 | phydev->supported, | |
464 | val & MDIO_PMA_EXTABLE_100BTX); | |
465 | ||
466 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, | |
467 | phydev->supported, | |
468 | val & MDIO_PMA_EXTABLE_10BT); | |
469 | linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, | |
470 | phydev->supported, | |
471 | val & MDIO_PMA_EXTABLE_10BT); | |
7fd8afa8 MC |
472 | |
473 | if (val & MDIO_PMA_EXTABLE_NBT) { | |
474 | val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, | |
475 | MDIO_PMA_NG_EXTABLE); | |
476 | if (val < 0) | |
477 | return val; | |
478 | ||
479 | linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, | |
480 | phydev->supported, | |
481 | val & MDIO_PMA_NG_EXTABLE_2_5GBT); | |
482 | ||
483 | linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, | |
484 | phydev->supported, | |
485 | val & MDIO_PMA_NG_EXTABLE_5GBT); | |
486 | } | |
ac3f5533 MC |
487 | } |
488 | ||
489 | return 0; | |
490 | } | |
491 | EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities); | |
492 | ||
70fa3a96 HK |
493 | /** |
494 | * genphy_c45_read_status - read PHY status | |
495 | * @phydev: target phy_device struct | |
496 | * | |
497 | * Reads status from PHY and sets phy_device members accordingly. | |
498 | */ | |
499 | int genphy_c45_read_status(struct phy_device *phydev) | |
500 | { | |
501 | int ret; | |
502 | ||
503 | ret = genphy_c45_read_link(phydev); | |
504 | if (ret) | |
505 | return ret; | |
506 | ||
507 | phydev->speed = SPEED_UNKNOWN; | |
508 | phydev->duplex = DUPLEX_UNKNOWN; | |
509 | phydev->pause = 0; | |
510 | phydev->asym_pause = 0; | |
511 | ||
512 | if (phydev->autoneg == AUTONEG_ENABLE) { | |
513 | ret = genphy_c45_read_lpa(phydev); | |
514 | if (ret) | |
515 | return ret; | |
516 | ||
517 | phy_resolve_aneg_linkmode(phydev); | |
518 | } else { | |
519 | ret = genphy_c45_read_pma(phydev); | |
520 | } | |
521 | ||
522 | return ret; | |
523 | } | |
524 | EXPORT_SYMBOL_GPL(genphy_c45_read_status); | |
525 | ||
921690f2 RK |
526 | /* The gen10g_* functions are the old Clause 45 stub */ |
527 | ||
e8a714e0 | 528 | int gen10g_config_aneg(struct phy_device *phydev) |
921690f2 RK |
529 | { |
530 | return 0; | |
531 | } | |
e8a714e0 | 532 | EXPORT_SYMBOL_GPL(gen10g_config_aneg); |
921690f2 | 533 | |
22b56e82 | 534 | struct phy_driver genphy_c45_driver = { |
921690f2 RK |
535 | .phy_id = 0xffffffff, |
536 | .phy_id_mask = 0xffffffff, | |
22b56e82 | 537 | .name = "Generic Clause 45 PHY", |
7be3ad84 | 538 | .soft_reset = genphy_no_soft_reset, |
22b56e82 | 539 | .read_status = genphy_c45_read_status, |
921690f2 | 540 | }; |