Merge tag 'block-5.11-2021-01-10' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / net / pcs / pcs-xpcs.c
blob1aa9903d602e7a3f30a13d81fef195d5ff2da0c8
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Synopsys, Inc. and/or its affiliates.
4 * Synopsys DesignWare XPCS helpers
6 * Author: Jose Abreu <Jose.Abreu@synopsys.com>
7 */
9 #include <linux/delay.h>
10 #include <linux/pcs/pcs-xpcs.h>
11 #include <linux/mdio.h>
12 #include <linux/phylink.h>
13 #include <linux/workqueue.h>
15 #define SYNOPSYS_XPCS_USXGMII_ID 0x7996ced0
16 #define SYNOPSYS_XPCS_10GKR_ID 0x7996ced0
17 #define SYNOPSYS_XPCS_XLGMII_ID 0x7996ced0
18 #define SYNOPSYS_XPCS_MASK 0xffffffff
20 /* Vendor regs access */
21 #define DW_VENDOR BIT(15)
23 /* VR_XS_PCS */
24 #define DW_USXGMII_RST BIT(10)
25 #define DW_USXGMII_EN BIT(9)
26 #define DW_VR_XS_PCS_DIG_STS 0x0010
27 #define DW_RXFIFO_ERR GENMASK(6, 5)
29 /* SR_MII */
30 #define DW_USXGMII_FULL BIT(8)
31 #define DW_USXGMII_SS_MASK (BIT(13) | BIT(6) | BIT(5))
32 #define DW_USXGMII_10000 (BIT(13) | BIT(6))
33 #define DW_USXGMII_5000 (BIT(13) | BIT(5))
34 #define DW_USXGMII_2500 (BIT(5))
35 #define DW_USXGMII_1000 (BIT(6))
36 #define DW_USXGMII_100 (BIT(13))
37 #define DW_USXGMII_10 (0)
39 /* SR_AN */
40 #define DW_SR_AN_ADV1 0x10
41 #define DW_SR_AN_ADV2 0x11
42 #define DW_SR_AN_ADV3 0x12
43 #define DW_SR_AN_LP_ABL1 0x13
44 #define DW_SR_AN_LP_ABL2 0x14
45 #define DW_SR_AN_LP_ABL3 0x15
47 /* Clause 73 Defines */
48 /* AN_LP_ABL1 */
49 #define DW_C73_PAUSE BIT(10)
50 #define DW_C73_ASYM_PAUSE BIT(11)
51 #define DW_C73_AN_ADV_SF 0x1
52 /* AN_LP_ABL2 */
53 #define DW_C73_1000KX BIT(5)
54 #define DW_C73_10000KX4 BIT(6)
55 #define DW_C73_10000KR BIT(7)
56 /* AN_LP_ABL3 */
57 #define DW_C73_2500KX BIT(0)
58 #define DW_C73_5000KR BIT(1)
60 static const int xpcs_usxgmii_features[] = {
61 ETHTOOL_LINK_MODE_Pause_BIT,
62 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
63 ETHTOOL_LINK_MODE_Autoneg_BIT,
64 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
65 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
66 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
67 ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
68 __ETHTOOL_LINK_MODE_MASK_NBITS,
71 static const int xpcs_10gkr_features[] = {
72 ETHTOOL_LINK_MODE_Pause_BIT,
73 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
74 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
75 __ETHTOOL_LINK_MODE_MASK_NBITS,
78 static const int xpcs_xlgmii_features[] = {
79 ETHTOOL_LINK_MODE_Pause_BIT,
80 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
81 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
82 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
83 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
84 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
85 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
86 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
87 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
88 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
89 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
90 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
91 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
92 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
93 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
94 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
95 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
96 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
97 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
98 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
99 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
100 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
101 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
102 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
103 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
104 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
105 __ETHTOOL_LINK_MODE_MASK_NBITS,
108 static const phy_interface_t xpcs_usxgmii_interfaces[] = {
109 PHY_INTERFACE_MODE_USXGMII,
110 PHY_INTERFACE_MODE_MAX,
113 static const phy_interface_t xpcs_10gkr_interfaces[] = {
114 PHY_INTERFACE_MODE_10GKR,
115 PHY_INTERFACE_MODE_MAX,
118 static const phy_interface_t xpcs_xlgmii_interfaces[] = {
119 PHY_INTERFACE_MODE_XLGMII,
120 PHY_INTERFACE_MODE_MAX,
123 static struct xpcs_id {
124 u32 id;
125 u32 mask;
126 const int *supported;
127 const phy_interface_t *interface;
128 } xpcs_id_list[] = {
130 .id = SYNOPSYS_XPCS_USXGMII_ID,
131 .mask = SYNOPSYS_XPCS_MASK,
132 .supported = xpcs_usxgmii_features,
133 .interface = xpcs_usxgmii_interfaces,
134 }, {
135 .id = SYNOPSYS_XPCS_10GKR_ID,
136 .mask = SYNOPSYS_XPCS_MASK,
137 .supported = xpcs_10gkr_features,
138 .interface = xpcs_10gkr_interfaces,
139 }, {
140 .id = SYNOPSYS_XPCS_XLGMII_ID,
141 .mask = SYNOPSYS_XPCS_MASK,
142 .supported = xpcs_xlgmii_features,
143 .interface = xpcs_xlgmii_interfaces,
147 static int xpcs_read(struct mdio_xpcs_args *xpcs, int dev, u32 reg)
149 u32 reg_addr = MII_ADDR_C45 | dev << 16 | reg;
151 return mdiobus_read(xpcs->bus, xpcs->addr, reg_addr);
154 static int xpcs_write(struct mdio_xpcs_args *xpcs, int dev, u32 reg, u16 val)
156 u32 reg_addr = MII_ADDR_C45 | dev << 16 | reg;
158 return mdiobus_write(xpcs->bus, xpcs->addr, reg_addr, val);
161 static int xpcs_read_vendor(struct mdio_xpcs_args *xpcs, int dev, u32 reg)
163 return xpcs_read(xpcs, dev, DW_VENDOR | reg);
166 static int xpcs_write_vendor(struct mdio_xpcs_args *xpcs, int dev, int reg,
167 u16 val)
169 return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
172 static int xpcs_read_vpcs(struct mdio_xpcs_args *xpcs, int reg)
174 return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
177 static int xpcs_write_vpcs(struct mdio_xpcs_args *xpcs, int reg, u16 val)
179 return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
182 static int xpcs_poll_reset(struct mdio_xpcs_args *xpcs, int dev)
184 /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
185 unsigned int retries = 12;
186 int ret;
188 do {
189 msleep(50);
190 ret = xpcs_read(xpcs, dev, MDIO_CTRL1);
191 if (ret < 0)
192 return ret;
193 } while (ret & MDIO_CTRL1_RESET && --retries);
195 return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0;
198 static int xpcs_soft_reset(struct mdio_xpcs_args *xpcs, int dev)
200 int ret;
202 ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET);
203 if (ret < 0)
204 return ret;
206 return xpcs_poll_reset(xpcs, dev);
209 #define xpcs_warn(__xpcs, __state, __args...) \
210 ({ \
211 if ((__state)->link) \
212 dev_warn(&(__xpcs)->bus->dev, ##__args); \
215 static int xpcs_read_fault(struct mdio_xpcs_args *xpcs,
216 struct phylink_link_state *state)
218 int ret;
220 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
221 if (ret < 0)
222 return ret;
224 if (ret & MDIO_STAT1_FAULT) {
225 xpcs_warn(xpcs, state, "Link fault condition detected!\n");
226 return -EFAULT;
229 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2);
230 if (ret < 0)
231 return ret;
233 if (ret & MDIO_STAT2_RXFAULT)
234 xpcs_warn(xpcs, state, "Receiver fault detected!\n");
235 if (ret & MDIO_STAT2_TXFAULT)
236 xpcs_warn(xpcs, state, "Transmitter fault detected!\n");
238 ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS);
239 if (ret < 0)
240 return ret;
242 if (ret & DW_RXFIFO_ERR) {
243 xpcs_warn(xpcs, state, "FIFO fault condition detected!\n");
244 return -EFAULT;
247 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
248 if (ret < 0)
249 return ret;
251 if (!(ret & MDIO_PCS_10GBRT_STAT1_BLKLK))
252 xpcs_warn(xpcs, state, "Link is not locked!\n");
254 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2);
255 if (ret < 0)
256 return ret;
258 if (ret & MDIO_PCS_10GBRT_STAT2_ERR) {
259 xpcs_warn(xpcs, state, "Link has errors!\n");
260 return -EFAULT;
263 return 0;
266 static int xpcs_read_link(struct mdio_xpcs_args *xpcs, bool an)
268 bool link = true;
269 int ret;
271 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
272 if (ret < 0)
273 return ret;
275 if (!(ret & MDIO_STAT1_LSTATUS))
276 link = false;
278 if (an) {
279 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
280 if (ret < 0)
281 return ret;
283 if (!(ret & MDIO_STAT1_LSTATUS))
284 link = false;
287 return link;
290 static int xpcs_get_max_usxgmii_speed(const unsigned long *supported)
292 int max = SPEED_UNKNOWN;
294 if (phylink_test(supported, 1000baseKX_Full))
295 max = SPEED_1000;
296 if (phylink_test(supported, 2500baseX_Full))
297 max = SPEED_2500;
298 if (phylink_test(supported, 10000baseKX4_Full))
299 max = SPEED_10000;
300 if (phylink_test(supported, 10000baseKR_Full))
301 max = SPEED_10000;
303 return max;
306 static int xpcs_config_usxgmii(struct mdio_xpcs_args *xpcs, int speed)
308 int ret, speed_sel;
310 switch (speed) {
311 case SPEED_10:
312 speed_sel = DW_USXGMII_10;
313 break;
314 case SPEED_100:
315 speed_sel = DW_USXGMII_100;
316 break;
317 case SPEED_1000:
318 speed_sel = DW_USXGMII_1000;
319 break;
320 case SPEED_2500:
321 speed_sel = DW_USXGMII_2500;
322 break;
323 case SPEED_5000:
324 speed_sel = DW_USXGMII_5000;
325 break;
326 case SPEED_10000:
327 speed_sel = DW_USXGMII_10000;
328 break;
329 default:
330 /* Nothing to do here */
331 return -EINVAL;
334 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
335 if (ret < 0)
336 return ret;
338 ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN);
339 if (ret < 0)
340 return ret;
342 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
343 if (ret < 0)
344 return ret;
346 ret &= ~DW_USXGMII_SS_MASK;
347 ret |= speed_sel | DW_USXGMII_FULL;
349 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
350 if (ret < 0)
351 return ret;
353 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
354 if (ret < 0)
355 return ret;
357 return xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST);
360 static int xpcs_config_aneg_c73(struct mdio_xpcs_args *xpcs)
362 int ret, adv;
364 /* By default, in USXGMII mode XPCS operates at 10G baud and
365 * replicates data to achieve lower speeds. Hereby, in this
366 * default configuration we need to advertise all supported
367 * modes and not only the ones we want to use.
370 /* SR_AN_ADV3 */
371 adv = 0;
372 if (phylink_test(xpcs->supported, 2500baseX_Full))
373 adv |= DW_C73_2500KX;
375 /* TODO: 5000baseKR */
377 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv);
378 if (ret < 0)
379 return ret;
381 /* SR_AN_ADV2 */
382 adv = 0;
383 if (phylink_test(xpcs->supported, 1000baseKX_Full))
384 adv |= DW_C73_1000KX;
385 if (phylink_test(xpcs->supported, 10000baseKX4_Full))
386 adv |= DW_C73_10000KX4;
387 if (phylink_test(xpcs->supported, 10000baseKR_Full))
388 adv |= DW_C73_10000KR;
390 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv);
391 if (ret < 0)
392 return ret;
394 /* SR_AN_ADV1 */
395 adv = DW_C73_AN_ADV_SF;
396 if (phylink_test(xpcs->supported, Pause))
397 adv |= DW_C73_PAUSE;
398 if (phylink_test(xpcs->supported, Asym_Pause))
399 adv |= DW_C73_ASYM_PAUSE;
401 return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv);
404 static int xpcs_config_aneg(struct mdio_xpcs_args *xpcs)
406 int ret;
408 ret = xpcs_config_aneg_c73(xpcs);
409 if (ret < 0)
410 return ret;
412 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1);
413 if (ret < 0)
414 return ret;
416 ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
418 return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret);
421 static int xpcs_aneg_done(struct mdio_xpcs_args *xpcs,
422 struct phylink_link_state *state)
424 int ret;
426 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
427 if (ret < 0)
428 return ret;
430 if (ret & MDIO_AN_STAT1_COMPLETE) {
431 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
432 if (ret < 0)
433 return ret;
435 /* Check if Aneg outcome is valid */
436 if (!(ret & DW_C73_AN_ADV_SF)) {
437 xpcs_config_aneg(xpcs);
438 return 0;
441 return 1;
444 return 0;
447 static int xpcs_read_lpa(struct mdio_xpcs_args *xpcs,
448 struct phylink_link_state *state)
450 int ret;
452 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
453 if (ret < 0)
454 return ret;
456 if (!(ret & MDIO_AN_STAT1_LPABLE)) {
457 phylink_clear(state->lp_advertising, Autoneg);
458 return 0;
461 phylink_set(state->lp_advertising, Autoneg);
463 /* Clause 73 outcome */
464 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3);
465 if (ret < 0)
466 return ret;
468 if (ret & DW_C73_2500KX)
469 phylink_set(state->lp_advertising, 2500baseX_Full);
471 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2);
472 if (ret < 0)
473 return ret;
475 if (ret & DW_C73_1000KX)
476 phylink_set(state->lp_advertising, 1000baseKX_Full);
477 if (ret & DW_C73_10000KX4)
478 phylink_set(state->lp_advertising, 10000baseKX4_Full);
479 if (ret & DW_C73_10000KR)
480 phylink_set(state->lp_advertising, 10000baseKR_Full);
482 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
483 if (ret < 0)
484 return ret;
486 if (ret & DW_C73_PAUSE)
487 phylink_set(state->lp_advertising, Pause);
488 if (ret & DW_C73_ASYM_PAUSE)
489 phylink_set(state->lp_advertising, Asym_Pause);
491 linkmode_and(state->lp_advertising, state->lp_advertising,
492 state->advertising);
493 return 0;
496 static void xpcs_resolve_lpa(struct mdio_xpcs_args *xpcs,
497 struct phylink_link_state *state)
499 int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising);
501 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
502 state->speed = max_speed;
503 state->duplex = DUPLEX_FULL;
506 static int xpcs_get_max_xlgmii_speed(struct mdio_xpcs_args *xpcs,
507 struct phylink_link_state *state)
509 unsigned long *adv = state->advertising;
510 int speed = SPEED_UNKNOWN;
511 int bit;
513 for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) {
514 int new_speed = SPEED_UNKNOWN;
516 switch (bit) {
517 case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
518 case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
519 case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
520 new_speed = SPEED_25000;
521 break;
522 case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
523 case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
524 case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
525 case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
526 new_speed = SPEED_40000;
527 break;
528 case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT:
529 case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT:
530 case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT:
531 case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
532 case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
533 case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
534 case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
535 case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT:
536 new_speed = SPEED_50000;
537 break;
538 case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
539 case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
540 case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
541 case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
542 case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT:
543 case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT:
544 case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT:
545 case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT:
546 case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT:
547 new_speed = SPEED_100000;
548 break;
549 default:
550 continue;
553 if (new_speed > speed)
554 speed = new_speed;
557 return speed;
560 static void xpcs_resolve_pma(struct mdio_xpcs_args *xpcs,
561 struct phylink_link_state *state)
563 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
564 state->duplex = DUPLEX_FULL;
566 switch (state->interface) {
567 case PHY_INTERFACE_MODE_10GKR:
568 state->speed = SPEED_10000;
569 break;
570 case PHY_INTERFACE_MODE_XLGMII:
571 state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
572 break;
573 default:
574 state->speed = SPEED_UNKNOWN;
575 break;
579 static int xpcs_validate(struct mdio_xpcs_args *xpcs,
580 unsigned long *supported,
581 struct phylink_link_state *state)
583 linkmode_and(supported, supported, xpcs->supported);
584 linkmode_and(state->advertising, state->advertising, xpcs->supported);
585 return 0;
588 static int xpcs_config(struct mdio_xpcs_args *xpcs,
589 const struct phylink_link_state *state)
591 int ret;
593 if (state->an_enabled) {
594 ret = xpcs_config_aneg(xpcs);
595 if (ret)
596 return ret;
599 return 0;
602 static int xpcs_get_state(struct mdio_xpcs_args *xpcs,
603 struct phylink_link_state *state)
605 int ret;
607 /* Link needs to be read first ... */
608 state->link = xpcs_read_link(xpcs, state->an_enabled) > 0 ? 1 : 0;
610 /* ... and then we check the faults. */
611 ret = xpcs_read_fault(xpcs, state);
612 if (ret) {
613 ret = xpcs_soft_reset(xpcs, MDIO_MMD_PCS);
614 if (ret)
615 return ret;
617 state->link = 0;
619 return xpcs_config(xpcs, state);
622 if (state->an_enabled && xpcs_aneg_done(xpcs, state)) {
623 state->an_complete = true;
624 xpcs_read_lpa(xpcs, state);
625 xpcs_resolve_lpa(xpcs, state);
626 } else if (state->an_enabled) {
627 state->link = 0;
628 } else if (state->link) {
629 xpcs_resolve_pma(xpcs, state);
632 return 0;
635 static int xpcs_link_up(struct mdio_xpcs_args *xpcs, int speed,
636 phy_interface_t interface)
638 if (interface == PHY_INTERFACE_MODE_USXGMII)
639 return xpcs_config_usxgmii(xpcs, speed);
641 return 0;
644 static u32 xpcs_get_id(struct mdio_xpcs_args *xpcs)
646 int ret;
647 u32 id;
649 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1);
650 if (ret < 0)
651 return 0xffffffff;
653 id = ret << 16;
655 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2);
656 if (ret < 0)
657 return 0xffffffff;
659 return id | ret;
662 static bool xpcs_check_features(struct mdio_xpcs_args *xpcs,
663 struct xpcs_id *match,
664 phy_interface_t interface)
666 int i;
668 for (i = 0; match->interface[i] != PHY_INTERFACE_MODE_MAX; i++) {
669 if (match->interface[i] == interface)
670 break;
673 if (match->interface[i] == PHY_INTERFACE_MODE_MAX)
674 return false;
676 for (i = 0; match->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
677 set_bit(match->supported[i], xpcs->supported);
679 return true;
682 static int xpcs_probe(struct mdio_xpcs_args *xpcs, phy_interface_t interface)
684 u32 xpcs_id = xpcs_get_id(xpcs);
685 struct xpcs_id *match = NULL;
686 int i;
688 for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
689 struct xpcs_id *entry = &xpcs_id_list[i];
691 if ((xpcs_id & entry->mask) == entry->id) {
692 match = entry;
694 if (xpcs_check_features(xpcs, match, interface))
695 return xpcs_soft_reset(xpcs, MDIO_MMD_PCS);
699 return -ENODEV;
702 static struct mdio_xpcs_ops xpcs_ops = {
703 .validate = xpcs_validate,
704 .config = xpcs_config,
705 .get_state = xpcs_get_state,
706 .link_up = xpcs_link_up,
707 .probe = xpcs_probe,
710 struct mdio_xpcs_ops *mdio_xpcs_get_ops(void)
712 return &xpcs_ops;
714 EXPORT_SYMBOL_GPL(mdio_xpcs_get_ops);
716 MODULE_LICENSE("GPL v2");