{
        u32 val;
 
-       if (mtk_is_netsys_v2_or_greater(eth)) {
+       if (mtk_is_netsys_v2_or_greater(eth))
                regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0);
+
+       if (mtk_is_netsys_v3_or_greater(eth)) {
+               val = RSTCTRL_PPE0_V3;
+
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
+                       val |= RSTCTRL_PPE1_V3;
+
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2))
+                       val |= RSTCTRL_PPE2;
+
+               val |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2;
+       } else if (mtk_is_netsys_v2_or_greater(eth)) {
                val = RSTCTRL_PPE0_V2;
+
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
+                       val |= RSTCTRL_PPE1;
        } else {
                val = RSTCTRL_PPE0;
        }
 
-       if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
-               val |= RSTCTRL_PPE1;
-
        ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val);
 
-       if (mtk_is_netsys_v2_or_greater(eth))
+       if (mtk_is_netsys_v3_or_greater(eth))
+               regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN,
+                            0x6f8ff);
+       else if (mtk_is_netsys_v2_or_greater(eth))
                regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN,
                             0x3ffffff);
 }
                return;
        }
 
-       if (mtk_is_netsys_v2_or_greater(eth))
+       if (mtk_is_netsys_v3_or_greater(eth)) {
+               rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V3;
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
+                       rst_mask |= RSTCTRL_PPE1_V3;
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2))
+                       rst_mask |= RSTCTRL_PPE2;
+
+               rst_mask |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2;
+       } else if (mtk_is_netsys_v2_or_greater(eth)) {
                rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2;
-       else
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
+                       rst_mask |= RSTCTRL_PPE1;
+       } else {
                rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0;
-
-       if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
-               rst_mask |= RSTCTRL_PPE1;
+       }
 
        regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask);
 
        u32 val;
        int i;
 
-       /* disabe FE P3 and P4 */
-       val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3;
-       if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
-               val |= MTK_FE_LINK_DOWN_P4;
-       mtk_w32(eth, val, MTK_FE_GLO_CFG);
+       /* set FE PPE ports link down */
+       for (i = MTK_GMAC1_ID;
+            i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID);
+            i += 2) {
+               val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) | MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT);
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
+                       val |= MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT);
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2))
+                       val |= MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT);
+               mtk_w32(eth, val, MTK_FE_GLO_CFG(i));
+       }
 
        /* adjust PPE configurations to prepare for reset */
        for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
                }
        }
 
-       /* enabe FE P3 and P4 */
-       val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3;
-       if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
-               val &= ~MTK_FE_LINK_DOWN_P4;
-       mtk_w32(eth, val, MTK_FE_GLO_CFG);
+       /* set FE PPE ports link up */
+       for (i = MTK_GMAC1_ID;
+            i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID);
+            i += 2) {
+               val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) & ~MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT);
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
+                       val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT);
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2))
+                       val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT);
+
+               mtk_w32(eth, val, MTK_FE_GLO_CFG(i));
+       }
 
        clear_bit(MTK_RESETTING, ð->state);
 
 
 #define        MTK_HW_LRO_SDL_REMAIN_ROOM      1522
 
 /* Frame Engine Global Configuration */
-#define MTK_FE_GLO_CFG         0x00
-#define MTK_FE_LINK_DOWN_P3    BIT(11)
-#define MTK_FE_LINK_DOWN_P4    BIT(12)
+#define MTK_FE_GLO_CFG(x)      (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00)
+#define MTK_FE_LINK_DOWN_P(x)  BIT(((x) + 8) % 16)
 
 /* Frame Engine Global Reset Register */
 #define MTK_RST_GL             0x04
 /* ethernet reset control register */
 #define ETHSYS_RSTCTRL                 0x34
 #define RSTCTRL_FE                     BIT(6)
+#define RSTCTRL_WDMA0                  BIT(24)
+#define RSTCTRL_WDMA1                  BIT(25)
+#define RSTCTRL_WDMA2                  BIT(26)
 #define RSTCTRL_PPE0                   BIT(31)
 #define RSTCTRL_PPE0_V2                        BIT(30)
 #define RSTCTRL_PPE1                   BIT(31)
+#define RSTCTRL_PPE0_V3                        BIT(29)
+#define RSTCTRL_PPE1_V3                        BIT(30)
+#define RSTCTRL_PPE2                   BIT(31)
 #define RSTCTRL_ETH                    BIT(23)
 
 /* ethernet reset check idle register */
        MTK_QDMA_BIT,
        MTK_SOC_MT7628_BIT,
        MTK_RSTCTRL_PPE1_BIT,
+       MTK_RSTCTRL_PPE2_BIT,
        MTK_U3_COPHY_V2_BIT,
 
        /* MUX BITS*/
 #define MTK_QDMA               BIT_ULL(MTK_QDMA_BIT)
 #define MTK_SOC_MT7628         BIT_ULL(MTK_SOC_MT7628_BIT)
 #define MTK_RSTCTRL_PPE1       BIT_ULL(MTK_RSTCTRL_PPE1_BIT)
+#define MTK_RSTCTRL_PPE2       BIT_ULL(MTK_RSTCTRL_PPE2_BIT)
 #define MTK_U3_COPHY_V2                BIT_ULL(MTK_U3_COPHY_V2_BIT)
 
 #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW          \
                      MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
                      MTK_RSTCTRL_PPE1)
 
-#define MT7988_CAPS  (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1)
+#define MT7988_CAPS  (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \
+                     MTK_RSTCTRL_PPE2)
 
 struct mtk_tx_dma_desc_info {
        dma_addr_t      addr;