xref: /linux/drivers/net/pcs/pcs-xpcs.c (revision d6fd48ef)
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");
1323