diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2020-04-30 09:21:39 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-01 15:40:15 -0700 |
commit | 7019bba4330750a29d87b6ce70ac6fabc007b3dc (patch) | |
tree | 3aa0641edb6157650aeb9dd3ca85bc190c77e10f /drivers/net/dsa/mv88e6xxx/serdes.c | |
parent | bf604bc90b30a7c9d024e3be9b3ad3b0dc3f51c4 (diff) | |
download | linux-7019bba4330750a29d87b6ce70ac6fabc007b3dc.tar.gz linux-7019bba4330750a29d87b6ce70ac6fabc007b3dc.tar.bz2 linux-7019bba4330750a29d87b6ce70ac6fabc007b3dc.zip |
net: dsa: mv88e6xxx: 88e6390 10G serdes support
Add support for reading and reporting the 10G link status on the
88e6390 in addition to the 1000BASE-X/2500BASE-X/SGMII status.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/serdes.c')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 33d9923cf7c5..9c07b4f3d345 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -748,8 +748,8 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, MV88E6390_SGMII_BMCR, bmcr); } -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - u8 lane, struct phylink_link_state *state) +static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, + int port, u8 lane, struct phylink_link_state *state) { u16 lpa, status; int err; @@ -771,6 +771,45 @@ int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); } +static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, + int port, u8 lane, struct phylink_link_state *state) +{ + u16 status; + int err; + + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_10G_STAT1, &status); + if (err) + return err; + + state->link = !!(status & MDIO_STAT1_LSTATUS); + if (state->link) { + state->speed = SPEED_10000; + state->duplex = DUPLEX_FULL; + } + + return 0; +} + +int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, + u8 lane, struct phylink_link_state *state) +{ + switch (state->interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane, + state); + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_RXAUI: + return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane, + state); + + default: + return -EOPNOTSUPP; + } +} + int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, u8 lane) { |