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