net: dsa: mv88e6xxx: support 2500base-x in SGMII IRQ handler
authorMarek Behún <marek.behun@nic.cz>
Mon, 26 Aug 2019 21:31:50 +0000 (23:31 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Aug 2019 04:42:16 +0000 (21:42 -0700)
The mv88e6390_serdes_irq_link_sgmii IRQ handler reads the SERDES PHY
status register to determine speed, among other things. If cmode of the
port is set to 2500base-x, though, the PHY still reports 1000 Mbps (the
PHY register itself does not differentiate between 1000 Mbps and 2500
Mbps - it thinks it is running at 1000 Mbps, although clock is 2.5x
faster).
Look at the cmode and set SPEED_2500 if cmode is set to 2500base-x.
Also tell mv88e6xxx_port_setup_mac the PHY interface mode corresponding
to current cmode in terms of phy_interface_t.

Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Vivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/serdes.c

index 20c526c2a9ee648f42521a882fc84f7a53f75b4b..678aaba3d019c5613738a905913739e65b0ca80f 100644 (file)
@@ -505,9 +505,11 @@ int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
                                            int port, int lane)
 {
+       u8 cmode = chip->ports[port].cmode;
        struct dsa_switch *ds = chip->ds;
        int duplex = DUPLEX_UNKNOWN;
        int speed = SPEED_UNKNOWN;
+       phy_interface_t mode;
        int link, err;
        u16 status;
 
@@ -527,7 +529,10 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
 
                switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
                case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
-                       speed = SPEED_1000;
+                       if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+                               speed = SPEED_2500;
+                       else
+                               speed = SPEED_1000;
                        break;
                case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
                        speed = SPEED_100;
@@ -541,8 +546,22 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
                }
        }
 
+       switch (cmode) {
+       case MV88E6XXX_PORT_STS_CMODE_SGMII:
+               mode = PHY_INTERFACE_MODE_SGMII;
+               break;
+       case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+               mode = PHY_INTERFACE_MODE_1000BASEX;
+               break;
+       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
+               mode = PHY_INTERFACE_MODE_2500BASEX;
+               break;
+       default:
+               mode = PHY_INTERFACE_MODE_NA;
+       }
+
        err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
-                                      PAUSE_OFF, PHY_INTERFACE_MODE_NA);
+                                      PAUSE_OFF, mode);
        if (err)
                dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
                        err);