xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/serdes.c (revision caa80275)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Marvell 88E6xxx SERDES manipulation, via SMI bus
4  *
5  * Copyright (c) 2008 Marvell Semiconductor
6  *
7  * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
8  */
9 
10 #include <linux/interrupt.h>
11 #include <linux/irqdomain.h>
12 #include <linux/mii.h>
13 
14 #include "chip.h"
15 #include "global2.h"
16 #include "phy.h"
17 #include "port.h"
18 #include "serdes.h"
19 
20 static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
21 				 u16 *val)
22 {
23 	return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
24 				       MV88E6352_SERDES_PAGE_FIBER,
25 				       reg, val);
26 }
27 
28 static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
29 				  u16 val)
30 {
31 	return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
32 					MV88E6352_SERDES_PAGE_FIBER,
33 					reg, val);
34 }
35 
36 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
37 				 int lane, int device, int reg, u16 *val)
38 {
39 	int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
40 
41 	return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
42 }
43 
44 static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
45 				  int lane, int device, int reg, u16 val)
46 {
47 	int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
48 
49 	return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
50 }
51 
52 static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
53 					  u16 status, u16 lpa,
54 					  struct phylink_link_state *state)
55 {
56 	if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
57 		state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
58 		state->duplex = status &
59 				MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
60 			                         DUPLEX_FULL : DUPLEX_HALF;
61 
62 		if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
63 			state->pause |= MLO_PAUSE_TX;
64 		if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
65 			state->pause |= MLO_PAUSE_RX;
66 
67 		switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
68 		case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
69 			if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
70 				state->speed = SPEED_2500;
71 			else
72 				state->speed = SPEED_1000;
73 			break;
74 		case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
75 			state->speed = SPEED_100;
76 			break;
77 		case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
78 			state->speed = SPEED_10;
79 			break;
80 		default:
81 			dev_err(chip->dev, "invalid PHY speed\n");
82 			return -EINVAL;
83 		}
84 	} else {
85 		state->link = false;
86 	}
87 
88 	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
89 		mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
90 				       ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
91 	else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
92 		mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
93 				       ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
94 
95 	return 0;
96 }
97 
98 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
99 			   bool up)
100 {
101 	u16 val, new_val;
102 	int err;
103 
104 	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
105 	if (err)
106 		return err;
107 
108 	if (up)
109 		new_val = val & ~BMCR_PDOWN;
110 	else
111 		new_val = val | BMCR_PDOWN;
112 
113 	if (val != new_val)
114 		err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
115 
116 	return err;
117 }
118 
119 int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
120 				int lane, unsigned int mode,
121 				phy_interface_t interface,
122 				const unsigned long *advertise)
123 {
124 	u16 adv, bmcr, val;
125 	bool changed;
126 	int err;
127 
128 	switch (interface) {
129 	case PHY_INTERFACE_MODE_SGMII:
130 		adv = 0x0001;
131 		break;
132 
133 	case PHY_INTERFACE_MODE_1000BASEX:
134 		adv = linkmode_adv_to_mii_adv_x(advertise,
135 					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
136 		break;
137 
138 	default:
139 		return 0;
140 	}
141 
142 	err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val);
143 	if (err)
144 		return err;
145 
146 	changed = val != adv;
147 	if (changed) {
148 		err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv);
149 		if (err)
150 			return err;
151 	}
152 
153 	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
154 	if (err)
155 		return err;
156 
157 	if (phylink_autoneg_inband(mode))
158 		bmcr = val | BMCR_ANENABLE;
159 	else
160 		bmcr = val & ~BMCR_ANENABLE;
161 
162 	if (bmcr == val)
163 		return changed;
164 
165 	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
166 }
167 
168 int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
169 				   int lane, struct phylink_link_state *state)
170 {
171 	u16 lpa, status;
172 	int err;
173 
174 	err = mv88e6352_serdes_read(chip, 0x11, &status);
175 	if (err) {
176 		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
177 		return err;
178 	}
179 
180 	err = mv88e6352_serdes_read(chip, MII_LPA, &lpa);
181 	if (err) {
182 		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
183 		return err;
184 	}
185 
186 	return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
187 }
188 
189 int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
190 				    int lane)
191 {
192 	u16 bmcr;
193 	int err;
194 
195 	err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr);
196 	if (err)
197 		return err;
198 
199 	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART);
200 }
201 
202 int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
203 				 int lane, int speed, int duplex)
204 {
205 	u16 val, bmcr;
206 	int err;
207 
208 	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
209 	if (err)
210 		return err;
211 
212 	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
213 	switch (speed) {
214 	case SPEED_1000:
215 		bmcr |= BMCR_SPEED1000;
216 		break;
217 	case SPEED_100:
218 		bmcr |= BMCR_SPEED100;
219 		break;
220 	case SPEED_10:
221 		break;
222 	}
223 
224 	if (duplex == DUPLEX_FULL)
225 		bmcr |= BMCR_FULLDPLX;
226 
227 	if (bmcr == val)
228 		return 0;
229 
230 	return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
231 }
232 
233 int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
234 {
235 	u8 cmode = chip->ports[port].cmode;
236 	int lane = -ENODEV;
237 
238 	if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
239 	    (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
240 	    (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
241 		lane = 0xff; /* Unused */
242 
243 	return lane;
244 }
245 
246 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
247 {
248 	if (mv88e6xxx_serdes_get_lane(chip, port) >= 0)
249 		return true;
250 
251 	return false;
252 }
253 
254 struct mv88e6352_serdes_hw_stat {
255 	char string[ETH_GSTRING_LEN];
256 	int sizeof_stat;
257 	int reg;
258 };
259 
260 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
261 	{ "serdes_fibre_rx_error", 16, 21 },
262 	{ "serdes_PRBS_error", 32, 24 },
263 };
264 
265 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
266 {
267 	if (mv88e6352_port_has_serdes(chip, port))
268 		return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
269 
270 	return 0;
271 }
272 
273 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
274 				 int port, uint8_t *data)
275 {
276 	struct mv88e6352_serdes_hw_stat *stat;
277 	int i;
278 
279 	if (!mv88e6352_port_has_serdes(chip, port))
280 		return 0;
281 
282 	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
283 		stat = &mv88e6352_serdes_hw_stats[i];
284 		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
285 		       ETH_GSTRING_LEN);
286 	}
287 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
288 }
289 
290 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
291 					  struct mv88e6352_serdes_hw_stat *stat)
292 {
293 	u64 val = 0;
294 	u16 reg;
295 	int err;
296 
297 	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
298 	if (err) {
299 		dev_err(chip->dev, "failed to read statistic\n");
300 		return 0;
301 	}
302 
303 	val = reg;
304 
305 	if (stat->sizeof_stat == 32) {
306 		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
307 		if (err) {
308 			dev_err(chip->dev, "failed to read statistic\n");
309 			return 0;
310 		}
311 		val = val << 16 | reg;
312 	}
313 
314 	return val;
315 }
316 
317 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
318 			       uint64_t *data)
319 {
320 	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
321 	struct mv88e6352_serdes_hw_stat *stat;
322 	u64 value;
323 	int i;
324 
325 	if (!mv88e6352_port_has_serdes(chip, port))
326 		return 0;
327 
328 	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
329 		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
330 
331 	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
332 		stat = &mv88e6352_serdes_hw_stats[i];
333 		value = mv88e6352_serdes_get_stat(chip, stat);
334 		mv88e6xxx_port->serdes_stats[i] += value;
335 		data[i] = mv88e6xxx_port->serdes_stats[i];
336 	}
337 
338 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
339 }
340 
341 static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
342 {
343 	u16 bmsr;
344 	int err;
345 
346 	/* If the link has dropped, we want to know about it. */
347 	err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
348 	if (err) {
349 		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
350 		return;
351 	}
352 
353 	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
354 }
355 
356 irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
357 					int lane)
358 {
359 	irqreturn_t ret = IRQ_NONE;
360 	u16 status;
361 	int err;
362 
363 	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
364 	if (err)
365 		return ret;
366 
367 	if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
368 		ret = IRQ_HANDLED;
369 		mv88e6352_serdes_irq_link(chip, port);
370 	}
371 
372 	return ret;
373 }
374 
375 int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
376 				bool enable)
377 {
378 	u16 val = 0;
379 
380 	if (enable)
381 		val |= MV88E6352_SERDES_INT_LINK_CHANGE;
382 
383 	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
384 }
385 
386 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
387 {
388 	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
389 }
390 
391 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
392 {
393 	if (!mv88e6352_port_has_serdes(chip, port))
394 		return 0;
395 
396 	return 32 * sizeof(u16);
397 }
398 
399 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
400 {
401 	u16 *p = _p;
402 	u16 reg;
403 	int err;
404 	int i;
405 
406 	if (!mv88e6352_port_has_serdes(chip, port))
407 		return;
408 
409 	for (i = 0 ; i < 32; i++) {
410 		err = mv88e6352_serdes_read(chip, i, &reg);
411 		if (!err)
412 			p[i] = reg;
413 	}
414 }
415 
416 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
417 {
418 	u8 cmode = chip->ports[port].cmode;
419 	int lane = -ENODEV;
420 
421 	switch (port) {
422 	case 5:
423 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
424 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
425 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
426 			lane = MV88E6341_PORT5_LANE;
427 		break;
428 	}
429 
430 	return lane;
431 }
432 
433 int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
434 			   bool up)
435 {
436 	/* The serdes power can't be controlled on this switch chip but we need
437 	 * to supply this function to avoid returning -EOPNOTSUPP in
438 	 * mv88e6xxx_serdes_power_up/mv88e6xxx_serdes_power_down
439 	 */
440 	return 0;
441 }
442 
443 int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
444 {
445 	/* There are no configurable serdes lanes on this switch chip but we
446 	 * need to return a non-negative lane number so that callers of
447 	 * mv88e6xxx_serdes_get_lane() know this is a serdes port.
448 	 */
449 	switch (chip->ports[port].cmode) {
450 	case MV88E6185_PORT_STS_CMODE_SERDES:
451 	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
452 		return 0;
453 	default:
454 		return -ENODEV;
455 	}
456 }
457 
458 int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
459 				   int lane, struct phylink_link_state *state)
460 {
461 	int err;
462 	u16 status;
463 
464 	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
465 	if (err)
466 		return err;
467 
468 	state->link = !!(status & MV88E6XXX_PORT_STS_LINK);
469 
470 	if (state->link) {
471 		state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? DUPLEX_FULL : DUPLEX_HALF;
472 
473 		switch (status &  MV88E6XXX_PORT_STS_SPEED_MASK) {
474 		case MV88E6XXX_PORT_STS_SPEED_1000:
475 			state->speed = SPEED_1000;
476 			break;
477 		case MV88E6XXX_PORT_STS_SPEED_100:
478 			state->speed = SPEED_100;
479 			break;
480 		case MV88E6XXX_PORT_STS_SPEED_10:
481 			state->speed = SPEED_10;
482 			break;
483 		default:
484 			dev_err(chip->dev, "invalid PHY speed\n");
485 			return -EINVAL;
486 		}
487 	} else {
488 		state->duplex = DUPLEX_UNKNOWN;
489 		state->speed = SPEED_UNKNOWN;
490 	}
491 
492 	return 0;
493 }
494 
495 int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
496 				bool enable)
497 {
498 	u8 cmode = chip->ports[port].cmode;
499 
500 	/* The serdes interrupts are enabled in the G2_INT_MASK register. We
501 	 * need to return 0 to avoid returning -EOPNOTSUPP in
502 	 * mv88e6xxx_serdes_irq_enable/mv88e6xxx_serdes_irq_disable
503 	 */
504 	switch (cmode) {
505 	case MV88E6185_PORT_STS_CMODE_SERDES:
506 	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
507 		return 0;
508 	}
509 
510 	return -EOPNOTSUPP;
511 }
512 
513 static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
514 {
515 	u16 status;
516 	int err;
517 
518 	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
519 	if (err) {
520 		dev_err(chip->dev, "can't read port status: %d\n", err);
521 		return;
522 	}
523 
524 	dsa_port_phylink_mac_change(chip->ds, port, !!(status & MV88E6XXX_PORT_STS_LINK));
525 }
526 
527 irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
528 					int lane)
529 {
530 	u8 cmode = chip->ports[port].cmode;
531 
532 	switch (cmode) {
533 	case MV88E6185_PORT_STS_CMODE_SERDES:
534 	case MV88E6185_PORT_STS_CMODE_1000BASE_X:
535 		mv88e6097_serdes_irq_link(chip, port);
536 		return IRQ_HANDLED;
537 	}
538 
539 	return IRQ_NONE;
540 }
541 
542 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
543 {
544 	u8 cmode = chip->ports[port].cmode;
545 	int lane = -ENODEV;
546 
547 	switch (port) {
548 	case 9:
549 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
550 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
551 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
552 			lane = MV88E6390_PORT9_LANE0;
553 		break;
554 	case 10:
555 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
556 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
557 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
558 			lane = MV88E6390_PORT10_LANE0;
559 		break;
560 	}
561 
562 	return lane;
563 }
564 
565 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
566 {
567 	u8 cmode_port = chip->ports[port].cmode;
568 	u8 cmode_port10 = chip->ports[10].cmode;
569 	u8 cmode_port9 = chip->ports[9].cmode;
570 	int lane = -ENODEV;
571 
572 	switch (port) {
573 	case 2:
574 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
575 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
576 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
577 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
578 				lane = MV88E6390_PORT9_LANE1;
579 		break;
580 	case 3:
581 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
582 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
583 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
584 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
585 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
586 				lane = MV88E6390_PORT9_LANE2;
587 		break;
588 	case 4:
589 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
590 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
591 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
592 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
593 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
594 				lane = MV88E6390_PORT9_LANE3;
595 		break;
596 	case 5:
597 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
598 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
599 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
600 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
601 				lane = MV88E6390_PORT10_LANE1;
602 		break;
603 	case 6:
604 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
605 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
606 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
607 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
608 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
609 				lane = MV88E6390_PORT10_LANE2;
610 		break;
611 	case 7:
612 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
613 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
614 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
615 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
616 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
617 				lane = MV88E6390_PORT10_LANE3;
618 		break;
619 	case 9:
620 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
621 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
622 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
623 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
624 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
625 			lane = MV88E6390_PORT9_LANE0;
626 		break;
627 	case 10:
628 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
629 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
630 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
631 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
632 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
633 			lane = MV88E6390_PORT10_LANE0;
634 		break;
635 	}
636 
637 	return lane;
638 }
639 
640 /* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
641  * a port is using else Returns -ENODEV.
642  */
643 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
644 {
645 	u8 cmode = chip->ports[port].cmode;
646 	int lane = -ENODEV;
647 
648 	if (port != 0 && port != 9 && port != 10)
649 		return -EOPNOTSUPP;
650 
651 	if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
652 	    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
653 	    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
654 	    cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
655 	    cmode == MV88E6393X_PORT_STS_CMODE_10GBASER)
656 		lane = port;
657 
658 	return lane;
659 }
660 
661 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
662 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
663 				      bool up)
664 {
665 	u16 val, new_val;
666 	int err;
667 
668 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
669 				    MV88E6390_10G_CTRL1, &val);
670 
671 	if (err)
672 		return err;
673 
674 	if (up)
675 		new_val = val & ~(MDIO_CTRL1_RESET |
676 				  MDIO_PCS_CTRL1_LOOPBACK |
677 				  MDIO_CTRL1_LPOWER);
678 	else
679 		new_val = val | MDIO_CTRL1_LPOWER;
680 
681 	if (val != new_val)
682 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
683 					     MV88E6390_10G_CTRL1, new_val);
684 
685 	return err;
686 }
687 
688 /* Set power up/down for SGMII and 1000Base-X */
689 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
690 					bool up)
691 {
692 	u16 val, new_val;
693 	int err;
694 
695 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
696 				    MV88E6390_SGMII_BMCR, &val);
697 	if (err)
698 		return err;
699 
700 	if (up)
701 		new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
702 	else
703 		new_val = val | BMCR_PDOWN;
704 
705 	if (val != new_val)
706 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
707 					     MV88E6390_SGMII_BMCR, new_val);
708 
709 	return err;
710 }
711 
712 struct mv88e6390_serdes_hw_stat {
713 	char string[ETH_GSTRING_LEN];
714 	int reg;
715 };
716 
717 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
718 	{ "serdes_rx_pkts", 0xf021 },
719 	{ "serdes_rx_bytes", 0xf024 },
720 	{ "serdes_rx_pkts_error", 0xf027 },
721 };
722 
723 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
724 {
725 	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
726 		return 0;
727 
728 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
729 }
730 
731 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
732 				 int port, uint8_t *data)
733 {
734 	struct mv88e6390_serdes_hw_stat *stat;
735 	int i;
736 
737 	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
738 		return 0;
739 
740 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
741 		stat = &mv88e6390_serdes_hw_stats[i];
742 		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
743 		       ETH_GSTRING_LEN);
744 	}
745 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
746 }
747 
748 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
749 					  struct mv88e6390_serdes_hw_stat *stat)
750 {
751 	u16 reg[3];
752 	int err, i;
753 
754 	for (i = 0; i < 3; i++) {
755 		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
756 					    stat->reg + i, &reg[i]);
757 		if (err) {
758 			dev_err(chip->dev, "failed to read statistic\n");
759 			return 0;
760 		}
761 	}
762 
763 	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
764 }
765 
766 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
767 			       uint64_t *data)
768 {
769 	struct mv88e6390_serdes_hw_stat *stat;
770 	int lane;
771 	int i;
772 
773 	lane = mv88e6xxx_serdes_get_lane(chip, port);
774 	if (lane < 0)
775 		return 0;
776 
777 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
778 		stat = &mv88e6390_serdes_hw_stats[i];
779 		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
780 	}
781 
782 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
783 }
784 
785 static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane)
786 {
787 	u16 reg;
788 	int err;
789 
790 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
791 				    MV88E6390_PG_CONTROL, &reg);
792 	if (err)
793 		return err;
794 
795 	reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
796 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
797 				      MV88E6390_PG_CONTROL, reg);
798 }
799 
800 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
801 			   bool up)
802 {
803 	u8 cmode = chip->ports[port].cmode;
804 	int err = 0;
805 
806 	switch (cmode) {
807 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
808 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
809 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
810 		err = mv88e6390_serdes_power_sgmii(chip, lane, up);
811 		break;
812 	case MV88E6XXX_PORT_STS_CMODE_XAUI:
813 	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
814 		err = mv88e6390_serdes_power_10g(chip, lane, up);
815 		break;
816 	}
817 
818 	if (!err && up)
819 		err = mv88e6390_serdes_enable_checker(chip, lane);
820 
821 	return err;
822 }
823 
824 int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
825 				int lane, unsigned int mode,
826 				phy_interface_t interface,
827 				const unsigned long *advertise)
828 {
829 	u16 val, bmcr, adv;
830 	bool changed;
831 	int err;
832 
833 	switch (interface) {
834 	case PHY_INTERFACE_MODE_SGMII:
835 		adv = 0x0001;
836 		break;
837 
838 	case PHY_INTERFACE_MODE_1000BASEX:
839 		adv = linkmode_adv_to_mii_adv_x(advertise,
840 					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
841 		break;
842 
843 	case PHY_INTERFACE_MODE_2500BASEX:
844 		adv = linkmode_adv_to_mii_adv_x(advertise,
845 					ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
846 		break;
847 
848 	default:
849 		return 0;
850 	}
851 
852 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
853 				    MV88E6390_SGMII_ADVERTISE, &val);
854 	if (err)
855 		return err;
856 
857 	changed = val != adv;
858 	if (changed) {
859 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
860 					     MV88E6390_SGMII_ADVERTISE, adv);
861 		if (err)
862 			return err;
863 	}
864 
865 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
866 				    MV88E6390_SGMII_BMCR, &val);
867 	if (err)
868 		return err;
869 
870 	if (phylink_autoneg_inband(mode))
871 		bmcr = val | BMCR_ANENABLE;
872 	else
873 		bmcr = val & ~BMCR_ANENABLE;
874 
875 	/* setting ANENABLE triggers a restart of negotiation */
876 	if (bmcr == val)
877 		return changed;
878 
879 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
880 				      MV88E6390_SGMII_BMCR, bmcr);
881 }
882 
883 static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
884 	int port, int lane, struct phylink_link_state *state)
885 {
886 	u16 lpa, status;
887 	int err;
888 
889 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
890 				    MV88E6390_SGMII_PHY_STATUS, &status);
891 	if (err) {
892 		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
893 		return err;
894 	}
895 
896 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
897 				    MV88E6390_SGMII_LPA, &lpa);
898 	if (err) {
899 		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
900 		return err;
901 	}
902 
903 	return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
904 }
905 
906 static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
907 	int port, int lane, struct phylink_link_state *state)
908 {
909 	u16 status;
910 	int err;
911 
912 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
913 				    MV88E6390_10G_STAT1, &status);
914 	if (err)
915 		return err;
916 
917 	state->link = !!(status & MDIO_STAT1_LSTATUS);
918 	if (state->link) {
919 		state->speed = SPEED_10000;
920 		state->duplex = DUPLEX_FULL;
921 	}
922 
923 	return 0;
924 }
925 
926 static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
927 					       int port, int lane,
928 					       struct phylink_link_state *state)
929 {
930 	u16 status;
931 	int err;
932 
933 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
934 				    MV88E6390_10G_STAT1, &status);
935 	if (err)
936 		return err;
937 
938 	state->link = !!(status & MDIO_STAT1_LSTATUS);
939 	if (state->link) {
940 		if (state->interface == PHY_INTERFACE_MODE_5GBASER)
941 			state->speed = SPEED_5000;
942 		else
943 			state->speed = SPEED_10000;
944 		state->duplex = DUPLEX_FULL;
945 	}
946 
947 	return 0;
948 }
949 
950 int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
951 				   int lane, struct phylink_link_state *state)
952 {
953 	switch (state->interface) {
954 	case PHY_INTERFACE_MODE_SGMII:
955 	case PHY_INTERFACE_MODE_1000BASEX:
956 	case PHY_INTERFACE_MODE_2500BASEX:
957 		return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
958 							    state);
959 	case PHY_INTERFACE_MODE_XAUI:
960 	case PHY_INTERFACE_MODE_RXAUI:
961 		return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
962 							  state);
963 
964 	default:
965 		return -EOPNOTSUPP;
966 	}
967 }
968 
969 int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
970 				    int lane, struct phylink_link_state *state)
971 {
972 	switch (state->interface) {
973 	case PHY_INTERFACE_MODE_SGMII:
974 	case PHY_INTERFACE_MODE_1000BASEX:
975 	case PHY_INTERFACE_MODE_2500BASEX:
976 		return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
977 							    state);
978 	case PHY_INTERFACE_MODE_5GBASER:
979 	case PHY_INTERFACE_MODE_10GBASER:
980 		return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
981 							   state);
982 
983 	default:
984 		return -EOPNOTSUPP;
985 	}
986 }
987 
988 int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
989 				    int lane)
990 {
991 	u16 bmcr;
992 	int err;
993 
994 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
995 				    MV88E6390_SGMII_BMCR, &bmcr);
996 	if (err)
997 		return err;
998 
999 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1000 				      MV88E6390_SGMII_BMCR,
1001 				      bmcr | BMCR_ANRESTART);
1002 }
1003 
1004 int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
1005 				 int lane, int speed, int duplex)
1006 {
1007 	u16 val, bmcr;
1008 	int err;
1009 
1010 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1011 				    MV88E6390_SGMII_BMCR, &val);
1012 	if (err)
1013 		return err;
1014 
1015 	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
1016 	switch (speed) {
1017 	case SPEED_2500:
1018 	case SPEED_1000:
1019 		bmcr |= BMCR_SPEED1000;
1020 		break;
1021 	case SPEED_100:
1022 		bmcr |= BMCR_SPEED100;
1023 		break;
1024 	case SPEED_10:
1025 		break;
1026 	}
1027 
1028 	if (duplex == DUPLEX_FULL)
1029 		bmcr |= BMCR_FULLDPLX;
1030 
1031 	if (bmcr == val)
1032 		return 0;
1033 
1034 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1035 				      MV88E6390_SGMII_BMCR, bmcr);
1036 }
1037 
1038 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
1039 					    int port, int lane)
1040 {
1041 	u16 bmsr;
1042 	int err;
1043 
1044 	/* If the link has dropped, we want to know about it. */
1045 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1046 				    MV88E6390_SGMII_BMSR, &bmsr);
1047 	if (err) {
1048 		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
1049 		return;
1050 	}
1051 
1052 	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
1053 }
1054 
1055 static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip,
1056 					   int port, u8 lane)
1057 {
1058 	u16 status;
1059 	int err;
1060 
1061 	/* If the link has dropped, we want to know about it. */
1062 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1063 				    MV88E6390_10G_STAT1, &status);
1064 	if (err) {
1065 		dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err);
1066 		return;
1067 	}
1068 
1069 	dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS));
1070 }
1071 
1072 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
1073 					     int lane, bool enable)
1074 {
1075 	u16 val = 0;
1076 
1077 	if (enable)
1078 		val |= MV88E6390_SGMII_INT_LINK_DOWN |
1079 			MV88E6390_SGMII_INT_LINK_UP;
1080 
1081 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1082 				      MV88E6390_SGMII_INT_ENABLE, val);
1083 }
1084 
1085 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
1086 				bool enable)
1087 {
1088 	u8 cmode = chip->ports[port].cmode;
1089 
1090 	switch (cmode) {
1091 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1092 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1093 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1094 		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1095 	}
1096 
1097 	return 0;
1098 }
1099 
1100 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
1101 					     int lane, u16 *status)
1102 {
1103 	int err;
1104 
1105 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1106 				    MV88E6390_SGMII_INT_STATUS, status);
1107 
1108 	return err;
1109 }
1110 
1111 static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip,
1112 					    u8 lane, bool enable)
1113 {
1114 	u16 val = 0;
1115 
1116 	if (enable)
1117 		val |= MV88E6393X_10G_INT_LINK_CHANGE;
1118 
1119 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1120 				      MV88E6393X_10G_INT_ENABLE, val);
1121 }
1122 
1123 int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
1124 				 int lane, bool enable)
1125 {
1126 	u8 cmode = chip->ports[port].cmode;
1127 
1128 	switch (cmode) {
1129 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1130 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1131 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1132 		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1133 	case MV88E6393X_PORT_STS_CMODE_5GBASER:
1134 	case MV88E6393X_PORT_STS_CMODE_10GBASER:
1135 		return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
1136 	}
1137 
1138 	return 0;
1139 }
1140 
1141 static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip,
1142 					    u8 lane, u16 *status)
1143 {
1144 	int err;
1145 
1146 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1147 				    MV88E6393X_10G_INT_STATUS, status);
1148 
1149 	return err;
1150 }
1151 
1152 irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1153 					 int lane)
1154 {
1155 	u8 cmode = chip->ports[port].cmode;
1156 	irqreturn_t ret = IRQ_NONE;
1157 	u16 status;
1158 	int err;
1159 
1160 	switch (cmode) {
1161 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1162 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1163 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1164 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1165 		if (err)
1166 			return ret;
1167 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1168 			      MV88E6390_SGMII_INT_LINK_UP)) {
1169 			ret = IRQ_HANDLED;
1170 			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1171 		}
1172 		break;
1173 	case MV88E6393X_PORT_STS_CMODE_5GBASER:
1174 	case MV88E6393X_PORT_STS_CMODE_10GBASER:
1175 		err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
1176 		if (err)
1177 			return err;
1178 		if (status & MV88E6393X_10G_INT_LINK_CHANGE) {
1179 			ret = IRQ_HANDLED;
1180 			mv88e6393x_serdes_irq_link_10g(chip, port, lane);
1181 		}
1182 		break;
1183 	}
1184 
1185 	return ret;
1186 }
1187 
1188 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1189 					int lane)
1190 {
1191 	u8 cmode = chip->ports[port].cmode;
1192 	irqreturn_t ret = IRQ_NONE;
1193 	u16 status;
1194 	int err;
1195 
1196 	switch (cmode) {
1197 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1198 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1199 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1200 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1201 		if (err)
1202 			return ret;
1203 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1204 			      MV88E6390_SGMII_INT_LINK_UP)) {
1205 			ret = IRQ_HANDLED;
1206 			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1207 		}
1208 	}
1209 
1210 	return ret;
1211 }
1212 
1213 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
1214 {
1215 	return irq_find_mapping(chip->g2_irq.domain, port);
1216 }
1217 
1218 static const u16 mv88e6390_serdes_regs[] = {
1219 	/* SERDES common registers */
1220 	0xf00a, 0xf00b, 0xf00c,
1221 	0xf010, 0xf011, 0xf012, 0xf013,
1222 	0xf016, 0xf017, 0xf018,
1223 	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
1224 	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
1225 	0xf028, 0xf029,
1226 	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
1227 	0xf038, 0xf039,
1228 	/* SGMII */
1229 	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
1230 	0x2008,
1231 	0x200f,
1232 	0xa000, 0xa001, 0xa002, 0xa003,
1233 	/* 10Gbase-X */
1234 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1235 	0x1008,
1236 	0x100e, 0x100f,
1237 	0x1018, 0x1019,
1238 	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
1239 	0x9006,
1240 	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
1241 	/* 10Gbase-R */
1242 	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1243 	0x1028, 0x1029, 0x102a, 0x102b,
1244 };
1245 
1246 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
1247 {
1248 	if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
1249 		return 0;
1250 
1251 	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
1252 }
1253 
1254 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
1255 {
1256 	u16 *p = _p;
1257 	int lane;
1258 	u16 reg;
1259 	int err;
1260 	int i;
1261 
1262 	lane = mv88e6xxx_serdes_get_lane(chip, port);
1263 	if (lane < 0)
1264 		return;
1265 
1266 	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
1267 		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1268 					    mv88e6390_serdes_regs[i], &reg);
1269 		if (!err)
1270 			p[i] = reg;
1271 	}
1272 }
1273 
1274 static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane)
1275 {
1276 	u16 reg, pcs;
1277 	int err;
1278 
1279 	/* mv88e6393x family errata 4.6:
1280 	 * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD
1281 	 * mode or P0_mode is configured for [x]MII.
1282 	 * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
1283 	 *
1284 	 * It seems that after this workaround the SERDES is automatically
1285 	 * powered up (the bit is cleared), so power it down.
1286 	 */
1287 	if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE ||
1288 	    lane == MV88E6393X_PORT10_LANE) {
1289 		err = mv88e6390_serdes_read(chip, lane,
1290 					    MDIO_MMD_PHYXS,
1291 					    MV88E6393X_SERDES_POC, &reg);
1292 		if (err)
1293 			return err;
1294 
1295 		reg &= ~MV88E6393X_SERDES_POC_PDOWN;
1296 		reg |= MV88E6393X_SERDES_POC_RESET;
1297 
1298 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1299 					     MV88E6393X_SERDES_POC, reg);
1300 		if (err)
1301 			return err;
1302 
1303 		err = mv88e6390_serdes_power_sgmii(chip, lane, false);
1304 		if (err)
1305 			return err;
1306 	}
1307 
1308 	/* mv88e6393x family errata 4.8:
1309 	 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may
1310 	 * not come up after hardware reset or software reset of SERDES core.
1311 	 * Workaround is to write SERDES register 4.F074.14=1 for only those
1312 	 * modes and 0 in all other modes.
1313 	 */
1314 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1315 				    MV88E6393X_SERDES_POC, &pcs);
1316 	if (err)
1317 		return err;
1318 
1319 	pcs &= MV88E6393X_SERDES_POC_PCS_MASK;
1320 
1321 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1322 				    MV88E6393X_ERRATA_4_8_REG, &reg);
1323 	if (err)
1324 		return err;
1325 
1326 	if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
1327 	    pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
1328 	    pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
1329 		reg |= MV88E6393X_ERRATA_4_8_BIT;
1330 	else
1331 		reg &= ~MV88E6393X_ERRATA_4_8_BIT;
1332 
1333 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1334 				      MV88E6393X_ERRATA_4_8_REG, reg);
1335 }
1336 
1337 int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip)
1338 {
1339 	int err;
1340 
1341 	err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT0_LANE);
1342 	if (err)
1343 		return err;
1344 
1345 	err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT9_LANE);
1346 	if (err)
1347 		return err;
1348 
1349 	return mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT10_LANE);
1350 }
1351 
1352 int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
1353 			    bool on)
1354 {
1355 	u8 cmode = chip->ports[port].cmode;
1356 
1357 	if (port != 0 && port != 9 && port != 10)
1358 		return -EOPNOTSUPP;
1359 
1360 	switch (cmode) {
1361 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
1362 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1363 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1364 		return mv88e6390_serdes_power_sgmii(chip, lane, on);
1365 	case MV88E6393X_PORT_STS_CMODE_5GBASER:
1366 	case MV88E6393X_PORT_STS_CMODE_10GBASER:
1367 		return mv88e6390_serdes_power_10g(chip, lane, on);
1368 	}
1369 
1370 	return 0;
1371 }
1372