xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/serdes.c (revision 4c8b7350)
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 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
53 			   bool up)
54 {
55 	u16 val, new_val;
56 	int err;
57 
58 	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
59 	if (err)
60 		return err;
61 
62 	if (up)
63 		new_val = val & ~BMCR_PDOWN;
64 	else
65 		new_val = val | BMCR_PDOWN;
66 
67 	if (val != new_val)
68 		err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
69 
70 	return err;
71 }
72 
73 u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
74 {
75 	u8 cmode = chip->ports[port].cmode;
76 	u8 lane = 0;
77 
78 	if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
79 	    (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
80 	    (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
81 		lane = 0xff; /* Unused */
82 
83 	return lane;
84 }
85 
86 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
87 {
88 	if (mv88e6xxx_serdes_get_lane(chip, port))
89 		return true;
90 
91 	return false;
92 }
93 
94 struct mv88e6352_serdes_hw_stat {
95 	char string[ETH_GSTRING_LEN];
96 	int sizeof_stat;
97 	int reg;
98 };
99 
100 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
101 	{ "serdes_fibre_rx_error", 16, 21 },
102 	{ "serdes_PRBS_error", 32, 24 },
103 };
104 
105 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
106 {
107 	if (mv88e6352_port_has_serdes(chip, port))
108 		return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
109 
110 	return 0;
111 }
112 
113 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
114 				 int port, uint8_t *data)
115 {
116 	struct mv88e6352_serdes_hw_stat *stat;
117 	int i;
118 
119 	if (!mv88e6352_port_has_serdes(chip, port))
120 		return 0;
121 
122 	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
123 		stat = &mv88e6352_serdes_hw_stats[i];
124 		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
125 		       ETH_GSTRING_LEN);
126 	}
127 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
128 }
129 
130 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
131 					  struct mv88e6352_serdes_hw_stat *stat)
132 {
133 	u64 val = 0;
134 	u16 reg;
135 	int err;
136 
137 	err = mv88e6352_serdes_read(chip, stat->reg, &reg);
138 	if (err) {
139 		dev_err(chip->dev, "failed to read statistic\n");
140 		return 0;
141 	}
142 
143 	val = reg;
144 
145 	if (stat->sizeof_stat == 32) {
146 		err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
147 		if (err) {
148 			dev_err(chip->dev, "failed to read statistic\n");
149 			return 0;
150 		}
151 		val = val << 16 | reg;
152 	}
153 
154 	return val;
155 }
156 
157 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
158 			       uint64_t *data)
159 {
160 	struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
161 	struct mv88e6352_serdes_hw_stat *stat;
162 	u64 value;
163 	int i;
164 
165 	if (!mv88e6352_port_has_serdes(chip, port))
166 		return 0;
167 
168 	BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
169 		     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
170 
171 	for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
172 		stat = &mv88e6352_serdes_hw_stats[i];
173 		value = mv88e6352_serdes_get_stat(chip, stat);
174 		mv88e6xxx_port->serdes_stats[i] += value;
175 		data[i] = mv88e6xxx_port->serdes_stats[i];
176 	}
177 
178 	return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
179 }
180 
181 static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
182 {
183 	struct dsa_switch *ds = chip->ds;
184 	u16 status;
185 	bool up;
186 	int err;
187 
188 	err = mv88e6352_serdes_read(chip, MII_BMSR, &status);
189 	if (err)
190 		return;
191 
192 	/* Status must be read twice in order to give the current link
193 	 * status. Otherwise the change in link status since the last
194 	 * read of the register is returned.
195 	 */
196 	err = mv88e6352_serdes_read(chip, MII_BMSR, &status);
197 	if (err)
198 		return;
199 
200 	up = status & BMSR_LSTATUS;
201 
202 	dsa_port_phylink_mac_change(ds, port, up);
203 }
204 
205 irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
206 					u8 lane)
207 {
208 	irqreturn_t ret = IRQ_NONE;
209 	u16 status;
210 	int err;
211 
212 	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
213 	if (err)
214 		return ret;
215 
216 	if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
217 		ret = IRQ_HANDLED;
218 		mv88e6352_serdes_irq_link(chip, port);
219 	}
220 
221 	return ret;
222 }
223 
224 int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
225 				bool enable)
226 {
227 	u16 val = 0;
228 
229 	if (enable)
230 		val |= MV88E6352_SERDES_INT_LINK_CHANGE;
231 
232 	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
233 }
234 
235 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
236 {
237 	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
238 }
239 
240 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
241 {
242 	if (!mv88e6352_port_has_serdes(chip, port))
243 		return 0;
244 
245 	return 32 * sizeof(u16);
246 }
247 
248 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
249 {
250 	u16 *p = _p;
251 	u16 reg;
252 	int i;
253 
254 	if (!mv88e6352_port_has_serdes(chip, port))
255 		return;
256 
257 	for (i = 0 ; i < 32; i++) {
258 		mv88e6352_serdes_read(chip, i, &reg);
259 		p[i] = reg;
260 	}
261 }
262 
263 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
264 {
265 	u8 cmode = chip->ports[port].cmode;
266 	u8 lane = 0;
267 
268 	switch (port) {
269 	case 5:
270 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
271 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
272 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
273 			lane = MV88E6341_PORT5_LANE;
274 		break;
275 	}
276 
277 	return lane;
278 }
279 
280 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
281 {
282 	u8 cmode = chip->ports[port].cmode;
283 	u8 lane = 0;
284 
285 	switch (port) {
286 	case 9:
287 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
288 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
289 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
290 			lane = MV88E6390_PORT9_LANE0;
291 		break;
292 	case 10:
293 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
294 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
295 		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
296 			lane = MV88E6390_PORT10_LANE0;
297 		break;
298 	}
299 
300 	return lane;
301 }
302 
303 u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
304 {
305 	u8 cmode_port = chip->ports[port].cmode;
306 	u8 cmode_port10 = chip->ports[10].cmode;
307 	u8 cmode_port9 = chip->ports[9].cmode;
308 	u8 lane = 0;
309 
310 	switch (port) {
311 	case 2:
312 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
313 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
314 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
315 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
316 				lane = MV88E6390_PORT9_LANE1;
317 		break;
318 	case 3:
319 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
320 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
321 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
322 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
323 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
324 				lane = MV88E6390_PORT9_LANE2;
325 		break;
326 	case 4:
327 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
328 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
329 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
330 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
331 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
332 				lane = MV88E6390_PORT9_LANE3;
333 		break;
334 	case 5:
335 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
336 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
337 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
338 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
339 				lane = MV88E6390_PORT10_LANE1;
340 		break;
341 	case 6:
342 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
343 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
344 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
345 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
346 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
347 				lane = MV88E6390_PORT10_LANE2;
348 		break;
349 	case 7:
350 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
351 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
352 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
353 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
354 			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
355 				lane = MV88E6390_PORT10_LANE3;
356 		break;
357 	case 9:
358 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
359 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
360 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
361 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
362 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
363 			lane = MV88E6390_PORT9_LANE0;
364 		break;
365 	case 10:
366 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
367 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
368 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
369 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
370 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
371 			lane = MV88E6390_PORT10_LANE0;
372 		break;
373 	}
374 
375 	return lane;
376 }
377 
378 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
379 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
380 				      bool up)
381 {
382 	u16 val, new_val;
383 	int err;
384 
385 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
386 				    MV88E6390_PCS_CONTROL_1, &val);
387 
388 	if (err)
389 		return err;
390 
391 	if (up)
392 		new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
393 				  MV88E6390_PCS_CONTROL_1_LOOPBACK |
394 				  MV88E6390_PCS_CONTROL_1_PDOWN);
395 	else
396 		new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
397 
398 	if (val != new_val)
399 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
400 					     MV88E6390_PCS_CONTROL_1, new_val);
401 
402 	return err;
403 }
404 
405 /* Set power up/down for SGMII and 1000Base-X */
406 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
407 					bool up)
408 {
409 	u16 val, new_val;
410 	int err;
411 
412 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
413 				    MV88E6390_SGMII_BMCR, &val);
414 	if (err)
415 		return err;
416 
417 	if (up)
418 		new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
419 	else
420 		new_val = val | BMCR_PDOWN;
421 
422 	if (val != new_val)
423 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
424 					     MV88E6390_SGMII_BMCR, new_val);
425 
426 	return err;
427 }
428 
429 struct mv88e6390_serdes_hw_stat {
430 	char string[ETH_GSTRING_LEN];
431 	int reg;
432 };
433 
434 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
435 	{ "serdes_rx_pkts", 0xf021 },
436 	{ "serdes_rx_bytes", 0xf024 },
437 	{ "serdes_rx_pkts_error", 0xf027 },
438 };
439 
440 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
441 {
442 	if (mv88e6390_serdes_get_lane(chip, port) == 0)
443 		return 0;
444 
445 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
446 }
447 
448 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
449 				 int port, uint8_t *data)
450 {
451 	struct mv88e6390_serdes_hw_stat *stat;
452 	int i;
453 
454 	if (mv88e6390_serdes_get_lane(chip, port) == 0)
455 		return 0;
456 
457 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
458 		stat = &mv88e6390_serdes_hw_stats[i];
459 		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
460 		       ETH_GSTRING_LEN);
461 	}
462 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
463 }
464 
465 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
466 					  struct mv88e6390_serdes_hw_stat *stat)
467 {
468 	u16 reg[3];
469 	int err, i;
470 
471 	for (i = 0; i < 3; i++) {
472 		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
473 					    stat->reg + i, &reg[i]);
474 		if (err) {
475 			dev_err(chip->dev, "failed to read statistic\n");
476 			return 0;
477 		}
478 	}
479 
480 	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
481 }
482 
483 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
484 			       uint64_t *data)
485 {
486 	struct mv88e6390_serdes_hw_stat *stat;
487 	int lane;
488 	int i;
489 
490 	lane = mv88e6390_serdes_get_lane(chip, port);
491 	if (lane == 0)
492 		return 0;
493 
494 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
495 		stat = &mv88e6390_serdes_hw_stats[i];
496 		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
497 	}
498 
499 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
500 }
501 
502 static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
503 {
504 	u16 reg;
505 	int err;
506 
507 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
508 				    MV88E6390_PG_CONTROL, &reg);
509 	if (err)
510 		return err;
511 
512 	reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
513 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
514 				      MV88E6390_PG_CONTROL, reg);
515 }
516 
517 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
518 			   bool up)
519 {
520 	u8 cmode = chip->ports[port].cmode;
521 	int err = 0;
522 
523 	switch (cmode) {
524 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
525 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
526 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
527 		err = mv88e6390_serdes_power_sgmii(chip, lane, up);
528 		break;
529 	case MV88E6XXX_PORT_STS_CMODE_XAUI:
530 	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
531 		err = mv88e6390_serdes_power_10g(chip, lane, up);
532 		break;
533 	}
534 
535 	if (!err && up)
536 		err = mv88e6390_serdes_enable_checker(chip, lane);
537 
538 	return err;
539 }
540 
541 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
542 					    int port, u8 lane)
543 {
544 	u8 cmode = chip->ports[port].cmode;
545 	struct dsa_switch *ds = chip->ds;
546 	int duplex = DUPLEX_UNKNOWN;
547 	int speed = SPEED_UNKNOWN;
548 	phy_interface_t mode;
549 	int link, err;
550 	u16 status;
551 
552 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
553 				    MV88E6390_SGMII_PHY_STATUS, &status);
554 	if (err) {
555 		dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err);
556 		return;
557 	}
558 
559 	link = status & MV88E6390_SGMII_PHY_STATUS_LINK ?
560 	       LINK_FORCED_UP : LINK_FORCED_DOWN;
561 
562 	if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
563 		duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
564 			 DUPLEX_FULL : DUPLEX_HALF;
565 
566 		switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
567 		case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
568 			if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
569 				speed = SPEED_2500;
570 			else
571 				speed = SPEED_1000;
572 			break;
573 		case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
574 			speed = SPEED_100;
575 			break;
576 		case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
577 			speed = SPEED_10;
578 			break;
579 		default:
580 			dev_err(chip->dev, "invalid PHY speed\n");
581 			return;
582 		}
583 	}
584 
585 	switch (cmode) {
586 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
587 		mode = PHY_INTERFACE_MODE_SGMII;
588 		break;
589 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
590 		mode = PHY_INTERFACE_MODE_1000BASEX;
591 		break;
592 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
593 		mode = PHY_INTERFACE_MODE_2500BASEX;
594 		break;
595 	default:
596 		mode = PHY_INTERFACE_MODE_NA;
597 	}
598 
599 	err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
600 				       PAUSE_OFF, mode);
601 	if (err)
602 		dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
603 			err);
604 	else
605 		dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP);
606 }
607 
608 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
609 					     u8 lane, bool enable)
610 {
611 	u16 val = 0;
612 
613 	if (enable)
614 		val |= MV88E6390_SGMII_INT_LINK_DOWN |
615 			MV88E6390_SGMII_INT_LINK_UP;
616 
617 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
618 				      MV88E6390_SGMII_INT_ENABLE, val);
619 }
620 
621 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
622 				bool enable)
623 {
624 	u8 cmode = chip->ports[port].cmode;
625 
626 	switch (cmode) {
627 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
628 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
629 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
630 		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
631 	}
632 
633 	return 0;
634 }
635 
636 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
637 					     u8 lane, u16 *status)
638 {
639 	int err;
640 
641 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
642 				    MV88E6390_SGMII_INT_STATUS, status);
643 
644 	return err;
645 }
646 
647 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
648 					u8 lane)
649 {
650 	u8 cmode = chip->ports[port].cmode;
651 	irqreturn_t ret = IRQ_NONE;
652 	u16 status;
653 	int err;
654 
655 	switch (cmode) {
656 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
657 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
658 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
659 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
660 		if (err)
661 			return ret;
662 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
663 			      MV88E6390_SGMII_INT_LINK_UP)) {
664 			ret = IRQ_HANDLED;
665 			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
666 		}
667 	}
668 
669 	return ret;
670 }
671 
672 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
673 {
674 	return irq_find_mapping(chip->g2_irq.domain, port);
675 }
676 
677 static const u16 mv88e6390_serdes_regs[] = {
678 	/* SERDES common registers */
679 	0xf00a, 0xf00b, 0xf00c,
680 	0xf010, 0xf011, 0xf012, 0xf013,
681 	0xf016, 0xf017, 0xf018,
682 	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
683 	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
684 	0xf028, 0xf029,
685 	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
686 	0xf038, 0xf039,
687 	/* SGMII */
688 	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
689 	0x2008,
690 	0x200f,
691 	0xa000, 0xa001, 0xa002, 0xa003,
692 	/* 10Gbase-X */
693 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
694 	0x1008,
695 	0x100e, 0x100f,
696 	0x1018, 0x1019,
697 	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
698 	0x9006,
699 	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
700 	/* 10Gbase-R */
701 	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
702 	0x1028, 0x1029, 0x102a, 0x102b,
703 };
704 
705 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
706 {
707 	if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
708 		return 0;
709 
710 	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
711 }
712 
713 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
714 {
715 	u16 *p = _p;
716 	int lane;
717 	u16 reg;
718 	int i;
719 
720 	lane = mv88e6xxx_serdes_get_lane(chip, port);
721 	if (lane == 0)
722 		return;
723 
724 	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
725 		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
726 				      mv88e6390_serdes_regs[i], &reg);
727 		p[i] = reg;
728 	}
729 }
730