PORT_PCS_CTRL_FORCE_LINK |
                 PORT_PCS_CTRL_DUPLEX_FULL |
                 PORT_PCS_CTRL_FORCE_DUPLEX |
-                PORT_PCS_CTRL_UNFORCED);
+                PORT_PCS_CTRL_SPEED_UNFORCED);
 
        reg |= PORT_PCS_CTRL_FORCE_LINK;
        if (phydev->link)
 
        switch (phydev->speed) {
        case SPEED_1000:
-               reg |= PORT_PCS_CTRL_1000;
+               reg |= PORT_PCS_CTRL_SPEED_1000;
                break;
        case SPEED_100:
-               reg |= PORT_PCS_CTRL_100;
+               reg |= PORT_PCS_CTRL_SPEED_100;
                break;
        case SPEED_10:
-               reg |= PORT_PCS_CTRL_10;
+               reg |= PORT_PCS_CTRL_SPEED_10;
                break;
        default:
                pr_info("Unknown speed");
                 */
                err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®);
                if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
-                       reg &= ~PORT_PCS_CTRL_UNFORCED;
+                       reg &= ~PORT_PCS_CTRL_SPEED_UNFORCED;
                        reg |= PORT_PCS_CTRL_FORCE_LINK |
                                PORT_PCS_CTRL_LINK_UP |
                                PORT_PCS_CTRL_DUPLEX_FULL |
                                PORT_PCS_CTRL_FORCE_DUPLEX;
                        if (mv88e6xxx_6065_family(chip))
-                               reg |= PORT_PCS_CTRL_100;
+                               reg |= PORT_PCS_CTRL_SPEED_100;
                        else
