break;
        };
 
-       if (mac->id == 0 && !mac->trgmii)
+       if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
+           !mac->id && !mac->trgmii)
                mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
 
        if (dev->phydev->link)
        mdelay(10);
 }
 
+static void mtk_clk_disable(struct mtk_eth *eth)
+{
+       int clk;
+
+       for (clk = MTK_CLK_MAX - 1; clk >= 0; clk--)
+               clk_disable_unprepare(eth->clks[clk]);
+}
+
+static int mtk_clk_enable(struct mtk_eth *eth)
+{
+       int clk, ret;
+
+       for (clk = 0; clk < MTK_CLK_MAX ; clk++) {
+               ret = clk_prepare_enable(eth->clks[clk]);
+               if (ret)
+                       goto err_disable_clks;
+       }
+
+       return 0;
+
+err_disable_clks:
+       while (--clk >= 0)
+               clk_disable_unprepare(eth->clks[clk]);
+
+       return ret;
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
-       int i, val;
+       int i, val, ret;
 
        if (test_and_set_bit(MTK_HW_INIT, ð->state))
                return 0;
        pm_runtime_enable(eth->dev);
        pm_runtime_get_sync(eth->dev);
 
-       clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
-       clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
-       clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
-       clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
+       ret = mtk_clk_enable(eth);
+       if (ret)
+               goto err_disable_pm;
+
        ethsys_reset(eth, RSTCTRL_FE);
        ethsys_reset(eth, RSTCTRL_PPE);
 
        }
 
        return 0;
+
+err_disable_pm:
+       pm_runtime_put_sync(eth->dev);
+       pm_runtime_disable(eth->dev);
+
+       return ret;
 }
 
 static int mtk_hw_deinit(struct mtk_eth *eth)
        if (!test_and_clear_bit(MTK_HW_INIT, ð->state))
                return 0;
 
-       clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
-       clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
-       clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
-       clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+       mtk_clk_disable(eth);
 
        pm_runtime_put_sync(eth->dev);
        pm_runtime_disable(eth->dev);
 {
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct device_node *mac_np;
+       const struct of_device_id *match;
        struct mtk_eth *eth;
        int err;
        int i;
        if (!eth)
                return -ENOMEM;
 
+       match = of_match_device(of_mtk_match, &pdev->dev);
+       eth->soc = (struct mtk_soc_data *)match->data;
+
        eth->dev = &pdev->dev;
        eth->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(eth->base))
                if (IS_ERR(eth->clks[i])) {
                        if (PTR_ERR(eth->clks[i]) == -EPROBE_DEFER)
                                return -EPROBE_DEFER;
-                       return -ENODEV;
+                       if (eth->soc->required_clks & BIT(i)) {
+                               dev_err(&pdev->dev, "clock %s not found\n",
+                                       mtk_clks_source_name[i]);
+                               return -EINVAL;
+                       }
+                       eth->clks[i] = NULL;
                }
        }
 
        return 0;
 }
 
+static const struct mtk_soc_data mt2701_data = {
+       .caps = MTK_GMAC1_TRGMII,
+       .required_clks = MT7623_CLKS_BITMAP
+};
+
+static const struct mtk_soc_data mt7623_data = {
+       .caps = MTK_GMAC1_TRGMII,
+       .required_clks = MT7623_CLKS_BITMAP
+};
+
 const struct of_device_id of_mtk_match[] = {
-       { .compatible = "mediatek,mt2701-eth" },
+       { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+       { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
        {},
 };
 MODULE_DEVICE_TABLE(of, of_mtk_match);
 
        MTK_CLK_MAX
 };
 
+#define MT7623_CLKS_BITMAP     (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) |  \
+                                BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \
+                                BIT(MTK_CLK_TRGPLL))
 enum mtk_dev_state {
        MTK_HW_INIT,
        MTK_RESETTING
        u32 crx_idx_reg;
 };
 
+#define MTK_TRGMII                     BIT(0)
+#define MTK_GMAC1_TRGMII               (BIT(1) | MTK_TRGMII)
+#define MTK_HAS_CAPS(caps, _x)         (((caps) & (_x)) == (_x))
+
+/* struct mtk_soc_data -       This is the structure holding all differences
+ *                             among various plaforms
+ * @caps                       Flags shown the extra capability for the SoC
+ * @required_clks              Flags shown the bitmap for required clocks on
+ *                             the target SoC
+ */
+struct mtk_soc_data {
+       u32             caps;
+       u32             required_clks;
+};
+
 /* currently no SoC has more than 2 macs */
 #define MTK_MAX_DEVS                   2
 
  * @clks:              clock array for all clocks required
  * @mii_bus:           If there is a bus we need to create an instance for it
  * @pending_work:      The workqueue used to reset the dma ring
- * @state               Initialization and runtime state of the device.
+ * @state              Initialization and runtime state of the device
+ * @soc:               Holding specific data among vaious SoCs
  */
 
 struct mtk_eth {
        struct mii_bus                  *mii_bus;
        struct work_struct              pending_work;
        unsigned long                   state;
+
+       const struct mtk_soc_data       *soc;
 };
 
 /* struct mtk_mac -    the structure that holds the info about the MACs of the