xref: /linux/drivers/net/dsa/mv88e6xxx/pcs-639x.c (revision eec8359f0797ef87c6ef6cbed6de08b02073b833)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Marvell 88E6352 family SERDES PCS support
4  *
5  * Copyright (c) 2008 Marvell Semiconductor
6  *
7  * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
8  */
9 #include <linux/interrupt.h>
10 #include <linux/irqdomain.h>
11 #include <linux/mii.h>
12 
13 #include "chip.h"
14 #include "global2.h"
15 #include "phy.h"
16 #include "port.h"
17 #include "serdes.h"
18 
19 struct mv88e639x_pcs {
20 	struct mdio_device mdio;
21 	struct phylink_pcs sgmii_pcs;
22 	struct phylink_pcs xg_pcs;
23 	bool erratum_3_14;
24 	bool supports_5g;
25 	phy_interface_t interface;
26 	unsigned int irq;
27 	char name[64];
28 	irqreturn_t (*handle_irq)(struct mv88e639x_pcs *mpcs);
29 };
30 
31 static int mv88e639x_read(struct mv88e639x_pcs *mpcs, u16 regnum, u16 *val)
32 {
33 	int err;
34 
35 	err = mdiodev_c45_read(&mpcs->mdio, MDIO_MMD_PHYXS, regnum);
36 	if (err < 0)
37 		return err;
38 
39 	*val = err;
40 
41 	return 0;
42 }
43 
44 static int mv88e639x_write(struct mv88e639x_pcs *mpcs, u16 regnum, u16 val)
45 {
46 	return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, val);
47 }
48 
49 static int mv88e639x_modify(struct mv88e639x_pcs *mpcs, u16 regnum, u16 mask,
50 			    u16 val)
51 {
52 	return mdiodev_c45_modify(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, mask,
53 				  val);
54 }
55 
56 static int mv88e639x_modify_changed(struct mv88e639x_pcs *mpcs, u16 regnum,
57 				    u16 mask, u16 set)
58 {
59 	return mdiodev_c45_modify_changed(&mpcs->mdio, MDIO_MMD_PHYXS, regnum,
60 					  mask, set);
61 }
62 
63 static struct mv88e639x_pcs *
64 mv88e639x_pcs_alloc(struct device *dev, struct mii_bus *bus, unsigned int addr,
65 		    int port)
66 {
67 	struct mv88e639x_pcs *mpcs;
68 
69 	mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
70 	if (!mpcs)
71 		return NULL;
72 
73 	mpcs->mdio.dev.parent = dev;
74 	mpcs->mdio.bus = bus;
75 	mpcs->mdio.addr = addr;
76 
77 	snprintf(mpcs->name, sizeof(mpcs->name),
78 		 "mv88e6xxx-%s-serdes-%d", dev_name(dev), port);
79 
80 	return mpcs;
81 }
82 
83 static irqreturn_t mv88e639x_pcs_handle_irq(int irq, void *dev_id)
84 {
85 	struct mv88e639x_pcs *mpcs = dev_id;
86 	irqreturn_t (*handler)(struct mv88e639x_pcs *);
87 
88 	handler = READ_ONCE(mpcs->handle_irq);
89 	if (!handler)
90 		return IRQ_NONE;
91 
92 	return handler(mpcs);
93 }
94 
95 static int mv88e639x_pcs_setup_irq(struct mv88e639x_pcs *mpcs,
96 				   struct mv88e6xxx_chip *chip, int port)
97 {
98 	unsigned int irq;
99 
100 	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
101 	if (!irq) {
102 		/* Use polling mode */
103 		mpcs->sgmii_pcs.poll = true;
104 		mpcs->xg_pcs.poll = true;
105 		return 0;
106 	}
107 
108 	mpcs->irq = irq;
109 
110 	return request_threaded_irq(irq, NULL, mv88e639x_pcs_handle_irq,
111 				    IRQF_ONESHOT, mpcs->name, mpcs);
112 }
113 
114 static void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port)
115 {
116 	struct mv88e639x_pcs *mpcs = chip->ports[port].pcs_private;
117 
118 	if (!mpcs)
119 		return;
120 
121 	if (mpcs->irq)
122 		free_irq(mpcs->irq, mpcs);
123 
124 	kfree(mpcs);
125 
126 	chip->ports[port].pcs_private = NULL;
127 }
128 
129 static struct mv88e639x_pcs *sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs)
130 {
131 	return container_of(pcs, struct mv88e639x_pcs, sgmii_pcs);
132 }
133 
134 static irqreturn_t mv88e639x_sgmii_handle_irq(struct mv88e639x_pcs *mpcs)
135 {
136 	u16 int_status;
137 	int err;
138 
139 	err = mv88e639x_read(mpcs, MV88E6390_SGMII_INT_STATUS, &int_status);
140 	if (err)
141 		return IRQ_NONE;
142 
143 	if (int_status & (MV88E6390_SGMII_INT_LINK_DOWN |
144 			  MV88E6390_SGMII_INT_LINK_UP)) {
145 		phylink_pcs_change(&mpcs->sgmii_pcs,
146 				   int_status & MV88E6390_SGMII_INT_LINK_UP);
147 
148 		return IRQ_HANDLED;
149 	}
150 
151 	return IRQ_NONE;
152 }
153 
154 static int mv88e639x_sgmii_pcs_control_irq(struct mv88e639x_pcs *mpcs,
155 					   bool enable)
156 {
157 	u16 val = 0;
158 
159 	if (enable)
160 		val |= MV88E6390_SGMII_INT_LINK_DOWN |
161 		       MV88E6390_SGMII_INT_LINK_UP;
162 
163 	return mv88e639x_modify(mpcs, MV88E6390_SGMII_INT_ENABLE,
164 				MV88E6390_SGMII_INT_LINK_DOWN |
165 				MV88E6390_SGMII_INT_LINK_UP, val);
166 }
167 
168 static int mv88e639x_sgmii_pcs_control_pwr(struct mv88e639x_pcs *mpcs,
169 					   bool enable)
170 {
171 	u16 mask, val;
172 
173 	if (enable) {
174 		mask = BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN;
175 		val = 0;
176 	} else {
177 		mask = val = BMCR_PDOWN;
178 	}
179 
180 	return mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, mask, val);
181 }
182 
183 static int mv88e639x_sgmii_pcs_enable(struct phylink_pcs *pcs)
184 {
185 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
186 
187 	/* power enable done in post_config */
188 	mpcs->handle_irq = mv88e639x_sgmii_handle_irq;
189 
190 	return mv88e639x_sgmii_pcs_control_irq(mpcs, !!mpcs->irq);
191 }
192 
193 static void mv88e639x_sgmii_pcs_disable(struct phylink_pcs *pcs)
194 {
195 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
196 
197 	mv88e639x_sgmii_pcs_control_irq(mpcs, false);
198 	mv88e639x_sgmii_pcs_control_pwr(mpcs, false);
199 }
200 
201 static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs *pcs,
202 					   phy_interface_t interface)
203 {
204 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
205 
206 	mv88e639x_sgmii_pcs_control_pwr(mpcs, false);
207 }
208 
209 static int mv88e6390_erratum_3_14(struct mv88e639x_pcs *mpcs)
210 {
211 	static const int lanes[] = { MV88E6390_PORT9_LANE0, MV88E6390_PORT9_LANE1,
212 		MV88E6390_PORT9_LANE2, MV88E6390_PORT9_LANE3,
213 		MV88E6390_PORT10_LANE0, MV88E6390_PORT10_LANE1,
214 		MV88E6390_PORT10_LANE2, MV88E6390_PORT10_LANE3 };
215 	int err, i;
216 
217 	/* 88e6190x and 88e6390x errata 3.14:
218 	 * After chip reset, SERDES reconfiguration or SERDES core
219 	 * Software Reset, the SERDES lanes may not be properly aligned
220 	 * resulting in CRC errors
221 	 */
222 
223 	for (i = 0; i < ARRAY_SIZE(lanes); i++) {
224 		err = mdiobus_c45_write(mpcs->mdio.bus, lanes[i],
225 					MDIO_MMD_PHYXS,
226 					0xf054, 0x400C);
227 		if (err)
228 			return err;
229 
230 		err = mdiobus_c45_write(mpcs->mdio.bus, lanes[i],
231 					MDIO_MMD_PHYXS,
232 					0xf054, 0x4000);
233 		if (err)
234 			return err;
235 	}
236 
237 	return 0;
238 }
239 
240 static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs *pcs,
241 					   phy_interface_t interface)
242 {
243 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
244 	int err;
245 
246 	mv88e639x_sgmii_pcs_control_pwr(mpcs, true);
247 
248 	if (mpcs->erratum_3_14) {
249 		err = mv88e6390_erratum_3_14(mpcs);
250 		if (err)
251 			dev_err(mpcs->mdio.dev.parent,
252 				"failed to apply erratum 3.14: %pe\n",
253 				ERR_PTR(err));
254 	}
255 
256 	return 0;
257 }
258 
259 static void mv88e639x_sgmii_pcs_get_state(struct phylink_pcs *pcs,
260 					  unsigned int neg_mode,
261 					  struct phylink_link_state *state)
262 {
263 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
264 	u16 bmsr, lpa, status;
265 	int err;
266 
267 	err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMSR, &bmsr);
268 	if (err) {
269 		dev_err(mpcs->mdio.dev.parent,
270 			"can't read Serdes PHY %s: %pe\n",
271 			"BMSR", ERR_PTR(err));
272 		state->link = false;
273 		return;
274 	}
275 
276 	err = mv88e639x_read(mpcs, MV88E6390_SGMII_LPA, &lpa);
277 	if (err) {
278 		dev_err(mpcs->mdio.dev.parent,
279 			"can't read Serdes PHY %s: %pe\n",
280 			"LPA", ERR_PTR(err));
281 		state->link = false;
282 		return;
283 	}
284 
285 	err = mv88e639x_read(mpcs, MV88E6390_SGMII_PHY_STATUS, &status);
286 	if (err) {
287 		dev_err(mpcs->mdio.dev.parent,
288 			"can't read Serdes PHY %s: %pe\n",
289 			"status", ERR_PTR(err));
290 		state->link = false;
291 		return;
292 	}
293 
294 	mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, status,
295 				   state);
296 }
297 
298 static int mv88e639x_sgmii_pcs_config(struct phylink_pcs *pcs,
299 				      unsigned int neg_mode,
300 				      phy_interface_t interface,
301 				      const unsigned long *advertising,
302 				      bool permit_pause_to_mac)
303 {
304 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
305 	u16 val, bmcr;
306 	bool changed;
307 	int adv, err;
308 
309 	adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising);
310 	if (adv < 0)
311 		return 0;
312 
313 	mpcs->interface = interface;
314 
315 	err = mv88e639x_modify_changed(mpcs, MV88E6390_SGMII_ADVERTISE,
316 				       0xffff, adv);
317 	if (err < 0)
318 		return err;
319 
320 	changed = err > 0;
321 
322 	err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMCR, &val);
323 	if (err)
324 		return err;
325 
326 	if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
327 		bmcr = val | BMCR_ANENABLE;
328 	else
329 		bmcr = val & ~BMCR_ANENABLE;
330 
331 	/* setting ANENABLE triggers a restart of negotiation */
332 	if (bmcr == val)
333 		return changed;
334 
335 	return mv88e639x_write(mpcs, MV88E6390_SGMII_BMCR, bmcr);
336 }
337 
338 static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs *pcs)
339 {
340 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
341 
342 	mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR,
343 			 BMCR_ANRESTART, BMCR_ANRESTART);
344 }
345 
346 static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs *pcs,
347 					unsigned int mode,
348 					phy_interface_t interface,
349 					int speed, int duplex)
350 {
351 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
352 	u16 bmcr;
353 	int err;
354 
355 	if (phylink_autoneg_inband(mode))
356 		return;
357 
358 	bmcr = mii_bmcr_encode_fixed(speed, duplex);
359 
360 	err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR,
361 			       BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX,
362 			       bmcr);
363 	if (err)
364 		dev_err(mpcs->mdio.dev.parent,
365 			"can't access Serdes PHY %s: %pe\n",
366 			"BMCR", ERR_PTR(err));
367 }
368 
369 static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops = {
370 	.pcs_enable = mv88e639x_sgmii_pcs_enable,
371 	.pcs_disable = mv88e639x_sgmii_pcs_disable,
372 	.pcs_pre_config = mv88e639x_sgmii_pcs_pre_config,
373 	.pcs_post_config = mv88e639x_sgmii_pcs_post_config,
374 	.pcs_get_state = mv88e639x_sgmii_pcs_get_state,
375 	.pcs_an_restart = mv88e639x_sgmii_pcs_an_restart,
376 	.pcs_config = mv88e639x_sgmii_pcs_config,
377 	.pcs_link_up = mv88e639x_sgmii_pcs_link_up,
378 };
379 
380 static struct mv88e639x_pcs *xg_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs)
381 {
382 	return container_of(pcs, struct mv88e639x_pcs, xg_pcs);
383 }
384 
385 static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs *mpcs)
386 {
387 	return mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1,
388 				MDIO_CTRL1_RESET | MDIO_PCS_CTRL1_LOOPBACK |
389 				MDIO_CTRL1_LPOWER, 0);
390 }
391 
392 static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs *mpcs)
393 {
394 	mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, MDIO_CTRL1_LPOWER,
395 			 MDIO_CTRL1_LPOWER);
396 }
397 
398 static void mv88e639x_xg_pcs_get_state(struct phylink_pcs *pcs,
399 				       unsigned int neg_mode,
400 				       struct phylink_link_state *state)
401 {
402 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
403 	u16 status;
404 	int err;
405 
406 	state->link = false;
407 
408 	err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &status);
409 	if (err) {
410 		dev_err(mpcs->mdio.dev.parent,
411 			"can't read Serdes PHY %s: %pe\n",
412 			"STAT1", ERR_PTR(err));
413 		return;
414 	}
415 
416 	state->link = !!(status & MDIO_STAT1_LSTATUS);
417 	if (state->link) {
418 		switch (state->interface) {
419 		case PHY_INTERFACE_MODE_5GBASER:
420 			state->speed = SPEED_5000;
421 			break;
422 
423 		case PHY_INTERFACE_MODE_10GBASER:
424 		case PHY_INTERFACE_MODE_RXAUI:
425 		case PHY_INTERFACE_MODE_XAUI:
426 			state->speed = SPEED_10000;
427 			break;
428 
429 		default:
430 			state->link = false;
431 			return;
432 		}
433 
434 		state->duplex = DUPLEX_FULL;
435 	}
436 }
437 
438 static int mv88e639x_xg_pcs_config(struct phylink_pcs *pcs,
439 				   unsigned int neg_mode,
440 				   phy_interface_t interface,
441 				   const unsigned long *advertising,
442 				   bool permit_pause_to_mac)
443 {
444 	return 0;
445 }
446 
447 static struct phylink_pcs *
448 mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port,
449 		     phy_interface_t mode)
450 {
451 	struct mv88e639x_pcs *mpcs;
452 
453 	mpcs = chip->ports[port].pcs_private;
454 	if (!mpcs)
455 		return NULL;
456 
457 	switch (mode) {
458 	case PHY_INTERFACE_MODE_SGMII:
459 	case PHY_INTERFACE_MODE_1000BASEX:
460 	case PHY_INTERFACE_MODE_2500BASEX:
461 		return &mpcs->sgmii_pcs;
462 
463 	case PHY_INTERFACE_MODE_5GBASER:
464 		if (!mpcs->supports_5g)
465 			return NULL;
466 		fallthrough;
467 	case PHY_INTERFACE_MODE_10GBASER:
468 	case PHY_INTERFACE_MODE_XAUI:
469 	case PHY_INTERFACE_MODE_RXAUI:
470 	case PHY_INTERFACE_MODE_USXGMII:
471 		return &mpcs->xg_pcs;
472 
473 	default:
474 		return NULL;
475 	}
476 }
477 
478 /* Marvell 88E6390 Specific support */
479 
480 static irqreturn_t mv88e6390_xg_handle_irq(struct mv88e639x_pcs *mpcs)
481 {
482 	u16 int_status;
483 	int err;
484 
485 	err = mv88e639x_read(mpcs, MV88E6390_10G_INT_STATUS, &int_status);
486 	if (err)
487 		return IRQ_NONE;
488 
489 	if (int_status & (MV88E6390_10G_INT_LINK_DOWN |
490 			  MV88E6390_10G_INT_LINK_UP)) {
491 		phylink_pcs_change(&mpcs->xg_pcs,
492 				   int_status & MV88E6390_10G_INT_LINK_UP);
493 
494 		return IRQ_HANDLED;
495 	}
496 
497 	return IRQ_NONE;
498 }
499 
500 static int mv88e6390_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable)
501 {
502 	u16 val = 0;
503 
504 	if (enable)
505 		val = MV88E6390_10G_INT_LINK_DOWN | MV88E6390_10G_INT_LINK_UP;
506 
507 	return mv88e639x_modify(mpcs, MV88E6390_10G_INT_ENABLE,
508 				MV88E6390_10G_INT_LINK_DOWN |
509 				MV88E6390_10G_INT_LINK_UP, val);
510 }
511 
512 static int mv88e6390_xg_pcs_enable(struct phylink_pcs *pcs)
513 {
514 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
515 	int err;
516 
517 	err = mv88e639x_xg_pcs_enable(mpcs);
518 	if (err)
519 		return err;
520 
521 	mpcs->handle_irq = mv88e6390_xg_handle_irq;
522 
523 	return mv88e6390_xg_control_irq(mpcs, !!mpcs->irq);
524 }
525 
526 static void mv88e6390_xg_pcs_disable(struct phylink_pcs *pcs)
527 {
528 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
529 
530 	mv88e6390_xg_control_irq(mpcs, false);
531 	mv88e639x_xg_pcs_disable(mpcs);
532 }
533 
534 static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops = {
535 	.pcs_enable = mv88e6390_xg_pcs_enable,
536 	.pcs_disable = mv88e6390_xg_pcs_disable,
537 	.pcs_get_state = mv88e639x_xg_pcs_get_state,
538 	.pcs_config = mv88e639x_xg_pcs_config,
539 };
540 
541 static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs *mpcs)
542 {
543 	return mv88e639x_modify(mpcs, MV88E6390_PG_CONTROL,
544 				MV88E6390_PG_CONTROL_ENABLE_PC,
545 				MV88E6390_PG_CONTROL_ENABLE_PC);
546 }
547 
548 static int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port)
549 {
550 	struct mv88e639x_pcs *mpcs;
551 	struct mii_bus *bus;
552 	struct device *dev;
553 	int lane, err;
554 
555 	lane = mv88e6xxx_serdes_get_lane(chip, port);
556 	if (lane < 0)
557 		return 0;
558 
559 	bus = mv88e6xxx_default_mdio_bus(chip);
560 	dev = chip->dev;
561 
562 	mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port);
563 	if (!mpcs)
564 		return -ENOMEM;
565 
566 	mpcs->sgmii_pcs.ops = &mv88e639x_sgmii_pcs_ops;
567 	mpcs->sgmii_pcs.neg_mode = true;
568 	mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops;
569 	mpcs->xg_pcs.neg_mode = true;
570 
571 	if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6190X ||
572 	    chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6390X)
573 		mpcs->erratum_3_14 = true;
574 
575 	err = mv88e639x_pcs_setup_irq(mpcs, chip, port);
576 	if (err)
577 		goto err_free;
578 
579 	/* 6390 and 6390x has the checker, 6393x doesn't appear to? */
580 	/* This is to enable gathering the statistics. Maybe this
581 	 * should call out to a helper? Or we could do this at init time.
582 	 */
583 	err = mv88e6390_pcs_enable_checker(mpcs);
584 	if (err)
585 		goto err_free;
586 
587 	chip->ports[port].pcs_private = mpcs;
588 
589 	return 0;
590 
591 err_free:
592 	kfree(mpcs);
593 	return err;
594 }
595 
596 const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops = {
597 	.pcs_init = mv88e6390_pcs_init,
598 	.pcs_teardown = mv88e639x_pcs_teardown,
599 	.pcs_select = mv88e639x_pcs_select,
600 };
601 
602 /* Marvell 88E6393X Specific support */
603 
604 static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable)
605 {
606 	u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN |
607 		  MV88E6393X_SERDES_CTRL1_RX_PDOWN;
608 
609 	return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val,
610 				enable ? 0 : val);
611 }
612 
613 /* mv88e6393x family errata 4.6:
614  * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or
615  * P0_mode is configured for [x]MII.
616  * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
617  *
618  * It seems that after this workaround the SERDES is automatically powered up
619  * (the bit is cleared), so power it down.
620  */
621 static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs)
622 {
623 	int err;
624 
625 	err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC,
626 			       MV88E6393X_SERDES_POC_PDOWN |
627 			       MV88E6393X_SERDES_POC_RESET,
628 			       MV88E6393X_SERDES_POC_RESET);
629 	if (err)
630 		return err;
631 
632 	err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR,
633 			       BMCR_PDOWN, BMCR_PDOWN);
634 	if (err)
635 		return err;
636 
637 	err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false);
638 	if (err)
639 		return err;
640 
641 	return mv88e6393x_power_lane(mpcs, false);
642 }
643 
644 /* mv88e6393x family errata 4.8:
645  * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not
646  * come up after hardware reset or software reset of SERDES core. Workaround
647  * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all
648  * other modes.
649  */
650 static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs)
651 {
652 	u16 reg, poc;
653 	int err;
654 
655 	err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc);
656 	if (err)
657 		return err;
658 
659 	poc &= MV88E6393X_SERDES_POC_PCS_MASK;
660 	if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
661 	    poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
662 	    poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
663 		reg = MV88E6393X_ERRATA_4_8_BIT;
664 	else
665 		reg = 0;
666 
667 	return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG,
668 				MV88E6393X_ERRATA_4_8_BIT, reg);
669 }
670 
671 /* mv88e6393x family errata 5.2:
672  * For optimal signal integrity the following sequence should be applied to
673  * SERDES operating in 10G mode. These registers only apply to 10G operation
674  * and have no effect on other speeds.
675  */
676 static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs)
677 {
678 	static const struct {
679 		u16 dev, reg, val, mask;
680 	} fixes[] = {
681 		{ MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff },
682 		{ MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff },
683 		{ MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff },
684 		{ MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f },
685 		{ MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 },
686 		{ MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff },
687 		{ MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC,
688 		  MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET },
689 	};
690 	int err, i;
691 
692 	for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
693 		err = mdiodev_c45_modify(&mpcs->mdio, fixes[i].dev,
694 					 fixes[i].reg, fixes[i].mask,
695 					 fixes[i].val);
696 		if (err)
697 			return err;
698 	}
699 
700 	return 0;
701 }
702 
703 /* Inband AN is broken on Amethyst in 2500base-x mode when set by standard
704  * mechanism (via cmode).
705  * We can get around this by configuring the PCS mode to 1000base-x and then
706  * writing value 0x58 to register 1e.8000. (This must be done while SerDes
707  * receiver and transmitter are disabled, which is, when this function is
708  * called.)
709  * It seem that when we do this configuration to 2500base-x mode (by changing
710  * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then
711  * configure to sgmii or 1000base-x, the device thinks that it already has
712  * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes
713  * at 3.125 GHz.
714  * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from
715  * 2500base-x mode.
716  */
717 static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on)
718 {
719 	u16 reg;
720 	int err;
721 
722 	if (on)
723 		reg = MV88E6393X_SERDES_POC_PCS_1000BASEX |
724 		      MV88E6393X_SERDES_POC_AN;
725 	else
726 		reg = MV88E6393X_SERDES_POC_PCS_2500BASEX;
727 
728 	reg |= MV88E6393X_SERDES_POC_RESET;
729 
730 	err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC,
731 			       MV88E6393X_SERDES_POC_PCS_MASK |
732 			       MV88E6393X_SERDES_POC_AN |
733 			       MV88E6393X_SERDES_POC_RESET, reg);
734 	if (err)
735 		return err;
736 
737 	return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_VEND1, 0x8000, 0x58);
738 }
739 
740 static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs,
741 					       phy_interface_t interface,
742 					       bool enable)
743 {
744 	int err;
745 
746 	if (interface != PHY_INTERFACE_MODE_2500BASEX)
747 		return 0;
748 
749 	err = mv88e6393x_fix_2500basex_an(mpcs, enable);
750 	if (err)
751 		dev_err(mpcs->mdio.dev.parent,
752 			"failed to %s 2500basex fix: %pe\n",
753 			enable ? "enable" : "disable", ERR_PTR(err));
754 
755 	return err;
756 }
757 
758 static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs)
759 {
760 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
761 
762 	mv88e639x_sgmii_pcs_disable(pcs);
763 	mv88e6393x_power_lane(mpcs, false);
764 	mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false);
765 }
766 
767 static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs,
768 					    phy_interface_t interface)
769 {
770 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
771 
772 	mv88e639x_sgmii_pcs_pre_config(pcs, interface);
773 	mv88e6393x_power_lane(mpcs, false);
774 	mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false);
775 }
776 
777 static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs,
778 					    phy_interface_t interface)
779 {
780 	struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
781 	int err;
782 
783 	err = mv88e6393x_erratum_4_8(mpcs);
784 	if (err)
785 		return err;
786 
787 	err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true);
788 	if (err)
789 		return err;
790 
791 	err = mv88e6393x_power_lane(mpcs, true);
792 	if (err)
793 		return err;
794 
795 	return mv88e639x_sgmii_pcs_post_config(pcs, interface);
796 }
797 
798 static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = {
799 	.pcs_enable = mv88e639x_sgmii_pcs_enable,
800 	.pcs_disable = mv88e6393x_sgmii_pcs_disable,
801 	.pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config,
802 	.pcs_post_config = mv88e6393x_sgmii_pcs_post_config,
803 	.pcs_get_state = mv88e639x_sgmii_pcs_get_state,
804 	.pcs_an_restart = mv88e639x_sgmii_pcs_an_restart,
805 	.pcs_config = mv88e639x_sgmii_pcs_config,
806 	.pcs_link_up = mv88e639x_sgmii_pcs_link_up,
807 };
808 
809 static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs)
810 {
811 	u16 int_status, stat1;
812 	bool link_down;
813 	int err;
814 
815 	err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status);
816 	if (err)
817 		return IRQ_NONE;
818 
819 	if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) {
820 		err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1);
821 		if (err)
822 			return IRQ_NONE;
823 
824 		link_down = !(stat1 & MDIO_STAT1_LSTATUS);
825 
826 		phylink_pcs_change(&mpcs->xg_pcs, !link_down);
827 
828 		return IRQ_HANDLED;
829 	}
830 
831 	return IRQ_NONE;
832 }
833 
834 static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable)
835 {
836 	u16 val = 0;
837 
838 	if (enable)
839 		val = MV88E6393X_10G_INT_LINK_CHANGE;
840 
841 	return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE,
842 				MV88E6393X_10G_INT_LINK_CHANGE, val);
843 }
844 
845 static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs)
846 {
847 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
848 
849 	mpcs->handle_irq = mv88e6393x_xg_handle_irq;
850 
851 	return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq);
852 }
853 
854 static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs)
855 {
856 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
857 
858 	mv88e6393x_xg_control_irq(mpcs, false);
859 	mv88e639x_xg_pcs_disable(mpcs);
860 	mv88e6393x_power_lane(mpcs, false);
861 }
862 
863 /* The PCS has to be powered down while CMODE is changed */
864 static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs,
865 					 phy_interface_t interface)
866 {
867 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
868 
869 	mv88e639x_xg_pcs_disable(mpcs);
870 	mv88e6393x_power_lane(mpcs, false);
871 }
872 
873 static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs,
874 					 phy_interface_t interface)
875 {
876 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
877 	int err;
878 
879 	if (interface == PHY_INTERFACE_MODE_10GBASER ||
880 	    interface == PHY_INTERFACE_MODE_USXGMII) {
881 		err = mv88e6393x_erratum_5_2(mpcs);
882 		if (err)
883 			return err;
884 	}
885 
886 	err = mv88e6393x_power_lane(mpcs, true);
887 	if (err)
888 		return err;
889 
890 	return mv88e639x_xg_pcs_enable(mpcs);
891 }
892 
893 static void mv88e6393x_xg_pcs_get_state(struct phylink_pcs *pcs,
894 					unsigned int neg_mode,
895 					struct phylink_link_state *state)
896 {
897 	struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
898 	u16 status, lp_status;
899 	int err;
900 
901 	if (state->interface != PHY_INTERFACE_MODE_USXGMII)
902 		return mv88e639x_xg_pcs_get_state(pcs, neg_mode, state);
903 
904 	state->link = false;
905 
906 	err = mv88e639x_read(mpcs, MV88E6390_USXGMII_PHY_STATUS, &status);
907 	err = err ? : mv88e639x_read(mpcs, MV88E6390_USXGMII_LP_STATUS, &lp_status);
908 	if (err) {
909 		dev_err(mpcs->mdio.dev.parent,
910 			"can't read USXGMII status: %pe\n", ERR_PTR(err));
911 		return;
912 	}
913 
914 	state->link = !!(status & MDIO_USXGMII_LINK);
915 	state->an_complete = state->link;
916 	phylink_decode_usxgmii_word(state, lp_status);
917 }
918 
919 static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = {
920 	.pcs_enable = mv88e6393x_xg_pcs_enable,
921 	.pcs_disable = mv88e6393x_xg_pcs_disable,
922 	.pcs_pre_config = mv88e6393x_xg_pcs_pre_config,
923 	.pcs_post_config = mv88e6393x_xg_pcs_post_config,
924 	.pcs_get_state = mv88e6393x_xg_pcs_get_state,
925 	.pcs_config = mv88e639x_xg_pcs_config,
926 };
927 
928 static int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port)
929 {
930 	struct mv88e639x_pcs *mpcs;
931 	struct mii_bus *bus;
932 	struct device *dev;
933 	int lane, err;
934 
935 	lane = mv88e6xxx_serdes_get_lane(chip, port);
936 	if (lane < 0)
937 		return 0;
938 
939 	bus = mv88e6xxx_default_mdio_bus(chip);
940 	dev = chip->dev;
941 
942 	mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port);
943 	if (!mpcs)
944 		return -ENOMEM;
945 
946 	mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops;
947 	mpcs->sgmii_pcs.neg_mode = true;
948 	mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops;
949 	mpcs->xg_pcs.neg_mode = true;
950 	mpcs->supports_5g = true;
951 
952 	err = mv88e6393x_erratum_4_6(mpcs);
953 	if (err)
954 		goto err_free;
955 
956 	err = mv88e639x_pcs_setup_irq(mpcs, chip, port);
957 	if (err)
958 		goto err_free;
959 
960 	chip->ports[port].pcs_private = mpcs;
961 
962 	return 0;
963 
964 err_free:
965 	kfree(mpcs);
966 	return err;
967 }
968 
969 const struct mv88e6xxx_pcs_ops mv88e6393x_pcs_ops = {
970 	.pcs_init = mv88e6393x_pcs_init,
971 	.pcs_teardown = mv88e639x_pcs_teardown,
972 	.pcs_select = mv88e639x_pcs_select,
973 };
974