-                               reg |= PORT_PCS_CTRL_1000;
+                               reg |= PORT_PCS_CTRL_SPEED_1000;
                } else {
-                       reg |= PORT_PCS_CTRL_UNFORCED;
+                       reg |= PORT_PCS_CTRL_SPEED_UNFORCED;
                }
 
                err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
        .phy_write = mv88e6xxx_phy_ppu_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6095_ops = {
        .phy_write = mv88e6xxx_phy_ppu_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6123_ops = {
        .phy_write = mv88e6xxx_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6131_ops = {
        .phy_write = mv88e6xxx_phy_ppu_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6161_ops = {
        .phy_write = mv88e6xxx_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6165_ops = {
        .phy_write = mv88e6xxx_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6171_ops = {
        .phy_write = mv88e6xxx_g2_smi_phy_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6172_ops = {
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+       .port_set_speed = mv88e6352_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6175_ops = {
        .phy_write = mv88e6xxx_g2_smi_phy_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6176_ops = {
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+       .port_set_speed = mv88e6352_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6185_ops = {
        .phy_write = mv88e6xxx_phy_ppu_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6240_ops = {
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+       .port_set_speed = mv88e6352_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6320_ops = {
        .phy_write = mv88e6xxx_g2_smi_phy_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6321_ops = {
        .phy_write = mv88e6xxx_g2_smi_phy_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6350_ops = {
        .phy_write = mv88e6xxx_g2_smi_phy_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6351_ops = {
        .phy_write = mv88e6xxx_g2_smi_phy_write,
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
+       .port_set_speed = mv88e6185_port_set_speed,
 };
 
 static const struct mv88e6xxx_ops mv88e6352_ops = {
        .port_set_link = mv88e6xxx_port_set_link,
        .port_set_duplex = mv88e6xxx_port_set_duplex,
        .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+       .port_set_speed = mv88e6352_port_set_speed,
 };
 
 static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 
 #define PORT_PCS_CTRL          0x01
 #define PORT_PCS_CTRL_RGMII_DELAY_RXCLK        BIT(15)
 #define PORT_PCS_CTRL_RGMII_DELAY_TXCLK        BIT(14)
+#define PORT_PCS_CTRL_FORCE_SPEED      BIT(13) /* 6390 */
+#define PORT_PCS_CTRL_ALTSPEED         BIT(12) /* 6390 */
+#define PORT_PCS_CTRL_200BASE          BIT(12) /* 6352 */
 #define PORT_PCS_CTRL_FC               BIT(7)
 #define PORT_PCS_CTRL_FORCE_FC         BIT(6)
 #define PORT_PCS_CTRL_LINK_UP          BIT(5)
 #define PORT_PCS_CTRL_FORCE_LINK       BIT(4)
 #define PORT_PCS_CTRL_DUPLEX_FULL      BIT(3)
 #define PORT_PCS_CTRL_FORCE_DUPLEX     BIT(2)
-#define PORT_PCS_CTRL_10               0x00
-#define PORT_PCS_CTRL_100              0x01
-#define PORT_PCS_CTRL_1000             0x02
-#define PORT_PCS_CTRL_UNFORCED         0x03
+#define PORT_PCS_CTRL_SPEED_MASK       (0x03)
+#define PORT_PCS_CTRL_SPEED_10         (0x00)
+#define PORT_PCS_CTRL_SPEED_100                (0x01)
+#define PORT_PCS_CTRL_SPEED_200                (0x02) /* 6065 and non Gb chips */
+#define PORT_PCS_CTRL_SPEED_1000       (0x02)
+#define PORT_PCS_CTRL_SPEED_10000      (0x03) /* 6390X */
+#define PORT_PCS_CTRL_SPEED_UNFORCED   (0x03)
 #define PORT_PAUSE_CTRL                0x02
 #define PORT_SWITCH_ID         0x03
 #define PORT_SWITCH_ID_PROD_NUM_6085   0x04a
         * or DUPLEX_UNFORCED for normal duplex detection.
         */
        int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
+
+#define SPEED_MAX              INT_MAX
+#define SPEED_UNFORCED         -2
+
+       /* Port's MAC speed (in Mbps)
+        *
+        * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
+        * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
+        */
+       int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
 };
 
 enum stat_type {
 
 /* Offset 0x01: MAC (or PCS or Physical) Control Register
  *
  * Link, Duplex and Flow Control have one force bit, one value bit.
+ *
+ * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
+ * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
+ * Newer chips need a ForcedSpd bit 13 set to consider the value.
  */
 
 static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
        return 0;
 }
 
+static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
+                                   int speed, bool alt_bit, bool force_bit)
+{
+       u16 reg, ctrl;
+       int err;
+
+       switch (speed) {
+       case 10:
+               ctrl = PORT_PCS_CTRL_SPEED_10;
+               break;
+       case 100:
+               ctrl = PORT_PCS_CTRL_SPEED_100;
+               break;
+       case 200:
+               if (alt_bit)
+                       ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED;
+               else
+                       ctrl = PORT_PCS_CTRL_SPEED_200;
+               break;
+       case 1000:
+               ctrl = PORT_PCS_CTRL_SPEED_1000;
+               break;
+       case 2500:
+               ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED;
+               break;
+       case 10000:
+               /* all bits set, fall through... */
+       case SPEED_UNFORCED:
+               ctrl = PORT_PCS_CTRL_SPEED_UNFORCED;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®);
+       if (err)
+               return err;
+
+       reg &= ~PORT_PCS_CTRL_SPEED_MASK;
+       if (alt_bit)
+               reg &= ~PORT_PCS_CTRL_ALTSPEED;
+       if (force_bit) {
+               reg &= ~PORT_PCS_CTRL_FORCE_SPEED;
+               if (speed)
+                       ctrl |= PORT_PCS_CTRL_FORCE_SPEED;
+       }
+       reg |= ctrl;
+
+       err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+       if (err)
+               return err;
+
+       if (speed)
+               netdev_dbg(chip->ds->ports[port].netdev,
+                          "Speed set to %d Mbps\n", speed);
+       else
+               netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n");
+
+       return 0;
+}
+
+/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
+int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+       if (speed == SPEED_MAX)
+               speed = 200;
+
+       if (speed > 200)
+               return -EOPNOTSUPP;
+
+       /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
+       return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
+/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
+int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+       if (speed == SPEED_MAX)
+               speed = 1000;
+
+       if (speed == 200 || speed > 1000)
+               return -EOPNOTSUPP;
+
+       return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
+/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
+int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+       if (speed == SPEED_MAX)
+               speed = 1000;
+
+       if (speed > 1000)
+               return -EOPNOTSUPP;
+
+       if (speed == 200 && port < 5)
+               return -EOPNOTSUPP;
+
+       return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
+}
+
+/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
+int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+       if (speed == SPEED_MAX)
+               speed = port < 9 ? 1000 : 2500;
+
+       if (speed > 2500)
+               return -EOPNOTSUPP;
+
+       if (speed == 200 && port != 0)
+               return -EOPNOTSUPP;
+
+       if (speed == 2500 && port < 9)
+               return -EOPNOTSUPP;
+
+       return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
+}
+
+/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
+int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+       if (speed == SPEED_MAX)
+               speed = port < 9 ? 1000 : 10000;
+
+       if (speed == 200 && port != 0)
+               return -EOPNOTSUPP;
+
+       if (speed >= 2500 && port < 9)
+               return -EOPNOTSUPP;
+
+       return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
+}
+
 /* Offset 0x04: Port Control Register */
 
 static const char * const mv88e6xxx_port_state_names[] = {