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