From 7304ce8edabcbc34433307b02de429c2d118abaa Mon Sep 17 00:00:00 2001
From: mtk27745 <rex.lu@mediatek.com>
Date: Tue, 23 May 2023 11:19:30 +0800
Subject: [PATCH] mtk-wed-add-wed3-ser-support

---
 drivers/net/ethernet/mediatek/mtk_wed.c      | 236 +++++++++++++++++--
 drivers/net/ethernet/mediatek/mtk_wed_regs.h |  73 +++++-
 include/linux/soc/mediatek/mtk_wed.h         |   6 +-
 3 files changed, 291 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
index 6ed1c83..990888d 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -99,11 +99,65 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
 	u32 status;
 	u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
 	int busy, i;
+	u32 value;
 
 	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
 	busy = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-			       !(status & mask), 0, 10000);
+				  !(status & mask), 0, 10000);
 
+	if (dev->hw->version == 3) {
+		wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
+		wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_PREF_TX_CFG);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_PREF_RX_CFG);
+
+		wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
+		wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_WRBK_TX_CFG);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_WRBK_RX_CFG);
+
+		/* Prefetch FIFO */
+		wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
+		wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
+
+		/* Core FIFO */
+		value = (MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
+
+		wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, value);
+		wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, value);
+
+		/* Writeback FIFO */
+		wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
+		wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
+
+		wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
+		wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
+
+		/* Prefetch ring status */
+		wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
+		wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
+		/* Writeback ring status */
+		wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
+		wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
+	}
 	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
 	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
 
@@ -121,13 +175,62 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
 {
 	u32 status;
 	u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
-	int i;
+	int busy, i;
+	u32 value;
 
 	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
 	if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
 			       !(status & mask), 0, 10000))
 		WARN_ON_ONCE(1);
 
+	if (dev->hw->version == 3) {
+		wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
+		wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_PREF_TX_CFG);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_PREF_RX_CFG);
+
+		wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
+		wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_WRBK_TX_CFG);
+		busy = read_poll_timeout(wdma_r32, status,
+					 !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), 0, 10000,
+					 false, dev, MTK_WDMA_WRBK_RX_CFG);
+
+		/* Prefetch FIFO */
+		wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
+		wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
+		/* Core FIFO */
+		value = (MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
+			 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
+
+		wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, value);
+		wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, value);
+		/* Writeback FIFO */
+		wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
+		wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
+
+		wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
+		wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
+
+		/* Prefetch ring status */
+		wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
+		wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
+		/* Writeback ring status */
+		wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
+		wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
+	}
 	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
 	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
@@ -903,7 +1006,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
 				MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
 
 			wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-			//wdma_w32(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
+			wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
 			if (mtk_wed_get_rx_capa(dev)) {
 				wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
 					MTK_WED_WPDMA_RX_D_PREF_EN |
@@ -1477,13 +1580,30 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
 	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
 			     &state, sizeof(state), true);
 
+	if (dev->wlan.hwrro) {
+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
+		mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS,
+				  MTK_WED_RX_IND_CMD_BUSY);
+		mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG);
+	}
 	wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
 	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
 				 MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
+	if (dev->hw->version == 3)
+		busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
+					 MTK_WED_WPDMA_RX_D_PREF_BUSY);
 	if (busy) {
 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
 	} else {
+		if (dev->hw->version == 3) {
+			/*1.a. Disable Prefetch HW*/
+			wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, MTK_WED_WPDMA_RX_D_PREF_EN);
+			mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
+					  MTK_WED_WPDMA_RX_D_PREF_BUSY);
+			wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
+				MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL);
+		}
 		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
 			MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
 			MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
@@ -1511,6 +1631,24 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
 		wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
 	}
 
