xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/serdes.c (revision bf3504ce)
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_CONTROL, &val);
414 	if (err)
415 		return err;
416 
417 	if (up)
418 		new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
419 				  MV88E6390_SGMII_CONTROL_LOOPBACK |
420 				  MV88E6390_SGMII_CONTROL_PDOWN);
421 	else
422 		new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
423 
424 	if (val != new_val)
425 		err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
426 					     MV88E6390_SGMII_CONTROL, new_val);
427 
428 	return err;
429 }
430 
431 struct mv88e6390_serdes_hw_stat {
432 	char string[ETH_GSTRING_LEN];
433 	int reg;
434 };
435 
436 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
437 	{ "serdes_rx_pkts", 0xf021 },
438 	{ "serdes_rx_bytes", 0xf024 },
439 	{ "serdes_rx_pkts_error", 0xf027 },
440 };
441 
442 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
443 {
444 	if (mv88e6390_serdes_get_lane(chip, port) == 0)
445 		return 0;
446 
447 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
448 }
449 
450 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
451 				 int port, uint8_t *data)
452 {
453 	struct mv88e6390_serdes_hw_stat *stat;
454 	int i;
455 
456 	if (mv88e6390_serdes_get_lane(chip, port) == 0)
457 		return 0;
458 
459 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
460 		stat = &mv88e6390_serdes_hw_stats[i];
461 		memcpy(data + i * ETH_GSTRING_LEN, stat->string,
462 		       ETH_GSTRING_LEN);
463 	}
464 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
465 }
466 
467 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
468 					  struct mv88e6390_serdes_hw_stat *stat)
469 {
470 	u16 reg[3];
471 	int err, i;
472 
473 	for (i = 0; i < 3; i++) {
474 		err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
475 					    stat->reg + i, &reg[i]);
476 		if (err) {
477 			dev_err(chip->dev, "failed to read statistic\n");
478 			return 0;
479 		}
480 	}
481 
482 	return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
483 }
484 
485 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
486 			       uint64_t *data)
487 {
488 	struct mv88e6390_serdes_hw_stat *stat;
489 	int lane;
490 	int i;
491 
492 	lane = mv88e6390_serdes_get_lane(chip, port);
493 	if (lane == 0)
494 		return 0;
495 
496 	for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
497 		stat = &mv88e6390_serdes_hw_stats[i];
498 		data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
499 	}
500 
501 	return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
502 }
503 
504 static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
505 {
506 	u16 reg;
507 	int err;
508 
509 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
510 				    MV88E6390_PG_CONTROL, &reg);
511 	if (err)
512 		return err;
513 
514 	reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
515 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
516 				      MV88E6390_PG_CONTROL, reg);
517 }
518 
519 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
520 			   bool up)
521 {
522 	u8 cmode = chip->ports[port].cmode;
523 	int err = 0;
524 
525 	switch (cmode) {
526 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
527 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
528 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
529 		err = mv88e6390_serdes_power_sgmii(chip, lane, up);
530 		break;
531 	case MV88E6XXX_PORT_STS_CMODE_XAUI:
532 	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
533 		err = mv88e6390_serdes_power_10g(chip, lane, up);
534 		break;
535 	}
536 
537 	if (!err && up)
538 		err = mv88e6390_serdes_enable_checker(chip, lane);
539 
540 	return err;
541 }
542 
543 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
544 					    int port, u8 lane)
545 {
546 	u8 cmode = chip->ports[port].cmode;
547 	struct dsa_switch *ds = chip->ds;
548 	int duplex = DUPLEX_UNKNOWN;
549 	int speed = SPEED_UNKNOWN;
550 	phy_interface_t mode;
551 	int link, err;
552 	u16 status;
553 
554 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
555 				    MV88E6390_SGMII_PHY_STATUS, &status);
556 	if (err) {
557 		dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err);
558 		return;
559 	}
560 
561 	link = status & MV88E6390_SGMII_PHY_STATUS_LINK ?
562 	       LINK_FORCED_UP : LINK_FORCED_DOWN;
563 
564 	if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
565 		duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
566 			 DUPLEX_FULL : DUPLEX_HALF;
567 
568 		switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
569 		case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
570 			if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
571 				speed = SPEED_2500;
572 			else
573 				speed = SPEED_1000;
574 			break;
575 		case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
576 			speed = SPEED_100;
577 			break;
578 		case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
579 			speed = SPEED_10;
580 			break;
581 		default:
582 			dev_err(chip->dev, "invalid PHY speed\n");
583 			return;
584 		}
585 	}
586 
587 	switch (cmode) {
588 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
589 		mode = PHY_INTERFACE_MODE_SGMII;
590 		break;
591 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
592 		mode = PHY_INTERFACE_MODE_1000BASEX;
593 		break;
594 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
595 		mode = PHY_INTERFACE_MODE_2500BASEX;
596 		break;
597 	default:
598 		mode = PHY_INTERFACE_MODE_NA;
599 	}
600 
601 	err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
602 				       PAUSE_OFF, mode);
603 	if (err)
604 		dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
605 			err);
606 	else
607 		dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP);
608 }
609 
610 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
611 					     u8 lane, bool enable)
612 {
613 	u16 val = 0;
614 
615 	if (enable)
616 		val |= MV88E6390_SGMII_INT_LINK_DOWN |
617 			MV88E6390_SGMII_INT_LINK_UP;
618 
619 	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
620 				      MV88E6390_SGMII_INT_ENABLE, val);
621 }
622 
623 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
624 				bool enable)
625 {
626 	u8 cmode = chip->ports[port].cmode;
627 
628 	switch (cmode) {
629 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
630 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
631 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
632 		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
633 	}
634 
635 	return 0;
636 }
637 
638 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
639 					     u8 lane, u16 *status)
640 {
641 	int err;
642 
643 	err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
644 				    MV88E6390_SGMII_INT_STATUS, status);
645 
646 	return err;
647 }
648 
649 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
650 					u8 lane)
651 {
652 	u8 cmode = chip->ports[port].cmode;
653 	irqreturn_t ret = IRQ_NONE;
654 	u16 status;
655 	int err;
656 
657 	switch (cmode) {
658 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
659 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
660 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
661 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
662 		if (err)
663 			return ret;
664 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
665 			      MV88E6390_SGMII_INT_LINK_UP)) {
666 			ret = IRQ_HANDLED;
667 			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
668 		}
669 	}
670 
671 	return ret;
672 }
673 
674 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
675 {
676 	return irq_find_mapping(chip->g2_irq.domain, port);
677 }
678 
679 static const u16 mv88e6390_serdes_regs[] = {
680 	/* SERDES common registers */
681 	0xf00a, 0xf00b, 0xf00c,
682 	0xf010, 0xf011, 0xf012, 0xf013,
683 	0xf016, 0xf017, 0xf018,
684 	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
685 	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
686 	0xf028, 0xf029,
687 	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
688 	0xf038, 0xf039,
689 	/* SGMII */
690 	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
691 	0x2008,
692 	0x200f,
693 	0xa000, 0xa001, 0xa002, 0xa003,
694 	/* 10Gbase-X */
695 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
696 	0x1008,
697 	0x100e, 0x100f,
698 	0x1018, 0x1019,
699 	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
700 	0x9006,
701 	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
702 	/* 10Gbase-R */
703 	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
704 	0x1028, 0x1029, 0x102a, 0x102b,
705 };
706 
707 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
708 {
709 	if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
710 		return 0;
711 
712 	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
713 }
714 
715 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
716 {
717 	u16 *p = _p;
718 	int lane;
719 	u16 reg;
720 	int i;
721 
722 	lane = mv88e6xxx_serdes_get_lane(chip, port);
723 	if (lane == 0)
724 		return;
725 
726 	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
727 		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
728 				      mv88e6390_serdes_regs[i], &reg);
729 		p[i] = reg;
730 	}
731 }
732