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