+	if (dev->wlan.hwrro) {
+		/* Disable RRO MSDU Page Drv */
+		wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
+
+		/* Disable RRO Data Drv */
+		wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
+
+		/* RRO MSDU Page Drv Reset */
+		wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
+		mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
+				  MTK_WED_RRO_MSDU_PG_DRV_CLR);
+
+		/* RRO Data Drv Reset */
+		wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_CLR);
+		mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2),
+				  MTK_WED_RRO_RX_D_DRV_CLR);
+	}
+
 	/* reset route qm */
 	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
 	busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
@@ -1518,8 +1656,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
 	if (busy) {
 		mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
 	} else {
-		wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-			MTK_WED_RTQM_Q_RST);
+		if (dev->hw->version == 3) {
+			wed_set(dev, MTK_WED_RTQM_RST, BIT(0));
+			wed_clr(dev, MTK_WED_RTQM_RST, BIT(0));
+			mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
+		} else
+			wed_set(dev, MTK_WED_RTQM_GLO_CFG,
+				MTK_WED_RTQM_Q_RST);
 	}
 
 	/* reset tx wdma */
@@ -1527,8 +1670,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
 
 	/* reset tx wdma drv */
 	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
-	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-			  MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
+	if (dev->hw->version == 3)
+		mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS,
+				  MTK_WED_WPDMA_STATUS_TX_DRV);
+	else
+		mtk_wed_poll_busy(dev, MTK_WED_CTRL,
+				  MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
+
 	mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
 
 	/* reset wed rx dma */
@@ -1546,9 +1694,17 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
 	/* reset rx bm */
 	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
 	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-			   MTK_WED_CTRL_WED_RX_BM_BUSY);
+			  MTK_WED_CTRL_WED_RX_BM_BUSY);
 	mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
 
+	if (dev->wlan.hwrro) {
+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
+		mtk_wed_poll_busy(dev, MTK_WED_CTRL,
+				  MTK_WED_CTRL_WED_RX_PG_BM_BUSY);
+		wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
+		wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
+	}
+
 	/* wo change to enable state */
 	state = WO_STATE_ENABLE;
 	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
@@ -1565,6 +1721,9 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
 	}
 
 	mtk_wed_free_rx_buffer(dev);
+
+	if (dev->wlan.hwrro)
+		mtk_wed_rx_page_free_buffer(dev);
 }
 
 
@@ -1598,18 +1757,40 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
 
 	/* 2. Reset WDMA Rx DMA/Driver_Engine */
 	busy = !!mtk_wdma_rx_reset(dev);
+	if (dev->hw->version == 3) {
+		val = wed_r32(dev, MTK_WED_WDMA_GLO_CFG);
+		val |= MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
+		val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN;
+		wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val);
+	} else
+		wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
 
-	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
 	busy = !!(busy ||
 		  mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
-					 MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
+				    MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
+	if (dev->hw->version == 3)
+		busy = !!(busy ||
+			  mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
+					    MTK_WED_WDMA_RX_PREF_BUSY));
 
 	if (busy) {
 		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
 		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
 	} else {
+		if (dev->hw->version == 3) {
+			/*1.a. Disable Prefetch HW*/
+			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
+			mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
+					  MTK_WED_WDMA_RX_PREF_BUSY);
+			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_DDONE2_EN);
+
+			/*2. Reset dma index*/
+			wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
+				MTK_WED_WDMA_RESET_IDX_RX_ALL);
+		}
 		wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
-			MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV);
+			MTK_WED_WDMA_RESET_IDX_RX |
+			MTK_WED_WDMA_RESET_IDX_DRV);
 		wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0);
 
 		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
@@ -1624,9 +1805,15 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
 
 	for (i = 0; i < 100; i++) {
-		val = wed_r32(dev, MTK_WED_TX_BM_INTF);
-		if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
-			break;
+		if (dev->ver > MTK_WED_V1) {
+			val = wed_r32(dev, MTK_WED_TX_TKID_INTF);
+			if (FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP, val) == 0x40)
+				break;
+		} else {
+			val = wed_r32(dev, MTK_WED_TX_BM_INTF);
+			if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
+				break;
+		}
 	}
 	mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
 
