serdes_phy_addr = intel_priv->mdio_adhoc_addr;
 
+       /* Set the serdes rate and the PCLK rate */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR0);
+
+       data &= ~SERDES_RATE_MASK;
+       data &= ~SERDES_PCLK_MASK;
+
+       if (priv->plat->max_speed == 2500)
+               data |= SERDES_RATE_PCIE_GEN2 << SERDES_RATE_PCIE_SHIFT |
+                       SERDES_PCLK_37p5MHZ << SERDES_PCLK_SHIFT;
+       else
+               data |= SERDES_RATE_PCIE_GEN1 << SERDES_RATE_PCIE_SHIFT |
+                       SERDES_PCLK_70MHZ << SERDES_PCLK_SHIFT;
+
+       mdiobus_write(priv->mii, serdes_phy_addr, SERDES_GCR0, data);
+
        /* assert clk_req */
        data = mdiobus_read(priv->mii, serdes_phy_addr, SERDES_GCR0);
        data |= SERDES_PLL_CLK;
        }
 }
 
+static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
+{
+       struct intel_priv_data *intel_priv = intel_data;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       int serdes_phy_addr = 0;
+       u32 data = 0;
+
+       serdes_phy_addr = intel_priv->mdio_adhoc_addr;
+
+       /* Determine the link speed mode: 2.5Gbps/1Gbps */
+       data = mdiobus_read(priv->mii, serdes_phy_addr,
+                           SERDES_GCR);
+
+       if (((data & SERDES_LINK_MODE_MASK) >> SERDES_LINK_MODE_SHIFT) ==
+           SERDES_LINK_MODE_2G5) {
+               dev_info(priv->device, "Link Speed Mode: 2.5Gbps\n");
+               priv->plat->max_speed = 2500;
+               priv->plat->phy_interface = PHY_INTERFACE_MODE_2500BASEX;
+               priv->plat->mdio_bus_data->xpcs_an_inband = false;
+       } else {
+               priv->plat->max_speed = 1000;
+               priv->plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+               priv->plat->mdio_bus_data->xpcs_an_inband = true;
+       }
+}
+
 /* Program PTP Clock Frequency for different variant of
  * Intel mGBE that has slightly different GPO mapping
  */
 {
        plat->bus_id = 1;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
-
+       plat->speed_mode_2500 = intel_speed_mode_2500;
        plat->serdes_powerup = intel_serdes_powerup;
        plat->serdes_powerdown = intel_serdes_powerdown;
 
                                 struct plat_stmmacenet_data *plat)
 {
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->speed_mode_2500 = intel_speed_mode_2500;
        plat->serdes_powerup = intel_serdes_powerup;
        plat->serdes_powerdown = intel_serdes_powerdown;
        return ehl_pse0_common_data(pdev, plat);
                                 struct plat_stmmacenet_data *plat)
 {
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->speed_mode_2500 = intel_speed_mode_2500;
        plat->serdes_powerup = intel_serdes_powerup;
        plat->serdes_powerdown = intel_serdes_powerdown;
        return ehl_pse1_common_data(pdev, plat);
 {
        plat->bus_id = 1;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->speed_mode_2500 = intel_speed_mode_2500;
        plat->serdes_powerup = intel_serdes_powerup;
        plat->serdes_powerdown = intel_serdes_powerdown;
        return tgl_common_data(pdev, plat);
 {
        plat->bus_id = 2;
        plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+       plat->speed_mode_2500 = intel_speed_mode_2500;
        plat->serdes_powerup = intel_serdes_powerup;
        plat->serdes_powerdown = intel_serdes_powerdown;
        return tgl_common_data(pdev, plat);
 
 #define POLL_DELAY_US 8
 
 /* SERDES Register */
+#define SERDES_GCR     0x0     /* Global Conguration */
 #define SERDES_GSR0    0x5     /* Global Status Reg0 */
 #define SERDES_GCR0    0xb     /* Global Configuration Reg0 */
 
 #define SERDES_PHY_RX_CLK      BIT(1)          /* PSE SGMII PHY rx clk */
 #define SERDES_RST             BIT(2)          /* Serdes Reset */
 #define SERDES_PWR_ST_MASK     GENMASK(6, 4)   /* Serdes Power state*/
+#define SERDES_RATE_MASK       GENMASK(9, 8)
+#define SERDES_PCLK_MASK       GENMASK(14, 12) /* PCLK rate to PHY */
+#define SERDES_LINK_MODE_MASK  GENMASK(2, 1)
+#define SERDES_LINK_MODE_SHIFT 1
 #define SERDES_PWR_ST_SHIFT    4
 #define SERDES_PWR_ST_P0       0x0
 #define SERDES_PWR_ST_P3       0x3
+#define SERDES_LINK_MODE_2G5   0x3
+#define SERSED_LINK_MODE_1G    0x2
+#define SERDES_PCLK_37p5MHZ    0x0
+#define SERDES_PCLK_70MHZ      0x1
+#define SERDES_RATE_PCIE_GEN1  0x0
+#define SERDES_RATE_PCIE_GEN2  0x1
+#define SERDES_RATE_PCIE_SHIFT 8
+#define SERDES_PCLK_SHIFT      12
 
 #endif /* __DWMAC_INTEL_H__ */
 
        if ((max_speed > 0) && (max_speed < 1000)) {
                phylink_set(mask, 1000baseT_Full);
                phylink_set(mask, 1000baseX_Full);
+       } else if (priv->plat->has_gmac4) {
+               if (!max_speed || max_speed >= 2500)
+                       phylink_set(mac_supported, 2500baseT_Full);
+                       phylink_set(mac_supported, 2500baseX_Full);
        } else if (priv->plat->has_xgmac) {
                if (!max_speed || (max_speed >= 2500)) {
                        phylink_set(mac_supported, 2500baseT_Full);
                }
        }
 
+       if (priv->plat->speed_mode_2500)
+               priv->plat->speed_mode_2500(ndev, priv->plat->bsp_priv);
+
        if (priv->plat->mdio_bus_data) {
                if (priv->plat->mdio_bus_data->has_xpcs) {
                        ret = stmmac_xpcs_setup(priv->mii);