]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/net/dsa/mv88e6xxx/serdes.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152
[mirror_ubuntu-focal-kernel.git] / drivers / net / dsa / mv88e6xxx / serdes.c
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 }