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