#include "stmmac_platform.h"
 
+#define STARFIVE_DWMAC_PHY_INFT_RGMII  0x1
+#define STARFIVE_DWMAC_PHY_INFT_RMII   0x4
+#define STARFIVE_DWMAC_PHY_INFT_FIELD  0x7U
+
 struct starfive_dwmac {
        struct device *dev;
        struct clk *clk_tx;
                dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate);
 }
 
+static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat)
+{
+       struct starfive_dwmac *dwmac = plat_dat->bsp_priv;
+       struct regmap *regmap;
+       unsigned int args[2];
+       unsigned int mode;
+       int err;
+
+       switch (plat_dat->interface) {
+       case PHY_INTERFACE_MODE_RMII:
+               mode = STARFIVE_DWMAC_PHY_INFT_RMII;
+               break;
+
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+               mode = STARFIVE_DWMAC_PHY_INFT_RGMII;
+               break;
+
+       default:
+               dev_err(dwmac->dev, "unsupported interface %d\n",
+                       plat_dat->interface);
+               return -EINVAL;
+       }
+
+       regmap = syscon_regmap_lookup_by_phandle_args(dwmac->dev->of_node,
+                                                     "starfive,syscon",
+                                                     2, args);
+       if (IS_ERR(regmap))
+               return dev_err_probe(dwmac->dev, PTR_ERR(regmap), "getting the regmap failed\n");
+
+       /* args[0]:offset  args[1]: shift */
+       err = regmap_update_bits(regmap, args[0],
+                                STARFIVE_DWMAC_PHY_INFT_FIELD << args[1],
+                                mode << args[1]);
+       if (err)
+               return dev_err_probe(dwmac->dev, err, "error setting phy mode\n");
+
+       return 0;
+}
+
 static int starfive_dwmac_probe(struct platform_device *pdev)
 {
        struct plat_stmmacenet_data *plat_dat;
        plat_dat->bsp_priv = dwmac;
        plat_dat->dma_cfg->dche = true;
 
+       err = starfive_dwmac_set_mode(plat_dat);
+       if (err)
+               return err;
+
        err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
        if (err) {
                stmmac_remove_config_dt(pdev, plat_dat);