1
2
3
4
5
6
7
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
20static 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
28static 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
36static 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
44static 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
52static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
53 u16 status, u16 lpa,
54 struct phylink_link_state *state)
55{
56 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
57 state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
58 state->duplex = status &
59 MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
60 DUPLEX_FULL : DUPLEX_HALF;
61
62 if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
63 state->pause |= MLO_PAUSE_TX;
64 if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
65 state->pause |= MLO_PAUSE_RX;
66
67 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
68 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
69 if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
70 state->speed = SPEED_2500;
71 else
72 state->speed = SPEED_1000;
73 break;
74 case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
75 state->speed = SPEED_100;
76 break;
77 case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
78 state->speed = SPEED_10;
79 break;
80 default:
81 dev_err(chip->dev, "invalid PHY speed\n");
82 return -EINVAL;
83 }
84 } else {
85 state->link = false;
86 }
87
88 if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
89 mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
90 ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
91 else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
92 mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
93 ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
94
95 return 0;
96}
97
98int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
99 bool up)
100{
101 u16 val, new_val;
102 int err;
103
104 err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
105 if (err)
106 return err;
107
108 if (up)
109 new_val = val & ~BMCR_PDOWN;
110 else
111 new_val = val | BMCR_PDOWN;
112
113 if (val != new_val)
114 err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
115
116 return err;
117}
118
119int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
120 int lane, unsigned int mode,
121 phy_interface_t interface,
122 const unsigned long *advertise)
123{
124 u16 adv, bmcr, val;
125 bool changed;
126 int err;
127
128 switch (interface) {
129 case PHY_INTERFACE_MODE_SGMII:
130 adv = 0x0001;
131 break;
132
133 case PHY_INTERFACE_MODE_1000BASEX:
134 adv = linkmode_adv_to_mii_adv_x(advertise,
135 ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
136 break;
137
138 default:
139 return 0;
140 }
141
142 err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val);
143 if (err)
144 return err;
145
146 changed = val != adv;
147 if (changed) {
148 err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv);
149 if (err)
150 return err;
151 }
152
153 err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
154 if (err)
155 return err;
156
157 if (phylink_autoneg_inband(mode))
158 bmcr = val | BMCR_ANENABLE;
159 else
160 bmcr = val & ~BMCR_ANENABLE;
161
162 if (bmcr == val)
163 return changed;
164
165 return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
166}
167
168int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
169 int lane, struct phylink_link_state *state)
170{
171 u16 lpa, status;
172 int err;
173
174 err = mv88e6352_serdes_read(chip, 0x11, &status);
175 if (err) {
176 dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
177 return err;
178 }
179
180 err = mv88e6352_serdes_read(chip, MII_LPA, &lpa);
181 if (err) {
182 dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
183 return err;
184 }
185
186 return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
187}
188
189int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
190 int lane)
191{
192 u16 bmcr;
193 int err;
194
195 err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr);
196 if (err)
197 return err;
198
199 return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART);
200}
201
202int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
203 int lane, int speed, int duplex)
204{
205 u16 val, bmcr;
206 int err;
207
208 err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
209 if (err)
210 return err;
211
212 bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
213 switch (speed) {
214 case SPEED_1000:
215 bmcr |= BMCR_SPEED1000;
216 break;
217 case SPEED_100:
218 bmcr |= BMCR_SPEED100;
219 break;
220 case SPEED_10:
221 break;
222 }
223
224 if (duplex == DUPLEX_FULL)
225 bmcr |= BMCR_FULLDPLX;
226
227 if (bmcr == val)
228 return 0;
229
230 return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
231}
232
233int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
234{
235 u8 cmode = chip->ports[port].cmode;
236 int lane = -ENODEV;
237
238 if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
239 (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
240 (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
241 lane = 0xff;
242
243 return lane;
244}
245
246static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
247{
248 if (mv88e6xxx_serdes_get_lane(chip, port) >= 0)
249 return true;
250
251 return false;
252}
253
254struct mv88e6352_serdes_hw_stat {
255 char string[ETH_GSTRING_LEN];
256 int sizeof_stat;
257 int reg;
258};
259
260static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
261 { "serdes_fibre_rx_error", 16, 21 },
262 { "serdes_PRBS_error", 32, 24 },
263};
264
265int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
266{
267 if (mv88e6352_port_has_serdes(chip, port))
268 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
269
270 return 0;
271}
272
273int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
274 int port, uint8_t *data)
275{
276 struct mv88e6352_serdes_hw_stat *stat;
277 int i;
278
279 if (!mv88e6352_port_has_serdes(chip, port))
280 return 0;
281
282 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
283 stat = &mv88e6352_serdes_hw_stats[i];
284 memcpy(data + i * ETH_GSTRING_LEN, stat->string,
285 ETH_GSTRING_LEN);
286 }
287 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
288}
289
290static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
291 struct mv88e6352_serdes_hw_stat *stat)
292{
293 u64 val = 0;
294 u16 reg;
295 int err;
296
297 err = mv88e6352_serdes_read(chip, stat->reg, ®);
298 if (err) {
299 dev_err(chip->dev, "failed to read statistic\n");
300 return 0;
301 }
302
303 val = reg;
304
305 if (stat->sizeof_stat == 32) {
306 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®);
307 if (err) {
308 dev_err(chip->dev, "failed to read statistic\n");
309 return 0;
310 }
311 val = val << 16 | reg;
312 }
313
314 return val;
315}
316
317int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
318 uint64_t *data)
319{
320 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
321 struct mv88e6352_serdes_hw_stat *stat;
322 u64 value;
323 int i;
324
325 if (!mv88e6352_port_has_serdes(chip, port))
326 return 0;
327
328 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
329 ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
330
331 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
332 stat = &mv88e6352_serdes_hw_stats[i];
333 value = mv88e6352_serdes_get_stat(chip, stat);
334 mv88e6xxx_port->serdes_stats[i] += value;
335 data[i] = mv88e6xxx_port->serdes_stats[i];
336 }
337
338 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
339}
340
341static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
342{
343 u16 bmsr;
344 int err;
345
346
347 err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
348 if (err) {
349 dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
350 return;
351 }
352
353 dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
354}
355
356irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
357 int lane)
358{
359 irqreturn_t ret = IRQ_NONE;
360 u16 status;
361 int err;
362
363 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
364 if (err)
365 return ret;
366
367 if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
368 ret = IRQ_HANDLED;
369 mv88e6352_serdes_irq_link(chip, port);
370 }
371
372 return ret;
373}
374
375int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
376 bool enable)
377{
378 u16 val = 0;
379
380 if (enable)
381 val |= MV88E6352_SERDES_INT_LINK_CHANGE;
382
383 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
384}
385
386unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
387{
388 return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
389}
390
391int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
392{
393 if (!mv88e6352_port_has_serdes(chip, port))
394 return 0;
395
396 return 32 * sizeof(u16);
397}
398
399void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
400{
401 u16 *p = _p;
402 u16 reg;
403 int err;
404 int i;
405
406 if (!mv88e6352_port_has_serdes(chip, port))
407 return;
408
409 for (i = 0 ; i < 32; i++) {
410 err = mv88e6352_serdes_read(chip, i, ®);
411 if (!err)
412 p[i] = reg;
413 }
414}
415
416int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
417{
418 u8 cmode = chip->ports[port].cmode;
419 int lane = -ENODEV;
420
421 switch (port) {
422 case 5:
423 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
424 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
425 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
426 lane = MV88E6341_PORT5_LANE;
427 break;
428 }
429
430 return lane;
431}
432
433int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
434 bool up)
435{
436
437
438
439
440 return 0;
441}
442
443int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
444{
445
446
447
448
449 switch (chip->ports[port].cmode) {
450 case MV88E6185_PORT_STS_CMODE_SERDES:
451 case MV88E6185_PORT_STS_CMODE_1000BASE_X:
452 return 0;
453 default:
454 return -ENODEV;
455 }
456}
457
458int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
459 int lane, struct phylink_link_state *state)
460{
461 int err;
462 u16 status;
463
464 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
465 if (err)
466 return err;
467
468 state->link = !!(status & MV88E6XXX_PORT_STS_LINK);
469
470 if (state->link) {
471 state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? DUPLEX_FULL : DUPLEX_HALF;
472
473 switch (status & MV88E6XXX_PORT_STS_SPEED_MASK) {
474 case MV88E6XXX_PORT_STS_SPEED_1000:
475 state->speed = SPEED_1000;
476 break;
477 case MV88E6XXX_PORT_STS_SPEED_100:
478 state->speed = SPEED_100;
479 break;
480 case MV88E6XXX_PORT_STS_SPEED_10:
481 state->speed = SPEED_10;
482 break;
483 default:
484 dev_err(chip->dev, "invalid PHY speed\n");
485 return -EINVAL;
486 }
487 } else {
488 state->duplex = DUPLEX_UNKNOWN;
489 state->speed = SPEED_UNKNOWN;
490 }
491
492 return 0;
493}
494
495int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
496 bool enable)
497{
498 u8 cmode = chip->ports[port].cmode;
499
500
501
502
503
504 switch (cmode) {
505 case MV88E6185_PORT_STS_CMODE_SERDES:
506 case MV88E6185_PORT_STS_CMODE_1000BASE_X:
507 return 0;
508 }
509
510 return -EOPNOTSUPP;
511}
512
513static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
514{
515 u16 status;
516 int err;
517
518 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
519 if (err) {
520 dev_err(chip->dev, "can't read port status: %d\n", err);
521 return;
522 }
523
524 dsa_port_phylink_mac_change(chip->ds, port, !!(status & MV88E6XXX_PORT_STS_LINK));
525}
526
527irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
528 int lane)
529{
530 u8 cmode = chip->ports[port].cmode;
531
532 switch (cmode) {
533 case MV88E6185_PORT_STS_CMODE_SERDES:
534 case MV88E6185_PORT_STS_CMODE_1000BASE_X:
535 mv88e6097_serdes_irq_link(chip, port);
536 return IRQ_HANDLED;
537 }
538
539 return IRQ_NONE;
540}
541
542int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
543{
544 u8 cmode = chip->ports[port].cmode;
545 int lane = -ENODEV;
546
547 switch (port) {
548 case 9:
549 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
550 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
551 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
552 lane = MV88E6390_PORT9_LANE0;
553 break;
554 case 10:
555 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
556 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
557 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
558 lane = MV88E6390_PORT10_LANE0;
559 break;
560 }
561
562 return lane;
563}
564
565int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
566{
567 u8 cmode_port = chip->ports[port].cmode;
568 u8 cmode_port10 = chip->ports[10].cmode;
569 u8 cmode_port9 = chip->ports[9].cmode;
570 int lane = -ENODEV;
571
572 switch (port) {
573 case 2:
574 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
575 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
576 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
577 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
578 lane = MV88E6390_PORT9_LANE1;
579 break;
580 case 3:
581 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
582 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
583 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
584 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
585 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
586 lane = MV88E6390_PORT9_LANE2;
587 break;
588 case 4:
589 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
590 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
591 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
592 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
593 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
594 lane = MV88E6390_PORT9_LANE3;
595 break;
596 case 5:
597 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
598 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
599 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
600 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
601 lane = MV88E6390_PORT10_LANE1;
602 break;
603 case 6:
604 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
605 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
606 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
607 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
608 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
609 lane = MV88E6390_PORT10_LANE2;
610 break;
611 case 7:
612 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
613 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
614 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
615 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
616 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
617 lane = MV88E6390_PORT10_LANE3;
618 break;
619 case 9:
620 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
621 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
622 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
623 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
624 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
625 lane = MV88E6390_PORT9_LANE0;
626 break;
627 case 10:
628 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
629 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
630 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
631 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
632 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
633 lane = MV88E6390_PORT10_LANE0;
634 break;
635 }
636
637 return lane;
638}
639
640
641
642
643int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
644{
645 u8 cmode = chip->ports[port].cmode;
646 int lane = -ENODEV;
647
648 if (port != 0 && port != 9 && port != 10)
649 return -EOPNOTSUPP;
650
651 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
652 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
653 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
654 cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
655 cmode == MV88E6393X_PORT_STS_CMODE_10GBASER)
656 lane = port;
657
658 return lane;
659}
660
661
662static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
663 bool up)
664{
665 u16 val, new_val;
666 int err;
667
668 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
669 MV88E6390_10G_CTRL1, &val);
670
671 if (err)
672 return err;
673
674 if (up)
675 new_val = val & ~(MDIO_CTRL1_RESET |
676 MDIO_PCS_CTRL1_LOOPBACK |
677 MDIO_CTRL1_LPOWER);
678 else
679 new_val = val | MDIO_CTRL1_LPOWER;
680
681 if (val != new_val)
682 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
683 MV88E6390_10G_CTRL1, new_val);
684
685 return err;
686}
687
688
689static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
690 bool up)
691{
692 u16 val, new_val;
693 int err;
694
695 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
696 MV88E6390_SGMII_BMCR, &val);
697 if (err)
698 return err;
699
700 if (up)
701 new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
702 else
703 new_val = val | BMCR_PDOWN;
704
705 if (val != new_val)
706 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
707 MV88E6390_SGMII_BMCR, new_val);
708
709 return err;
710}
711
712struct mv88e6390_serdes_hw_stat {
713 char string[ETH_GSTRING_LEN];
714 int reg;
715};
716
717static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
718 { "serdes_rx_pkts", 0xf021 },
719 { "serdes_rx_bytes", 0xf024 },
720 { "serdes_rx_pkts_error", 0xf027 },
721};
722
723int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
724{
725 if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
726 return 0;
727
728 return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
729}
730
731int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
732 int port, uint8_t *data)
733{
734 struct mv88e6390_serdes_hw_stat *stat;
735 int i;
736
737 if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
738 return 0;
739
740 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
741 stat = &mv88e6390_serdes_hw_stats[i];
742 memcpy(data + i * ETH_GSTRING_LEN, stat->string,
743 ETH_GSTRING_LEN);
744 }
745 return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
746}
747
748static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
749 struct mv88e6390_serdes_hw_stat *stat)
750{
751 u16 reg[3];
752 int err, i;
753
754 for (i = 0; i < 3; i++) {
755 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
756 stat->reg + i, ®[i]);
757 if (err) {
758 dev_err(chip->dev, "failed to read statistic\n");
759 return 0;
760 }
761 }
762
763 return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
764}
765
766int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
767 uint64_t *data)
768{
769 struct mv88e6390_serdes_hw_stat *stat;
770 int lane;
771 int i;
772
773 lane = mv88e6xxx_serdes_get_lane(chip, port);
774 if (lane < 0)
775 return 0;
776
777 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
778 stat = &mv88e6390_serdes_hw_stats[i];
779 data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
780 }
781
782 return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
783}
784
785static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane)
786{
787 u16 reg;
788 int err;
789
790 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
791 MV88E6390_PG_CONTROL, ®);
792 if (err)
793 return err;
794
795 reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
796 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
797 MV88E6390_PG_CONTROL, reg);
798}
799
800int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
801 bool up)
802{
803 u8 cmode = chip->ports[port].cmode;
804 int err = 0;
805
806 switch (cmode) {
807 case MV88E6XXX_PORT_STS_CMODE_SGMII:
808 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
809 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
810 err = mv88e6390_serdes_power_sgmii(chip, lane, up);
811 break;
812 case MV88E6XXX_PORT_STS_CMODE_XAUI:
813 case MV88E6XXX_PORT_STS_CMODE_RXAUI:
814 err = mv88e6390_serdes_power_10g(chip, lane, up);
815 break;
816 }
817
818 if (!err && up)
819 err = mv88e6390_serdes_enable_checker(chip, lane);
820
821 return err;
822}
823
824int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
825 int lane, unsigned int mode,
826 phy_interface_t interface,
827 const unsigned long *advertise)
828{
829 u16 val, bmcr, adv;
830 bool changed;
831 int err;
832
833 switch (interface) {
834 case PHY_INTERFACE_MODE_SGMII:
835 adv = 0x0001;
836 break;
837
838 case PHY_INTERFACE_MODE_1000BASEX:
839 adv = linkmode_adv_to_mii_adv_x(advertise,
840 ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
841 break;
842
843 case PHY_INTERFACE_MODE_2500BASEX:
844 adv = linkmode_adv_to_mii_adv_x(advertise,
845 ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
846 break;
847
848 default:
849 return 0;
850 }
851
852 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
853 MV88E6390_SGMII_ADVERTISE, &val);
854 if (err)
855 return err;
856
857 changed = val != adv;
858 if (changed) {
859 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
860 MV88E6390_SGMII_ADVERTISE, adv);
861 if (err)
862 return err;
863 }
864
865 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
866 MV88E6390_SGMII_BMCR, &val);
867 if (err)
868 return err;
869
870 if (phylink_autoneg_inband(mode))
871 bmcr = val | BMCR_ANENABLE;
872 else
873 bmcr = val & ~BMCR_ANENABLE;
874
875
876 if (bmcr == val)
877 return changed;
878
879 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
880 MV88E6390_SGMII_BMCR, bmcr);
881}
882
883static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
884 int port, int lane, struct phylink_link_state *state)
885{
886 u16 lpa, status;
887 int err;
888
889 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
890 MV88E6390_SGMII_PHY_STATUS, &status);
891 if (err) {
892 dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
893 return err;
894 }
895
896 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
897 MV88E6390_SGMII_LPA, &lpa);
898 if (err) {
899 dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
900 return err;
901 }
902
903 return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
904}
905
906static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
907 int port, int lane, struct phylink_link_state *state)
908{
909 u16 status;
910 int err;
911
912 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
913 MV88E6390_10G_STAT1, &status);
914 if (err)
915 return err;
916
917 state->link = !!(status & MDIO_STAT1_LSTATUS);
918 if (state->link) {
919 state->speed = SPEED_10000;
920 state->duplex = DUPLEX_FULL;
921 }
922
923 return 0;
924}
925
926static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
927 int port, int lane,
928 struct phylink_link_state *state)
929{
930 u16 status;
931 int err;
932
933 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
934 MV88E6390_10G_STAT1, &status);
935 if (err)
936 return err;
937
938 state->link = !!(status & MDIO_STAT1_LSTATUS);
939 if (state->link) {
940 if (state->interface == PHY_INTERFACE_MODE_5GBASER)
941 state->speed = SPEED_5000;
942 else
943 state->speed = SPEED_10000;
944 state->duplex = DUPLEX_FULL;
945 }
946
947 return 0;
948}
949
950int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
951 int lane, struct phylink_link_state *state)
952{
953 switch (state->interface) {
954 case PHY_INTERFACE_MODE_SGMII:
955 case PHY_INTERFACE_MODE_1000BASEX:
956 case PHY_INTERFACE_MODE_2500BASEX:
957 return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
958 state);
959 case PHY_INTERFACE_MODE_XAUI:
960 case PHY_INTERFACE_MODE_RXAUI:
961 return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
962 state);
963
964 default:
965 return -EOPNOTSUPP;
966 }
967}
968
969int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
970 int lane, struct phylink_link_state *state)
971{
972 switch (state->interface) {
973 case PHY_INTERFACE_MODE_SGMII:
974 case PHY_INTERFACE_MODE_1000BASEX:
975 case PHY_INTERFACE_MODE_2500BASEX:
976 return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
977 state);
978 case PHY_INTERFACE_MODE_5GBASER:
979 case PHY_INTERFACE_MODE_10GBASER:
980 return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
981 state);
982
983 default:
984 return -EOPNOTSUPP;
985 }
986}
987
988int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
989 int lane)
990{
991 u16 bmcr;
992 int err;
993
994 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
995 MV88E6390_SGMII_BMCR, &bmcr);
996 if (err)
997 return err;
998
999 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1000 MV88E6390_SGMII_BMCR,
1001 bmcr | BMCR_ANRESTART);
1002}
1003
1004int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
1005 int lane, int speed, int duplex)
1006{
1007 u16 val, bmcr;
1008 int err;
1009
1010 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1011 MV88E6390_SGMII_BMCR, &val);
1012 if (err)
1013 return err;
1014
1015 bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
1016 switch (speed) {
1017 case SPEED_2500:
1018 case SPEED_1000:
1019 bmcr |= BMCR_SPEED1000;
1020 break;
1021 case SPEED_100:
1022 bmcr |= BMCR_SPEED100;
1023 break;
1024 case SPEED_10:
1025 break;
1026 }
1027
1028 if (duplex == DUPLEX_FULL)
1029 bmcr |= BMCR_FULLDPLX;
1030
1031 if (bmcr == val)
1032 return 0;
1033
1034 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1035 MV88E6390_SGMII_BMCR, bmcr);
1036}
1037
1038static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
1039 int port, int lane)
1040{
1041 u16 bmsr;
1042 int err;
1043
1044
1045 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1046 MV88E6390_SGMII_BMSR, &bmsr);
1047 if (err) {
1048 dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
1049 return;
1050 }
1051
1052 dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
1053}
1054
1055static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip,
1056 int port, u8 lane)
1057{
1058 u16 status;
1059 int err;
1060
1061
1062 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1063 MV88E6390_10G_STAT1, &status);
1064 if (err) {
1065 dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err);
1066 return;
1067 }
1068
1069 dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS));
1070}
1071
1072static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
1073 int lane, bool enable)
1074{
1075 u16 val = 0;
1076
1077 if (enable)
1078 val |= MV88E6390_SGMII_INT_LINK_DOWN |
1079 MV88E6390_SGMII_INT_LINK_UP;
1080
1081 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1082 MV88E6390_SGMII_INT_ENABLE, val);
1083}
1084
1085int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
1086 bool enable)
1087{
1088 u8 cmode = chip->ports[port].cmode;
1089
1090 switch (cmode) {
1091 case MV88E6XXX_PORT_STS_CMODE_SGMII:
1092 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1093 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1094 return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1095 }
1096
1097 return 0;
1098}
1099
1100static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
1101 int lane, u16 *status)
1102{
1103 int err;
1104
1105 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1106 MV88E6390_SGMII_INT_STATUS, status);
1107
1108 return err;
1109}
1110
1111static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip,
1112 u8 lane, bool enable)
1113{
1114 u16 val = 0;
1115
1116 if (enable)
1117 val |= MV88E6393X_10G_INT_LINK_CHANGE;
1118
1119 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1120 MV88E6393X_10G_INT_ENABLE, val);
1121}
1122
1123int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
1124 int lane, bool enable)
1125{
1126 u8 cmode = chip->ports[port].cmode;
1127
1128 switch (cmode) {
1129 case MV88E6XXX_PORT_STS_CMODE_SGMII:
1130 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1131 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1132 return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1133 case MV88E6393X_PORT_STS_CMODE_5GBASER:
1134 case MV88E6393X_PORT_STS_CMODE_10GBASER:
1135 return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
1136 }
1137
1138 return 0;
1139}
1140
1141static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip,
1142 u8 lane, u16 *status)
1143{
1144 int err;
1145
1146 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1147 MV88E6393X_10G_INT_STATUS, status);
1148
1149 return err;
1150}
1151
1152irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1153 int lane)
1154{
1155 u8 cmode = chip->ports[port].cmode;
1156 irqreturn_t ret = IRQ_NONE;
1157 u16 status;
1158 int err;
1159
1160 switch (cmode) {
1161 case MV88E6XXX_PORT_STS_CMODE_SGMII:
1162 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1163 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1164 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1165 if (err)
1166 return ret;
1167 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1168 MV88E6390_SGMII_INT_LINK_UP)) {
1169 ret = IRQ_HANDLED;
1170 mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1171 }
1172 break;
1173 case MV88E6393X_PORT_STS_CMODE_5GBASER:
1174 case MV88E6393X_PORT_STS_CMODE_10GBASER:
1175 err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
1176 if (err)
1177 return err;
1178 if (status & MV88E6393X_10G_INT_LINK_CHANGE) {
1179 ret = IRQ_HANDLED;
1180 mv88e6393x_serdes_irq_link_10g(chip, port, lane);
1181 }
1182 break;
1183 }
1184
1185 return ret;
1186}
1187
1188irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1189 int lane)
1190{
1191 u8 cmode = chip->ports[port].cmode;
1192 irqreturn_t ret = IRQ_NONE;
1193 u16 status;
1194 int err;
1195
1196 switch (cmode) {
1197 case MV88E6XXX_PORT_STS_CMODE_SGMII:
1198 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1199 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1200 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1201 if (err)
1202 return ret;
1203 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1204 MV88E6390_SGMII_INT_LINK_UP)) {
1205 ret = IRQ_HANDLED;
1206 mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1207 }
1208 }
1209
1210 return ret;
1211}
1212
1213unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
1214{
1215 return irq_find_mapping(chip->g2_irq.domain, port);
1216}
1217
1218static const u16 mv88e6390_serdes_regs[] = {
1219
1220 0xf00a, 0xf00b, 0xf00c,
1221 0xf010, 0xf011, 0xf012, 0xf013,
1222 0xf016, 0xf017, 0xf018,
1223 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
1224 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
1225 0xf028, 0xf029,
1226 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
1227 0xf038, 0xf039,
1228
1229 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
1230 0x2008,
1231 0x200f,
1232 0xa000, 0xa001, 0xa002, 0xa003,
1233
1234 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1235 0x1008,
1236 0x100e, 0x100f,
1237 0x1018, 0x1019,
1238 0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
1239 0x9006,
1240 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
1241
1242 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1243 0x1028, 0x1029, 0x102a, 0x102b,
1244};
1245
1246int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
1247{
1248 if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
1249 return 0;
1250
1251 return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
1252}
1253
1254void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
1255{
1256 u16 *p = _p;
1257 int lane;
1258 u16 reg;
1259 int err;
1260 int i;
1261
1262 lane = mv88e6xxx_serdes_get_lane(chip, port);
1263 if (lane < 0)
1264 return;
1265
1266 for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
1267 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1268 mv88e6390_serdes_regs[i], ®);
1269 if (!err)
1270 p[i] = reg;
1271 }
1272}
1273
1274static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane)
1275{
1276 u16 reg, pcs;
1277 int err;
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287 if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE ||
1288 lane == MV88E6393X_PORT10_LANE) {
1289 err = mv88e6390_serdes_read(chip, lane,
1290 MDIO_MMD_PHYXS,
1291 MV88E6393X_SERDES_POC, ®);
1292 if (err)
1293 return err;
1294
1295 reg &= ~MV88E6393X_SERDES_POC_PDOWN;
1296 reg |= MV88E6393X_SERDES_POC_RESET;
1297
1298 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1299 MV88E6393X_SERDES_POC, reg);
1300 if (err)
1301 return err;
1302
1303 err = mv88e6390_serdes_power_sgmii(chip, lane, false);
1304 if (err)
1305 return err;
1306 }
1307
1308
1309
1310
1311
1312
1313
1314 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1315 MV88E6393X_SERDES_POC, &pcs);
1316 if (err)
1317 return err;
1318
1319 pcs &= MV88E6393X_SERDES_POC_PCS_MASK;
1320
1321 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1322 MV88E6393X_ERRATA_4_8_REG, ®);
1323 if (err)
1324 return err;
1325
1326 if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
1327 pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
1328 pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
1329 reg |= MV88E6393X_ERRATA_4_8_BIT;
1330 else
1331 reg &= ~MV88E6393X_ERRATA_4_8_BIT;
1332
1333 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1334 MV88E6393X_ERRATA_4_8_REG, reg);
1335}
1336
1337int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip)
1338{
1339 int err;
1340
1341 err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT0_LANE);
1342 if (err)
1343 return err;
1344
1345 err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT9_LANE);
1346 if (err)
1347 return err;
1348
1349 return mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT10_LANE);
1350}
1351
1352int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
1353 bool on)
1354{
1355 u8 cmode = chip->ports[port].cmode;
1356
1357 if (port != 0 && port != 9 && port != 10)
1358 return -EOPNOTSUPP;
1359
1360 switch (cmode) {
1361 case MV88E6XXX_PORT_STS_CMODE_SGMII:
1362 case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1363 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1364 return mv88e6390_serdes_power_sgmii(chip, lane, on);
1365 case MV88E6393X_PORT_STS_CMODE_5GBASER:
1366 case MV88E6393X_PORT_STS_CMODE_10GBASER:
1367 return mv88e6390_serdes_power_10g(chip, lane, on);
1368 }
1369
1370 return 0;
1371}
1372