1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6xxx SERDES manipulation, via SMI bus
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
10 #include <linux/interrupt.h>
11 #include <linux/irqdomain.h>
12 #include <linux/mii.h>
20 static int mv88e6352_serdes_read(struct mv88e6xxx_chip
*chip
, int reg
,
23 return mv88e6xxx_phy_page_read(chip
, MV88E6352_ADDR_SERDES
,
24 MV88E6352_SERDES_PAGE_FIBER
,
28 static int mv88e6352_serdes_write(struct mv88e6xxx_chip
*chip
, int reg
,
31 return mv88e6xxx_phy_page_write(chip
, MV88E6352_ADDR_SERDES
,
32 MV88E6352_SERDES_PAGE_FIBER
,
36 static int mv88e6390_serdes_read(struct mv88e6xxx_chip
*chip
,
37 int lane
, int device
, int reg
, u16
*val
)
39 int reg_c45
= MII_ADDR_C45
| device
<< 16 | reg
;
41 return mv88e6xxx_phy_read(chip
, lane
, reg_c45
, val
);
44 static int mv88e6390_serdes_write(struct mv88e6xxx_chip
*chip
,
45 int lane
, int device
, int reg
, u16 val
)
47 int reg_c45
= MII_ADDR_C45
| device
<< 16 | reg
;
49 return mv88e6xxx_phy_write(chip
, lane
, reg_c45
, val
);
52 static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip
*chip
,
54 struct phylink_link_state
*state
)
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
;
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
;
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
;
72 state
->speed
= SPEED_1000
;
74 case MV88E6390_SGMII_PHY_STATUS_SPEED_100
:
75 state
->speed
= SPEED_100
;
77 case MV88E6390_SGMII_PHY_STATUS_SPEED_10
:
78 state
->speed
= SPEED_10
;
81 dev_err(chip
->dev
, "invalid PHY speed\n");
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
);
98 int mv88e6352_serdes_power(struct mv88e6xxx_chip
*chip
, int port
, u8 lane
,
104 err
= mv88e6352_serdes_read(chip
, MII_BMCR
, &val
);
109 new_val
= val
& ~BMCR_PDOWN
;
111 new_val
= val
| BMCR_PDOWN
;
114 err
= mv88e6352_serdes_write(chip
, MII_BMCR
, new_val
);
119 int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip
*chip
, int port
,
120 u8 lane
, unsigned int mode
,
121 phy_interface_t interface
,
122 const unsigned long *advertise
)
129 case PHY_INTERFACE_MODE_SGMII
:
133 case PHY_INTERFACE_MODE_1000BASEX
:
134 adv
= linkmode_adv_to_mii_adv_x(advertise
,
135 ETHTOOL_LINK_MODE_1000baseX_Full_BIT
);
142 err
= mv88e6352_serdes_read(chip
, MII_ADVERTISE
, &val
);
146 changed
= val
!= adv
;
148 err
= mv88e6352_serdes_write(chip
, MII_ADVERTISE
, adv
);
153 err
= mv88e6352_serdes_read(chip
, MII_BMCR
, &val
);
157 if (phylink_autoneg_inband(mode
))
158 bmcr
= val
| BMCR_ANENABLE
;
160 bmcr
= val
& ~BMCR_ANENABLE
;
165 return mv88e6352_serdes_write(chip
, MII_BMCR
, bmcr
);
168 int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip
*chip
, int port
,
169 u8 lane
, struct phylink_link_state
*state
)
174 err
= mv88e6352_serdes_read(chip
, 0x11, &status
);
176 dev_err(chip
->dev
, "can't read Serdes PHY status: %d\n", err
);
180 err
= mv88e6352_serdes_read(chip
, MII_LPA
, &lpa
);
182 dev_err(chip
->dev
, "can't read Serdes PHY LPA: %d\n", err
);
186 return mv88e6xxx_serdes_pcs_get_state(chip
, status
, lpa
, state
);
189 int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip
*chip
, int port
,
195 err
= mv88e6352_serdes_read(chip
, MII_BMCR
, &bmcr
);
199 return mv88e6352_serdes_write(chip
, MII_BMCR
, bmcr
| BMCR_ANRESTART
);
202 int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip
*chip
, int port
,
203 u8 lane
, int speed
, int duplex
)
208 err
= mv88e6352_serdes_read(chip
, MII_BMCR
, &val
);
212 bmcr
= val
& ~(BMCR_SPEED100
| BMCR_FULLDPLX
| BMCR_SPEED1000
);
215 bmcr
|= BMCR_SPEED1000
;
218 bmcr
|= BMCR_SPEED100
;
224 if (duplex
== DUPLEX_FULL
)
225 bmcr
|= BMCR_FULLDPLX
;
230 return mv88e6352_serdes_write(chip
, MII_BMCR
, bmcr
);
233 u8
mv88e6352_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
235 u8 cmode
= chip
->ports
[port
].cmode
;
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; /* Unused */
246 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip
*chip
, int port
)
248 if (mv88e6xxx_serdes_get_lane(chip
, port
))
254 struct mv88e6352_serdes_hw_stat
{
255 char string
[ETH_GSTRING_LEN
];
260 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats
[] = {
261 { "serdes_fibre_rx_error", 16, 21 },
262 { "serdes_PRBS_error", 32, 24 },
265 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip
*chip
, int port
)
267 if (mv88e6352_port_has_serdes(chip
, port
))
268 return ARRAY_SIZE(mv88e6352_serdes_hw_stats
);
273 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip
*chip
,
274 int port
, uint8_t *data
)
276 struct mv88e6352_serdes_hw_stat
*stat
;
279 if (!mv88e6352_port_has_serdes(chip
, port
))
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
,
287 return ARRAY_SIZE(mv88e6352_serdes_hw_stats
);
290 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip
*chip
,
291 struct mv88e6352_serdes_hw_stat
*stat
)
297 err
= mv88e6352_serdes_read(chip
, stat
->reg
, ®
);
299 dev_err(chip
->dev
, "failed to read statistic\n");
305 if (stat
->sizeof_stat
== 32) {
306 err
= mv88e6352_serdes_read(chip
, stat
->reg
+ 1, ®
);
308 dev_err(chip
->dev
, "failed to read statistic\n");
311 val
= val
<< 16 | reg
;
317 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip
*chip
, int port
,
320 struct mv88e6xxx_port
*mv88e6xxx_port
= &chip
->ports
[port
];
321 struct mv88e6352_serdes_hw_stat
*stat
;
325 if (!mv88e6352_port_has_serdes(chip
, port
))
328 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats
) >
329 ARRAY_SIZE(mv88e6xxx_port
->serdes_stats
));
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
];
338 return ARRAY_SIZE(mv88e6352_serdes_hw_stats
);
341 static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip
*chip
, int port
)
346 /* If the link has dropped, we want to know about it. */
347 err
= mv88e6352_serdes_read(chip
, MII_BMSR
, &bmsr
);
349 dev_err(chip
->dev
, "can't read Serdes BMSR: %d\n", err
);
353 dsa_port_phylink_mac_change(chip
->ds
, port
, !!(bmsr
& BMSR_LSTATUS
));
356 irqreturn_t
mv88e6352_serdes_irq_status(struct mv88e6xxx_chip
*chip
, int port
,
359 irqreturn_t ret
= IRQ_NONE
;
363 err
= mv88e6352_serdes_read(chip
, MV88E6352_SERDES_INT_STATUS
, &status
);
367 if (status
& MV88E6352_SERDES_INT_LINK_CHANGE
) {
369 mv88e6352_serdes_irq_link(chip
, port
);
375 int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip
*chip
, int port
, u8 lane
,
381 val
|= MV88E6352_SERDES_INT_LINK_CHANGE
;
383 return mv88e6352_serdes_write(chip
, MV88E6352_SERDES_INT_ENABLE
, val
);
386 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip
*chip
, int port
)
388 return irq_find_mapping(chip
->g2_irq
.domain
, MV88E6352_SERDES_IRQ
);
391 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip
*chip
, int port
)
393 if (!mv88e6352_port_has_serdes(chip
, port
))
396 return 32 * sizeof(u16
);
399 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip
*chip
, int port
, void *_p
)
406 if (!mv88e6352_port_has_serdes(chip
, port
))
409 for (i
= 0 ; i
< 32; i
++) {
410 err
= mv88e6352_serdes_read(chip
, i
, ®
);
416 u8
mv88e6341_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
418 u8 cmode
= chip
->ports
[port
].cmode
;
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
;
433 int mv88e6185_serdes_power(struct mv88e6xxx_chip
*chip
, int port
, u8 lane
,
436 /* The serdes power can't be controlled on this switch chip but we need
437 * to supply this function to avoid returning -EOPNOTSUPP in
438 * mv88e6xxx_serdes_power_up/mv88e6xxx_serdes_power_down
443 u8
mv88e6185_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
445 /* There are no configurable serdes lanes on this switch chip but we
446 * need to return non-zero so that callers of
447 * mv88e6xxx_serdes_get_lane() know this is a serdes port.
449 switch (chip
->ports
[port
].cmode
) {
450 case MV88E6185_PORT_STS_CMODE_SERDES
:
451 case MV88E6185_PORT_STS_CMODE_1000BASE_X
:
458 int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip
*chip
, int port
,
459 u8 lane
, struct phylink_link_state
*state
)
464 err
= mv88e6xxx_port_read(chip
, port
, MV88E6XXX_PORT_STS
, &status
);
468 state
->link
= !!(status
& MV88E6XXX_PORT_STS_LINK
);
471 state
->duplex
= status
& MV88E6XXX_PORT_STS_DUPLEX
? DUPLEX_FULL
: DUPLEX_HALF
;
473 switch (status
& MV88E6XXX_PORT_STS_SPEED_MASK
) {
474 case MV88E6XXX_PORT_STS_SPEED_1000
:
475 state
->speed
= SPEED_1000
;
477 case MV88E6XXX_PORT_STS_SPEED_100
:
478 state
->speed
= SPEED_100
;
480 case MV88E6XXX_PORT_STS_SPEED_10
:
481 state
->speed
= SPEED_10
;
484 dev_err(chip
->dev
, "invalid PHY speed\n");
488 state
->duplex
= DUPLEX_UNKNOWN
;
489 state
->speed
= SPEED_UNKNOWN
;
495 int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip
*chip
, int port
, u8 lane
,
498 u8 cmode
= chip
->ports
[port
].cmode
;
500 /* The serdes interrupts are enabled in the G2_INT_MASK register. We
501 * need to return 0 to avoid returning -EOPNOTSUPP in
502 * mv88e6xxx_serdes_irq_enable/mv88e6xxx_serdes_irq_disable
505 case MV88E6185_PORT_STS_CMODE_SERDES
:
506 case MV88E6185_PORT_STS_CMODE_1000BASE_X
:
513 static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip
*chip
, int port
)
518 err
= mv88e6xxx_port_read(chip
, port
, MV88E6XXX_PORT_STS
, &status
);
520 dev_err(chip
->dev
, "can't read port status: %d\n", err
);
524 dsa_port_phylink_mac_change(chip
->ds
, port
, !!(status
& MV88E6XXX_PORT_STS_LINK
));
527 irqreturn_t
mv88e6097_serdes_irq_status(struct mv88e6xxx_chip
*chip
, int port
,
530 u8 cmode
= chip
->ports
[port
].cmode
;
533 case MV88E6185_PORT_STS_CMODE_SERDES
:
534 case MV88E6185_PORT_STS_CMODE_1000BASE_X
:
535 mv88e6097_serdes_irq_link(chip
, port
);
542 u8
mv88e6390_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
544 u8 cmode
= chip
->ports
[port
].cmode
;
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
;
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
;
565 u8
mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip
*chip
, int port
)
567 u8 cmode_port
= chip
->ports
[port
].cmode
;
568 u8 cmode_port10
= chip
->ports
[10].cmode
;
569 u8 cmode_port9
= chip
->ports
[9].cmode
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
640 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
641 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip
*chip
, u8 lane
,
647 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
648 MV88E6390_10G_CTRL1
, &val
);
654 new_val
= val
& ~(MDIO_CTRL1_RESET
|
655 MDIO_PCS_CTRL1_LOOPBACK
|
658 new_val
= val
| MDIO_CTRL1_LPOWER
;
661 err
= mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
662 MV88E6390_10G_CTRL1
, new_val
);
667 /* Set power up/down for SGMII and 1000Base-X */
668 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip
*chip
, u8 lane
,
674 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
675 MV88E6390_SGMII_BMCR
, &val
);
680 new_val
= val
& ~(BMCR_RESET
| BMCR_LOOPBACK
| BMCR_PDOWN
);
682 new_val
= val
| BMCR_PDOWN
;
685 err
= mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
686 MV88E6390_SGMII_BMCR
, new_val
);
691 struct mv88e6390_serdes_hw_stat
{
692 char string
[ETH_GSTRING_LEN
];
696 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats
[] = {
697 { "serdes_rx_pkts", 0xf021 },
698 { "serdes_rx_bytes", 0xf024 },
699 { "serdes_rx_pkts_error", 0xf027 },
702 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip
*chip
, int port
)
704 if (mv88e6390_serdes_get_lane(chip
, port
) == 0)
707 return ARRAY_SIZE(mv88e6390_serdes_hw_stats
);
710 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip
*chip
,
711 int port
, uint8_t *data
)
713 struct mv88e6390_serdes_hw_stat
*stat
;
716 if (mv88e6390_serdes_get_lane(chip
, port
) == 0)
719 for (i
= 0; i
< ARRAY_SIZE(mv88e6390_serdes_hw_stats
); i
++) {
720 stat
= &mv88e6390_serdes_hw_stats
[i
];
721 memcpy(data
+ i
* ETH_GSTRING_LEN
, stat
->string
,
724 return ARRAY_SIZE(mv88e6390_serdes_hw_stats
);
727 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip
*chip
, int lane
,
728 struct mv88e6390_serdes_hw_stat
*stat
)
733 for (i
= 0; i
< 3; i
++) {
734 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
735 stat
->reg
+ i
, ®
[i
]);
737 dev_err(chip
->dev
, "failed to read statistic\n");
742 return reg
[0] | ((u64
)reg
[1] << 16) | ((u64
)reg
[2] << 32);
745 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip
*chip
, int port
,
748 struct mv88e6390_serdes_hw_stat
*stat
;
752 lane
= mv88e6390_serdes_get_lane(chip
, port
);
756 for (i
= 0; i
< ARRAY_SIZE(mv88e6390_serdes_hw_stats
); i
++) {
757 stat
= &mv88e6390_serdes_hw_stats
[i
];
758 data
[i
] = mv88e6390_serdes_get_stat(chip
, lane
, stat
);
761 return ARRAY_SIZE(mv88e6390_serdes_hw_stats
);
764 static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip
*chip
, u8 lane
)
769 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
770 MV88E6390_PG_CONTROL
, ®
);
774 reg
|= MV88E6390_PG_CONTROL_ENABLE_PC
;
775 return mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
776 MV88E6390_PG_CONTROL
, reg
);
779 int mv88e6390_serdes_power(struct mv88e6xxx_chip
*chip
, int port
, u8 lane
,
782 u8 cmode
= chip
->ports
[port
].cmode
;
786 case MV88E6XXX_PORT_STS_CMODE_SGMII
:
787 case MV88E6XXX_PORT_STS_CMODE_1000BASEX
:
788 case MV88E6XXX_PORT_STS_CMODE_2500BASEX
:
789 err
= mv88e6390_serdes_power_sgmii(chip
, lane
, up
);
791 case MV88E6XXX_PORT_STS_CMODE_XAUI
:
792 case MV88E6XXX_PORT_STS_CMODE_RXAUI
:
793 err
= mv88e6390_serdes_power_10g(chip
, lane
, up
);
798 err
= mv88e6390_serdes_enable_checker(chip
, lane
);
803 int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip
*chip
, int port
,
804 u8 lane
, unsigned int mode
,
805 phy_interface_t interface
,
806 const unsigned long *advertise
)
813 case PHY_INTERFACE_MODE_SGMII
:
817 case PHY_INTERFACE_MODE_1000BASEX
:
818 adv
= linkmode_adv_to_mii_adv_x(advertise
,
819 ETHTOOL_LINK_MODE_1000baseX_Full_BIT
);
822 case PHY_INTERFACE_MODE_2500BASEX
:
823 adv
= linkmode_adv_to_mii_adv_x(advertise
,
824 ETHTOOL_LINK_MODE_2500baseX_Full_BIT
);
831 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
832 MV88E6390_SGMII_ADVERTISE
, &val
);
836 changed
= val
!= adv
;
838 err
= mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
839 MV88E6390_SGMII_ADVERTISE
, adv
);
844 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
845 MV88E6390_SGMII_BMCR
, &val
);
849 if (phylink_autoneg_inband(mode
))
850 bmcr
= val
| BMCR_ANENABLE
;
852 bmcr
= val
& ~BMCR_ANENABLE
;
854 /* setting ANENABLE triggers a restart of negotiation */
858 return mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
859 MV88E6390_SGMII_BMCR
, bmcr
);
862 static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip
*chip
,
863 int port
, u8 lane
, struct phylink_link_state
*state
)
868 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
869 MV88E6390_SGMII_PHY_STATUS
, &status
);
871 dev_err(chip
->dev
, "can't read Serdes PHY status: %d\n", err
);
875 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
876 MV88E6390_SGMII_LPA
, &lpa
);
878 dev_err(chip
->dev
, "can't read Serdes PHY LPA: %d\n", err
);
882 return mv88e6xxx_serdes_pcs_get_state(chip
, status
, lpa
, state
);
885 static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip
*chip
,
886 int port
, u8 lane
, struct phylink_link_state
*state
)
891 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
892 MV88E6390_10G_STAT1
, &status
);
896 state
->link
= !!(status
& MDIO_STAT1_LSTATUS
);
898 state
->speed
= SPEED_10000
;
899 state
->duplex
= DUPLEX_FULL
;
905 int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip
*chip
, int port
,
906 u8 lane
, struct phylink_link_state
*state
)
908 switch (state
->interface
) {
909 case PHY_INTERFACE_MODE_SGMII
:
910 case PHY_INTERFACE_MODE_1000BASEX
:
911 case PHY_INTERFACE_MODE_2500BASEX
:
912 return mv88e6390_serdes_pcs_get_state_sgmii(chip
, port
, lane
,
914 case PHY_INTERFACE_MODE_XAUI
:
915 case PHY_INTERFACE_MODE_RXAUI
:
916 return mv88e6390_serdes_pcs_get_state_10g(chip
, port
, lane
,
924 int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip
*chip
, int port
,
930 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
931 MV88E6390_SGMII_BMCR
, &bmcr
);
935 return mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
936 MV88E6390_SGMII_BMCR
,
937 bmcr
| BMCR_ANRESTART
);
940 int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip
*chip
, int port
,
941 u8 lane
, int speed
, int duplex
)
946 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
947 MV88E6390_SGMII_BMCR
, &val
);
951 bmcr
= val
& ~(BMCR_SPEED100
| BMCR_FULLDPLX
| BMCR_SPEED1000
);
955 bmcr
|= BMCR_SPEED1000
;
958 bmcr
|= BMCR_SPEED100
;
964 if (duplex
== DUPLEX_FULL
)
965 bmcr
|= BMCR_FULLDPLX
;
970 return mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
971 MV88E6390_SGMII_BMCR
, bmcr
);
974 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip
*chip
,
980 /* If the link has dropped, we want to know about it. */
981 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
982 MV88E6390_SGMII_BMSR
, &bmsr
);
984 dev_err(chip
->dev
, "can't read Serdes BMSR: %d\n", err
);
988 dsa_port_phylink_mac_change(chip
->ds
, port
, !!(bmsr
& BMSR_LSTATUS
));
991 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip
*chip
,
992 u8 lane
, bool enable
)
997 val
|= MV88E6390_SGMII_INT_LINK_DOWN
|
998 MV88E6390_SGMII_INT_LINK_UP
;
1000 return mv88e6390_serdes_write(chip
, lane
, MDIO_MMD_PHYXS
,
1001 MV88E6390_SGMII_INT_ENABLE
, val
);
1004 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip
*chip
, int port
, u8 lane
,
1007 u8 cmode
= chip
->ports
[port
].cmode
;
1010 case MV88E6XXX_PORT_STS_CMODE_SGMII
:
1011 case MV88E6XXX_PORT_STS_CMODE_1000BASEX
:
1012 case MV88E6XXX_PORT_STS_CMODE_2500BASEX
:
1013 return mv88e6390_serdes_irq_enable_sgmii(chip
, lane
, enable
);
1019 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip
*chip
,
1020 u8 lane
, u16
*status
)
1024 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
1025 MV88E6390_SGMII_INT_STATUS
, status
);
1030 irqreturn_t
mv88e6390_serdes_irq_status(struct mv88e6xxx_chip
*chip
, int port
,
1033 u8 cmode
= chip
->ports
[port
].cmode
;
1034 irqreturn_t ret
= IRQ_NONE
;
1039 case MV88E6XXX_PORT_STS_CMODE_SGMII
:
1040 case MV88E6XXX_PORT_STS_CMODE_1000BASEX
:
1041 case MV88E6XXX_PORT_STS_CMODE_2500BASEX
:
1042 err
= mv88e6390_serdes_irq_status_sgmii(chip
, lane
, &status
);
1045 if (status
& (MV88E6390_SGMII_INT_LINK_DOWN
|
1046 MV88E6390_SGMII_INT_LINK_UP
)) {
1048 mv88e6390_serdes_irq_link_sgmii(chip
, port
, lane
);
1055 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip
*chip
, int port
)
1057 return irq_find_mapping(chip
->g2_irq
.domain
, port
);
1060 static const u16 mv88e6390_serdes_regs
[] = {
1061 /* SERDES common registers */
1062 0xf00a, 0xf00b, 0xf00c,
1063 0xf010, 0xf011, 0xf012, 0xf013,
1064 0xf016, 0xf017, 0xf018,
1065 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
1066 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
1068 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
1071 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
1074 0xa000, 0xa001, 0xa002, 0xa003,
1076 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1080 0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
1082 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
1084 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1085 0x1028, 0x1029, 0x102a, 0x102b,
1088 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip
*chip
, int port
)
1090 if (mv88e6xxx_serdes_get_lane(chip
, port
) == 0)
1093 return ARRAY_SIZE(mv88e6390_serdes_regs
) * sizeof(u16
);
1096 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip
*chip
, int port
, void *_p
)
1104 lane
= mv88e6xxx_serdes_get_lane(chip
, port
);
1108 for (i
= 0 ; i
< ARRAY_SIZE(mv88e6390_serdes_regs
); i
++) {
1109 err
= mv88e6390_serdes_read(chip
, lane
, MDIO_MMD_PHYXS
,
1110 mv88e6390_serdes_regs
[i
], ®
);