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/clk.h>
10 #include <linux/delay.h>
11 #include <linux/pcs/pcs-xpcs.h>
12 #include <linux/mdio.h>
13 #include <linux/phy.h>
14 #include <linux/phylink.h>
15 #include <linux/property.h>
16
17 #include "pcs-xpcs.h"
18
19 #define phylink_pcs_to_xpcs(pl_pcs) \
20 container_of((pl_pcs), struct dw_xpcs, pcs)
21
22 static const int xpcs_usxgmii_features[] = {
23 ETHTOOL_LINK_MODE_Pause_BIT,
24 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
25 ETHTOOL_LINK_MODE_Autoneg_BIT,
26 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
27 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
28 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
29 ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
30 __ETHTOOL_LINK_MODE_MASK_NBITS,
31 };
32
33 static const int xpcs_10gkr_features[] = {
34 ETHTOOL_LINK_MODE_Pause_BIT,
35 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
36 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
37 __ETHTOOL_LINK_MODE_MASK_NBITS,
38 };
39
40 static const int xpcs_25gbaser_features[] = {
41 ETHTOOL_LINK_MODE_MII_BIT,
42 ETHTOOL_LINK_MODE_Pause_BIT,
43 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
44 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
45 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
46 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
47 __ETHTOOL_LINK_MODE_MASK_NBITS,
48 };
49
50 static const int xpcs_xlgmii_features[] = {
51 ETHTOOL_LINK_MODE_Pause_BIT,
52 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
53 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
54 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
55 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
56 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
57 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
58 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
59 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
60 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
61 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
62 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
63 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
64 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
65 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
66 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
67 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
68 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
69 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
70 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
71 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
72 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
73 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
74 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
75 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
76 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
77 __ETHTOOL_LINK_MODE_MASK_NBITS,
78 };
79
80 static const int xpcs_50gbaser_features[] = {
81 ETHTOOL_LINK_MODE_MII_BIT,
82 ETHTOOL_LINK_MODE_Pause_BIT,
83 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
84 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
85 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
86 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
87 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
88 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
89 __ETHTOOL_LINK_MODE_MASK_NBITS,
90 };
91
92 static const int xpcs_50gbaser2_features[] = {
93 ETHTOOL_LINK_MODE_MII_BIT,
94 ETHTOOL_LINK_MODE_Pause_BIT,
95 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
96 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
97 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
98 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
99 __ETHTOOL_LINK_MODE_MASK_NBITS,
100 };
101
102 static const int xpcs_100gbasep_features[] = {
103 ETHTOOL_LINK_MODE_MII_BIT,
104 ETHTOOL_LINK_MODE_Pause_BIT,
105 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
106 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
107 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
108 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
109 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
110 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
111 __ETHTOOL_LINK_MODE_MASK_NBITS,
112 };
113
114 static const int xpcs_10gbaser_features[] = {
115 ETHTOOL_LINK_MODE_Pause_BIT,
116 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
117 ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
118 ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
119 ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
120 ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
121 __ETHTOOL_LINK_MODE_MASK_NBITS,
122 };
123
124 static const int xpcs_sgmii_features[] = {
125 ETHTOOL_LINK_MODE_Pause_BIT,
126 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
127 ETHTOOL_LINK_MODE_Autoneg_BIT,
128 ETHTOOL_LINK_MODE_10baseT_Half_BIT,
129 ETHTOOL_LINK_MODE_10baseT_Full_BIT,
130 ETHTOOL_LINK_MODE_100baseT_Half_BIT,
131 ETHTOOL_LINK_MODE_100baseT_Full_BIT,
132 ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
133 ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
134 __ETHTOOL_LINK_MODE_MASK_NBITS,
135 };
136
137 static const int xpcs_1000basex_features[] = {
138 ETHTOOL_LINK_MODE_Pause_BIT,
139 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
140 ETHTOOL_LINK_MODE_Autoneg_BIT,
141 ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
142 __ETHTOOL_LINK_MODE_MASK_NBITS,
143 };
144
145 static const int xpcs_2500basex_features[] = {
146 ETHTOOL_LINK_MODE_Pause_BIT,
147 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
148 ETHTOOL_LINK_MODE_Autoneg_BIT,
149 ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
150 ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
151 __ETHTOOL_LINK_MODE_MASK_NBITS,
152 };
153
154 struct dw_xpcs_compat {
155 phy_interface_t interface;
156 const int *supported;
157 int an_mode;
158 int (*pma_config)(struct dw_xpcs *xpcs);
159 };
160
161 struct dw_xpcs_desc {
162 u32 id;
163 u32 mask;
164 const struct dw_xpcs_compat *compat;
165 };
166
167 static const struct dw_xpcs_compat *
xpcs_find_compat(struct dw_xpcs * xpcs,phy_interface_t interface)168 xpcs_find_compat(struct dw_xpcs *xpcs, phy_interface_t interface)
169 {
170 const struct dw_xpcs_compat *compat;
171
172 for (compat = xpcs->desc->compat; compat->supported; compat++)
173 if (compat->interface == interface)
174 return compat;
175
176 return NULL;
177 }
178
xpcs_to_phylink_pcs(struct dw_xpcs * xpcs)179 struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs)
180 {
181 return &xpcs->pcs;
182 }
183 EXPORT_SYMBOL_GPL(xpcs_to_phylink_pcs);
184
xpcs_get_an_mode(struct dw_xpcs * xpcs,phy_interface_t interface)185 int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
186 {
187 const struct dw_xpcs_compat *compat;
188
189 compat = xpcs_find_compat(xpcs, interface);
190 if (!compat)
191 return -ENODEV;
192
193 return compat->an_mode;
194 }
195 EXPORT_SYMBOL_GPL(xpcs_get_an_mode);
196
__xpcs_linkmode_supported(const struct dw_xpcs_compat * compat,enum ethtool_link_mode_bit_indices linkmode)197 static bool __xpcs_linkmode_supported(const struct dw_xpcs_compat *compat,
198 enum ethtool_link_mode_bit_indices linkmode)
199 {
200 int i;
201
202 for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
203 if (compat->supported[i] == linkmode)
204 return true;
205
206 return false;
207 }
208
209 #define xpcs_linkmode_supported(compat, mode) \
210 __xpcs_linkmode_supported(compat, ETHTOOL_LINK_MODE_ ## mode ## _BIT)
211
xpcs_read(struct dw_xpcs * xpcs,int dev,u32 reg)212 int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg)
213 {
214 return mdiodev_c45_read(xpcs->mdiodev, dev, reg);
215 }
216
xpcs_write(struct dw_xpcs * xpcs,int dev,u32 reg,u16 val)217 int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
218 {
219 return mdiodev_c45_write(xpcs->mdiodev, dev, reg, val);
220 }
221
xpcs_modify(struct dw_xpcs * xpcs,int dev,u32 reg,u16 mask,u16 set)222 int xpcs_modify(struct dw_xpcs *xpcs, int dev, u32 reg, u16 mask, u16 set)
223 {
224 return mdiodev_c45_modify(xpcs->mdiodev, dev, reg, mask, set);
225 }
226
xpcs_modify_changed(struct dw_xpcs * xpcs,int dev,u32 reg,u16 mask,u16 set)227 static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
228 u16 mask, u16 set)
229 {
230 return mdiodev_c45_modify_changed(xpcs->mdiodev, dev, reg, mask, set);
231 }
232
xpcs_read_vendor(struct dw_xpcs * xpcs,int dev,u32 reg)233 static int xpcs_read_vendor(struct dw_xpcs *xpcs, int dev, u32 reg)
234 {
235 return xpcs_read(xpcs, dev, DW_VENDOR | reg);
236 }
237
xpcs_write_vendor(struct dw_xpcs * xpcs,int dev,int reg,u16 val)238 static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg,
239 u16 val)
240 {
241 return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
242 }
243
xpcs_modify_vendor(struct dw_xpcs * xpcs,int dev,int reg,u16 mask,u16 set)244 static int xpcs_modify_vendor(struct dw_xpcs *xpcs, int dev, int reg, u16 mask,
245 u16 set)
246 {
247 return xpcs_modify(xpcs, dev, DW_VENDOR | reg, mask, set);
248 }
249
xpcs_read_vpcs(struct dw_xpcs * xpcs,int reg)250 int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg)
251 {
252 return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
253 }
254
xpcs_write_vpcs(struct dw_xpcs * xpcs,int reg,u16 val)255 int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
256 {
257 return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
258 }
259
xpcs_modify_vpcs(struct dw_xpcs * xpcs,int reg,u16 mask,u16 val)260 static int xpcs_modify_vpcs(struct dw_xpcs *xpcs, int reg, u16 mask, u16 val)
261 {
262 return xpcs_modify_vendor(xpcs, MDIO_MMD_PCS, reg, mask, val);
263 }
264
xpcs_poll_reset(struct dw_xpcs * xpcs,int dev)265 static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
266 {
267 int ret, val;
268
269 ret = read_poll_timeout(xpcs_read, val,
270 val < 0 || !(val & BMCR_RESET),
271 50000, 600000, true, xpcs, dev, MII_BMCR);
272 if (val < 0)
273 ret = val;
274
275 return ret;
276 }
277
xpcs_soft_reset(struct dw_xpcs * xpcs,const struct dw_xpcs_compat * compat)278 static int xpcs_soft_reset(struct dw_xpcs *xpcs,
279 const struct dw_xpcs_compat *compat)
280 {
281 int ret, dev;
282
283 switch (compat->an_mode) {
284 case DW_AN_C73:
285 case DW_10GBASER:
286 dev = MDIO_MMD_PCS;
287 break;
288 case DW_AN_C37_SGMII:
289 case DW_2500BASEX:
290 case DW_AN_C37_1000BASEX:
291 dev = MDIO_MMD_VEND2;
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 ret = xpcs_write(xpcs, dev, MII_BMCR, BMCR_RESET);
298 if (ret < 0)
299 return ret;
300
301 return xpcs_poll_reset(xpcs, dev);
302 }
303
304 #define xpcs_warn(__xpcs, __state, __args...) \
305 ({ \
306 if ((__state)->link) \
307 dev_warn(&(__xpcs)->mdiodev->dev, ##__args); \
308 })
309
xpcs_read_fault_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state,u16 pcs_stat1)310 static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
311 struct phylink_link_state *state,
312 u16 pcs_stat1)
313 {
314 int ret;
315
316 if (pcs_stat1 & MDIO_STAT1_FAULT) {
317 xpcs_warn(xpcs, state, "Link fault condition detected!\n");
318 return -EFAULT;
319 }
320
321 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2);
322 if (ret < 0)
323 return ret;
324
325 if (ret & MDIO_STAT2_RXFAULT)
326 xpcs_warn(xpcs, state, "Receiver fault detected!\n");
327 if (ret & MDIO_STAT2_TXFAULT)
328 xpcs_warn(xpcs, state, "Transmitter fault detected!\n");
329
330 ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS);
331 if (ret < 0)
332 return ret;
333
334 if (ret & DW_RXFIFO_ERR) {
335 xpcs_warn(xpcs, state, "FIFO fault condition detected!\n");
336 return -EFAULT;
337 }
338
339 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
340 if (ret < 0)
341 return ret;
342
343 if (!(ret & MDIO_PCS_10GBRT_STAT1_BLKLK))
344 xpcs_warn(xpcs, state, "Link is not locked!\n");
345
346 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2);
347 if (ret < 0)
348 return ret;
349
350 if (ret & MDIO_PCS_10GBRT_STAT2_ERR) {
351 xpcs_warn(xpcs, state, "Link has errors!\n");
352 return -EFAULT;
353 }
354
355 return 0;
356 }
357
xpcs_link_up_usxgmii(struct dw_xpcs * xpcs,int speed)358 static void xpcs_link_up_usxgmii(struct dw_xpcs *xpcs, int speed)
359 {
360 int ret, speed_sel;
361
362 switch (speed) {
363 case SPEED_10:
364 speed_sel = DW_USXGMII_10;
365 break;
366 case SPEED_100:
367 speed_sel = DW_USXGMII_100;
368 break;
369 case SPEED_1000:
370 speed_sel = DW_USXGMII_1000;
371 break;
372 case SPEED_2500:
373 speed_sel = DW_USXGMII_2500;
374 break;
375 case SPEED_5000:
376 speed_sel = DW_USXGMII_5000;
377 break;
378 case SPEED_10000:
379 speed_sel = DW_USXGMII_10000;
380 break;
381 default:
382 /* Nothing to do here */
383 return;
384 }
385
386 ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_EN, DW_USXGMII_EN);
387 if (ret < 0)
388 goto out;
389
390 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, DW_USXGMII_SS_MASK,
391 speed_sel | DW_USXGMII_FULL);
392 if (ret < 0)
393 goto out;
394
395 ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_RST,
396 DW_USXGMII_RST);
397 if (ret < 0)
398 goto out;
399
400 return;
401
402 out:
403 dev_err(&xpcs->mdiodev->dev, "%s: XPCS access returned %pe\n",
404 __func__, ERR_PTR(ret));
405 }
406
_xpcs_config_aneg_c73(struct dw_xpcs * xpcs,const struct dw_xpcs_compat * compat)407 static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
408 const struct dw_xpcs_compat *compat)
409 {
410 int ret, adv;
411
412 /* By default, in USXGMII mode XPCS operates at 10G baud and
413 * replicates data to achieve lower speeds. Hereby, in this
414 * default configuration we need to advertise all supported
415 * modes and not only the ones we want to use.
416 */
417
418 /* SR_AN_ADV3 */
419 adv = 0;
420 if (xpcs_linkmode_supported(compat, 2500baseX_Full))
421 adv |= DW_C73_2500KX;
422
423 /* TODO: 5000baseKR */
424
425 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv);
426 if (ret < 0)
427 return ret;
428
429 /* SR_AN_ADV2 */
430 adv = 0;
431 if (xpcs_linkmode_supported(compat, 1000baseKX_Full))
432 adv |= DW_C73_1000KX;
433 if (xpcs_linkmode_supported(compat, 10000baseKX4_Full))
434 adv |= DW_C73_10000KX4;
435 if (xpcs_linkmode_supported(compat, 10000baseKR_Full))
436 adv |= DW_C73_10000KR;
437
438 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv);
439 if (ret < 0)
440 return ret;
441
442 /* SR_AN_ADV1 */
443 adv = DW_C73_AN_ADV_SF;
444 if (xpcs_linkmode_supported(compat, Pause))
445 adv |= DW_C73_PAUSE;
446 if (xpcs_linkmode_supported(compat, Asym_Pause))
447 adv |= DW_C73_ASYM_PAUSE;
448
449 return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv);
450 }
451
xpcs_config_aneg_c73(struct dw_xpcs * xpcs,const struct dw_xpcs_compat * compat)452 static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
453 const struct dw_xpcs_compat *compat)
454 {
455 int ret;
456
457 ret = _xpcs_config_aneg_c73(xpcs, compat);
458 if (ret < 0)
459 return ret;
460
461 return xpcs_modify(xpcs, MDIO_MMD_AN, MDIO_CTRL1,
462 MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART,
463 MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
464 }
465
xpcs_aneg_done_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state,const struct dw_xpcs_compat * compat,u16 an_stat1)466 static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
467 struct phylink_link_state *state,
468 const struct dw_xpcs_compat *compat, u16 an_stat1)
469 {
470 int ret;
471
472 if (an_stat1 & MDIO_AN_STAT1_COMPLETE) {
473 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA);
474 if (ret < 0)
475 return ret;
476
477 /* Check if Aneg outcome is valid */
478 if (!(ret & DW_C73_AN_ADV_SF)) {
479 xpcs_config_aneg_c73(xpcs, compat);
480 return 0;
481 }
482
483 return 1;
484 }
485
486 return 0;
487 }
488
xpcs_read_lpa_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state,u16 an_stat1)489 static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
490 struct phylink_link_state *state, u16 an_stat1)
491 {
492 u16 lpa[3];
493 int i, ret;
494
495 if (!(an_stat1 & MDIO_AN_STAT1_LPABLE)) {
496 phylink_clear(state->lp_advertising, Autoneg);
497 return 0;
498 }
499
500 phylink_set(state->lp_advertising, Autoneg);
501
502 /* Read Clause 73 link partner advertisement */
503 for (i = ARRAY_SIZE(lpa); --i >= 0; ) {
504 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i);
505 if (ret < 0)
506 return ret;
507
508 lpa[i] = ret;
509 }
510
511 mii_c73_mod_linkmode(state->lp_advertising, lpa);
512
513 return 0;
514 }
515
xpcs_get_max_xlgmii_speed(struct dw_xpcs * xpcs,struct phylink_link_state * state)516 static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
517 struct phylink_link_state *state)
518 {
519 unsigned long *adv = state->advertising;
520 int speed = SPEED_UNKNOWN;
521 int bit;
522
523 for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) {
524 int new_speed = SPEED_UNKNOWN;
525
526 switch (bit) {
527 case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
528 case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
529 case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
530 new_speed = SPEED_25000;
531 break;
532 case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
533 case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
534 case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
535 case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
536 new_speed = SPEED_40000;
537 break;
538 case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT:
539 case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT:
540 case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT:
541 case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
542 case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
543 case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
544 case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
545 case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT:
546 new_speed = SPEED_50000;
547 break;
548 case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
549 case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
550 case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
551 case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
552 case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT:
553 case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT:
554 case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT:
555 case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT:
556 case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT:
557 new_speed = SPEED_100000;
558 break;
559 default:
560 continue;
561 }
562
563 if (new_speed > speed)
564 speed = new_speed;
565 }
566
567 return speed;
568 }
569
xpcs_c45_read_pcs_speed(struct dw_xpcs * xpcs,struct phylink_link_state * state)570 static int xpcs_c45_read_pcs_speed(struct dw_xpcs *xpcs,
571 struct phylink_link_state *state)
572 {
573 int pcs_ctrl1;
574
575 pcs_ctrl1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL1);
576 if (pcs_ctrl1 < 0)
577 return pcs_ctrl1;
578
579 switch (pcs_ctrl1 & MDIO_CTRL1_SPEEDSEL) {
580 case MDIO_PCS_CTRL1_SPEED25G:
581 state->speed = SPEED_25000;
582 break;
583 case MDIO_PCS_CTRL1_SPEED50G:
584 state->speed = SPEED_50000;
585 break;
586 case MDIO_PCS_CTRL1_SPEED100G:
587 state->speed = SPEED_100000;
588 break;
589 default:
590 state->speed = SPEED_UNKNOWN;
591 break;
592 }
593
594 return 0;
595 }
596
xpcs_resolve_pma(struct dw_xpcs * xpcs,struct phylink_link_state * state)597 static int xpcs_resolve_pma(struct dw_xpcs *xpcs,
598 struct phylink_link_state *state)
599 {
600 int pmd_rxdet, err = 0;
601
602 /* The Meta Platforms FBNIC PMD will go into a training state for
603 * about 4 seconds when the link first comes up. During this time the
604 * PCS link will bounce. To avoid reporting link up too soon we include
605 * the PMD state provided by the driver.
606 */
607 if (xpcs->info.pma == MP_FBNIC_XPCS_PMA_100G_ID) {
608 pmd_rxdet = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_PMA_RXDET);
609 if (pmd_rxdet < 0) {
610 state->link = false;
611 return pmd_rxdet;
612 }
613
614 /* Verify Rx lanes are trained before reporting link up */
615 if (!(pmd_rxdet & MDIO_PMD_RXDET_GLOBAL)) {
616 state->link = false;
617 return 0;
618 }
619 }
620
621 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
622 state->duplex = DUPLEX_FULL;
623
624 switch (state->interface) {
625 case PHY_INTERFACE_MODE_10GKR:
626 state->speed = SPEED_10000;
627 break;
628 case PHY_INTERFACE_MODE_XLGMII:
629 state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
630 break;
631 case PHY_INTERFACE_MODE_100GBASEP:
632 case PHY_INTERFACE_MODE_LAUI:
633 case PHY_INTERFACE_MODE_50GBASER:
634 case PHY_INTERFACE_MODE_25GBASER:
635 err = xpcs_c45_read_pcs_speed(xpcs, state);
636 break;
637 default:
638 state->speed = SPEED_UNKNOWN;
639 break;
640 }
641
642 return err;
643 }
644
xpcs_validate(struct phylink_pcs * pcs,unsigned long * supported,const struct phylink_link_state * state)645 static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
646 const struct phylink_link_state *state)
647 {
648 __ETHTOOL_DECLARE_LINK_MODE_MASK(xpcs_supported) = { 0, };
649 const struct dw_xpcs_compat *compat;
650 struct dw_xpcs *xpcs;
651 int i;
652
653 xpcs = phylink_pcs_to_xpcs(pcs);
654 compat = xpcs_find_compat(xpcs, state->interface);
655 if (!compat)
656 return -EINVAL;
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 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_inband_caps(struct phylink_pcs * pcs,phy_interface_t interface)670 static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
671 phy_interface_t interface)
672 {
673 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
674 const struct dw_xpcs_compat *compat;
675
676 compat = xpcs_find_compat(xpcs, interface);
677 if (!compat)
678 return 0;
679
680 switch (compat->an_mode) {
681 case DW_AN_C73:
682 return LINK_INBAND_ENABLE;
683
684 case DW_AN_C37_SGMII:
685 case DW_AN_C37_1000BASEX:
686 return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
687
688 case DW_10GBASER:
689 case DW_2500BASEX:
690 return LINK_INBAND_DISABLE;
691
692 default:
693 return 0;
694 }
695 }
696
xpcs_get_interfaces(struct dw_xpcs * xpcs,unsigned long * interfaces)697 static void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
698 {
699 const struct dw_xpcs_compat *compat;
700
701 for (compat = xpcs->desc->compat; compat->supported; compat++)
702 __set_bit(compat->interface, interfaces);
703 }
704
xpcs_switch_interface_mode(struct dw_xpcs * xpcs,phy_interface_t interface)705 static int xpcs_switch_interface_mode(struct dw_xpcs *xpcs,
706 phy_interface_t interface)
707 {
708 int ret = 0;
709
710 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
711 ret = txgbe_xpcs_switch_mode(xpcs, interface);
712 } else if (xpcs->interface != interface) {
713 if (interface == PHY_INTERFACE_MODE_SGMII)
714 xpcs->need_reset = true;
715 xpcs->interface = interface;
716 }
717
718 return ret;
719 }
720
xpcs_pre_config(struct phylink_pcs * pcs,phy_interface_t interface)721 static void xpcs_pre_config(struct phylink_pcs *pcs, phy_interface_t interface)
722 {
723 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
724 const struct dw_xpcs_compat *compat;
725 int ret;
726
727 ret = xpcs_switch_interface_mode(xpcs, interface);
728 if (ret)
729 dev_err(&xpcs->mdiodev->dev, "switch interface failed: %pe\n",
730 ERR_PTR(ret));
731
732 if (!xpcs->need_reset)
733 return;
734
735 compat = xpcs_find_compat(xpcs, interface);
736 if (!compat) {
737 dev_err(&xpcs->mdiodev->dev, "unsupported interface %s\n",
738 phy_modes(interface));
739 return;
740 }
741
742 ret = xpcs_soft_reset(xpcs, compat);
743 if (ret)
744 dev_err(&xpcs->mdiodev->dev, "soft reset failed: %pe\n",
745 ERR_PTR(ret));
746
747 xpcs->need_reset = false;
748 }
749
xpcs_config_aneg_c37_sgmii(struct dw_xpcs * xpcs,unsigned int neg_mode)750 static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
751 unsigned int neg_mode)
752 {
753 int ret, mdio_ctrl, tx_conf;
754 u16 mask, val;
755
756 /* For AN for C37 SGMII mode, the settings are :-
757 * 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case
758 it is already enabled)
759 * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 10b (SGMII AN)
760 * 3) VR_MII_AN_CTRL Bit(3) [TX_CONFIG] = 0b (MAC side SGMII)
761 * DW xPCS used with DW EQoS MAC is always MAC side SGMII.
762 * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic
763 * speed/duplex mode change by HW after SGMII AN complete)
764 * 5) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 1b (Enable SGMII AN)
765 *
766 * Note that VR_MII_MMD_CTRL is MII_BMCR.
767 *
768 * Note: Since it is MAC side SGMII, there is no need to set
769 * SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config from
770 * PHY about the link state change after C28 AN is completed
771 * between PHY and Link Partner. There is also no need to
772 * trigger AN restart for MAC-side SGMII.
773 */
774 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
775 if (mdio_ctrl < 0)
776 return mdio_ctrl;
777
778 if (mdio_ctrl & BMCR_ANENABLE) {
779 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
780 mdio_ctrl & ~BMCR_ANENABLE);
781 if (ret < 0)
782 return ret;
783 }
784
785 mask = DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK;
786 val = FIELD_PREP(DW_VR_MII_PCS_MODE_MASK,
787 DW_VR_MII_PCS_MODE_C37_SGMII);
788
789 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
790 mask |= DW_VR_MII_AN_CTRL_8BIT;
791 val |= DW_VR_MII_AN_CTRL_8BIT;
792 /* Hardware requires it to be PHY side SGMII */
793 tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII;
794 } else {
795 tx_conf = DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII;
796 }
797
798 val |= FIELD_PREP(DW_VR_MII_TX_CONFIG_MASK, tx_conf);
799
800 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
801 if (ret < 0)
802 return ret;
803
804 val = 0;
805 mask = DW_VR_MII_DIG_CTRL1_2G5_EN | DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
806
807 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
808 val = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
809
810 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
811 mask |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
812 val |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
813 }
814
815 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, mask, val);
816 if (ret < 0)
817 return ret;
818
819 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
820 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
821 mdio_ctrl | BMCR_ANENABLE);
822
823 return ret;
824 }
825
xpcs_config_aneg_c37_1000basex(struct dw_xpcs * xpcs,unsigned int neg_mode,const unsigned long * advertising)826 static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
827 unsigned int neg_mode,
828 const unsigned long *advertising)
829 {
830 phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
831 int ret, mdio_ctrl, adv;
832 bool changed = 0;
833 u16 mask, val;
834
835 /* According to Chap 7.12, to set 1000BASE-X C37 AN, AN must
836 * be disabled first:-
837 * 1) VR_MII_MMD_CTRL Bit(12)[AN_ENABLE] = 0b
838 * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37)
839 *
840 * Note that VR_MII_MMD_CTRL is MII_BMCR.
841 */
842 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
843 if (mdio_ctrl < 0)
844 return mdio_ctrl;
845
846 if (mdio_ctrl & BMCR_ANENABLE) {
847 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
848 mdio_ctrl & ~BMCR_ANENABLE);
849 if (ret < 0)
850 return ret;
851 }
852
853 mask = DW_VR_MII_PCS_MODE_MASK;
854 val = FIELD_PREP(DW_VR_MII_PCS_MODE_MASK,
855 DW_VR_MII_PCS_MODE_C37_1000BASEX);
856
857 if (!xpcs->pcs.poll) {
858 mask |= DW_VR_MII_AN_INTR_EN;
859 val |= DW_VR_MII_AN_INTR_EN;
860 }
861
862 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
863 if (ret < 0)
864 return ret;
865
866 /* Check for advertising changes and update the C45 MII ADV
867 * register accordingly.
868 */
869 adv = phylink_mii_c22_pcs_encode_advertisement(interface,
870 advertising);
871 if (adv >= 0) {
872 ret = xpcs_modify_changed(xpcs, MDIO_MMD_VEND2,
873 MII_ADVERTISE, 0xffff, adv);
874 if (ret < 0)
875 return ret;
876
877 changed = ret;
878 }
879
880 /* Clear CL37 AN complete status */
881 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
882 if (ret < 0)
883 return ret;
884
885 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
886 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
887 mdio_ctrl | BMCR_ANENABLE);
888 if (ret < 0)
889 return ret;
890 }
891
892 return changed;
893 }
894
xpcs_config_2500basex(struct dw_xpcs * xpcs)895 static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
896 {
897 int ret;
898
899 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1,
900 DW_VR_MII_DIG_CTRL1_2G5_EN |
901 DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW,
902 DW_VR_MII_DIG_CTRL1_2G5_EN);
903 if (ret < 0)
904 return ret;
905
906 return xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR,
907 BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_SPEED100,
908 BMCR_SPEED1000);
909 }
910
xpcs_do_config(struct dw_xpcs * xpcs,phy_interface_t interface,const unsigned long * advertising,unsigned int neg_mode)911 static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
912 const unsigned long *advertising,
913 unsigned int neg_mode)
914 {
915 const struct dw_xpcs_compat *compat;
916 int ret;
917
918 compat = xpcs_find_compat(xpcs, interface);
919 if (!compat)
920 return -ENODEV;
921
922 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
923 /* Wangxun devices need backplane CL37 AN enabled for
924 * SGMII and 1000base-X
925 */
926 if (interface == PHY_INTERFACE_MODE_SGMII ||
927 interface == PHY_INTERFACE_MODE_1000BASEX)
928 xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1,
929 DW_CL37_BP | DW_EN_VSMMD1);
930 }
931
932 switch (compat->an_mode) {
933 case DW_10GBASER:
934 break;
935 case DW_AN_C73:
936 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
937 ret = xpcs_config_aneg_c73(xpcs, compat);
938 if (ret)
939 return ret;
940 }
941 break;
942 case DW_AN_C37_SGMII:
943 ret = xpcs_config_aneg_c37_sgmii(xpcs, neg_mode);
944 if (ret)
945 return ret;
946 break;
947 case DW_AN_C37_1000BASEX:
948 ret = xpcs_config_aneg_c37_1000basex(xpcs, neg_mode,
949 advertising);
950 if (ret)
951 return ret;
952 break;
953 case DW_2500BASEX:
954 ret = xpcs_config_2500basex(xpcs);
955 if (ret)
956 return ret;
957 break;
958 default:
959 return -EINVAL;
960 }
961
962 if (compat->pma_config) {
963 ret = compat->pma_config(xpcs);
964 if (ret)
965 return ret;
966 }
967
968 return 0;
969 }
970
xpcs_config(struct phylink_pcs * pcs,unsigned int neg_mode,phy_interface_t interface,const unsigned long * advertising,bool permit_pause_to_mac)971 static int xpcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
972 phy_interface_t interface,
973 const unsigned long *advertising,
974 bool permit_pause_to_mac)
975 {
976 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
977
978 return xpcs_do_config(xpcs, interface, advertising, neg_mode);
979 }
980
xpcs_get_state_c73(struct dw_xpcs * xpcs,struct phylink_link_state * state,const struct dw_xpcs_compat * compat)981 static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
982 struct phylink_link_state *state,
983 const struct dw_xpcs_compat *compat)
984 {
985 bool an_enabled;
986 int pcs_stat1;
987 int an_stat1;
988 int ret;
989
990 /* The link status bit is latching-low, so it is important to
991 * avoid unnecessary re-reads of this register to avoid missing
992 * a link-down event.
993 */
994 pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
995 if (pcs_stat1 < 0) {
996 state->link = false;
997 return pcs_stat1;
998 }
999
1000 /* Link needs to be read first ... */
1001 state->link = !!(pcs_stat1 & MDIO_STAT1_LSTATUS);
1002
1003 /* ... and then we check the faults. */
1004 ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1);
1005 if (ret) {
1006 ret = xpcs_soft_reset(xpcs, compat);
1007 if (ret)
1008 return ret;
1009
1010 state->link = 0;
1011
1012 return xpcs_do_config(xpcs, state->interface, NULL,
1013 PHYLINK_PCS_NEG_INBAND_ENABLED);
1014 }
1015
1016 /* There is no point doing anything else if the link is down. */
1017 if (!state->link)
1018 return 0;
1019
1020 an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
1021 state->advertising);
1022 if (an_enabled) {
1023 /* The link status bit is latching-low, so it is important to
1024 * avoid unnecessary re-reads of this register to avoid missing
1025 * a link-down event.
1026 */
1027 an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
1028 if (an_stat1 < 0) {
1029 state->link = false;
1030 return an_stat1;
1031 }
1032
1033 state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat,
1034 an_stat1);
1035 if (!state->an_complete) {
1036 state->link = false;
1037 return 0;
1038 }
1039
1040 ret = xpcs_read_lpa_c73(xpcs, state, an_stat1);
1041 if (ret < 0) {
1042 state->link = false;
1043 return ret;
1044 }
1045
1046 phylink_resolve_c73(state);
1047 } else {
1048 ret = xpcs_resolve_pma(xpcs, state);
1049 }
1050
1051 return ret;
1052 }
1053
xpcs_get_state_c37_sgmii(struct dw_xpcs * xpcs,struct phylink_link_state * state)1054 static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
1055 struct phylink_link_state *state)
1056 {
1057 int ret;
1058
1059 /* Reset link_state */
1060 state->link = false;
1061 state->an_complete = false;
1062 state->speed = SPEED_UNKNOWN;
1063 state->duplex = DUPLEX_UNKNOWN;
1064 state->pause = 0;
1065
1066 /* For C37 SGMII mode, we check DW_VR_MII_AN_INTR_STS for link
1067 * status, speed and duplex.
1068 */
1069 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS);
1070 if (ret < 0)
1071 return ret;
1072
1073 state->an_complete = ret & DW_VR_MII_AN_STS_C37_ANCMPLT_INTR;
1074
1075 if (ret & DW_VR_MII_C37_ANSGM_SP_LNKSTS) {
1076 int speed_value;
1077
1078 state->link = true;
1079
1080 speed_value = FIELD_GET(DW_VR_MII_AN_STS_C37_ANSGM_SP, ret);
1081 if (speed_value == DW_VR_MII_C37_ANSGM_SP_1000)
1082 state->speed = SPEED_1000;
1083 else if (speed_value == DW_VR_MII_C37_ANSGM_SP_100)
1084 state->speed = SPEED_100;
1085 else
1086 state->speed = SPEED_10;
1087
1088 if (ret & DW_VR_MII_AN_STS_C37_ANSGM_FD)
1089 state->duplex = DUPLEX_FULL;
1090 else
1091 state->duplex = DUPLEX_HALF;
1092
1093 return 0;
1094 }
1095
1096 /* Clear AN complete status or interrupt */
1097 if (state->an_complete)
1098 xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
1099
1100 return 0;
1101 }
1102
xpcs_get_state_c37_1000basex(struct dw_xpcs * xpcs,unsigned int neg_mode,struct phylink_link_state * state)1103 static int xpcs_get_state_c37_1000basex(struct dw_xpcs *xpcs,
1104 unsigned int neg_mode,
1105 struct phylink_link_state *state)
1106 {
1107 int lpa, bmsr;
1108
1109 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
1110 state->advertising)) {
1111 /* Reset link state */
1112 state->link = false;
1113
1114 lpa = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_LPA);
1115 if (lpa < 0 || lpa & LPA_RFAULT)
1116 return lpa;
1117
1118 bmsr = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
1119 if (bmsr < 0)
1120 return bmsr;
1121
1122 /* Clear AN complete interrupt */
1123 if (!xpcs->pcs.poll) {
1124 int an_intr;
1125
1126 an_intr = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS);
1127 if (an_intr & DW_VR_MII_AN_STS_C37_ANCMPLT_INTR) {
1128 an_intr &= ~DW_VR_MII_AN_STS_C37_ANCMPLT_INTR;
1129 xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, an_intr);
1130 }
1131 }
1132
1133 phylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lpa);
1134 }
1135
1136 return 0;
1137 }
1138
xpcs_get_state_2500basex(struct dw_xpcs * xpcs,struct phylink_link_state * state)1139 static int xpcs_get_state_2500basex(struct dw_xpcs *xpcs,
1140 struct phylink_link_state *state)
1141 {
1142 int ret;
1143
1144 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
1145 if (ret < 0) {
1146 state->link = 0;
1147 return ret;
1148 }
1149
1150 state->link = !!(ret & BMSR_LSTATUS);
1151 if (!state->link)
1152 return 0;
1153
1154 state->speed = SPEED_2500;
1155 state->pause |= MLO_PAUSE_TX | MLO_PAUSE_RX;
1156 state->duplex = DUPLEX_FULL;
1157
1158 return 0;
1159 }
1160
xpcs_get_state(struct phylink_pcs * pcs,unsigned int neg_mode,struct phylink_link_state * state)1161 static void xpcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
1162 struct phylink_link_state *state)
1163 {
1164 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1165 const struct dw_xpcs_compat *compat;
1166 int ret;
1167
1168 compat = xpcs_find_compat(xpcs, state->interface);
1169 if (!compat)
1170 return;
1171
1172 switch (compat->an_mode) {
1173 case DW_10GBASER:
1174 phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state);
1175 break;
1176 case DW_AN_C73:
1177 ret = xpcs_get_state_c73(xpcs, state, compat);
1178 if (ret)
1179 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1180 "xpcs_get_state_c73", ERR_PTR(ret));
1181 break;
1182 case DW_AN_C37_SGMII:
1183 ret = xpcs_get_state_c37_sgmii(xpcs, state);
1184 if (ret)
1185 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1186 "xpcs_get_state_c37_sgmii", ERR_PTR(ret));
1187 break;
1188 case DW_AN_C37_1000BASEX:
1189 ret = xpcs_get_state_c37_1000basex(xpcs, neg_mode, state);
1190 if (ret)
1191 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1192 "xpcs_get_state_c37_1000basex", ERR_PTR(ret));
1193 break;
1194 case DW_2500BASEX:
1195 ret = xpcs_get_state_2500basex(xpcs, state);
1196 if (ret)
1197 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1198 "xpcs_get_state_2500basex", ERR_PTR(ret));
1199 break;
1200 default:
1201 return;
1202 }
1203 }
1204
xpcs_link_up_sgmii_1000basex(struct dw_xpcs * xpcs,unsigned int neg_mode,phy_interface_t interface,int speed,int duplex)1205 static void xpcs_link_up_sgmii_1000basex(struct dw_xpcs *xpcs,
1206 unsigned int neg_mode,
1207 phy_interface_t interface,
1208 int speed, int duplex)
1209 {
1210 int ret;
1211
1212 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
1213 return;
1214
1215 if (interface == PHY_INTERFACE_MODE_1000BASEX) {
1216 if (speed != SPEED_1000) {
1217 dev_err(&xpcs->mdiodev->dev,
1218 "%s: speed %dMbps not supported\n",
1219 __func__, speed);
1220 return;
1221 }
1222
1223 if (duplex != DUPLEX_FULL)
1224 dev_err(&xpcs->mdiodev->dev,
1225 "%s: half duplex not supported\n",
1226 __func__);
1227 }
1228
1229 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
1230 mii_bmcr_encode_fixed(speed, duplex));
1231 if (ret)
1232 dev_err(&xpcs->mdiodev->dev, "%s: xpcs_write returned %pe\n",
1233 __func__, ERR_PTR(ret));
1234 }
1235
xpcs_link_up(struct phylink_pcs * pcs,unsigned int neg_mode,phy_interface_t interface,int speed,int duplex)1236 static void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
1237 phy_interface_t interface, int speed, int duplex)
1238 {
1239 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1240
1241 switch (interface) {
1242 case PHY_INTERFACE_MODE_USXGMII:
1243 xpcs_link_up_usxgmii(xpcs, speed);
1244 break;
1245
1246 case PHY_INTERFACE_MODE_SGMII:
1247 case PHY_INTERFACE_MODE_1000BASEX:
1248 xpcs_link_up_sgmii_1000basex(xpcs, neg_mode, interface, speed,
1249 duplex);
1250 break;
1251
1252 default:
1253 break;
1254 }
1255 }
1256
xpcs_an_restart(struct phylink_pcs * pcs)1257 static void xpcs_an_restart(struct phylink_pcs *pcs)
1258 {
1259 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1260
1261 xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, BMCR_ANRESTART,
1262 BMCR_ANRESTART);
1263 }
1264
xpcs_config_eee(struct dw_xpcs * xpcs,bool enable)1265 static int xpcs_config_eee(struct dw_xpcs *xpcs, bool enable)
1266 {
1267 u16 mask, val;
1268 int ret;
1269
1270 mask = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
1271 DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
1272 DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
1273 DW_VR_MII_EEE_MULT_FACT_100NS;
1274
1275 if (enable)
1276 val = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
1277 DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
1278 DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
1279 FIELD_PREP(DW_VR_MII_EEE_MULT_FACT_100NS,
1280 xpcs->eee_mult_fact);
1281 else
1282 val = 0;
1283
1284 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, mask,
1285 val);
1286 if (ret < 0)
1287 return ret;
1288
1289 return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1,
1290 DW_VR_MII_EEE_TRN_LPI,
1291 enable ? DW_VR_MII_EEE_TRN_LPI : 0);
1292 }
1293
xpcs_disable_eee(struct phylink_pcs * pcs)1294 static void xpcs_disable_eee(struct phylink_pcs *pcs)
1295 {
1296 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1297
1298 xpcs_config_eee(xpcs, false);
1299 }
1300
xpcs_enable_eee(struct phylink_pcs * pcs)1301 static void xpcs_enable_eee(struct phylink_pcs *pcs)
1302 {
1303 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1304
1305 xpcs_config_eee(xpcs, true);
1306 }
1307
1308 /**
1309 * xpcs_config_eee_mult_fact() - set the EEE clock multiplying factor
1310 * @xpcs: pointer to a &struct dw_xpcs instance
1311 * @mult_fact: the multiplying factor
1312 *
1313 * Configure the EEE clock multiplying factor. This value should be such that
1314 * clk_eee_time_period * (mult_fact + 1) is within the range 80 to 120ns.
1315 */
xpcs_config_eee_mult_fact(struct dw_xpcs * xpcs,u8 mult_fact)1316 void xpcs_config_eee_mult_fact(struct dw_xpcs *xpcs, u8 mult_fact)
1317 {
1318 xpcs->eee_mult_fact = mult_fact;
1319 }
1320 EXPORT_SYMBOL_GPL(xpcs_config_eee_mult_fact);
1321
xpcs_read_ids(struct dw_xpcs * xpcs)1322 static int xpcs_read_ids(struct dw_xpcs *xpcs)
1323 {
1324 int ret;
1325 u32 id;
1326
1327 /* First, search C73 PCS using PCS MMD 3. Return ENODEV if communication
1328 * failed indicating that device couldn't be reached.
1329 */
1330 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1);
1331 if (ret < 0)
1332 return -ENODEV;
1333
1334 id = ret << 16;
1335
1336 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2);
1337 if (ret < 0)
1338 return ret;
1339
1340 id |= ret;
1341
1342 /* If Device IDs are not all zeros or ones, then 10GBase-X/R or C73
1343 * KR/KX4 PCS found. Otherwise fallback to detecting 1000Base-X or C37
1344 * PCS in MII MMD 31.
1345 */
1346 if (!id || id == 0xffffffff) {
1347 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID1);
1348 if (ret < 0)
1349 return ret;
1350
1351 id = ret << 16;
1352
1353 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID2);
1354 if (ret < 0)
1355 return ret;
1356
1357 id |= ret;
1358 }
1359
1360 /* Set the PCS ID if it hasn't been pre-initialized */
1361 if (xpcs->info.pcs == DW_XPCS_ID_NATIVE)
1362 xpcs->info.pcs = id;
1363
1364 /* Find out PMA/PMD ID from MMD 1 device ID registers */
1365 ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID1);
1366 if (ret < 0)
1367 return ret;
1368
1369 id = ret << 16;
1370
1371 ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID2);
1372 if (ret < 0)
1373 return ret;
1374
1375 /* For now we only record the OUI for the PMAPMD, we may want to
1376 * add the model number at some point in the future.
1377 */
1378 id |= ret & MDIO_DEVID2_OUI;
1379
1380 /* Set the PMA ID if it hasn't been pre-initialized */
1381 if (xpcs->info.pma == DW_XPCS_PMA_ID_NATIVE)
1382 xpcs->info.pma = id;
1383
1384 return 0;
1385 }
1386
1387 static const struct dw_xpcs_compat synopsys_xpcs_compat[] = {
1388 {
1389 .interface = PHY_INTERFACE_MODE_USXGMII,
1390 .supported = xpcs_usxgmii_features,
1391 .an_mode = DW_AN_C73,
1392 }, {
1393 .interface = PHY_INTERFACE_MODE_10GKR,
1394 .supported = xpcs_10gkr_features,
1395 .an_mode = DW_AN_C73,
1396 }, {
1397 .interface = PHY_INTERFACE_MODE_25GBASER,
1398 .supported = xpcs_25gbaser_features,
1399 .an_mode = DW_AN_C73,
1400 }, {
1401 .interface = PHY_INTERFACE_MODE_XLGMII,
1402 .supported = xpcs_xlgmii_features,
1403 .an_mode = DW_AN_C73,
1404 }, {
1405 .interface = PHY_INTERFACE_MODE_50GBASER,
1406 .supported = xpcs_50gbaser_features,
1407 .an_mode = DW_AN_C73,
1408 }, {
1409 .interface = PHY_INTERFACE_MODE_LAUI,
1410 .supported = xpcs_50gbaser2_features,
1411 .an_mode = DW_AN_C73,
1412 }, {
1413 .interface = PHY_INTERFACE_MODE_100GBASEP,
1414 .supported = xpcs_100gbasep_features,
1415 .an_mode = DW_AN_C73,
1416 }, {
1417 .interface = PHY_INTERFACE_MODE_10GBASER,
1418 .supported = xpcs_10gbaser_features,
1419 .an_mode = DW_10GBASER,
1420 }, {
1421 .interface = PHY_INTERFACE_MODE_SGMII,
1422 .supported = xpcs_sgmii_features,
1423 .an_mode = DW_AN_C37_SGMII,
1424 }, {
1425 .interface = PHY_INTERFACE_MODE_1000BASEX,
1426 .supported = xpcs_1000basex_features,
1427 .an_mode = DW_AN_C37_1000BASEX,
1428 }, {
1429 .interface = PHY_INTERFACE_MODE_2500BASEX,
1430 .supported = xpcs_2500basex_features,
1431 .an_mode = DW_2500BASEX,
1432 }, {
1433 }
1434 };
1435
1436 static const struct dw_xpcs_compat nxp_sja1105_xpcs_compat[] = {
1437 {
1438 .interface = PHY_INTERFACE_MODE_SGMII,
1439 .supported = xpcs_sgmii_features,
1440 .an_mode = DW_AN_C37_SGMII,
1441 .pma_config = nxp_sja1105_sgmii_pma_config,
1442 }, {
1443 }
1444 };
1445
1446 static const struct dw_xpcs_compat nxp_sja1110_xpcs_compat[] = {
1447 {
1448 .interface = PHY_INTERFACE_MODE_SGMII,
1449 .supported = xpcs_sgmii_features,
1450 .an_mode = DW_AN_C37_SGMII,
1451 .pma_config = nxp_sja1110_sgmii_pma_config,
1452 }, {
1453 .interface = PHY_INTERFACE_MODE_2500BASEX,
1454 .supported = xpcs_2500basex_features,
1455 .an_mode = DW_2500BASEX,
1456 .pma_config = nxp_sja1110_2500basex_pma_config,
1457 }, {
1458 }
1459 };
1460
1461 static const struct dw_xpcs_desc xpcs_desc_list[] = {
1462 {
1463 .id = DW_XPCS_ID,
1464 .mask = DW_XPCS_ID_MASK,
1465 .compat = synopsys_xpcs_compat,
1466 }, {
1467 .id = NXP_SJA1105_XPCS_ID,
1468 .mask = DW_XPCS_ID_MASK,
1469 .compat = nxp_sja1105_xpcs_compat,
1470 }, {
1471 .id = NXP_SJA1110_XPCS_ID,
1472 .mask = DW_XPCS_ID_MASK,
1473 .compat = nxp_sja1110_xpcs_compat,
1474 },
1475 };
1476
1477 static const struct phylink_pcs_ops xpcs_phylink_ops = {
1478 .pcs_validate = xpcs_validate,
1479 .pcs_inband_caps = xpcs_inband_caps,
1480 .pcs_pre_config = xpcs_pre_config,
1481 .pcs_config = xpcs_config,
1482 .pcs_get_state = xpcs_get_state,
1483 .pcs_an_restart = xpcs_an_restart,
1484 .pcs_link_up = xpcs_link_up,
1485 .pcs_disable_eee = xpcs_disable_eee,
1486 .pcs_enable_eee = xpcs_enable_eee,
1487 };
1488
xpcs_identify(struct dw_xpcs * xpcs)1489 static int xpcs_identify(struct dw_xpcs *xpcs)
1490 {
1491 int i, ret;
1492
1493 ret = xpcs_read_ids(xpcs);
1494 if (ret < 0)
1495 return ret;
1496
1497 for (i = 0; i < ARRAY_SIZE(xpcs_desc_list); i++) {
1498 const struct dw_xpcs_desc *entry = &xpcs_desc_list[i];
1499
1500 if ((xpcs->info.pcs & entry->mask) == entry->id) {
1501 xpcs->desc = entry;
1502 return 0;
1503 }
1504 }
1505
1506 return -ENODEV;
1507 }
1508
xpcs_create_data(struct mdio_device * mdiodev)1509 static struct dw_xpcs *xpcs_create_data(struct mdio_device *mdiodev)
1510 {
1511 struct dw_xpcs *xpcs;
1512
1513 xpcs = kzalloc_obj(*xpcs);
1514 if (!xpcs)
1515 return ERR_PTR(-ENOMEM);
1516
1517 mdio_device_get(mdiodev);
1518 xpcs->mdiodev = mdiodev;
1519 xpcs->pcs.ops = &xpcs_phylink_ops;
1520 xpcs->pcs.poll = true;
1521
1522 return xpcs;
1523 }
1524
xpcs_free_data(struct dw_xpcs * xpcs)1525 static void xpcs_free_data(struct dw_xpcs *xpcs)
1526 {
1527 mdio_device_put(xpcs->mdiodev);
1528 kfree(xpcs);
1529 }
1530
xpcs_init_clks(struct dw_xpcs * xpcs)1531 static int xpcs_init_clks(struct dw_xpcs *xpcs)
1532 {
1533 static const char *ids[DW_XPCS_NUM_CLKS] = {
1534 [DW_XPCS_CORE_CLK] = "core",
1535 [DW_XPCS_PAD_CLK] = "pad",
1536 };
1537 struct device *dev = &xpcs->mdiodev->dev;
1538 int ret, i;
1539
1540 for (i = 0; i < DW_XPCS_NUM_CLKS; ++i)
1541 xpcs->clks[i].id = ids[i];
1542
1543 ret = clk_bulk_get_optional(dev, DW_XPCS_NUM_CLKS, xpcs->clks);
1544 if (ret)
1545 return dev_err_probe(dev, ret, "Failed to get clocks\n");
1546
1547 ret = clk_bulk_prepare_enable(DW_XPCS_NUM_CLKS, xpcs->clks);
1548 if (ret)
1549 return dev_err_probe(dev, ret, "Failed to enable clocks\n");
1550
1551 return 0;
1552 }
1553
xpcs_clear_clks(struct dw_xpcs * xpcs)1554 static void xpcs_clear_clks(struct dw_xpcs *xpcs)
1555 {
1556 clk_bulk_disable_unprepare(DW_XPCS_NUM_CLKS, xpcs->clks);
1557
1558 clk_bulk_put(DW_XPCS_NUM_CLKS, xpcs->clks);
1559 }
1560
xpcs_init_id(struct dw_xpcs * xpcs)1561 static int xpcs_init_id(struct dw_xpcs *xpcs)
1562 {
1563 const struct dw_xpcs_info *info;
1564
1565 info = dev_get_platdata(&xpcs->mdiodev->dev);
1566 if (!info) {
1567 xpcs->info.pcs = DW_XPCS_ID_NATIVE;
1568 xpcs->info.pma = DW_XPCS_PMA_ID_NATIVE;
1569 } else {
1570 xpcs->info = *info;
1571 }
1572
1573 return xpcs_identify(xpcs);
1574 }
1575
xpcs_create(struct mdio_device * mdiodev)1576 static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev)
1577 {
1578 struct dw_xpcs *xpcs;
1579 int ret;
1580
1581 xpcs = xpcs_create_data(mdiodev);
1582 if (IS_ERR(xpcs))
1583 return xpcs;
1584
1585 ret = xpcs_init_clks(xpcs);
1586 if (ret)
1587 goto out_free_data;
1588
1589 ret = xpcs_init_id(xpcs);
1590 if (ret)
1591 goto out_clear_clks;
1592
1593 xpcs_get_interfaces(xpcs, xpcs->pcs.supported_interfaces);
1594
1595 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID ||
1596 xpcs->info.pma == MP_FBNIC_XPCS_PMA_100G_ID)
1597 xpcs->pcs.poll = false;
1598 else
1599 xpcs->need_reset = true;
1600
1601 return xpcs;
1602
1603 out_clear_clks:
1604 xpcs_clear_clks(xpcs);
1605
1606 out_free_data:
1607 xpcs_free_data(xpcs);
1608
1609 return ERR_PTR(ret);
1610 }
1611
1612 /**
1613 * xpcs_create_mdiodev() - create a DW xPCS instance with the MDIO @addr
1614 * @bus: pointer to the MDIO-bus descriptor for the device to be looked at
1615 * @addr: device MDIO-bus ID
1616 *
1617 * Return: a pointer to the DW XPCS handle if successful, otherwise -ENODEV if
1618 * the PCS device couldn't be found on the bus and other negative errno related
1619 * to the data allocation and MDIO-bus communications.
1620 */
xpcs_create_mdiodev(struct mii_bus * bus,int addr)1621 struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr)
1622 {
1623 struct mdio_device *mdiodev;
1624 struct dw_xpcs *xpcs;
1625
1626 mdiodev = mdio_device_create(bus, addr);
1627 if (IS_ERR(mdiodev))
1628 return ERR_CAST(mdiodev);
1629
1630 xpcs = xpcs_create(mdiodev);
1631
1632 /* xpcs_create() has taken a refcount on the mdiodev if it was
1633 * successful. If xpcs_create() fails, this will free the mdio
1634 * device here. In any case, we don't need to hold our reference
1635 * anymore, and putting it here will allow mdio_device_put() in
1636 * xpcs_destroy() to automatically free the mdio device.
1637 */
1638 mdio_device_put(mdiodev);
1639
1640 return xpcs;
1641 }
1642 EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
1643
xpcs_create_pcs_mdiodev(struct mii_bus * bus,int addr)1644 struct phylink_pcs *xpcs_create_pcs_mdiodev(struct mii_bus *bus, int addr)
1645 {
1646 struct dw_xpcs *xpcs;
1647
1648 xpcs = xpcs_create_mdiodev(bus, addr);
1649 if (IS_ERR(xpcs))
1650 return ERR_CAST(xpcs);
1651
1652 return &xpcs->pcs;
1653 }
1654 EXPORT_SYMBOL_GPL(xpcs_create_pcs_mdiodev);
1655
1656 /**
1657 * xpcs_create_fwnode() - Create a DW xPCS instance from @fwnode
1658 * @fwnode: fwnode handle poining to the DW XPCS device
1659 *
1660 * Return: a pointer to the DW XPCS handle if successful, otherwise -ENODEV if
1661 * the fwnode device is unavailable or the PCS device couldn't be found on the
1662 * bus, -EPROBE_DEFER if the respective MDIO-device instance couldn't be found,
1663 * other negative errno related to the data allocations and MDIO-bus
1664 * communications.
1665 */
xpcs_create_fwnode(struct fwnode_handle * fwnode)1666 struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode)
1667 {
1668 struct mdio_device *mdiodev;
1669 struct dw_xpcs *xpcs;
1670
1671 if (!fwnode_device_is_available(fwnode))
1672 return ERR_PTR(-ENODEV);
1673
1674 mdiodev = fwnode_mdio_find_device(fwnode);
1675 if (!mdiodev)
1676 return ERR_PTR(-EPROBE_DEFER);
1677
1678 xpcs = xpcs_create(mdiodev);
1679
1680 /* xpcs_create() has taken a refcount on the mdiodev if it was
1681 * successful. If xpcs_create() fails, this will free the mdio
1682 * device here. In any case, we don't need to hold our reference
1683 * anymore, and putting it here will allow mdio_device_put() in
1684 * xpcs_destroy() to automatically free the mdio device.
1685 */
1686 mdio_device_put(mdiodev);
1687
1688 return xpcs;
1689 }
1690 EXPORT_SYMBOL_GPL(xpcs_create_fwnode);
1691
xpcs_destroy(struct dw_xpcs * xpcs)1692 void xpcs_destroy(struct dw_xpcs *xpcs)
1693 {
1694 if (!xpcs)
1695 return;
1696
1697 xpcs_clear_clks(xpcs);
1698
1699 xpcs_free_data(xpcs);
1700 }
1701 EXPORT_SYMBOL_GPL(xpcs_destroy);
1702
xpcs_destroy_pcs(struct phylink_pcs * pcs)1703 void xpcs_destroy_pcs(struct phylink_pcs *pcs)
1704 {
1705 xpcs_destroy(phylink_pcs_to_xpcs(pcs));
1706 }
1707 EXPORT_SYMBOL_GPL(xpcs_destroy_pcs);
1708
1709 MODULE_DESCRIPTION("Synopsys DesignWare XPCS library");
1710 MODULE_LICENSE("GPL v2");
1711