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
mv88e6352_serdes_read(struct mv88e6xxx_chip * chip,int reg,u16 * val)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
mv88e6352_serdes_write(struct mv88e6xxx_chip * chip,int reg,u16 val)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
mv88e6390_serdes_read(struct mv88e6xxx_chip * chip,int lane,int device,int reg,u16 * val)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
mv88e6390_serdes_write(struct mv88e6xxx_chip * chip,int lane,int device,int reg,u16 val)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
mv88e6352_serdes_power(struct mv88e6xxx_chip * chip,int port,u8 lane,bool up)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
mv88e6352_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)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
mv88e6352_port_has_serdes(struct mv88e6xxx_chip * chip,int port)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
mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip * chip,int port)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
mv88e6352_serdes_get_strings(struct mv88e6xxx_chip * chip,int port,uint8_t * data)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
mv88e6352_serdes_get_stat(struct mv88e6xxx_chip * chip,struct mv88e6352_serdes_hw_stat * stat)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, ®);
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, ®);
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
mv88e6352_serdes_get_stats(struct mv88e6xxx_chip * chip,int port,uint64_t * data)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
mv88e6352_serdes_irq_link(struct mv88e6xxx_chip * chip,int port)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
mv88e6352_serdes_irq_status(struct mv88e6xxx_chip * chip,int port,u8 lane)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
mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip * chip,int port,u8 lane,bool enable)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
mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip * chip,int port)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
mv88e6341_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)240 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
241 {
242 u8 cmode = chip->ports[port].cmode;
243 u8 lane = 0;
244
245 switch (port) {
246 case 5:
247 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
248 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
249 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
250 lane = MV88E6341_PORT5_LANE;
251 break;
252 }
253
254 return lane;
255 }
256
mv88e6390_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)257 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
258 {
259 u8 cmode = chip->ports[port].cmode;
260 u8 lane = 0;
261
262 switch (port) {
263 case 9:
264 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
265 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
266 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
267 lane = MV88E6390_PORT9_LANE0;
268 break;
269 case 10:
270 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
271 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
272 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
273 lane = MV88E6390_PORT10_LANE0;
274 break;
275 }
276
277 return lane;
278 }
279
mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)280 u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
281 {
282 u8 cmode_port = chip->ports[port].cmode;
283 u8 cmode_port10 = chip->ports[10].cmode;
284 u8 cmode_port9 = chip->ports[9].cmode;
285 u8 lane = 0;
286
287 switch (port) {
288 case 2:
289 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
290 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
291 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
292 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
293 lane = MV88E6390_PORT9_LANE1;
294 break;
295 case 3:
296 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
297 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
298 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
299 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
300 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
301 lane = MV88E6390_PORT9_LANE2;
302 break;
303 case 4:
304 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
305 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
306 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
307 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
308 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
309 lane = MV88E6390_PORT9_LANE3;
310 break;
311 case 5:
312 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
313 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
314 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
315 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
316 lane = MV88E6390_PORT10_LANE1;
317 break;
318 case 6:
319 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
320 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
321 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
322 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
323 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
324 lane = MV88E6390_PORT10_LANE2;
325 break;
326 case 7:
327 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
328 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
329 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
330 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
331 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
332 lane = MV88E6390_PORT10_LANE3;
333 break;
334 case 9:
335 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
336 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
337 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
338 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
339 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
340 lane = MV88E6390_PORT9_LANE0;
341 break;
342 case 10:
343 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
344 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
345 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
346 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
347 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
348 lane = MV88E6390_PORT10_LANE0;
349 break;
350 }
351
352 return lane;
353 }
354
355 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
mv88e6390_serdes_power_10g(struct mv88e6xxx_chip * chip,u8 lane,bool up)356 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
357 bool up)
358 {
359 u16 val, new_val;
360 int err;
361
362 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
363 MV88E6390_PCS_CONTROL_1, &val);
364
365 if (err)
366 return err;
367
368 if (up)
369 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
370 MV88E6390_PCS_CONTROL_1_LOOPBACK |
371 MV88E6390_PCS_CONTROL_1_PDOWN);
372 else
373 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
374
375 if (val != new_val)
376 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
377 MV88E6390_PCS_CONTROL_1, new_val);
378
379 return err;
380 }
381
382 /* Set power up/down for SGMII and 1000Base-X */
mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip * chip,u8 lane,bool up)383 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
384 bool up)
385 {
386 u16 val, new_val;
387 int err;
388
389 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
390 MV88E6390_SGMII_CONTROL, &val);
391 if (err)
392 return err;
393
394 if (up)
395 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
396 MV88E6390_SGMII_CONTROL_LOOPBACK |
397 MV88E6390_SGMII_CONTROL_PDOWN);
398 else
399 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
400
401 if (val != new_val)
402 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
403 MV88E6390_SGMII_CONTROL, new_val);
404
405 return err;
406 }
407
mv88e6390_serdes_power(struct mv88e6xxx_chip * chip,int port,u8 lane,bool up)408 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
409 bool up)
410 {
411 u8 cmode = chip->ports[port].cmode;
412
413 switch (cmode) {
414 case MV88E6XXX_PORT_STS_CMODE_SGMII:
415 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
416 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
417 return mv88e6390_serdes_power_sgmii(chip, lane, up);
418 case MV88E6XXX_PORT_STS_CMODE_XAUI:
419 case MV88E6XXX_PORT_STS_CMODE_RXAUI:
420 return mv88e6390_serdes_power_10g(chip, lane, up);
421 }
422
423 return 0;
424 }
425
mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip * chip,int port,u8 lane)426 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
427 int port, u8 lane)
428 {
429 u8 cmode = chip->ports[port].cmode;
430 struct dsa_switch *ds = chip->ds;
431 int duplex = DUPLEX_UNKNOWN;
432 int speed = SPEED_UNKNOWN;
433 phy_interface_t mode;
434 int link, err;
435 u16 status;
436
437 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
438 MV88E6390_SGMII_PHY_STATUS, &status);
439 if (err) {
440 dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err);
441 return;
442 }
443
444 link = status & MV88E6390_SGMII_PHY_STATUS_LINK ?
445 LINK_FORCED_UP : LINK_FORCED_DOWN;
446
447 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
448 duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
449 DUPLEX_FULL : DUPLEX_HALF;
450
451 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
452 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
453 if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
454 speed = SPEED_2500;
455 else
456 speed = SPEED_1000;
457 break;
458 case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
459 speed = SPEED_100;
460 break;
461 case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
462 speed = SPEED_10;
463 break;
464 default:
465 dev_err(chip->dev, "invalid PHY speed\n");
466 return;
467 }
468 }
469
470 switch (cmode) {
471 case MV88E6XXX_PORT_STS_CMODE_SGMII:
472 mode = PHY_INTERFACE_MODE_SGMII;
473 break;
474 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
475 mode = PHY_INTERFACE_MODE_1000BASEX;
476 break;
477 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
478 mode = PHY_INTERFACE_MODE_2500BASEX;
479 break;
480 default:
481 mode = PHY_INTERFACE_MODE_NA;
482 }
483
484 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
485 PAUSE_OFF, mode);
486 if (err)
487 dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
488 err);
489 else
490 dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP);
491 }
492
mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip * chip,u8 lane,bool enable)493 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
494 u8 lane, bool enable)
495 {
496 u16 val = 0;
497
498 if (enable)
499 val |= MV88E6390_SGMII_INT_LINK_DOWN |
500 MV88E6390_SGMII_INT_LINK_UP;
501
502 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
503 MV88E6390_SGMII_INT_ENABLE, val);
504 }
505
mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip * chip,int port,u8 lane,bool enable)506 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
507 bool enable)
508 {
509 u8 cmode = chip->ports[port].cmode;
510
511 switch (cmode) {
512 case MV88E6XXX_PORT_STS_CMODE_SGMII:
513 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
514 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
515 return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
516 }
517
518 return 0;
519 }
520
mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip * chip,u8 lane,u16 * status)521 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
522 u8 lane, u16 *status)
523 {
524 int err;
525
526 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
527 MV88E6390_SGMII_INT_STATUS, status);
528
529 return err;
530 }
531
mv88e6390_serdes_irq_status(struct mv88e6xxx_chip * chip,int port,u8 lane)532 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
533 u8 lane)
534 {
535 u8 cmode = chip->ports[port].cmode;
536 irqreturn_t ret = IRQ_NONE;
537 u16 status;
538 int err;
539
540 switch (cmode) {
541 case MV88E6XXX_PORT_STS_CMODE_SGMII:
542 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
543 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
544 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
545 if (err)
546 return ret;
547 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
548 MV88E6390_SGMII_INT_LINK_UP)) {
549 ret = IRQ_HANDLED;
550 mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
551 }
552 }
553
554 return ret;
555 }
556
mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip * chip,int port)557 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
558 {
559 return irq_find_mapping(chip->g2_irq.domain, port);
560 }
561