net: dsa: mv88e6xxx: 88e6390 10G serdes support
authorRussell King <rmk+kernel@armlinux.org.uk>
Thu, 30 Apr 2020 08:21:39 +0000 (09:21 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 May 2020 22:40:15 +0000 (15:40 -0700)
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>
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/dsa/mv88e6xxx/serdes.h

index 33d9923cf7c512c8cfc8d81c55d3383b3c76e292..9c07b4f3d3454e7d2ba9e8d8f7bd49dd934952b5 100644 (file)
@@ -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)
 {
index 71e3c3d0a24eb106c9b6d4c920754d963e6f296c..14315f26228a31417c7c105a36859615516e8c89 100644 (file)
@@ -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)