2 * Marvell 88E6xxx SERDES manipulation, via SMI bus
4 * Copyright (c) 2008 Marvell Semiconductor
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.
14 #include <linux/interrupt.h>
15 #include <linux/irqdomain.h>
16 #include <linux/mii.h>
24 static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
27 return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
28 MV88E6352_SERDES_PAGE_FIBER,
32 static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
35 return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
36 MV88E6352_SERDES_PAGE_FIBER,
40 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
41 int lane, int device, int reg, u16 *val)
43 int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
45 return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
48 static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
49 int lane, int device, int reg, u16 val)
51 int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
53 return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
56 static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
61 err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
66 new_val = val & ~BMCR_PDOWN;
68 new_val = val | BMCR_PDOWN;
71 err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
76 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
78 u8 cmode = chip->ports[port].cmode;
80 if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
81 (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
82 (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
88 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
92 if (mv88e6352_port_has_serdes(chip, port)) {
93 err = mv88e6352_serdes_power_set(chip, on);
101 struct mv88e6352_serdes_hw_stat {
102 char string[ETH_GSTRING_LEN];
107 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
108 { "serdes_fibre_rx_error", 16, 21 },
109 { "serdes_PRBS_error", 32, 24 },
112 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
114 if (mv88e6352_port_has_serdes(chip, port))
115 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
120 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
121 int port, uint8_t *data)
123 struct mv88e6352_serdes_hw_stat *stat;
126 if (!mv88e6352_port_has_serdes(chip, port))
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,
134 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
137 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
138 struct mv88e6352_serdes_hw_stat *stat)
144 err = mv88e6352_serdes_read(chip, stat->reg, ®);
146 dev_err(chip->dev, "failed to read statistic\n");
152 if (stat->sizeof_stat == 32) {
153 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®);
155 dev_err(chip->dev, "failed to read statistic\n");
158 val = val << 16 | reg;
164 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
167 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
168 struct mv88e6352_serdes_hw_stat *stat;
172 if (!mv88e6352_port_has_serdes(chip, port))
175 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
176 ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
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];
185 return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
188 static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
190 struct dsa_switch *ds = chip->ds;
194 mv88e6352_serdes_read(chip, MII_BMSR, &status);
196 /* Status must be read twice in order to give the current link
197 * status. Otherwise the change in link status since the last
198 * read of the register is returned.
200 mv88e6352_serdes_read(chip, MII_BMSR, &status);
202 up = status & BMSR_LSTATUS;
204 dsa_port_phylink_mac_change(ds, port, up);
207 static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id)
209 struct mv88e6xxx_port *port = dev_id;
210 struct mv88e6xxx_chip *chip = port->chip;
211 irqreturn_t ret = IRQ_NONE;
215 mutex_lock(&chip->reg_lock);
217 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
221 if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
223 mv88e6352_serdes_irq_link(chip, port->port);
226 mutex_unlock(&chip->reg_lock);
231 static int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip)
233 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE,
234 MV88E6352_SERDES_INT_LINK_CHANGE);
237 static int mv88e6352_serdes_irq_disable(struct mv88e6xxx_chip *chip)
239 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 0);
242 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
246 if (!mv88e6352_port_has_serdes(chip, port))
249 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
250 MV88E6352_SERDES_IRQ);
251 if (chip->ports[port].serdes_irq < 0) {
252 dev_err(chip->dev, "Unable to map SERDES irq: %d\n",
253 chip->ports[port].serdes_irq);
254 return chip->ports[port].serdes_irq;
257 /* Requesting the IRQ will trigger irq callbacks. So we cannot
260 mutex_unlock(&chip->reg_lock);
261 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL,
262 mv88e6352_serdes_thread_fn,
263 IRQF_ONESHOT, "mv88e6xxx-serdes",
265 mutex_lock(&chip->reg_lock);
268 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
273 return mv88e6352_serdes_irq_enable(chip);
276 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
278 if (!mv88e6352_port_has_serdes(chip, port))
281 mv88e6352_serdes_irq_disable(chip);
283 /* Freeing the IRQ will trigger irq callbacks. So we cannot
286 mutex_unlock(&chip->reg_lock);
287 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
288 mutex_lock(&chip->reg_lock);
290 chip->ports[port].serdes_irq = 0;
293 /* Return the SERDES lane address a port is using. Only Ports 9 and 10
294 * have SERDES lanes. Returns -ENODEV if a port does not have a lane.
296 static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
298 u8 cmode = chip->ports[port].cmode;
302 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
303 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
304 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
305 return MV88E6390_PORT9_LANE0;
308 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
309 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
310 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
311 return MV88E6390_PORT10_LANE0;
318 /* Return the SERDES lane address a port is using. Ports 9 and 10 can
319 * use multiple lanes. If so, return the first lane the port uses.
320 * Returns -ENODEV if a port does not have a lane.
322 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
324 u8 cmode_port9, cmode_port10, cmode_port;
326 cmode_port9 = chip->ports[9].cmode;
327 cmode_port10 = chip->ports[10].cmode;
328 cmode_port = chip->ports[port].cmode;
332 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
333 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
334 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
335 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
336 return MV88E6390_PORT9_LANE1;
339 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
340 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
341 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
342 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
343 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
344 return MV88E6390_PORT9_LANE2;
347 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
348 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
349 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
350 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
351 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
352 return MV88E6390_PORT9_LANE3;
355 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
356 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
357 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
358 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
359 return MV88E6390_PORT10_LANE1;
362 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
363 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
364 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
365 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
366 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
367 return MV88E6390_PORT10_LANE2;
370 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
371 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
372 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
373 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
374 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
375 return MV88E6390_PORT10_LANE3;
378 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
379 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
380 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
381 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
382 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
383 return MV88E6390_PORT9_LANE0;
386 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
387 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
388 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
389 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
390 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
391 return MV88E6390_PORT10_LANE0;
398 /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
399 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
405 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
406 MV88E6390_PCS_CONTROL_1, &val);
412 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
413 MV88E6390_PCS_CONTROL_1_LOOPBACK |
414 MV88E6390_PCS_CONTROL_1_PDOWN);
416 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
419 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
420 MV88E6390_PCS_CONTROL_1, new_val);
425 /* Set the power on/off for SGMII and 1000Base-X */
426 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
432 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
433 MV88E6390_SGMII_CONTROL, &val);
438 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
439 MV88E6390_SGMII_CONTROL_LOOPBACK |
440 MV88E6390_SGMII_CONTROL_PDOWN);
442 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
445 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
446 MV88E6390_SGMII_CONTROL, new_val);
451 static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
454 u8 cmode = chip->ports[port].cmode;
457 case MV88E6XXX_PORT_STS_CMODE_SGMII:
458 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
459 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
460 return mv88e6390_serdes_power_sgmii(chip, lane, on);
461 case MV88E6XXX_PORT_STS_CMODE_XAUI:
462 case MV88E6XXX_PORT_STS_CMODE_RXAUI:
463 return mv88e6390_serdes_power_10g(chip, lane, on);
469 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
473 lane = mv88e6390_serdes_get_lane(chip, port);
482 return mv88e6390_serdes_power_lane(chip, port, lane, on);
488 int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
492 lane = mv88e6390x_serdes_get_lane(chip, port);
503 return mv88e6390_serdes_power_lane(chip, port, lane, on);
509 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
512 struct dsa_switch *ds = chip->ds;
516 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
517 MV88E6390_SGMII_STATUS, &status);
519 /* Status must be read twice in order to give the current link
520 * status. Otherwise the change in link status since the last
521 * read of the register is returned.
523 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
524 MV88E6390_SGMII_STATUS, &status);
525 up = status & MV88E6390_SGMII_STATUS_LINK;
527 dsa_port_phylink_mac_change(ds, port, up);
530 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
533 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
534 MV88E6390_SGMII_INT_ENABLE,
535 MV88E6390_SGMII_INT_LINK_DOWN |
536 MV88E6390_SGMII_INT_LINK_UP);
539 static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip,
542 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
543 MV88E6390_SGMII_INT_ENABLE, 0);
546 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
549 u8 cmode = chip->ports[port].cmode;
553 case MV88E6XXX_PORT_STS_CMODE_SGMII:
554 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
555 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
556 err = mv88e6390_serdes_irq_enable_sgmii(chip, lane);
562 int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
565 u8 cmode = chip->ports[port].cmode;
569 case MV88E6XXX_PORT_STS_CMODE_SGMII:
570 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
571 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
572 err = mv88e6390_serdes_irq_disable_sgmii(chip, lane);
578 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
579 int lane, u16 *status)
583 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
584 MV88E6390_SGMII_INT_STATUS, status);
589 static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
591 struct mv88e6xxx_port *port = dev_id;
592 struct mv88e6xxx_chip *chip = port->chip;
593 irqreturn_t ret = IRQ_NONE;
594 u8 cmode = port->cmode;
599 lane = mv88e6390x_serdes_get_lane(chip, port->port);
601 mutex_lock(&chip->reg_lock);
604 case MV88E6XXX_PORT_STS_CMODE_SGMII:
605 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
606 case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
607 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
610 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
611 MV88E6390_SGMII_INT_LINK_UP)) {
613 mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane);
617 mutex_unlock(&chip->reg_lock);
622 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
627 /* Only support ports 9 and 10 at the moment */
631 lane = mv88e6390x_serdes_get_lane(chip, port);
639 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
641 if (chip->ports[port].serdes_irq < 0) {
642 dev_err(chip->dev, "Unable to map SERDES irq: %d\n",
643 chip->ports[port].serdes_irq);
644 return chip->ports[port].serdes_irq;
647 /* Requesting the IRQ will trigger irq callbacks. So we cannot
650 mutex_unlock(&chip->reg_lock);
651 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL,
652 mv88e6390_serdes_thread_fn,
653 IRQF_ONESHOT, "mv88e6xxx-serdes",
655 mutex_lock(&chip->reg_lock);
658 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
663 return mv88e6390_serdes_irq_enable(chip, port, lane);
666 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
668 int lane = mv88e6390x_serdes_get_lane(chip, port);
676 mv88e6390_serdes_irq_disable(chip, port, lane);
678 /* Freeing the IRQ will trigger irq callbacks. So we cannot
681 mutex_unlock(&chip->reg_lock);
682 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
683 mutex_lock(&chip->reg_lock);
685 chip->ports[port].serdes_irq = 0;
688 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
690 u8 cmode = chip->ports[port].cmode;
695 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
696 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
697 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
698 return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES,