1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Synopsys, Inc. and/or its affiliates.
4 * Synopsys DesignWare XPCS helpers
5 *
6 * Author: Jose Abreu <Jose.Abreu@synopsys.com>
7 */
8
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>
14 #include "pcs-xpcs.h"
15
16 #define phylink_pcs_to_xpcs(pl_pcs) \
17 container_of((pl_pcs), struct dw_xpcs, pcs)
18
19 static const int xpcs_usxgmii_features[] = {
20 ETHTOOL_LINK_MODE_Pause_BIT,
21 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
22 ETHTOOL_LINK_MODE_Autoneg_BIT,
23 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
24 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
25 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
26 ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
27 __ETHTOOL_LINK_MODE_MASK_NBITS,
28 };
29
30 static const int xpcs_10gkr_features[] = {
31 ETHTOOL_LINK_MODE_Pause_BIT,
32 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
33 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
34 __ETHTOOL_LINK_MODE_MASK_NBITS,
35 };
36
37 static const int xpcs_xlgmii_features[] = {
38 ETHTOOL_LINK_MODE_Pause_BIT,
39 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
40 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
41 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
42 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
43 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
44 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
45 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
46 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
47 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
48 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
49 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
50 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
51 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
52 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
53 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
54 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
55 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
56 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
57 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
58 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
59 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
60 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
61 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
62 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
63 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
64 __ETHTOOL_LINK_MODE_MASK_NBITS,
65 };
66
67 static const int xpcs_sgmii_features[] = {
68 ETHTOOL_LINK_MODE_Pause_BIT,
69 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
70 ETHTOOL_LINK_MODE_Autoneg_BIT,
71 ETHTOOL_LINK_MODE_10baseT_Half_BIT,
72 ETHTOOL_LINK_MODE_10baseT_Full_BIT,
73 ETHTOOL_LINK_MODE_100baseT_Half_BIT,
74 ETHTOOL_LINK_MODE_100baseT_Full_BIT,
75 ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
76 ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
77 __ETHTOOL_LINK_MODE_MASK_NBITS,
78 };
79
80 static const int xpcs_1000basex_features[] = {
81 ETHTOOL_LINK_MODE_Pause_BIT,
82 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
83 ETHTOOL_LINK_MODE_Autoneg_BIT,
84 ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
85 __ETHTOOL_LINK_MODE_MASK_NBITS,
86 };
87
88 static const int xpcs_2500basex_features[] = {
89 ETHTOOL_LINK_MODE_Pause_BIT,
90 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
91 ETHTOOL_LINK_MODE_Autoneg_BIT,
92 ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
93 ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
94 __ETHTOOL_LINK_MODE_MASK_NBITS,
95 };
96
97 static const phy_interface_t xpcs_usxgmii_interfaces[] = {
98 PHY_INTERFACE_MODE_USXGMII,
99 };
100
101 static const phy_interface_t xpcs_10gkr_interfaces[] = {
102 PHY_INTERFACE_MODE_10GKR,
103 };
104
105 static const phy_interface_t xpcs_xlgmii_interfaces[] = {
106 PHY_INTERFACE_MODE_XLGMII,
107 };
108
109 static const phy_interface_t xpcs_sgmii_interfaces[] = {
110 PHY_INTERFACE_MODE_SGMII,
111 };
112
113 static const phy_interface_t xpcs_1000basex_interfaces[] = {
114 PHY_INTERFACE_MODE_1000BASEX,
115 };
116
117 static const phy_interface_t xpcs_2500basex_interfaces[] = {
118 PHY_INTERFACE_MODE_2500BASEX,
119 PHY_INTERFACE_MODE_MAX,
120 };
121
122 enum {
123 DW_XPCS_USXGMII,
124 DW_XPCS_10GKR,
125 DW_XPCS_XLGMII,
126 DW_XPCS_SGMII,
127 DW_XPCS_1000BASEX,
128 DW_XPCS_2500BASEX,
129 DW_XPCS_INTERFACE_MAX,
130 };
131
132 struct xpcs_compat {
133 const int *supported;
134 const phy_interface_t *interface;
135 int num_interfaces;
136 int an_mode;
137 int (*pma_config)(struct dw_xpcs *xpcs);
138 };
139
140 struct xpcs_id {
141 u32 id;
142 u32 mask;
143 const struct xpcs_compat *compat;
144 };
145
xpcs_find_compat(const struct xpcs_id * id,phy_interface_t interface)146 static const struct xpcs_compat *xpcs_find_compat(const struct xpcs_id *id,
147 phy_interface_t interface)
148 {
149 int i, j;
150
151 for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
152 const struct xpcs_compat *compat = &id->compat[i];
153
154 for (j = 0; j < compat->num_interfaces; j++)
155 if (compat->interface[j] == interface)
156 return compat;
157 }
158
159 return NULL;
160 }
161
xpcs_get_an_mode(struct dw_xpcs * xpcs,phy_interface_t interface)162 int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
163 {
164 const struct xpcs_compat *compat;
165
166 compat = xpcs_find_compat(xpcs->id, interface);
167 if (!compat)
168 return -ENODEV;
169
170 return compat->an_mode;
171 }
172 EXPORT_SYMBOL_GPL(xpcs_get_an_mode);
173
__xpcs_linkmode_supported(const struct xpcs_compat * compat,enum ethtool_link_mode_bit_indices linkmode)174 static bool __xpcs_linkmode_supported(const struct xpcs_compat *compat,
175 enum ethtool_link_mode_bit_indices linkmode)
176 {
177 int i;
178
179 for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
180 if (compat->supported[i] == linkmode)
181 return true;
182
183 return false;
184 }
185
186 #define xpcs_linkmode_supported(compat, mode) \
187 __xpcs_linkmode_supported(compat, ETHTOOL_LINK_MODE_ ## mode ## _BIT)
188
xpcs_read(struct dw_xpcs * xpcs,int dev,u32 reg)189 int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg)
190 {
191 struct mii_bus *bus = xpcs->mdiodev->bus;
192 int addr = xpcs->mdiodev->addr;
193
194 return mdiobus_c45_read(bus, addr, dev, reg);
195 }
196
xpcs_write(struct dw_xpcs * xpcs,int dev,u32 reg,u16 val)197 int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
198 {
199 struct mii_bus *bus = xpcs->mdiodev->bus;
200 int addr = xpcs->mdiodev->addr;
201
202 return mdiobus_c45_write(bus, addr, dev, reg, val);
203 }
204
xpcs_modify_changed(struct dw_xpcs * xpcs,int dev,u32 reg,u16 mask,u16 set)205 static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
206 u16 mask, u16 set)
207 {
208 u32 reg_addr = mdiobus_c45_addr(dev, reg);
209
210 return mdiodev_modify_changed(xpcs->mdiodev, reg_addr, mask, set);
211 }
212
xpcs_read_vendor(struct dw_xpcs * xpcs,int dev,u32 reg)213 static int xpcs_read_vendor(struct dw_xpcs *xpcs, int dev, u32 reg)
214 {
215 return xpcs_read(xpcs, dev, DW_VENDOR | reg);
216 }
217
xpcs_write_vendor(struct dw_xpcs * xpcs,int dev,int reg,u16 val)218 static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg,
219 u16 val)
220 {
221 return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
222 }
223
xpcs_read_vpcs(struct dw_xpcs * xpcs,int reg)224 static int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg)
225 {
226 return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
227 }
228
xpcs_write_vpcs(struct dw_xpcs * xpcs,int reg,u16 val)229 static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
230 {
231 return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
232 }
233
xpcs_poll_reset(struct dw_xpcs * xpcs,int dev)234 static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
235 {
236 /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
237 unsigned int retries = 12;
238 int ret;
239
240 do {
241 msleep(50);
242 ret = xpcs_read(xpcs, dev, MDIO_CTRL1);
243 if (ret < 0)
244 return ret;
245 } while (ret & MDIO_CTRL1_RESET && --retries);
246
247 return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0;
248 }
249
xpcs_soft_reset(struct dw_xpcs * xpcs,const struct xpcs_compat * compat)250 static int xpcs_soft_reset(struct dw_xpcs *xpcs,
251 const struct xpcs_compat *compat)
252 {
253 int ret, dev;
254
255 switch (compat->an_mode) {
256 case DW_AN_C73:
257 dev = MDIO_MMD_PCS;
258 break;
259 case DW_AN_C37_SGMII:
260 case DW_2500BASEX:
261 case DW_AN_C37_1000BASEX:
262 dev = MDIO_MMD_VEND2;
263 break;
264 default:
265 return -1;
266 }
267
268 ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET);
269 if (ret < 0)
270 return ret;
271
272 return xpcs_poll_reset(xpcs, dev);
273 }
274
275 #define xpcs_warn(__xpcs, __state, __args...) \
276 ({ \
277 if ((__state)->link) \
278 dev_warn(&(__xpcs)->mdiodev->dev, ##__args); \
279 })
280
xpcs_read_fault_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state)281 static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
282 struct phylink_link_state *state)
283 {
284 int ret;
285
286 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
287 if (ret < 0)
288 return ret;
289
290 if (ret & MDIO_STAT1_FAULT) {
291 xpcs_warn(xpcs, state, "Link fault condition detected!\n");
292 return -EFAULT;
293 }
294
295 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2);
296 if (ret < 0)
297 return ret;
298
299 if (ret & MDIO_STAT2_RXFAULT)
300 xpcs_warn(xpcs, state, "Receiver fault detected!\n");
301 if (ret & MDIO_STAT2_TXFAULT)
302 xpcs_warn(xpcs, state, "Transmitter fault detected!\n");
303
304 ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS);
305 if (ret < 0)
306 return ret;
307
308 if (ret & DW_RXFIFO_ERR) {
309 xpcs_warn(xpcs, state, "FIFO fault condition detected!\n");
310 return -EFAULT;
311 }
312
313 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
314 if (ret < 0)
315 return ret;
316
317 if (!(ret & MDIO_PCS_10GBRT_STAT1_BLKLK))
318 xpcs_warn(xpcs, state, "Link is not locked!\n");
319
320 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2);
321 if (ret < 0)
322 return ret;
323
324 if (ret & MDIO_PCS_10GBRT_STAT2_ERR) {
325 xpcs_warn(xpcs, state, "Link has errors!\n");
326 return -EFAULT;
327 }
328
329 return 0;
330 }
331
xpcs_read_link_c73(struct dw_xpcs * xpcs)332 static int xpcs_read_link_c73(struct dw_xpcs *xpcs)
333 {
334 bool link = true;
335 int ret;
336
337 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
338 if (ret < 0)
339 return ret;
340
341 if (!(ret & MDIO_STAT1_LSTATUS))
342 link = false;
343
344 return link;
345 }
346
xpcs_get_max_usxgmii_speed(const unsigned long * supported)347 static int xpcs_get_max_usxgmii_speed(const unsigned long *supported)
348 {
349 int max = SPEED_UNKNOWN;
350
351 if (phylink_test(supported, 1000baseKX_Full))
352 max = SPEED_1000;
353 if (phylink_test(supported, 2500baseX_Full))
354 max = SPEED_2500;
355 if (phylink_test(supported, 10000baseKX4_Full))
356 max = SPEED_10000;
357 if (phylink_test(supported, 10000baseKR_Full))
358 max = SPEED_10000;
359
360 return max;
361 }
362
xpcs_config_usxgmii(struct dw_xpcs * xpcs,int speed)363 static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
364 {
365 int ret, speed_sel;
366
367 switch (speed) {
368 case SPEED_10:
369 speed_sel = DW_USXGMII_10;
370 break;
371 case SPEED_100:
372 speed_sel = DW_USXGMII_100;
373 break;
374 case SPEED_1000:
375 speed_sel = DW_USXGMII_1000;
376 break;
377 case SPEED_2500:
378 speed_sel = DW_USXGMII_2500;
379 break;
380 case SPEED_5000:
381 speed_sel = DW_USXGMII_5000;
382 break;
383 case SPEED_10000:
384 speed_sel = DW_USXGMII_10000;
385 break;
386 default:
387 /* Nothing to do here */
388 return;
389 }
390
391 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
392 if (ret < 0)
393 goto out;
394
395 ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN);
396 if (ret < 0)
397 goto out;
398
399 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
400 if (ret < 0)
401 goto out;
402
403 ret &= ~DW_USXGMII_SS_MASK;
404 ret |= speed_sel | DW_USXGMII_FULL;
405
406 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
407 if (ret < 0)
408 goto out;
409
410 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
411 if (ret < 0)
412 goto out;
413
414 ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST);
415 if (ret < 0)
416 goto out;
417
418 return;
419
420 out:
421 pr_err("%s: XPCS access returned %pe\n", __func__, ERR_PTR(ret));
422 }
423
_xpcs_config_aneg_c73(struct dw_xpcs * xpcs,const struct xpcs_compat * compat)424 static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
425 const struct xpcs_compat *compat)
426 {
427 int ret, adv;
428
429 /* By default, in USXGMII mode XPCS operates at 10G baud and
430 * replicates data to achieve lower speeds. Hereby, in this
431 * default configuration we need to advertise all supported
432 * modes and not only the ones we want to use.
433 */
434
435 /* SR_AN_ADV3 */
436 adv = 0;
437 if (xpcs_linkmode_supported(compat, 2500baseX_Full))
438 adv |= DW_C73_2500KX;
439
440 /* TODO: 5000baseKR */
441
442 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv);
443 if (ret < 0)
444 return ret;
445
446 /* SR_AN_ADV2 */
447 adv = 0;
448 if (xpcs_linkmode_supported(compat, 1000baseKX_Full))
449 adv |= DW_C73_1000KX;
450 if (xpcs_linkmode_supported(compat, 10000baseKX4_Full))
451 adv |= DW_C73_10000KX4;
452 if (xpcs_linkmode_supported(compat, 10000baseKR_Full))
453 adv |= DW_C73_10000KR;
454
455 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv);
456 if (ret < 0)
457 return ret;
458
459 /* SR_AN_ADV1 */
460 adv = DW_C73_AN_ADV_SF;
461 if (xpcs_linkmode_supported(compat, Pause))
462 adv |= DW_C73_PAUSE;
463 if (xpcs_linkmode_supported(compat, Asym_Pause))
464 adv |= DW_C73_ASYM_PAUSE;
465
466 return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv);
467 }
468
xpcs_config_aneg_c73(struct dw_xpcs * xpcs,const struct xpcs_compat * compat)469 static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
470 const struct xpcs_compat *compat)
471 {
472 int ret;
473
474 ret = _xpcs_config_aneg_c73(xpcs, compat);
475 if (ret < 0)
476 return ret;
477
478 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1);
479 if (ret < 0)
480 return ret;
481
482 ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
483
484 return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret);
485 }
486
xpcs_aneg_done_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state,const struct xpcs_compat * compat)487 static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
488 struct phylink_link_state *state,
489 const struct xpcs_compat *compat)
490 {
491 int ret;
492
493 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
494 if (ret < 0)
495 return ret;
496
497 if (ret & MDIO_AN_STAT1_COMPLETE) {
498 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
499 if (ret < 0)
500 return ret;
501
502 /* Check if Aneg outcome is valid */
503 if (!(ret & DW_C73_AN_ADV_SF)) {
504 xpcs_config_aneg_c73(xpcs, compat);
505 return 0;
506 }
507
508 return 1;
509 }
510
511 return 0;
512 }
513
xpcs_read_lpa_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state)514 static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
515 struct phylink_link_state *state)
516 {
517 int ret;
518
519 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
520 if (ret < 0)
521 return ret;
522
523 if (!(ret & MDIO_AN_STAT1_LPABLE)) {
524 phylink_clear(state->lp_advertising, Autoneg);
525 return 0;
526 }
527
528 phylink_set(state->lp_advertising, Autoneg);
529
530 /* Clause 73 outcome */
531 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3);
532 if (ret < 0)
533 return ret;
534
535 if (ret & DW_C73_2500KX)
536 phylink_set(state->lp_advertising, 2500baseX_Full);
537
538 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2);
539 if (ret < 0)
540 return ret;
541
542 if (ret & DW_C73_1000KX)
543 phylink_set(state->lp_advertising, 1000baseKX_Full);
544 if (ret & DW_C73_10000KX4)
545 phylink_set(state->lp_advertising, 10000baseKX4_Full);
546 if (ret & DW_C73_10000KR)
547 phylink_set(state->lp_advertising, 10000baseKR_Full);
548
549 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
550 if (ret < 0)
551 return ret;
552
553 if (ret & DW_C73_PAUSE)
554 phylink_set(state->lp_advertising, Pause);
555 if (ret & DW_C73_ASYM_PAUSE)
556 phylink_set(state->lp_advertising, Asym_Pause);
557
558 linkmode_and(state->lp_advertising, state->lp_advertising,
559 state->advertising);
560 return 0;
561 }
562
xpcs_resolve_lpa_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state)563 static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
564 struct phylink_link_state *state)
565 {
566 int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising);
567
568 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
569 state->speed = max_speed;
570 state->duplex = DUPLEX_FULL;
571 }
572
xpcs_get_max_xlgmii_speed(struct dw_xpcs * xpcs,struct phylink_link_state * state)573 static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
574 struct phylink_link_state *state)
575 {
576 unsigned long *adv = state->advertising;
577 int speed = SPEED_UNKNOWN;
578 int bit;
579
580 for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) {
581 int new_speed = SPEED_UNKNOWN;
582
583 switch (bit) {
584 case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
585 case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
586 case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
587 new_speed = SPEED_25000;
588 break;
589 case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
590 case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
591 case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
592 case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
593 new_speed = SPEED_40000;
594 break;
595 case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT:
596 case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT:
597 case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT:
598 case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
599 case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
600 case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
601 case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
602 case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT:
603 new_speed = SPEED_50000;
604 break;
605 case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
606 case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
607 case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
608 case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
609 case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT:
610 case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT:
611 case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT:
612 case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT:
613 case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT:
614 new_speed = SPEED_100000;
615 break;
616 default:
617 continue;
618 }
619
620 if (new_speed > speed)
621 speed = new_speed;
622 }
623
624 return speed;
625 }
626
xpcs_resolve_pma(struct dw_xpcs * xpcs,struct phylink_link_state * state)627 static void xpcs_resolve_pma(struct dw_xpcs *xpcs,
628 struct phylink_link_state *state)
629 {
630 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
631 state->duplex = DUPLEX_FULL;
632
633 switch (state->interface) {
634 case PHY_INTERFACE_MODE_10GKR:
635 state->speed = SPEED_10000;
636 break;
637 case PHY_INTERFACE_MODE_XLGMII:
638 state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
639 break;
640 default:
641 state->speed = SPEED_UNKNOWN;
642 break;
643 }
644 }
645
xpcs_validate(struct phylink_pcs * pcs,unsigned long * supported,const struct phylink_link_state * state)646 static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
647 const struct phylink_link_state *state)
648 {
649 __ETHTOOL_DECLARE_LINK_MODE_MASK(xpcs_supported) = { 0, };
650 const struct xpcs_compat *compat;
651 struct dw_xpcs *xpcs;
652 int i;
653
654 xpcs = phylink_pcs_to_xpcs(pcs);
655 compat = xpcs_find_compat(xpcs->id, state->interface);
656
657 /* Populate the supported link modes for this PHY interface type.
658 * FIXME: what about the port modes and autoneg bit? This masks
659 * all those away.
660 */
661 if (compat)
662 for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
663 set_bit(compat->supported[i], xpcs_supported);
664
665 linkmode_and(supported, supported, xpcs_supported);
666
667 return 0;
668 }
669
xpcs_get_interfaces(struct dw_xpcs * xpcs,unsigned long * interfaces)670 void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
671 {
672 int i, j;
673
674 for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
675 const struct xpcs_compat *compat = &xpcs->id->compat[i];
676
677 for (j = 0; j < compat->num_interfaces; j++)
678 if (compat->interface[j] < PHY_INTERFACE_MODE_MAX)
679 __set_bit(compat->interface[j], interfaces);
680 }
681 }
682 EXPORT_SYMBOL_GPL(xpcs_get_interfaces);
683
xpcs_config_eee(struct dw_xpcs * xpcs,int mult_fact_100ns,int enable)684 int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
685 {
686 int ret;
687
688 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0);
689 if (ret < 0)
690 return ret;
691
692 if (enable) {
693 /* Enable EEE */
694 ret = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
695 DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
696 DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
697 mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT;
698 } else {
699 ret &= ~(DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
700 DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
701 DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
702 DW_VR_MII_EEE_MULT_FACT_100NS);
703 }
704
705 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret);
706 if (ret < 0)
707 return ret;
708
709 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1);
710 if (ret < 0)
711 return ret;
712
713 if (enable)
714 ret |= DW_VR_MII_EEE_TRN_LPI;
715 else
716 ret &= ~DW_VR_MII_EEE_TRN_LPI;
717
718 return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret);
719 }
720 EXPORT_SYMBOL_GPL(xpcs_config_eee);
721
xpcs_config_aneg_c37_sgmii(struct dw_xpcs * xpcs,unsigned int mode)722 static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
723 {
724 int ret, mdio_ctrl;
725
726 /* For AN for C37 SGMII mode, the settings are :-
727 * 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case
728 it is already enabled)
729 * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 10b (SGMII AN)
730 * 3) VR_MII_AN_CTRL Bit(3) [TX_CONFIG] = 0b (MAC side SGMII)
731 * DW xPCS used with DW EQoS MAC is always MAC side SGMII.
732 * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic
733 * speed/duplex mode change by HW after SGMII AN complete)
734 * 5) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 1b (Enable SGMII AN)
735 *
736 * Note: Since it is MAC side SGMII, there is no need to set
737 * SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config from
738 * PHY about the link state change after C28 AN is completed
739 * between PHY and Link Partner. There is also no need to
740 * trigger AN restart for MAC-side SGMII.
741 */
742 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
743 if (mdio_ctrl < 0)
744 return mdio_ctrl;
745
746 if (mdio_ctrl & AN_CL37_EN) {
747 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
748 mdio_ctrl & ~AN_CL37_EN);
749 if (ret < 0)
750 return ret;
751 }
752
753 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
754 if (ret < 0)
755 return ret;
756
757 ret &= ~(DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK);
758 ret |= (DW_VR_MII_PCS_MODE_C37_SGMII <<
759 DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT &
760 DW_VR_MII_PCS_MODE_MASK);
761 ret |= (DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII <<
762 DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT &
763 DW_VR_MII_TX_CONFIG_MASK);
764 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
765 if (ret < 0)
766 return ret;
767
768 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
769 if (ret < 0)
770 return ret;
771
772 if (phylink_autoneg_inband(mode))
773 ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
774 else
775 ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
776
777 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
778 if (ret < 0)
779 return ret;
780
781 if (phylink_autoneg_inband(mode))
782 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
783 mdio_ctrl | AN_CL37_EN);
784
785 return ret;
786 }
787
xpcs_config_aneg_c37_1000basex(struct dw_xpcs * xpcs,unsigned int mode,const unsigned long * advertising)788 static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
789 const unsigned long *advertising)
790 {
791 phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
792 int ret, mdio_ctrl, adv;
793 bool changed = 0;
794
795 /* According to Chap 7.12, to set 1000BASE-X C37 AN, AN must
796 * be disabled first:-
797 * 1) VR_MII_MMD_CTRL Bit(12)[AN_ENABLE] = 0b
798 * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37)
799 */
800 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
801 if (mdio_ctrl < 0)
802 return mdio_ctrl;
803
804 if (mdio_ctrl & AN_CL37_EN) {
805 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
806 mdio_ctrl & ~AN_CL37_EN);
807 if (ret < 0)
808 return ret;
809 }
810
811 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
812 if (ret < 0)
813 return ret;
814
815 ret &= ~DW_VR_MII_PCS_MODE_MASK;
816 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
817 if (ret < 0)
818 return ret;
819
820 /* Check for advertising changes and update the C45 MII ADV
821 * register accordingly.
822 */
823 adv = phylink_mii_c22_pcs_encode_advertisement(interface,
824 advertising);
825 if (adv >= 0) {
826 ret = xpcs_modify_changed(xpcs, MDIO_MMD_VEND2,
827 MII_ADVERTISE, 0xffff, adv);
828 if (ret < 0)
829 return ret;
830
831 changed = ret;
832 }
833
834 /* Clear CL37 AN complete status */
835 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
836 if (ret < 0)
837 return ret;
838
839 if (phylink_autoneg_inband(mode) &&
840 linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
841 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
842 mdio_ctrl | AN_CL37_EN);
843 if (ret < 0)
844 return ret;
845 }
846
847 return changed;
848 }
849
xpcs_config_2500basex(struct dw_xpcs * xpcs)850 static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
851 {
852 int ret;
853
854 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
855 if (ret < 0)
856 return ret;
857 ret |= DW_VR_MII_DIG_CTRL1_2G5_EN;
858 ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
859 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
860 if (ret < 0)
861 return ret;
862
863 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
864 if (ret < 0)
865 return ret;
866 ret &= ~AN_CL37_EN;
867 ret |= SGMII_SPEED_SS6;
868 ret &= ~SGMII_SPEED_SS13;
869 return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, ret);
870 }
871
xpcs_do_config(struct dw_xpcs * xpcs,phy_interface_t interface,unsigned int mode,const unsigned long * advertising)872 int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
873 unsigned int mode, const unsigned long *advertising)
874 {
875 const struct xpcs_compat *compat;
876 int ret;
877
878 compat = xpcs_find_compat(xpcs->id, interface);
879 if (!compat)
880 return -ENODEV;
881
882 switch (compat->an_mode) {
883 case DW_AN_C73:
884 if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
885 ret = xpcs_config_aneg_c73(xpcs, compat);
886 if (ret)
887 return ret;
888 }
889 break;
890 case DW_AN_C37_SGMII:
891 ret = xpcs_config_aneg_c37_sgmii(xpcs, mode);
892 if (ret)
893 return ret;
894 break;
895 case DW_AN_C37_1000BASEX:
896 ret = xpcs_config_aneg_c37_1000basex(xpcs, mode,
897 advertising);
898 if (ret)
899 return ret;
900 break;
901 case DW_2500BASEX:
902 ret = xpcs_config_2500basex(xpcs);
903 if (ret)
904 return ret;
905 break;
906 default:
907 return -1;
908 }
909
910 if (compat->pma_config) {
911 ret = compat->pma_config(xpcs);
912 if (ret)
913 return ret;
914 }
915
916 return 0;
917 }
918 EXPORT_SYMBOL_GPL(xpcs_do_config);
919
xpcs_config(struct phylink_pcs * pcs,unsigned int mode,phy_interface_t interface,const unsigned long * advertising,bool permit_pause_to_mac)920 static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode,
921 phy_interface_t interface,
922 const unsigned long *advertising,
923 bool permit_pause_to_mac)
924 {
925 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
926
927 return xpcs_do_config(xpcs, interface, mode, advertising);
928 }
929
xpcs_get_state_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state,const struct xpcs_compat * compat)930 static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
931 struct phylink_link_state *state,
932 const struct xpcs_compat *compat)
933 {
934 int ret;
935
936 /* Link needs to be read first ... */
937 state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0;
938
939 /* ... and then we check the faults. */
940 ret = xpcs_read_fault_c73(xpcs, state);
941 if (ret) {
942 ret = xpcs_soft_reset(xpcs, compat);
943 if (ret)
944 return ret;
945
946 state->link = 0;
947
948 return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL);
949 }
950
951 if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) {
952 state->an_complete = true;
953 xpcs_read_lpa_c73(xpcs, state);
954 xpcs_resolve_lpa_c73(xpcs, state);
955 } else if (state->an_enabled) {
956 state->link = 0;
957 } else if (state->link) {
958 xpcs_resolve_pma(xpcs, state);
959 }
960
961 return 0;
962 }
963
xpcs_get_state_c37_sgmii(struct dw_xpcs * xpcs,struct phylink_link_state * state)964 static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
965 struct phylink_link_state *state)
966 {
967 int ret;
968
969 /* Reset link_state */
970 state->link = false;
971 state->speed = SPEED_UNKNOWN;
972 state->duplex = DUPLEX_UNKNOWN;
973 state->pause = 0;
974
975 /* For C37 SGMII mode, we check DW_VR_MII_AN_INTR_STS for link
976 * status, speed and duplex.
977 */
978 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS);
979 if (ret < 0)
980 return ret;
981
982 if (ret & DW_VR_MII_C37_ANSGM_SP_LNKSTS) {
983 int speed_value;
984
985 state->link = true;
986
987 speed_value = (ret & DW_VR_MII_AN_STS_C37_ANSGM_SP) >>
988 DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT;
989 if (speed_value == DW_VR_MII_C37_ANSGM_SP_1000)
990 state->speed = SPEED_1000;
991 else if (speed_value == DW_VR_MII_C37_ANSGM_SP_100)
992 state->speed = SPEED_100;
993 else
994 state->speed = SPEED_10;
995
996 if (ret & DW_VR_MII_AN_STS_C37_ANSGM_FD)
997 state->duplex = DUPLEX_FULL;
998 else
999 state->duplex = DUPLEX_HALF;
1000 }
1001
1002 return 0;
1003 }
1004
xpcs_get_state_c37_1000basex(struct dw_xpcs * xpcs,struct phylink_link_state * state)1005 static int xpcs_get_state_c37_1000basex(struct dw_xpcs *xpcs,
1006 struct phylink_link_state *state)
1007 {
1008 int lpa, bmsr;
1009
1010 if (state->an_enabled) {
1011 /* Reset link state */
1012 state->link = false;
1013
1014 lpa = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_LPA);
1015 if (lpa < 0 || lpa & LPA_RFAULT)
1016 return lpa;
1017
1018 bmsr = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
1019 if (bmsr < 0)
1020 return bmsr;
1021
1022 phylink_mii_c22_pcs_decode_state(state, bmsr, lpa);
1023 }
1024
1025 return 0;
1026 }
1027
xpcs_get_state(struct phylink_pcs * pcs,struct phylink_link_state * state)1028 static void xpcs_get_state(struct phylink_pcs *pcs,
1029 struct phylink_link_state *state)
1030 {
1031 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1032 const struct xpcs_compat *compat;
1033 int ret;
1034
1035 compat = xpcs_find_compat(xpcs->id, state->interface);
1036 if (!compat)
1037 return;
1038
1039 switch (compat->an_mode) {
1040 case DW_AN_C73:
1041 ret = xpcs_get_state_c73(xpcs, state, compat);
1042 if (ret) {
1043 pr_err("xpcs_get_state_c73 returned %pe\n",
1044 ERR_PTR(ret));
1045 return;
1046 }
1047 break;
1048 case DW_AN_C37_SGMII:
1049 ret = xpcs_get_state_c37_sgmii(xpcs, state);
1050 if (ret) {
1051 pr_err("xpcs_get_state_c37_sgmii returned %pe\n",
1052 ERR_PTR(ret));
1053 }
1054 break;
1055 case DW_AN_C37_1000BASEX:
1056 ret = xpcs_get_state_c37_1000basex(xpcs, state);
1057 if (ret) {
1058 pr_err("xpcs_get_state_c37_1000basex returned %pe\n",
1059 ERR_PTR(ret));
1060 }
1061 break;
1062 default:
1063 return;
1064 }
1065 }
1066
xpcs_link_up_sgmii(struct dw_xpcs * xpcs,unsigned int mode,int speed,int duplex)1067 static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
1068 int speed, int duplex)
1069 {
1070 int val, ret;
1071
1072 if (phylink_autoneg_inband(mode))
1073 return;
1074
1075 val = mii_bmcr_encode_fixed(speed, duplex);
1076 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
1077 if (ret)
1078 pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
1079 }
1080
xpcs_link_up_1000basex(struct dw_xpcs * xpcs,unsigned int mode,int speed,int duplex)1081 static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
1082 int speed, int duplex)
1083 {
1084 int val, ret;
1085
1086 if (phylink_autoneg_inband(mode))
1087 return;
1088
1089 switch (speed) {
1090 case SPEED_1000:
1091 val = BMCR_SPEED1000;
1092 break;
1093 case SPEED_100:
1094 case SPEED_10:
1095 default:
1096 pr_err("%s: speed = %d\n", __func__, speed);
1097 return;
1098 }
1099
1100 if (duplex == DUPLEX_FULL)
1101 val |= BMCR_FULLDPLX;
1102 else
1103 pr_err("%s: half duplex not supported\n", __func__);
1104
1105 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
1106 if (ret)
1107 pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
1108 }
1109
xpcs_link_up(struct phylink_pcs * pcs,unsigned int mode,phy_interface_t interface,int speed,int duplex)1110 void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
1111 phy_interface_t interface, int speed, int duplex)
1112 {
1113 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1114
1115 if (interface == PHY_INTERFACE_MODE_USXGMII)
1116 return xpcs_config_usxgmii(xpcs, speed);
1117 if (interface == PHY_INTERFACE_MODE_SGMII)
1118 return xpcs_link_up_sgmii(xpcs, mode, speed, duplex);
1119 if (interface == PHY_INTERFACE_MODE_1000BASEX)
1120 return xpcs_link_up_1000basex(xpcs, mode, speed, duplex);
1121 }
1122 EXPORT_SYMBOL_GPL(xpcs_link_up);
1123
xpcs_an_restart(struct phylink_pcs * pcs)1124 static void xpcs_an_restart(struct phylink_pcs *pcs)
1125 {
1126 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1127 int ret;
1128
1129 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
1130 if (ret >= 0) {
1131 ret |= BMCR_ANRESTART;
1132 xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
1133 }
1134 }
1135
xpcs_get_id(struct dw_xpcs * xpcs)1136 static u32 xpcs_get_id(struct dw_xpcs *xpcs)
1137 {
1138 int ret;
1139 u32 id;
1140
1141 /* First, search C73 PCS using PCS MMD */
1142 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1);
1143 if (ret < 0)
1144 return 0xffffffff;
1145
1146 id = ret << 16;
1147
1148 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2);
1149 if (ret < 0)
1150 return 0xffffffff;
1151
1152 /* If Device IDs are not all zeros or all ones,
1153 * we found C73 AN-type device
1154 */
1155 if ((id | ret) && (id | ret) != 0xffffffff)
1156 return id | ret;
1157
1158 /* Next, search C37 PCS using Vendor-Specific MII MMD */
1159 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID1);
1160 if (ret < 0)
1161 return 0xffffffff;
1162
1163 id = ret << 16;
1164
1165 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID2);
1166 if (ret < 0)
1167 return 0xffffffff;
1168
1169 /* If Device IDs are not all zeros, we found C37 AN-type device */
1170 if (id | ret)
1171 return id | ret;
1172
1173 return 0xffffffff;
1174 }
1175
1176 static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
1177 [DW_XPCS_USXGMII] = {
1178 .supported = xpcs_usxgmii_features,
1179 .interface = xpcs_usxgmii_interfaces,
1180 .num_interfaces = ARRAY_SIZE(xpcs_usxgmii_interfaces),
1181 .an_mode = DW_AN_C73,
1182 },
1183 [DW_XPCS_10GKR] = {
1184 .supported = xpcs_10gkr_features,
1185 .interface = xpcs_10gkr_interfaces,
1186 .num_interfaces = ARRAY_SIZE(xpcs_10gkr_interfaces),
1187 .an_mode = DW_AN_C73,
1188 },
1189 [DW_XPCS_XLGMII] = {
1190 .supported = xpcs_xlgmii_features,
1191 .interface = xpcs_xlgmii_interfaces,
1192 .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
1193 .an_mode = DW_AN_C73,
1194 },
1195 [DW_XPCS_SGMII] = {
1196 .supported = xpcs_sgmii_features,
1197 .interface = xpcs_sgmii_interfaces,
1198 .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
1199 .an_mode = DW_AN_C37_SGMII,
1200 },
1201 [DW_XPCS_1000BASEX] = {
1202 .supported = xpcs_1000basex_features,
1203 .interface = xpcs_1000basex_interfaces,
1204 .num_interfaces = ARRAY_SIZE(xpcs_1000basex_interfaces),
1205 .an_mode = DW_AN_C37_1000BASEX,
1206 },
1207 [DW_XPCS_2500BASEX] = {
1208 .supported = xpcs_2500basex_features,
1209 .interface = xpcs_2500basex_interfaces,
1210 .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features),
1211 .an_mode = DW_2500BASEX,
1212 },
1213 };
1214
1215 static const struct xpcs_compat nxp_sja1105_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
1216 [DW_XPCS_SGMII] = {
1217 .supported = xpcs_sgmii_features,
1218 .interface = xpcs_sgmii_interfaces,
1219 .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
1220 .an_mode = DW_AN_C37_SGMII,
1221 .pma_config = nxp_sja1105_sgmii_pma_config,
1222 },
1223 };
1224
1225 static const struct xpcs_compat nxp_sja1110_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
1226 [DW_XPCS_SGMII] = {
1227 .supported = xpcs_sgmii_features,
1228 .interface = xpcs_sgmii_interfaces,
1229 .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
1230 .an_mode = DW_AN_C37_SGMII,
1231 .pma_config = nxp_sja1110_sgmii_pma_config,
1232 },
1233 [DW_XPCS_2500BASEX] = {
1234 .supported = xpcs_2500basex_features,
1235 .interface = xpcs_2500basex_interfaces,
1236 .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
1237 .an_mode = DW_2500BASEX,
1238 .pma_config = nxp_sja1110_2500basex_pma_config,
1239 },
1240 };
1241
1242 static const struct xpcs_id xpcs_id_list[] = {
1243 {
1244 .id = SYNOPSYS_XPCS_ID,
1245 .mask = SYNOPSYS_XPCS_MASK,
1246 .compat = synopsys_xpcs_compat,
1247 }, {
1248 .id = NXP_SJA1105_XPCS_ID,
1249 .mask = SYNOPSYS_XPCS_MASK,
1250 .compat = nxp_sja1105_xpcs_compat,
1251 }, {
1252 .id = NXP_SJA1110_XPCS_ID,
1253 .mask = SYNOPSYS_XPCS_MASK,
1254 .compat = nxp_sja1110_xpcs_compat,
1255 },
1256 };
1257
1258 static const struct phylink_pcs_ops xpcs_phylink_ops = {
1259 .pcs_validate = xpcs_validate,
1260 .pcs_config = xpcs_config,
1261 .pcs_get_state = xpcs_get_state,
1262 .pcs_an_restart = xpcs_an_restart,
1263 .pcs_link_up = xpcs_link_up,
1264 };
1265
xpcs_create(struct mdio_device * mdiodev,phy_interface_t interface)1266 struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
1267 phy_interface_t interface)
1268 {
1269 struct dw_xpcs *xpcs;
1270 u32 xpcs_id;
1271 int i, ret;
1272
1273 xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
1274 if (!xpcs)
1275 return ERR_PTR(-ENOMEM);
1276
1277 xpcs->mdiodev = mdiodev;
1278
1279 xpcs_id = xpcs_get_id(xpcs);
1280
1281 for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
1282 const struct xpcs_id *entry = &xpcs_id_list[i];
1283 const struct xpcs_compat *compat;
1284
1285 if ((xpcs_id & entry->mask) != entry->id)
1286 continue;
1287
1288 xpcs->id = entry;
1289
1290 compat = xpcs_find_compat(entry, interface);
1291 if (!compat) {
1292 ret = -ENODEV;
1293 goto out;
1294 }
1295
1296 xpcs->pcs.ops = &xpcs_phylink_ops;
1297 xpcs->pcs.poll = true;
1298
1299 ret = xpcs_soft_reset(xpcs, compat);
1300 if (ret)
1301 goto out;
1302
1303 return xpcs;
1304 }
1305
1306 ret = -ENODEV;
1307
1308 out:
1309 kfree(xpcs);
1310
1311 return ERR_PTR(ret);
1312 }
1313 EXPORT_SYMBOL_GPL(xpcs_create);
1314
xpcs_destroy(struct dw_xpcs * xpcs)1315 void xpcs_destroy(struct dw_xpcs *xpcs)
1316 {
1317 kfree(xpcs);
1318 }
1319 EXPORT_SYMBOL_GPL(xpcs_destroy);
1320
1321 MODULE_LICENSE("GPL v2");
1322