xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/serdes.c (revision f97769fd)
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, u8 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 				u8 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 				   u8 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 				    u8 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 				 u8 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 u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
234 {
235 	u8 cmode = chip->ports[port].cmode;
236 	u8 lane = 0;
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))
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 					u8 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, u8 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 i;
404 
405 	if (!mv88e6352_port_has_serdes(chip, port))
406 		return;
407 
408 	for (i = 0 ; i < 32; i++) {
409 		mv88e6352_serdes_read(chip, i, &reg);
410 		p[i] = reg;
411 	}
412 }
413 
414 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
415 {
416 	u8 cmode = chip->ports[port].cmode;
417 	u8 lane = 0;
418 
419 	switch (port) {
420 	case 5:
421 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
422 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
423 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
424 			lane = MV88E6341_PORT5_LANE;
425 		break;
426 	}
427 
428 	return lane;
429 }
430 
431 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
432 {
433 	u8 cmode = chip->ports[port].cmode;
434 	u8 lane = 0;
435 
436 	switch (port) {
437 	case 9:
438 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
439 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
440 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
441 			lane = MV88E6390_PORT9_LANE0;
442 		break;
443 	case 10:
444 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
445 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
446 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
447 			lane = MV88E6390_PORT10_LANE0;
448 		break;
449 	}
450 
451 	return lane;
452 }
453 
454 u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
455 {
456 	u8 cmode_port = chip->ports[port].cmode;
457 	u8 cmode_port10 = chip->ports[10].cmode;
458 	u8 cmode_port9 = chip->ports[9].cmode;
459 	u8 lane = 0;
460 
461 	switch (port) {
462 	case 2:
463 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
464 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
465 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
466 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
467 				lane = MV88E6390_PORT9_LANE1;
468 		break;
469 	case 3:
470 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
471 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
472 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
473 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
474 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
475 				lane = MV88E6390_PORT9_LANE2;
476 		break;
477 	case 4:
478 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
479 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
480 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
481 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
482 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
483 				lane = MV88E6390_PORT9_LANE3;
484 		break;
485 	case 5:
486 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
487 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
488 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
489 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
490 				lane = MV88E6390_PORT10_LANE1;
491 		break;
492 	case 6:
493 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
494 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
495 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
496 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
497 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
498 				lane = MV88E6390_PORT10_LANE2;
499 		break;
500 	case 7:
501 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
502 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
503 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
504 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
505 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
506 				lane = MV88E6390_PORT10_LANE3;
507 		break;
508 	case 9:
509 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
510 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
511 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
512 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
513 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
514 			lane = MV88E6390_PORT9_LANE0;
515 		break;
516 	case 10:
517 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
518 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
519 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
520 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
521 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
522 			lane = MV88E6390_PORT10_LANE0;
523 		break;
524 	}
525 
526 	return lane;
527 }
528 
529 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
530 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
531 				      bool up)
532 {
533 	u16 val, new_val;
534 	int err;
535 
536 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
537 				    MV88E6390_10G_CTRL1, &val);
538 
539 	if (err)
540 		return err;
541 
542 	if (up)
543 		new_val = val & ~(MDIO_CTRL1_RESET |
544 				  MDIO_PCS_CTRL1_LOOPBACK |
545 				  MDIO_CTRL1_LPOWER);
546 	else
547 		new_val = val | MDIO_CTRL1_LPOWER;
548 
549 	if (val != new_val)
550 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
551 					     MV88E6390_10G_CTRL1, new_val);
552 
553 	return err;
554 }
555 
556 /* Set power up/down for SGMII and 1000Base-X */
557 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
558 					bool up)
559 {
560 	u16 val, new_val;
561 	int err;
562 
563 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
564 				    MV88E6390_SGMII_BMCR, &val);
565 	if (err)
566 		return err;
567 
568 	if (up)
569 		new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
570 	else
571 		new_val = val | BMCR_PDOWN;
572 
573 	if (val != new_val)
574 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
575 					     MV88E6390_SGMII_BMCR, new_val);
576 
577 	return err;
578 }
579 
580 struct mv88e6390_serdes_hw_stat {
581 	char string[ETH_GSTRING_LEN];
582 	int reg;
583 };
584 
585 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
586 	{ "serdes_rx_pkts", 0xf021 },
587 	{ "serdes_rx_bytes", 0xf024 },
588 	{ "serdes_rx_pkts_error", 0xf027 },
589 };
590 
591 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
592 {
593 	if (mv88e6390_serdes_get_lane(chip, port) == 0)
594 		return 0;
595 
596 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
597 }
598 
599 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
600 				 int port, uint8_t *data)
601 {
602 	struct mv88e6390_serdes_hw_stat *stat;
603 	int i;
604 
605 	if (mv88e6390_serdes_get_lane(chip, port) == 0)
606 		return 0;
607 
608 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
609 		stat = &mv88e6390_serdes_hw_stats[i];
610 		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
611 		       ETH_GSTRING_LEN);
612 	}
613 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
614 }
615 
616 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
617 					  struct mv88e6390_serdes_hw_stat *stat)
618 {
619 	u16 reg[3];
620 	int err, i;
621 
622 	for (i = 0; i < 3; i++) {
623 		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
624 					    stat->reg + i, &reg[i]);
625 		if (err) {
626 			dev_err(chip->dev, "failed to read statistic\n");
627 			return 0;
628 		}
629 	}
630 
631 	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
632 }
633 
634 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
635 			       uint64_t *data)
636 {
637 	struct mv88e6390_serdes_hw_stat *stat;
638 	int lane;
639 	int i;
640 
641 	lane = mv88e6390_serdes_get_lane(chip, port);
642 	if (lane == 0)
643 		return 0;
644 
645 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
646 		stat = &mv88e6390_serdes_hw_stats[i];
647 		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
648 	}
649 
650 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
651 }
652 
653 static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
654 {
655 	u16 reg;
656 	int err;
657 
658 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
659 				    MV88E6390_PG_CONTROL, &reg);
660 	if (err)
661 		return err;
662 
663 	reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
664 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
665 				      MV88E6390_PG_CONTROL, reg);
666 }
667 
668 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
669 			   bool up)
670 {
671 	u8 cmode = chip->ports[port].cmode;
672 	int err = 0;
673 
674 	switch (cmode) {
675 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
676 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
677 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
678 		err = mv88e6390_serdes_power_sgmii(chip, lane, up);
679 		break;
680 	case MV88E6XXX_PORT_STS_CMODE_XAUI:
681 	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
682 		err = mv88e6390_serdes_power_10g(chip, lane, up);
683 		break;
684 	}
685 
686 	if (!err && up)
687 		err = mv88e6390_serdes_enable_checker(chip, lane);
688 
689 	return err;
690 }
691 
692 int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
693 				u8 lane, unsigned int mode,
694 				phy_interface_t interface,
695 				const unsigned long *advertise)
696 {
697 	u16 val, bmcr, adv;
698 	bool changed;
699 	int err;
700 
701 	switch (interface) {
702 	case PHY_INTERFACE_MODE_SGMII:
703 		adv = 0x0001;
704 		break;
705 
706 	case PHY_INTERFACE_MODE_1000BASEX:
707 		adv = linkmode_adv_to_mii_adv_x(advertise,
708 					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
709 		break;
710 
711 	case PHY_INTERFACE_MODE_2500BASEX:
712 		adv = linkmode_adv_to_mii_adv_x(advertise,
713 					ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
714 		break;
715 
716 	default:
717 		return 0;
718 	}
719 
720 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
721 				    MV88E6390_SGMII_ADVERTISE, &val);
722 	if (err)
723 		return err;
724 
725 	changed = val != adv;
726 	if (changed) {
727 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
728 					     MV88E6390_SGMII_ADVERTISE, adv);
729 		if (err)
730 			return err;
731 	}
732 
733 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
734 				    MV88E6390_SGMII_BMCR, &val);
735 	if (err)
736 		return err;
737 
738 	if (phylink_autoneg_inband(mode))
739 		bmcr = val | BMCR_ANENABLE;
740 	else
741 		bmcr = val & ~BMCR_ANENABLE;
742 
743 	/* setting ANENABLE triggers a restart of negotiation */
744 	if (bmcr == val)
745 		return changed;
746 
747 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
748 				      MV88E6390_SGMII_BMCR, bmcr);
749 }
750 
751 static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
752 	int port, u8 lane, struct phylink_link_state *state)
753 {
754 	u16 lpa, status;
755 	int err;
756 
757 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
758 				    MV88E6390_SGMII_PHY_STATUS, &status);
759 	if (err) {
760 		dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
761 		return err;
762 	}
763 
764 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
765 				    MV88E6390_SGMII_LPA, &lpa);
766 	if (err) {
767 		dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
768 		return err;
769 	}
770 
771 	return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
772 }
773 
774 static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
775 	int port, u8 lane, struct phylink_link_state *state)
776 {
777 	u16 status;
778 	int err;
779 
780 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
781 				    MV88E6390_10G_STAT1, &status);
782 	if (err)
783 		return err;
784 
785 	state->link = !!(status & MDIO_STAT1_LSTATUS);
786 	if (state->link) {
787 		state->speed = SPEED_10000;
788 		state->duplex = DUPLEX_FULL;
789 	}
790 
791 	return 0;
792 }
793 
794 int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
795 				   u8 lane, struct phylink_link_state *state)
796 {
797 	switch (state->interface) {
798 	case PHY_INTERFACE_MODE_SGMII:
799 	case PHY_INTERFACE_MODE_1000BASEX:
800 	case PHY_INTERFACE_MODE_2500BASEX:
801 		return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
802 							    state);
803 	case PHY_INTERFACE_MODE_XAUI:
804 	case PHY_INTERFACE_MODE_RXAUI:
805 		return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
806 							  state);
807 
808 	default:
809 		return -EOPNOTSUPP;
810 	}
811 }
812 
813 int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
814 				    u8 lane)
815 {
816 	u16 bmcr;
817 	int err;
818 
819 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
820 				    MV88E6390_SGMII_BMCR, &bmcr);
821 	if (err)
822 		return err;
823 
824 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
825 				      MV88E6390_SGMII_BMCR,
826 				      bmcr | BMCR_ANRESTART);
827 }
828 
829 int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
830 				 u8 lane, int speed, int duplex)
831 {
832 	u16 val, bmcr;
833 	int err;
834 
835 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
836 				    MV88E6390_SGMII_BMCR, &val);
837 	if (err)
838 		return err;
839 
840 	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
841 	switch (speed) {
842 	case SPEED_2500:
843 	case SPEED_1000:
844 		bmcr |= BMCR_SPEED1000;
845 		break;
846 	case SPEED_100:
847 		bmcr |= BMCR_SPEED100;
848 		break;
849 	case SPEED_10:
850 		break;
851 	}
852 
853 	if (duplex == DUPLEX_FULL)
854 		bmcr |= BMCR_FULLDPLX;
855 
856 	if (bmcr == val)
857 		return 0;
858 
859 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
860 				      MV88E6390_SGMII_BMCR, bmcr);
861 }
862 
863 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
864 					    int port, u8 lane)
865 {
866 	u16 bmsr;
867 	int err;
868 
869 	/* If the link has dropped, we want to know about it. */
870 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
871 				    MV88E6390_SGMII_BMSR, &bmsr);
872 	if (err) {
873 		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
874 		return;
875 	}
876 
877 	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
878 }
879 
880 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
881 					     u8 lane, bool enable)
882 {
883 	u16 val = 0;
884 
885 	if (enable)
886 		val |= MV88E6390_SGMII_INT_LINK_DOWN |
887 			MV88E6390_SGMII_INT_LINK_UP;
888 
889 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
890 				      MV88E6390_SGMII_INT_ENABLE, val);
891 }
892 
893 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
894 				bool enable)
895 {
896 	u8 cmode = chip->ports[port].cmode;
897 
898 	switch (cmode) {
899 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
900 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
901 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
902 		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
903 	}
904 
905 	return 0;
906 }
907 
908 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
909 					     u8 lane, u16 *status)
910 {
911 	int err;
912 
913 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
914 				    MV88E6390_SGMII_INT_STATUS, status);
915 
916 	return err;
917 }
918 
919 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
920 					u8 lane)
921 {
922 	u8 cmode = chip->ports[port].cmode;
923 	irqreturn_t ret = IRQ_NONE;
924 	u16 status;
925 	int err;
926 
927 	switch (cmode) {
928 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
929 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
930 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
931 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
932 		if (err)
933 			return ret;
934 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
935 			      MV88E6390_SGMII_INT_LINK_UP)) {
936 			ret = IRQ_HANDLED;
937 			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
938 		}
939 	}
940 
941 	return ret;
942 }
943 
944 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
945 {
946 	return irq_find_mapping(chip->g2_irq.domain, port);
947 }
948 
949 static const u16 mv88e6390_serdes_regs[] = {
950 	/* SERDES common registers */
951 	0xf00a, 0xf00b, 0xf00c,
952 	0xf010, 0xf011, 0xf012, 0xf013,
953 	0xf016, 0xf017, 0xf018,
954 	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
955 	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
956 	0xf028, 0xf029,
957 	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
958 	0xf038, 0xf039,
959 	/* SGMII */
960 	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
961 	0x2008,
962 	0x200f,
963 	0xa000, 0xa001, 0xa002, 0xa003,
964 	/* 10Gbase-X */
965 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
966 	0x1008,
967 	0x100e, 0x100f,
968 	0x1018, 0x1019,
969 	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
970 	0x9006,
971 	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
972 	/* 10Gbase-R */
973 	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
974 	0x1028, 0x1029, 0x102a, 0x102b,
975 };
976 
977 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
978 {
979 	if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
980 		return 0;
981 
982 	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
983 }
984 
985 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
986 {
987 	u16 *p = _p;
988 	int lane;
989 	u16 reg;
990 	int i;
991 
992 	lane = mv88e6xxx_serdes_get_lane(chip, port);
993 	if (lane == 0)
994 		return;
995 
996 	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
997 		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
998 				      mv88e6390_serdes_regs[i], &reg);
999 		p[i] = reg;
1000 	}
1001 }
1002