.get_strings            = mv88e6xxx_get_strings,
        .get_ethtool_stats      = mv88e6xxx_get_ethtool_stats,
        .get_sset_count         = mv88e6xxx_get_sset_count,
+       .adjust_link            = mv88e6xxx_adjust_link,
 #ifdef CONFIG_NET_DSA_HWMON
        .get_temp               = mv88e6xxx_get_temp,
 #endif
 
        .get_strings            = mv88e6xxx_get_strings,
        .get_ethtool_stats      = mv88e6xxx_get_ethtool_stats,
        .get_sset_count         = mv88e6xxx_get_sset_count,
+       .adjust_link            = mv88e6xxx_adjust_link,
 #ifdef CONFIG_NET_DSA_HWMON
        .get_temp               = mv88e6xxx_get_temp,
 #endif
 
        .get_strings            = mv88e6xxx_get_strings,
        .get_ethtool_stats      = mv88e6xxx_get_ethtool_stats,
        .get_sset_count         = mv88e6xxx_get_sset_count,
+       .adjust_link            = mv88e6xxx_adjust_link,
        .set_eee                = mv88e6xxx_set_eee,
        .get_eee                = mv88e6xxx_get_eee,
 #ifdef CONFIG_NET_DSA_HWMON
 
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
+#include <linux/ethtool.h>
 #include <linux/if_bridge.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
        return false;
 }
 
+/* We expect the switch to perform auto negotiation if there is a real
+ * phy. However, in the case of a fixed link phy, we force the port
+ * settings from the fixed link settings.
+ */
+void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
+                          struct phy_device *phydev)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       u32 ret, reg;
+
+       if (!phy_is_pseudo_fixed_link(phydev))
+               return;
+
+       mutex_lock(&ps->smi_mutex);
+
+       ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
+       if (ret < 0)
+               goto out;
+
+       reg = ret & ~(PORT_PCS_CTRL_LINK_UP |
+                     PORT_PCS_CTRL_FORCE_LINK |
+                     PORT_PCS_CTRL_DUPLEX_FULL |
+                     PORT_PCS_CTRL_FORCE_DUPLEX |
+                     PORT_PCS_CTRL_UNFORCED);
+
+       reg |= PORT_PCS_CTRL_FORCE_LINK;
+       if (phydev->link)
+                       reg |= PORT_PCS_CTRL_LINK_UP;
+
+       if (mv88e6xxx_6065_family(ds) && phydev->speed > SPEED_100)
+               goto out;
+
+       switch (phydev->speed) {
+       case SPEED_1000:
+               reg |= PORT_PCS_CTRL_1000;
+               break;
+       case SPEED_100:
+               reg |= PORT_PCS_CTRL_100;
+               break;
+       case SPEED_10:
+               reg |= PORT_PCS_CTRL_10;
+               break;
+       default:
+               pr_info("Unknown speed");
+               goto out;
+       }
+
+       reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
+       if (phydev->duplex == DUPLEX_FULL)
+               reg |= PORT_PCS_CTRL_DUPLEX_FULL;
+
+       _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_PCS_CTRL, reg);
+
+out:
+       mutex_unlock(&ps->smi_mutex);
+}
+
 /* Must be called with SMI mutex held */
 static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
 {
 
                                 uint64_t *data);
 int mv88e6xxx_get_sset_count(struct dsa_switch *ds);
 int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds);
+void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
+                          struct phy_device *phydev);
 int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
 void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
                        struct ethtool_regs *regs, void *_p);