2 * Marvell 88E6xxx SERDES manipulation, via SMI bus
4 * Copyright (c) 2008 Marvell Semiconductor
6 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
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 /* 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.
191 static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
193 u8 cmode = chip->ports[port].cmode;
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;
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;
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.
217 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
219 u8 cmode_port9, cmode_port10, cmode_port;
221 cmode_port9 = chip->ports[9].cmode;
222 cmode_port10 = chip->ports[10].cmode;
223 cmode_port = chip->ports[port].cmode;
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;
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;
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;
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;
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;
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;
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;
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;
293 /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
294 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
300 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
301 MV88E6390_PCS_CONTROL_1, &val);
307 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
308 MV88E6390_PCS_CONTROL_1_LOOPBACK |
309 MV88E6390_PCS_CONTROL_1_PDOWN);
311 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN;
314 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
315 MV88E6390_PCS_CONTROL_1, new_val);
320 /* Set the power on/off for SGMII and 1000Base-X */
321 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
327 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
328 MV88E6390_SGMII_CONTROL, &val);
333 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
334 MV88E6390_SGMII_CONTROL_LOOPBACK |
335 MV88E6390_SGMII_CONTROL_PDOWN);
337 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN;
340 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
341 MV88E6390_SGMII_CONTROL, new_val);
346 static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
349 u8 cmode = chip->ports[port].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);
364 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
368 lane = mv88e6390_serdes_get_lane(chip, port);
377 return mv88e6390_serdes_power_lane(chip, port, lane, on);
383 int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
387 lane = mv88e6390x_serdes_get_lane(chip, port);
398 return mv88e6390_serdes_power_lane(chip, port, lane, on);
404 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
407 struct dsa_switch *ds = chip->ds;
411 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
412 MV88E6390_SGMII_STATUS, &status);
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.
418 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
419 MV88E6390_SGMII_STATUS, &status);
420 up = status & MV88E6390_SGMII_STATUS_LINK;
422 dsa_port_phylink_mac_change(ds, port, up);
425 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
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);
434 static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip,
437 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
438 MV88E6390_SGMII_INT_ENABLE, 0);
441 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
444 u8 cmode = chip->ports[port].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);
457 int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
460 u8 cmode = chip->ports[port].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);
473 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
474 int lane, u16 *status)
478 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
479 MV88E6390_SGMII_INT_STATUS, status);
484 static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
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;
494 lane = mv88e6390x_serdes_get_lane(chip, port->port);
496 mutex_lock(&chip->reg_lock);
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);
505 if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
506 MV88E6390_SGMII_INT_LINK_UP)) {
508 mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane);
512 mutex_unlock(&chip->reg_lock);
517 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
522 /* Only support ports 9 and 10 at the moment */
526 lane = mv88e6390x_serdes_get_lane(chip, port);
534 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
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;
542 /* Requesting the IRQ will trigger irq callbacks. So we cannot
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",
550 mutex_lock(&chip->reg_lock);
553 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
558 return mv88e6390_serdes_irq_enable(chip, port, lane);
561 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
563 int lane = mv88e6390x_serdes_get_lane(chip, port);
571 mv88e6390_serdes_irq_disable(chip, port, lane);
573 /* Freeing the IRQ will trigger irq callbacks. So we cannot
576 mutex_unlock(&chip->reg_lock);
577 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
578 mutex_lock(&chip->reg_lock);
580 chip->ports[port].serdes_irq = 0;
583 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
585 u8 cmode = chip->ports[port].cmode;
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,