1 /*
2 * Marvell 88E6xxx SERDES manipulation, via SMI bus
3 *
4 * Copyright (c) 2008 Marvell Semiconductor
5 *
6 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14 #include <linux/interrupt.h>
15 #include <linux/irqdomain.h>
16 #include <linux/mii.h>
17
18 #include "chip.h"
19 #include "global2.h"
20 #include "phy.h"
21 #include "port.h"
22 #include "serdes.h"
23
mv88e6352_serdes_read(struct mv88e6xxx_chip * chip,int reg,u16 * val)24 static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
25 u16 *val)
26 {
27 return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
28 MV88E6352_SERDES_PAGE_FIBER,
29 reg, val);
30 }
31
mv88e6352_serdes_write(struct mv88e6xxx_chip * chip,int reg,u16 val)32 static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
33 u16 val)
34 {
35 return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
36 MV88E6352_SERDES_PAGE_FIBER,
37 reg, val);
38 }
39
mv88e6390_serdes_read(struct mv88e6xxx_chip * chip,int lane,int device,int reg,u16 * val)40 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
41 int lane, int device, int reg, u16 *val)
42 {
43 int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
44
45 return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
46 }
47
mv88e6390_serdes_write(struct mv88e6xxx_chip * chip,int lane,int device,int reg,u16 val)48 static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
49 int lane, int device, int reg, u16 val)
50 {
51 int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
52
53 return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
54 }
55
mv88e6352_serdes_power_set(struct mv88e6xxx_chip * chip,bool on)56 static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
57 {
58 u16 val, new_val;
59 int err;
60
61 err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
62 if (err)
63 return err;
64
65 if (on)
66 new_val = val & ~BMCR_PDOWN;
67 else
68 new_val = val | BMCR_PDOWN;
69
70 if (val != new_val)
71 err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
72
73 return err;
74 }
75
mv88e6352_port_has_serdes(struct mv88e6xxx_chip * chip,int port)76 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
77 {
78 u8 cmode = chip->ports[port].cmode;
79
80 if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
81 (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
82 (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
83 return true;
84
85 return false;
86 }
87
mv88e6352_serdes_power(struct mv88e6xxx_chip * chip,int port,bool on)88 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
89 {
90 int err;
91
92 if (mv88e6352_port_has_serdes(chip, port)) {
93 err = mv88e6352_serdes_power_set(chip, on);
94 if (err < 0)
95 return err;
96 }
97
98 return 0;
99 }
100
101 struct mv88e6352_serdes_hw_stat {
102 char string[ETH_GSTRING_LEN];
103 int sizeof_stat;
104 int reg;
105 };
106
107 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
108 { "serdes_fibre_rx_error", 16, 21 },
109 { "serdes_PRBS_error", 32, 24 },
110 };
111
mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip * chip,int port)112 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
113 {
114 if (mv88e6352_port_has_serdes(chip, port))
115 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
116
117 return 0;
118 }
119
mv88e6352_serdes_get_strings(struct mv88e6xxx_chip * chip,int port,uint8_t * data)120 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
121 int port, uint8_t *data)
122 {
123 struct mv88e6352_serdes_hw_stat *stat;
124 int i;
125
126 if (!mv88e6352_port_has_serdes(chip, port))
127 return 0;
128
129 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
130 stat = &mv88e6352_serdes_hw_stats[i];
131 memcpy(data + i * ETH_GSTRING_LEN, stat->string,
132 ETH_GSTRING_LEN);
133 }
134 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
135 }
136
mv88e6352_serdes_get_stat(struct mv88e6xxx_chip * chip,struct mv88e6352_serdes_hw_stat * stat)137 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
138 struct mv88e6352_serdes_hw_stat *stat)
139 {
140 u64 val = 0;
141 u16 reg;
142 int err;
143
144 err = mv88e6352_serdes_read(chip, stat->reg, ®);
145 if (err) {
146 dev_err(chip->dev, "failed to read statistic\n");
147 return 0;
148 }
149
150 val = reg;
151
152 if (stat->sizeof_stat == 32) {
153 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®);
154 if (err) {
155 dev_err(chip->dev, "failed to read statistic\n");
156 return 0;
157 }
158 val = val << 16 | reg;
159 }
160
161 return val;
162 }
163
mv88e6352_serdes_get_stats(struct mv88e6xxx_chip * chip,int port,uint64_t * data)164 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
165 uint64_t *data)
166 {
167 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
168 struct mv88e6352_serdes_hw_stat *stat;
169 u64 value;
170 int i;
171
172 if (!mv88e6352_port_has_serdes(chip, port))
173 return 0;
174
175 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
176 ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
177
178 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
179 stat = &mv88e6352_serdes_hw_stats[i];
180 value = mv88e6352_serdes_get_stat(chip, stat);
181 mv88e6xxx_port->serdes_stats[i] += value;
182 data[i] = mv88e6xxx_port->serdes_stats[i];
183 }
184
185 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
186 }
187
188 /* Return the SERDES lane address a port is using. Only Ports 9 and 10
189 * have SERDES lanes. Returns -ENODEV if a port does not have a lane.
190 */
mv88e6390_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)191 static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
192 {
193 u8 cmode = chip->ports[port].cmode;
194
195 switch (port) {
196 case 9:
197 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
198 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
199 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
200 return MV88E6390_PORT9_LANE0;
201 return -ENODEV;
202 case 10:
203 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
204 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
205 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
206 return MV88E6390_PORT10_LANE0;
207 return -ENODEV;
208 default:
209 return -ENODEV;
210 }
211 }
212
213 /* Return the SERDES lane address a port is using. Ports 9 and 10 can
214 * use multiple lanes. If so, return the first lane the port uses.
215 * Returns -ENODEV if a port does not have a lane.
216 */
mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip * chip,int port)217 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
218 {
219 u8 cmode_port9, cmode_port10, cmode_port;
220
221 cmode_port9 = chip->ports[9].cmode;
222 cmode_port10 = chip->ports[10].cmode;
223 cmode_port = chip->ports[port].cmode;
224
225 switch (port) {
226 case 2:
227 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
228 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
229 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
230 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
231 return MV88E6390_PORT9_LANE1;
232 return -ENODEV;
233 case 3:
234 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
235 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
236 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
237 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
238 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
239 return MV88E6390_PORT9_LANE2;
240 return -ENODEV;
241 case 4:
242 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
243 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
244 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
245 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
246 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
247 return MV88E6390_PORT9_LANE3;
248 return -ENODEV;
249 case 5:
250 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
251 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
252 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
253 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
254 return MV88E6390_PORT10_LANE1;
255 return -ENODEV;
256 case 6:
257 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
258 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
259 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
260 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
261 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
262 return MV88E6390_PORT10_LANE2;
263 return -ENODEV;
264 case 7:
265 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
266 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
267 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
268 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
269 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
270 return MV88E6390_PORT10_LANE3;
271 return -ENODEV;
272 case 9:
273 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
274 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
275 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
276 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
277 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
278 return MV88E6390_PORT9_LANE0;
279 return -ENODEV;
280 case 10:
281 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
282 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
283 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
284 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
285 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
286 return MV88E6390_PORT10_LANE0;
287 return -ENODEV;
288 default:
289 return -ENODEV;
290 }
291 }
292
293 /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
mv88e6390_serdes_power_10g(struct mv88e6xxx_chip * chip,int lane,bool on)294 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
295 bool on)
296 {
297 u16 val, new_val;
298 int err;
299
300 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
301 MV88E6390_PCS_CONTROL_1, &val);
302
303 if (err)
304 return err;
305
306 if (on)
307 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
308 MV88E6390_PCS_CONTROL_1_LOOPBACK |
309 MV88E6390_PCS_CONTROL_1_PDOWN);
310 else
311 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
312
313 if (val != new_val)
314 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
315 MV88E6390_PCS_CONTROL_1, new_val);
316
317 return err;
318 }
319
320 /* Set the power on/off for SGMII and 1000Base-X */
mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip * chip,int lane,bool on)321 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
322 bool on)
323 {
324 u16 val, new_val;
325 int err;
326
327 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
328 MV88E6390_SGMII_CONTROL, &val);
329 if (err)
330 return err;
331
332 if (on)
333 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
334 MV88E6390_SGMII_CONTROL_LOOPBACK |
335 MV88E6390_SGMII_CONTROL_PDOWN);
336 else
337 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
338
339 if (val != new_val)
340 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
341 MV88E6390_SGMII_CONTROL, new_val);
342
343 return err;
344 }
345
mv88e6390_serdes_power_lane(struct mv88e6xxx_chip * chip,int port,int lane,bool on)346 static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
347 int lane, bool on)
348 {
349 u8 cmode = chip->ports[port].cmode;
350
351 switch (cmode) {
352 case MV88E6XXX_PORT_STS_CMODE_SGMII:
353 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
354 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
355 return mv88e6390_serdes_power_sgmii(chip, lane, on);
356 case MV88E6XXX_PORT_STS_CMODE_XAUI:
357 case MV88E6XXX_PORT_STS_CMODE_RXAUI:
358 return mv88e6390_serdes_power_10g(chip, lane, on);
359 }
360
361 return 0;
362 }
363
mv88e6390_serdes_power(struct mv88e6xxx_chip * chip,int port,bool on)364 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
365 {
366 int lane;
367
368 lane = mv88e6390_serdes_get_lane(chip, port);
369 if (lane == -ENODEV)
370 return 0;
371
372 if (lane < 0)
373 return lane;
374
375 switch (port) {
376 case 9 ... 10:
377 return mv88e6390_serdes_power_lane(chip, port, lane, on);
378 }
379
380 return 0;
381 }
382
mv88e6390x_serdes_power(struct mv88e6xxx_chip * chip,int port,bool on)383 int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
384 {
385 int lane;
386
387 lane = mv88e6390x_serdes_get_lane(chip, port);
388 if (lane == -ENODEV)
389 return 0;
390
391 if (lane < 0)
392 return lane;
393
394 switch (port) {
395 case 2 ... 4:
396 case 5 ... 7:
397 case 9 ... 10:
398 return mv88e6390_serdes_power_lane(chip, port, lane, on);
399 }
400
401 return 0;
402 }
403
mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip * chip,int port,int lane)404 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
405 int port, int lane)
406 {
407 struct dsa_switch *ds = chip->ds;
408 u16 status;
409 bool up;
410
411 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
412 MV88E6390_SGMII_STATUS, &status);
413
414 /* Status must be read twice in order to give the current link
415 * status. Otherwise the change in link status since the last
416 * read of the register is returned.
417 */
418 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
419 MV88E6390_SGMII_STATUS, &status);
420 up = status & MV88E6390_SGMII_STATUS_LINK;
421
422 dsa_port_phylink_mac_change(ds, port, up);
423 }
424
mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip * chip,int lane)425 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
426 int lane)
427 {
428 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
429 MV88E6390_SGMII_INT_ENABLE,
430 MV88E6390_SGMII_INT_LINK_DOWN |
431 MV88E6390_SGMII_INT_LINK_UP);
432 }
433
mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip * chip,int lane)434 static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip,
435 int lane)
436 {
437 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
438 MV88E6390_SGMII_INT_ENABLE, 0);
439 }
440
mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip * chip,int port,int lane)441 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
442 int lane)
443 {
444 u8 cmode = chip->ports[port].cmode;
445 int err = 0;
446
447 switch (cmode) {
448 case MV88E6XXX_PORT_STS_CMODE_SGMII:
449 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
450 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
451 err = mv88e6390_serdes_irq_enable_sgmii(chip, lane);
452 }
453
454 return err;
455 }
456
mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip * chip,int port,int lane)457 int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
458 int lane)
459 {
460 u8 cmode = chip->ports[port].cmode;
461 int err = 0;
462
463 switch (cmode) {
464 case MV88E6XXX_PORT_STS_CMODE_SGMII:
465 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
466 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
467 err = mv88e6390_serdes_irq_disable_sgmii(chip, lane);
468 }
469
470 return err;
471 }
472
mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip * chip,int lane,u16 * status)473 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
474 int lane, u16 *status)
475 {
476 int err;
477
478 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
479 MV88E6390_SGMII_INT_STATUS, status);
480
481 return err;
482 }
483
mv88e6390_serdes_thread_fn(int irq,void * dev_id)484 static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
485 {
486 struct mv88e6xxx_port *port = dev_id;
487 struct mv88e6xxx_chip *chip = port->chip;
488 irqreturn_t ret = IRQ_NONE;
489 u8 cmode = port->cmode;
490 u16 status;
491 int lane;
492 int err;
493
494 lane = mv88e6390x_serdes_get_lane(chip, port->port);
495
496 mutex_lock(&chip->reg_lock);
497
498 switch (cmode) {
499 case MV88E6XXX_PORT_STS_CMODE_SGMII:
500 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
501 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
502 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
503 if (err)
504 goto out;
505 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
506 MV88E6390_SGMII_INT_LINK_UP)) {
507 ret = IRQ_HANDLED;
508 mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane);
509 }
510 }
511 out:
512 mutex_unlock(&chip->reg_lock);
513
514 return ret;
515 }
516
mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip * chip,int port)517 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
518 {
519 int lane;
520 int err;
521
522 /* Only support ports 9 and 10 at the moment */
523 if (port < 9)
524 return 0;
525
526 lane = mv88e6390x_serdes_get_lane(chip, port);
527
528 if (lane == -ENODEV)
529 return 0;
530
531 if (lane < 0)
532 return lane;
533
534 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
535 port);
536 if (chip->ports[port].serdes_irq < 0) {
537 dev_err(chip->dev, "Unable to map SERDES irq: %d\n",
538 chip->ports[port].serdes_irq);
539 return chip->ports[port].serdes_irq;
540 }
541
542 /* Requesting the IRQ will trigger irq callbacks. So we cannot
543 * hold the reg_lock.
544 */
545 mutex_unlock(&chip->reg_lock);
546 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL,
547 mv88e6390_serdes_thread_fn,
548 IRQF_ONESHOT, "mv88e6xxx-serdes",
549 &chip->ports[port]);
550 mutex_lock(&chip->reg_lock);
551
552 if (err) {
553 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
554 err);
555 return err;
556 }
557
558 return mv88e6390_serdes_irq_enable(chip, port, lane);
559 }
560
mv88e6390_serdes_irq_free(struct mv88e6xxx_chip * chip,int port)561 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
562 {
563 int lane = mv88e6390x_serdes_get_lane(chip, port);
564
565 if (port < 9)
566 return;
567
568 if (lane < 0)
569 return;
570
571 mv88e6390_serdes_irq_disable(chip, port, lane);
572
573 /* Freeing the IRQ will trigger irq callbacks. So we cannot
574 * hold the reg_lock.
575 */
576 mutex_unlock(&chip->reg_lock);
577 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
578 mutex_lock(&chip->reg_lock);
579
580 chip->ports[port].serdes_irq = 0;
581 }
582
mv88e6341_serdes_power(struct mv88e6xxx_chip * chip,int port,bool on)583 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
584 {
585 u8 cmode = chip->ports[port].cmode;
586
587 if (port != 5)
588 return 0;
589
590 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
591 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
592 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
593 return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES,
594 on);
595
596 return 0;
597 }
598