@@ -1635,18 +1822,20 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
 
 	/* 4. Reset WED WPDMA Tx Driver Engine */
 	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-				      MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
+				 MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
 	wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
 		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
 		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
 
 	busy = !!(busy ||
 		  mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-					 MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
+				    MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
 	if (busy) {
 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV);
+		if (dev->hw->version == 3)
+			wed_w32(dev, MTK_WED_RX1_CTRL2, 0);
 	} else {
 		wed_w32(dev, MTK_WED_WPDMA_RESET_IDX,
 			MTK_WED_WPDMA_RESET_IDX_TX |
@@ -1659,7 +1848,13 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
 		}
 	}
 
-	if (dev->ver > MTK_WED_V1) {
+	if (dev->hw->version == 3) {
+		/*reset wed pao*/
+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
+		mtk_wed_reset(dev, MTK_WED_RESET_TX_PAO);
+	}
+
+	if (mtk_wed_get_rx_capa(dev)) {
 		dev->init_done = false;
 		mtk_wed_rx_reset(dev);
 	}
@@ -1874,7 +2069,7 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
 }
 
 static void
-mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
+mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask, bool reset)
 {
 	int idx, ret;
 
@@ -1884,6 +2079,11 @@ mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
 	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hwrro)
 		return;
 
+	if (reset) {
+		wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
+		return;
+	}
+	
 	wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
 	wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
 
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
index 25be547..4379dc4 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
@@ -42,6 +42,8 @@ struct mtk_wdma_desc {
 #define MTK_WED_RESET					0x008
 #define MTK_WED_RESET_TX_BM				BIT(0)
 #define MTK_WED_RESET_RX_BM				BIT(1)
+#define MTK_WED_RESET_RX_PG_BM				BIT(2)
+#define MTK_WED_RESET_RRO_RX_TO_PG			BIT(3)
 #define MTK_WED_RESET_TX_FREE_AGENT			BIT(4)
 #define MTK_WED_RESET_WPDMA_TX_DRV			BIT(8)
 #define MTK_WED_RESET_WPDMA_RX_DRV			BIT(9)
@@ -64,7 +66,7 @@ struct mtk_wdma_desc {
 #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY		BIT(3)
 #define MTK_WED_CTRL_WED_RX_IND_CMD_EN			BIT(5)
 #define MTK_WED_CTRL_WED_RX_PG_BM_EN			BIT(6)
-#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU			BIT(7)
+#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY			BIT(7)
 #define MTK_WED_CTRL_WED_TX_BM_EN			BIT(8)
 #define MTK_WED_CTRL_WED_TX_BM_BUSY			BIT(9)
 #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN		BIT(10)
@@ -123,6 +125,10 @@ struct mtk_wdma_desc {
 #define MTK_WED_STATUS					0x060
 #define MTK_WED_STATUS_TX				GENMASK(15, 8)
 
+#define MTK_WED_WPDMA_STATUS				0x068
+#define MTK_WED_WPDMA_STATUS_TX_DRV			GENMASK(15, 8)
+
+
 #define MTK_WED_TX_BM_CTRL				0x080
 #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM			GENMASK(6, 0)
 #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM			GENMASK(22, 16)
@@ -167,6 +173,9 @@ struct mtk_wdma_desc {
 
 #define MTK_WED_TX_TKID_CTRL_PAUSE			BIT(28)
 
+#define MTK_WED_TX_TKID_INTF				0x0dc
+#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP		GENMASK(25, 16)
+
 #define MTK_WED_TX_TKID_DYN_THR				0x0e0
 #define MTK_WED_TX_TKID_DYN_THR_LO			GENMASK(6, 0)
 #define MTK_WED_TX_TKID_DYN_THR_HI			GENMASK(22, 16)
@@ -203,10 +212,11 @@ struct mtk_wdma_desc {
 #define MTK_WED_GLO_CFG_RX_2B_OFFSET			BIT(31)
 
 #define MTK_WED_RESET_IDX				0x20c
-#define MTK_WED_RESET_IDX_TX				GENMASK(3, 0)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_WED_RESET_IDX_TX				GENMASK(1, 0)
 #define MTK_WED_RESET_IDX_RX				GENMASK(7, 6)
 #else
+#define MTK_WED_RESET_IDX_TX				GENMASK(3, 0)
 #define MTK_WED_RESET_IDX_RX				GENMASK(17, 16)
 #endif
 #define MTK_WED_RESET_WPDMA_IDX_RX			GENMASK(31, 30)
@@ -221,6 +231,7 @@ struct mtk_wdma_desc {
 #define MTK_WED_RING_RX_DATA(_n)			(0x420 + (_n) * 0x10)
 
 #define MTK_WED_SCR0					0x3c0
+#define MTK_WED_RX1_CTRL2				0x418
 #define MTK_WED_WPDMA_INT_TRIGGER			0x504
 #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE		BIT(1)
 #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE		GENMASK(5, 4)
@@ -336,6 +347,7 @@ struct mtk_wdma_desc {
 
 #define MTK_WED_WPDMA_RX_D_RST_IDX			0x760
 #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX			GENMASK(17, 16)
+#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL		BIT(20)
 #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX			GENMASK(25, 24)
 
 #define MTK_WED_WPDMA_RX_GLO_CFG			0x76c
@@ -352,6 +364,7 @@ struct mtk_wdma_desc {
 
 #define MTK_WED_WPDMA_RX_D_PREF_CFG			0x7b4
 #define MTK_WED_WPDMA_RX_D_PREF_EN			BIT(0)
+#define MTK_WED_WPDMA_RX_D_PREF_BUSY		BIT(1)
 #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE		GENMASK(12, 8)
 #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES		GENMASK(21, 16)
 
@@ -373,11 +386,13 @@ struct mtk_wdma_desc {
 
 #define MTK_WED_WDMA_RX_PREF_CFG			0x950
 #define MTK_WED_WDMA_RX_PREF_EN				BIT(0)
+#define MTK_WED_WDMA_RX_PREF_BUSY			BIT(1)
 #define MTK_WED_WDMA_RX_PREF_BURST_SIZE			GENMASK(12, 8)
 #define MTK_WED_WDMA_RX_PREF_LOW_THRES			GENMASK(21, 16)
 #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR		BIT(24)
 #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR		BIT(25)
 #define MTK_WED_WDMA_RX_PREF_DDONE2_EN			BIT(26)
+#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY		BIT(27)
 
 #define MTK_WED_WDMA_RX_PREF_FIFO_CFG			0x95C
 #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR		BIT(0)
@@ -406,6 +421,7 @@ struct mtk_wdma_desc {
 
 #define MTK_WED_WDMA_RESET_IDX				0xa08
 #define MTK_WED_WDMA_RESET_IDX_RX			GENMASK(17, 16)
+#define MTK_WED_WDMA_RESET_IDX_RX_ALL			BIT(20)
 #define MTK_WED_WDMA_RESET_IDX_DRV			GENMASK(25, 24)
 
 #define MTK_WED_WDMA_INT_CLR				0xa24
@@ -474,21 +490,66 @@ struct mtk_wdma_desc {
 #define MTK_WDMA_INT_MASK_RX_DELAY			BIT(30)
 #define MTK_WDMA_INT_MASK_RX_COHERENT			BIT(31)
 
+#define MTK_WDMA_XDMA_TX_FIFO_CFG			0x238
+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR		BIT(0)
+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR		BIT(4)
+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR		BIT(8)
+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR		BIT(12)
+
+#define MTK_WDMA_XDMA_RX_FIFO_CFG			0x23c
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR		BIT(0)
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR		BIT(4)
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR		BIT(8)
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR		BIT(12)
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR		BIT(15)
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR		BIT(18)
+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR		BIT(21)
+
+
+
 #define MTK_WDMA_INT_GRP1				0x250
 #define MTK_WDMA_INT_GRP2				0x254
 
 #define MTK_WDMA_PREF_TX_CFG				0x2d0
 #define MTK_WDMA_PREF_TX_CFG_PREF_EN			BIT(0)
+#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY			BIT(1)
 
 #define MTK_WDMA_PREF_RX_CFG				0x2dc
 #define MTK_WDMA_PREF_RX_CFG_PREF_EN			BIT(0)
+#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY			BIT(1)
+
+#define MTK_WDMA_PREF_RX_FIFO_CFG			0x2e0
+#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR		BIT(0)
+#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR		BIT(16)
+
+#define MTK_WDMA_PREF_TX_FIFO_CFG			0x2d4
+#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR		BIT(0)
+#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR		BIT(16)
+
+#define MTK_WDMA_PREF_SIDX_CFG				0x2e4
+#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR		GENMASK(3, 0)
+#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR		GENMASK(5, 4)
 
 #define MTK_WDMA_WRBK_TX_CFG				0x300
+#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY			BIT(0)
 #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN			BIT(30)
 
+#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n)			(0x304 + (_n) * 0x4)
+#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR		BIT(0)
+
+
 #define MTK_WDMA_WRBK_RX_CFG				0x344
+#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY			BIT(0)
 #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN			BIT(30)
 
+#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n)			(0x348 + (_n) * 0x4)
+#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR		BIT(0)
+
+
+#define MTK_WDMA_WRBK_SIDX_CFG				0x388
+#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR		GENMASK(3, 0)
+#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR		GENMASK(5, 4)
+
 #define MTK_PCIE_MIRROR_MAP(n)				((n) ? 0x4 : 0x0)
 #define MTK_PCIE_MIRROR_MAP_EN				BIT(0)
 #define MTK_PCIE_MIRROR_MAP_WED_ID			BIT(1)
@@ -502,6 +563,9 @@ struct mtk_wdma_desc {
 #define MTK_WED_RTQM_Q_DBG_BYPASS			BIT(5)
 #define MTK_WED_RTQM_TXDMAD_FPORT			GENMASK(23, 20)
 
+#define MTK_WED_RTQM_RST				0xb04
+
+
 #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT		0xb1c
 #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n)		(0xb20 + (_n) * 0x4)
 #define	MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT			0xb28
@@ -691,6 +755,9 @@ struct mtk_wdma_desc {
 #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR		BIT(17)
 #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG	GENMASK(22, 18)
 
+#define MTK_WED_RRO_RX_HW_STS				0xf00
+#define MTK_WED_RX_IND_CMD_BUSY			GENMASK(31, 0)
+
 #define MTK_WED_RX_IND_CMD_CNT0				0xf20
 #define MTK_WED_RX_IND_CMD_DBG_CNT_EN			BIT(31)
 
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
index 2b389e8..bb02ba5 100644
--- a/include/linux/soc/mediatek/mtk_wed.h
+++ b/include/linux/soc/mediatek/mtk_wed.h
@@ -240,7 +240,7 @@ struct mtk_wed_ops {
 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
 	void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
 			  u32 reason, u32 hash);
-	void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask);
+	void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask, bool reset);
 };
 
 extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
@@ -317,8 +317,8 @@ mtk_wed_device_support_pao(struct mtk_wed_device *dev)
 	(_dev)->ops->reset_dma(_dev)
 #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
 	(_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
-#define mtk_wed_device_start_hwrro(_dev, _mask) \
-	(_dev)->ops->start_hwrro(_dev, _mask)
+#define mtk_wed_device_start_hwrro(_dev, _mask, _reset) \
+	(_dev)->ops->start_hwrro(_dev, _mask, _reset)
 
 #else
 static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
-- 
2.18.0

