xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/serdes.c (revision 7e0e6243)
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_PCS_CONTROL_1, &val);
538 
539 	if (err)
540 		return err;
541 
542 	if (up)
543 		new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
544 				  MV88E6390_PCS_CONTROL_1_LOOPBACK |
545 				  MV88E6390_PCS_CONTROL_1_PDOWN);
546 	else
547 		new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
548 
549 	if (val != new_val)
550 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
551 					     MV88E6390_PCS_CONTROL_1, 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 int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
752 				   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 int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
775 				    u8 lane)
776 {
777 	u16 bmcr;
778 	int err;
779 
780 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
781 				    MV88E6390_SGMII_BMCR, &bmcr);
782 	if (err)
783 		return err;
784 
785 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
786 				      MV88E6390_SGMII_BMCR,
787 				      bmcr | BMCR_ANRESTART);
788 }
789 
790 int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
791 				 u8 lane, int speed, int duplex)
792 {
793 	u16 val, bmcr;
794 	int err;
795 
796 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
797 				    MV88E6390_SGMII_BMCR, &val);
798 	if (err)
799 		return err;
800 
801 	bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
802 	switch (speed) {
803 	case SPEED_2500:
804 	case SPEED_1000:
805 		bmcr |= BMCR_SPEED1000;
806 		break;
807 	case SPEED_100:
808 		bmcr |= BMCR_SPEED100;
809 		break;
810 	case SPEED_10:
811 		break;
812 	}
813 
814 	if (duplex == DUPLEX_FULL)
815 		bmcr |= BMCR_FULLDPLX;
816 
817 	if (bmcr == val)
818 		return 0;
819 
820 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
821 				      MV88E6390_SGMII_BMCR, bmcr);
822 }
823 
824 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
825 					    int port, u8 lane)
826 {
827 	u16 bmsr;
828 	int err;
829 
830 	/* If the link has dropped, we want to know about it. */
831 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
832 				    MV88E6390_SGMII_BMSR, &bmsr);
833 	if (err) {
834 		dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
835 		return;
836 	}
837 
838 	dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
839 }
840 
841 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
842 					     u8 lane, bool enable)
843 {
844 	u16 val = 0;
845 
846 	if (enable)
847 		val |= MV88E6390_SGMII_INT_LINK_DOWN |
848 			MV88E6390_SGMII_INT_LINK_UP;
849 
850 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
851 				      MV88E6390_SGMII_INT_ENABLE, val);
852 }
853 
854 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
855 				bool enable)
856 {
857 	u8 cmode = chip->ports[port].cmode;
858 
859 	switch (cmode) {
860 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
861 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
862 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
863 		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
864 	}
865 
866 	return 0;
867 }
868 
869 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
870 					     u8 lane, u16 *status)
871 {
872 	int err;
873 
874 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
875 				    MV88E6390_SGMII_INT_STATUS, status);
876 
877 	return err;
878 }
879 
880 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
881 					u8 lane)
882 {
883 	u8 cmode = chip->ports[port].cmode;
884 	irqreturn_t ret = IRQ_NONE;
885 	u16 status;
886 	int err;
887 
888 	switch (cmode) {
889 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
890 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
891 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
892 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
893 		if (err)
894 			return ret;
895 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
896 			      MV88E6390_SGMII_INT_LINK_UP)) {
897 			ret = IRQ_HANDLED;
898 			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
899 		}
900 	}
901 
902 	return ret;
903 }
904 
905 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
906 {
907 	return irq_find_mapping(chip->g2_irq.domain, port);
908 }
909 
910 static const u16 mv88e6390_serdes_regs[] = {
911 	/* SERDES common registers */
912 	0xf00a, 0xf00b, 0xf00c,
913 	0xf010, 0xf011, 0xf012, 0xf013,
914 	0xf016, 0xf017, 0xf018,
915 	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
916 	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
917 	0xf028, 0xf029,
918 	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
919 	0xf038, 0xf039,
920 	/* SGMII */
921 	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
922 	0x2008,
923 	0x200f,
924 	0xa000, 0xa001, 0xa002, 0xa003,
925 	/* 10Gbase-X */
926 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
927 	0x1008,
928 	0x100e, 0x100f,
929 	0x1018, 0x1019,
930 	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
931 	0x9006,
932 	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
933 	/* 10Gbase-R */
934 	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
935 	0x1028, 0x1029, 0x102a, 0x102b,
936 };
937 
938 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
939 {
940 	if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
941 		return 0;
942 
943 	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
944 }
945 
946 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
947 {
948 	u16 *p = _p;
949 	int lane;
950 	u16 reg;
951 	int i;
952 
953 	lane = mv88e6xxx_serdes_get_lane(chip, port);
954 	if (lane == 0)
955 		return;
956 
957 	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
958 		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
959 				      mv88e6390_serdes_regs[i], &reg);
960 		p[i] = reg;
961 	}
962 }
963