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+ker...@armlinux.org.uk>
---
 drivers/net/dsa/mv88e6xxx/serdes.c | 43 ++++++++++++++++++++++++++++--
 drivers/net/dsa/mv88e6xxx/serdes.h |  1 +
 2 files changed, 42 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)
 {
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h 
b/drivers/net/dsa/mv88e6xxx/serdes.h
index 71e3c3d0a24e..14315f26228a 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -41,6 +41,7 @@
 
 /* 10GBASE-R and 10GBASE-X4/X2 */
 #define MV88E6390_10G_CTRL1            (0x1000 + MDIO_CTRL1)
+#define MV88E6390_10G_STAT1            (0x1000 + MDIO_STAT1)
 
 /* 1000BASE-X and SGMII */
 #define MV88E6390_SGMII_BMCR           (0x2000 + MII_BMCR)
-- 
2.20.1

Reply via email to