net: dsa: mv88e6xxx: 6390 vs 6390X SERDES support
authorAndrew Lunn <andrew@lunn.ch>
Thu, 9 Aug 2018 13:38:41 +0000 (15:38 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 9 Aug 2018 18:08:20 +0000 (11:08 -0700)
The 6390 has two SERDES interfaces, used by ports 9 and 10.  The 6390X
has eight SERDES interfaces. These allow ports 9 and 10 to do 10G. Or
if lower speeds are used, some of the SERDES interfaces can be used by
ports 2-8 for 1000Base-X.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/dsa/mv88e6xxx/serdes.h

index 1427541..4c9ae5b 100644 (file)
@@ -3234,7 +3234,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .vtu_getnext = mv88e6390_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
-       .serdes_power = mv88e6390_serdes_power,
+       .serdes_power = mv88e6390x_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .phylink_validate = mv88e6390x_phylink_validate,
 };
@@ -3697,7 +3697,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .vtu_getnext = mv88e6390_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
-       .serdes_power = mv88e6390_serdes_power,
+       .serdes_power = mv88e6390x_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6390_avb_ops,
        .ptp_ops = &mv88e6352_ptp_ops,
index a218870..c534749 100644 (file)
@@ -174,11 +174,41 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
        return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 }
 
+/* Return the SERDES lane address a port is using. Only Ports 9 and 10
+ * have SERDES lanes. Returns -ENODEV if a port does not have a lane.
+ */
+static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
+{
+       u8 cmode;
+       int err;
+
+       err = mv88e6xxx_port_get_cmode(chip, port, &cmode);
+       if (err)
+               return err;
+
+       switch (port) {
+       case 9:
+               if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+                   cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
+                   cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+                       return MV88E6390_PORT9_LANE0;
+               return -ENODEV;
+       case 10:
+               if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+                   cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
+                   cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+                       return MV88E6390_PORT10_LANE0;
+               return -ENODEV;
+       default:
+               return -ENODEV;
+       }
+}
+
 /* Return the SERDES lane address a port is using. Ports 9 and 10 can
  * use multiple lanes. If so, return the first lane the port uses.
  * Returns -ENODEV if a port does not have a lane.
  */
-static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
+static int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
        u8 cmode_port9, cmode_port10, cmode_port;
        int err;
@@ -351,6 +381,25 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
                return lane;
 
        switch (port) {
+       case 9 ... 10:
+               return mv88e6390_serdes_power_lane(chip, port, lane, on);
+       }
+
+       return 0;
+}
+
+int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
+{
+       int lane;
+
+       lane = mv88e6390x_serdes_get_lane(chip, port);
+       if (lane == -ENODEV)
+               return 0;
+
+       if (lane < 0)
+               return lane;
+
+       switch (port) {
        case 2 ... 4:
        case 5 ... 7:
        case 9 ... 10:
index b6e5fbd..05c4825 100644 (file)
@@ -47,6 +47,7 @@
 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
+int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
                                 int port, uint8_t *data);