blob: 7f159a0d581290506eb2dc4b8f29a7a76adcb068 [file] [log] [blame]
developer8cb3ac72022-07-04 10:55:14 +08001From bc8244ada5c668374813f7f9b73d990bf2695aaf Mon Sep 17 00:00:00 2001
2From: Sujuan Chen <sujuan.chen@mediatek.com>
3Date: Wed, 15 Jun 2022 14:38:54 +0800
4Subject: [PATCH 8/8] 9997-add-wed-rx-support-for-mt7896
5
6Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
7---
8 arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 42 +-
9 arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 42 +-
10 drivers/net/ethernet/mediatek/Makefile | 2 +-
developerc1b2cd12022-07-28 18:35:24 +080011 drivers/net/ethernet/mediatek/mtk_wed.c | 627 ++++++++++++++++--
developera3f86ed2022-07-08 14:15:13 +080012 drivers/net/ethernet/mediatek/mtk_wed.h | 51 ++
13 drivers/net/ethernet/mediatek/mtk_wed_ccif.c | 133 ++++
developer8cb3ac72022-07-04 10:55:14 +080014 drivers/net/ethernet/mediatek/mtk_wed_ccif.h | 45 ++
15 .../net/ethernet/mediatek/mtk_wed_debugfs.c | 90 +++
developera3f86ed2022-07-08 14:15:13 +080016 drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 561 ++++++++++++++++
developer8cb3ac72022-07-04 10:55:14 +080017 drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 125 ++++
developerc1b2cd12022-07-28 18:35:24 +080018 drivers/net/ethernet/mediatek/mtk_wed_regs.h | 145 +++-
19 drivers/net/ethernet/mediatek/mtk_wed_wo.c | 588 ++++++++++++++++
developera3f86ed2022-07-08 14:15:13 +080020 drivers/net/ethernet/mediatek/mtk_wed_wo.h | 336 ++++++++++
developerc1b2cd12022-07-28 18:35:24 +080021 include/linux/soc/mediatek/mtk_wed.h | 64 +-
developer8cb3ac72022-07-04 10:55:14 +080022 14 files changed, 2643 insertions(+), 69 deletions(-)
developer8cb3ac72022-07-04 10:55:14 +080023 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ccif.c
24 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ccif.h
25 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c
26 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.h
27 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c
28 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h
29
30diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
31index 644255b35..ddcc0b809 100644
32--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
33+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
34@@ -65,6 +65,12 @@
35 interrupt-parent = <&gic>;
36 interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
37 mediatek,wed_pcie = <&wed_pcie>;
38+ mediatek,ap2woccif = <&ap2woccif0>;
39+ mediatek,wocpu_ilm = <&wocpu0_ilm>;
40+ mediatek,wocpu_dlm = <&wocpu0_dlm>;
41+ mediatek,wocpu_boot = <&cpu_boot>;
42+ mediatek,wocpu_emi = <&wocpu0_emi>;
43+ mediatek,wocpu_data = <&wocpu_data>;
44 };
45
46 wed1: wed@15011000 {
47@@ -74,15 +80,26 @@
48 interrupt-parent = <&gic>;
49 interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
50 mediatek,wed_pcie = <&wed_pcie>;
51+ mediatek,ap2woccif = <&ap2woccif1>;
52+ mediatek,wocpu_ilm = <&wocpu1_ilm>;
53+ mediatek,wocpu_dlm = <&wocpu1_dlm>;
54+ mediatek,wocpu_boot = <&cpu_boot>;
55+ mediatek,wocpu_emi = <&wocpu1_emi>;
56+ mediatek,wocpu_data = <&wocpu_data>;
57 };
58
59- ap2woccif: ap2woccif@151A5000 {
60- compatible = "mediatek,ap2woccif";
61- reg = <0 0x151A5000 0 0x1000>,
62- <0 0x151AD000 0 0x1000>;
63+ ap2woccif0: ap2woccif@151A5000 {
64+ compatible = "mediatek,ap2woccif", "syscon";
65+ reg = <0 0x151A5000 0 0x1000>;
66 interrupt-parent = <&gic>;
67- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
68- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
69+ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
70+ };
71+
72+ ap2woccif1: ap2woccif@0x151AD000 {
73+ compatible = "mediatek,ap2woccif", "syscon";
74+ reg = <0 0x151AD000 0 0x1000>;
75+ interrupt-parent = <&gic>;
76+ interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
77 };
78
79 wocpu0_ilm: wocpu0_ilm@151E0000 {
80@@ -95,10 +112,17 @@
81 reg = <0 0x151F0000 0 0x8000>;
82 };
83
84- wocpu_dlm: wocpu_dlm@151E8000 {
85+ wocpu0_dlm: wocpu_dlm@151E8000 {
86+ compatible = "mediatek,wocpu_dlm";
87+ reg = <0 0x151E8000 0 0x2000>;
88+
89+ resets = <&ethsysrst 0>;
90+ reset-names = "wocpu_rst";
91+ };
92+
93+ wocpu1_dlm: wocpu_dlm@0x151F8000 {
94 compatible = "mediatek,wocpu_dlm";
95- reg = <0 0x151E8000 0 0x2000>,
96- <0 0x151F8000 0 0x2000>;
97+ reg = <0 0x151F8000 0 0x2000>;
98
99 resets = <&ethsysrst 0>;
100 reset-names = "wocpu_rst";
101diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
102index 67bf86f6a..6710b388b 100644
103--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
104+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
105@@ -65,6 +65,12 @@
106 interrupt-parent = <&gic>;
107 interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
108 mediatek,wed_pcie = <&wed_pcie>;
109+ mediatek,ap2woccif = <&ap2woccif0>;
110+ mediatek,wocpu_ilm = <&wocpu0_ilm>;
111+ mediatek,wocpu_dlm = <&wocpu0_dlm>;
112+ mediatek,wocpu_boot = <&cpu_boot>;
113+ mediatek,wocpu_emi = <&wocpu0_emi>;
114+ mediatek,wocpu_data = <&wocpu_data>;
115 };
116
117 wed1: wed@15011000 {
118@@ -74,15 +80,26 @@
119 interrupt-parent = <&gic>;
120 interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
121 mediatek,wed_pcie = <&wed_pcie>;
122+ mediatek,ap2woccif = <&ap2woccif1>;
123+ mediatek,wocpu_ilm = <&wocpu1_ilm>;
124+ mediatek,wocpu_dlm = <&wocpu1_dlm>;
125+ mediatek,wocpu_boot = <&cpu_boot>;
126+ mediatek,wocpu_emi = <&wocpu1_emi>;
127+ mediatek,wocpu_data = <&wocpu_data>;
128 };
129
130- ap2woccif: ap2woccif@151A5000 {
131- compatible = "mediatek,ap2woccif";
132- reg = <0 0x151A5000 0 0x1000>,
133- <0 0x151AD000 0 0x1000>;
134+ ap2woccif0: ap2woccif@151A5000 {
135+ compatible = "mediatek,ap2woccif", "syscon";
136+ reg = <0 0x151A5000 0 0x1000>;
137 interrupt-parent = <&gic>;
138- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
139- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
140+ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
141+ };
142+
143+ ap2woccif1: ap2woccif@0x151AD000 {
144+ compatible = "mediatek,ap2woccif", "syscon";
145+ reg = <0 0x151AD000 0 0x1000>;
146+ interrupt-parent = <&gic>;
147+ interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
148 };
149
150 wocpu0_ilm: wocpu0_ilm@151E0000 {
151@@ -95,10 +112,17 @@
152 reg = <0 0x151F0000 0 0x8000>;
153 };
154
155- wocpu_dlm: wocpu_dlm@151E8000 {
156+ wocpu0_dlm: wocpu_dlm@151E8000 {
157+ compatible = "mediatek,wocpu_dlm";
158+ reg = <0 0x151E8000 0 0x2000>;
159+
160+ resets = <&ethsysrst 0>;
161+ reset-names = "wocpu_rst";
162+ };
163+
164+ wocpu1_dlm: wocpu_dlm@0x151F8000 {
165 compatible = "mediatek,wocpu_dlm";
166- reg = <0 0x151E8000 0 0x2000>,
167- <0 0x151F8000 0 0x2000>;
168+ reg = <0 0x151F8000 0 0x2000>;
169
170 resets = <&ethsysrst 0>;
171 reset-names = "wocpu_rst";
172diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
developera3f86ed2022-07-08 14:15:13 +0800173index 3528f1b..0c724a5 100644
developer8cb3ac72022-07-04 10:55:14 +0800174--- a/drivers/net/ethernet/mediatek/Makefile
175+++ b/drivers/net/ethernet/mediatek/Makefile
176@@ -10,5 +10,5 @@ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o
177 ifdef CONFIG_DEBUG_FS
178 mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
179 endif
180-obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o
181+obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o mtk_wed_wo.o mtk_wed_mcu.o mtk_wed_ccif.o
182 obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
183diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
developerc1b2cd12022-07-28 18:35:24 +0800184index 48b0353..0750def 100644
developer8cb3ac72022-07-04 10:55:14 +0800185--- a/drivers/net/ethernet/mediatek/mtk_wed.c
186+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
187@@ -13,11 +13,19 @@
188 #include <linux/debugfs.h>
189 #include <linux/iopoll.h>
190 #include <linux/soc/mediatek/mtk_wed.h>
191+
192 #include "mtk_eth_soc.h"
193 #include "mtk_wed_regs.h"
194 #include "mtk_wed.h"
195 #include "mtk_ppe.h"
196-
197+#include "mtk_wed_mcu.h"
198+#include "mtk_wed_wo.h"
199+
200+struct wo_cmd_ring {
201+ u32 q_base;
202+ u32 cnt;
203+ u32 unit;
204+};
205 static struct mtk_wed_hw *hw_list[2];
206 static DEFINE_MUTEX(hw_lock);
207
developera3f86ed2022-07-08 14:15:13 +0800208@@ -51,6 +59,56 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
developer8cb3ac72022-07-04 10:55:14 +0800209 wdma_m32(dev, reg, 0, mask);
210 }
211
212+static void
213+wdma_clr(struct mtk_wed_device *dev, u32 reg, u32 mask)
214+{
215+ wdma_m32(dev, reg, mask, 0);
216+}
217+
developera3f86ed2022-07-08 14:15:13 +0800218+static u32
219+mtk_wdma_read_reset(struct mtk_wed_device *dev)
220+{
221+ return wdma_r32(dev, MTK_WDMA_GLO_CFG);
222+}
223+
224+static void
225+mtk_wdma_rx_reset(struct mtk_wed_device *dev)
226+{
227+ u32 status;
228+ u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
229+ int i;
230+
231+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
232+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
233+ !(status & mask), 0, 1000))
234+ WARN_ON_ONCE(1);
235+
236+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
237+ if (!dev->rx_wdma[i].desc) {
238+ wdma_w32(dev, MTK_WDMA_RING_RX(i) +
239+ MTK_WED_RING_OFS_CPU_IDX, 0);
240+ }
241+}
242+
243+static void
244+mtk_wdma_tx_reset(struct mtk_wed_device *dev)
245+{
246+ u32 status;
247+ u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
248+ int i;
249+
250+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
251+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
252+ !(status & mask), 0, 1000))
253+ WARN_ON_ONCE(1);
254+
255+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
256+ if (!dev->tx_wdma[i].desc) {
257+ wdma_w32(dev, MTK_WDMA_RING_TX(i) +
258+ MTK_WED_RING_OFS_CPU_IDX, 0);
259+ }
260+}
261+
developer8cb3ac72022-07-04 10:55:14 +0800262 static u32
263 mtk_wed_read_reset(struct mtk_wed_device *dev)
264 {
developera3f86ed2022-07-08 14:15:13 +0800265@@ -68,6 +126,52 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
developer8cb3ac72022-07-04 10:55:14 +0800266 WARN_ON_ONCE(1);
267 }
268
269+static void
270+mtk_wed_wo_reset(struct mtk_wed_device *dev)
271+{
272+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
273+ u8 state = WO_STATE_DISABLE;
274+ u8 state_done = WOIF_DISABLE_DONE;
275+ void __iomem *reg;
276+ u32 value;
277+ unsigned long timeout = jiffies + WOCPU_TIMEOUT;
278+
developerc1b2cd12022-07-28 18:35:24 +0800279+ mtk_wdma_tx_reset(dev);
developera3f86ed2022-07-08 14:15:13 +0800280+
281+ mtk_wed_reset(dev, MTK_WED_RESET_WED);
282+
developer8cb3ac72022-07-04 10:55:14 +0800283+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, WO_CMD_CHANGE_STATE,
284+ &state, sizeof(state), false);
285+
286+ do {
287+ value = wed_r32(dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_WO_STATUS);
288+ } while (value != state_done && !time_after(jiffies, timeout));
289+
290+ reg = ioremap(WOCPU_MCUSYS_RESET_ADDR, 4);
291+ value = readl((void *)reg);
292+ switch(dev->hw->index) {
293+ case 0:
294+ value |= WOCPU_WO0_MCUSYS_RESET_MASK;
295+ writel(value, (void *)reg);
296+ value &= ~WOCPU_WO0_MCUSYS_RESET_MASK;
297+ writel(value, (void *)reg);
298+ break;
299+ case 1:
300+ value |= WOCPU_WO1_MCUSYS_RESET_MASK;
301+ writel(value, (void *)reg);
302+ value &= ~WOCPU_WO1_MCUSYS_RESET_MASK;
303+ writel(value, (void *)reg);
304+ break;
305+ default:
306+ dev_err(dev->hw->dev, "wrong mtk_wed%d\n",
307+ dev->hw->index);
308+
309+ break;
310+ }
311+
312+ iounmap((void *)reg);
313+}
314+
315 static struct mtk_wed_hw *
316 mtk_wed_assign(struct mtk_wed_device *dev)
317 {
developera3f86ed2022-07-08 14:15:13 +0800318@@ -178,7 +282,7 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
319 {
320 struct mtk_wdma_desc *desc = dev->buf_ring.desc;
321 void **page_list = dev->buf_ring.pages;
322- int page_idx;
323+ int ring_size, page_idx;
324 int i;
325
326 if (!page_list)
327@@ -187,6 +291,13 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
328 if (!desc)
329 goto free_pagelist;
330
331+ if (dev->ver == MTK_WED_V1) {
332+ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
333+ } else {
334+ ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
335+ MTK_WED_WDMA_RING_SIZE * 2;
336+ }
337+
338 for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
339 void *page = page_list[page_idx++];
340
341@@ -205,6 +316,42 @@ free_pagelist:
developer8cb3ac72022-07-04 10:55:14 +0800342 kfree(page_list);
343 }
344
345+static int
346+mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
347+{
348+ struct mtk_rxbm_desc *desc;
349+ dma_addr_t desc_phys;
350+ int ring_size;
351+
352+ ring_size = dev->wlan.rx_nbuf;
353+ dev->rx_buf_ring.size = ring_size;
354+ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
355+ &desc_phys, GFP_KERNEL);
356+ if (!desc)
357+ return -ENOMEM;
358+
359+ dev->rx_buf_ring.desc = desc;
360+ dev->rx_buf_ring.desc_phys = desc_phys;
361+
362+ dev->wlan.init_rx_buf(dev, dev->wlan.rx_pkt);
363+ return 0;
364+}
365+
366+static void
367+mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
368+{
369+ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
developera3f86ed2022-07-08 14:15:13 +0800370+ int ring_size = dev->rx_buf_ring.size;
developer8cb3ac72022-07-04 10:55:14 +0800371+
372+ if (!desc)
373+ return;
374+
375+ dev->wlan.release_rx_buf(dev);
376+
developera3f86ed2022-07-08 14:15:13 +0800377+ /* dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
378+ desc, dev->buf_ring.desc_phys); */
developer8cb3ac72022-07-04 10:55:14 +0800379+}
380+
381 static void
382 mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
383 {
developera3f86ed2022-07-08 14:15:13 +0800384@@ -226,13 +373,22 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800385 mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
386 }
387
388+static void
389+mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
390+{
391+ mtk_wed_free_rx_bm(dev);
392+ mtk_wed_free_ring(dev, &dev->rro.rro_ring, 1);
393+}
394+
395 static void
396 mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
397 {
398 u32 wdma_mask;
399
400 wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
401-
402+ if (dev->ver > MTK_WED_V1)
403+ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
404+ GENMASK(1, 0));
405 /* wed control cr set */
406 wed_set(dev, MTK_WED_CTRL,
407 MTK_WED_CTRL_WDMA_INT_AGENT_EN |
developera3f86ed2022-07-08 14:15:13 +0800408@@ -251,7 +407,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
developer8cb3ac72022-07-04 10:55:14 +0800409 wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
410 MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
411 } else {
412- /* initail tx interrupt trigger */
413+
414 wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
415 MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
416 MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
developera3f86ed2022-07-08 14:15:13 +0800417@@ -262,22 +418,30 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
developer8cb3ac72022-07-04 10:55:14 +0800418 FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
419 dev->wlan.tx_tbit[1]));
420
421- /* initail txfree interrupt trigger */
422 wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
423 MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
424 MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
425 FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
426 dev->wlan.txfree_tbit));
427+
428+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
429+ MTK_WED_WPDMA_INT_CTRL_RX0_EN |
430+ MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
431+ MTK_WED_WPDMA_INT_CTRL_RX1_EN |
432+ MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
433+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
434+ dev->wlan.rx_tbit[0]) |
435+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
436+ dev->wlan.rx_tbit[1]));
437 }
438- /* initail wdma interrupt agent */
439 wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
440 if (dev->ver == MTK_WED_V1) {
441 wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
442 } else {
443 wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
444 wed_set(dev, MTK_WED_WDMA_INT_CTRL,
445- FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
446-
447+ FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,
448+ dev->wdma_idx));
449 }
450
451 wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
developerc1b2cd12022-07-28 18:35:24 +0800452@@ -312,6 +476,40 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
developer8cb3ac72022-07-04 10:55:14 +0800453 }
454 }
455
456+static void
457+mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
458+{
459+#define MTK_WFMDA_RX_DMA_EN BIT(2)
460+
461+ int timeout = 3;
462+ u32 cur_idx, regs;
463+
464+ do {
465+ regs = MTK_WED_WPDMA_RING_RX_DATA(idx) +
developerc1b2cd12022-07-28 18:35:24 +0800466+ MTK_WED_RING_OFS_CPU_IDX;
developer8cb3ac72022-07-04 10:55:14 +0800467+ cur_idx = wed_r32(dev, regs);
468+ if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
469+ break;
470+
471+ usleep_range(100000, 200000);
developerc1b2cd12022-07-28 18:35:24 +0800472+ timeout--;
473+ } while (timeout > 0);
developer8cb3ac72022-07-04 10:55:14 +0800474+
475+ if (timeout) {
476+ unsigned int val;
477+
478+ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
479+ dev->wlan.phy_base);
480+ val |= MTK_WFMDA_RX_DMA_EN;
481+
482+ wifi_w32(dev, dev->wlan.wpdma_rx_glo -
483+ dev->wlan.phy_base, val);
484+ } else {
485+ dev_err(dev->hw->dev, "mtk_wed%d: rx dma enable failed!\n",
486+ dev->hw->index);
487+ }
488+}
489+
490 static void
491 mtk_wed_dma_enable(struct mtk_wed_device *dev)
492 {
developerc1b2cd12022-07-28 18:35:24 +0800493@@ -336,9 +534,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800494 wdma_set(dev, MTK_WDMA_GLO_CFG,
495 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
496 } else {
497+ int idx = 0;
498+
499 wed_set(dev, MTK_WED_WPDMA_CTRL,
500 MTK_WED_WPDMA_CTRL_SDL1_FIXED);
501
502+ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
developerc1b2cd12022-07-28 18:35:24 +0800503+ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
developer8cb3ac72022-07-04 10:55:14 +0800504+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
505+
506 wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
507 MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
508 MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
developerc1b2cd12022-07-28 18:35:24 +0800509@@ -346,6 +550,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800510 wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
511 MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
512 MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
513+
514+ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
515+ MTK_WED_WPDMA_RX_D_RX_DRV_EN |
516+ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
517+ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
518+ 0x2));
519+
520+ for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++)
521+ mtk_wed_check_wfdma_rx_fill(dev, idx);
522 }
523 }
524
developerc1b2cd12022-07-28 18:35:24 +0800525@@ -363,19 +576,23 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800526 MTK_WED_GLO_CFG_TX_DMA_EN |
527 MTK_WED_GLO_CFG_RX_DMA_EN);
528
529- wdma_m32(dev, MTK_WDMA_GLO_CFG,
530+ wdma_clr(dev, MTK_WDMA_GLO_CFG,
531 MTK_WDMA_GLO_CFG_TX_DMA_EN |
532 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
533- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0);
534+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
535
536 if (dev->ver == MTK_WED_V1) {
537 regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
538- wdma_m32(dev, MTK_WDMA_GLO_CFG,
539- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0);
540+ wdma_clr(dev, MTK_WDMA_GLO_CFG,
541+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
542 } else {
543 wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
544 MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
545 MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
546+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
547+ MTK_WED_WPDMA_RX_D_RX_DRV_EN);
548+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
549+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
550 }
551 }
552
developerc1b2cd12022-07-28 18:35:24 +0800553@@ -383,10 +600,12 @@ static void
554 mtk_wed_stop(struct mtk_wed_device *dev)
developera3f86ed2022-07-08 14:15:13 +0800555 {
556 mtk_wed_dma_disable(dev);
developerc1b2cd12022-07-28 18:35:24 +0800557+ mtk_wed_set_512_support(dev, false);
developera3f86ed2022-07-08 14:15:13 +0800558
559- if (dev->ver > MTK_WED_V1)
developerc1b2cd12022-07-28 18:35:24 +0800560- mtk_wed_set_512_support(dev, false);
561-
developera3f86ed2022-07-08 14:15:13 +0800562+ if (dev->ver > MTK_WED_V1) {
developera3f86ed2022-07-08 14:15:13 +0800563+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
564+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
565+ }
developera3f86ed2022-07-08 14:15:13 +0800566 mtk_wed_set_ext_int(dev, false);
567
developerc1b2cd12022-07-28 18:35:24 +0800568 wed_clr(dev, MTK_WED_CTRL,
569@@ -395,6 +614,11 @@ mtk_wed_stop(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800570 MTK_WED_CTRL_WED_TX_BM_EN |
571 MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
572
573+ if (dev->ver > MTK_WED_V1) {
574+ wed_clr(dev, MTK_WED_CTRL,
575+ MTK_WED_CTRL_WED_RX_BM_EN);
576+ }
577+
578 wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
579 wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
580 wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
developerc1b2cd12022-07-28 18:35:24 +0800581@@ -417,8 +641,19 @@ mtk_wed_detach(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800582
583 mtk_wed_reset(dev, MTK_WED_RESET_WED);
developera3f86ed2022-07-08 14:15:13 +0800584
developer8cb3ac72022-07-04 10:55:14 +0800585+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
586+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
587+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
developera3f86ed2022-07-08 14:15:13 +0800588+
developer8cb3ac72022-07-04 10:55:14 +0800589 mtk_wed_free_buffer(dev);
590 mtk_wed_free_tx_rings(dev);
developera3f86ed2022-07-08 14:15:13 +0800591+ if (dev->ver > MTK_WED_V1) {
592+ mtk_wed_wo_reset(dev);
developerf50c1802022-07-05 20:35:53 +0800593+ mtk_wed_free_rx_rings(dev);
developera3f86ed2022-07-08 14:15:13 +0800594+ mtk_wed_wo_exit(hw);
595+ }
596+
developerc1b2cd12022-07-28 18:35:24 +0800597+ mtk_wdma_rx_reset(dev);
developer8cb3ac72022-07-04 10:55:14 +0800598
599 if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
600 wlan_node = dev->wlan.pci_dev->dev.of_node;
developerc1b2cd12022-07-28 18:35:24 +0800601@@ -477,7 +712,6 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800602 value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
603 value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
604
605- /* pcie interrupt status trigger register */
606 wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
607 wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
608
developerc1b2cd12022-07-28 18:35:24 +0800609@@ -501,6 +735,9 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800610 wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
611 wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
612 wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
613+
614+ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
615+ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx);
616 } else {
617 wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
618 }
developerc1b2cd12022-07-28 18:35:24 +0800619@@ -549,24 +786,92 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800620 FIELD_PREP(MTK_WED_WDMA_OFST1_RX_CTRL,
621 MTK_WDMA_RING_RX(0)));
622 }
623+}
developera3f86ed2022-07-08 14:15:13 +0800624
developer8cb3ac72022-07-04 10:55:14 +0800625+static void
626+mtk_wed_rx_bm_hw_init(struct mtk_wed_device *dev)
627+{
628+ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD,
629+ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_pkt_size));
630+
631+ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys);
developera3f86ed2022-07-08 14:15:13 +0800632+
developer8cb3ac72022-07-04 10:55:14 +0800633+ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL |
634+ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_pkt));
635+
636+ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH,
637+ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
638+
639+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
640 }
641
642 static void
643-mtk_wed_hw_init(struct mtk_wed_device *dev)
644+mtk_wed_rro_hw_init(struct mtk_wed_device *dev)
645+{
646+ wed_w32(dev, MTK_WED_RROQM_MIOD_CFG,
647+ FIELD_PREP(MTK_WED_RROQM_MIOD_MID_DW, 0x70 >> 2) |
648+ FIELD_PREP(MTK_WED_RROQM_MIOD_MOD_DW, 0x10 >> 2) |
649+ FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW,
650+ MTK_WED_MIOD_ENTRY_CNT >> 2));
651+
652+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_desc_phys);
653+
654+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1,
655+ FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT));
656+
657+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_desc_phys);
658+
659+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1,
660+ FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT));
661+
662+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0);
663+
664+ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.rro_ring.desc_phys);
665+
666+ wed_set(dev, MTK_WED_RROQM_RST_IDX,
667+ MTK_WED_RROQM_RST_IDX_MIOD |
668+ MTK_WED_RROQM_RST_IDX_FDBK);
669+
670+ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
671+
672+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL2, MTK_WED_MIOD_CNT -1);
673+
674+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN);
675+}
676+
677+static void
678+mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
679+{
680+ wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM);
681+
682+ do {
683+ udelay(100);
684+
685+ if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM))
686+ break;
687+ } while (1);
688+
689+ /* configure RX_ROUTE_QM */
690+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
691+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
692+ wed_set(dev, MTK_WED_RTQM_GLO_CFG,
693+ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
694+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
695+
696+ /* enable RX_ROUTE_QM */
697+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
698+}
699+
700+static void
701+mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
702 {
703 int size = dev->buf_ring.size;
704 int rev_size = MTK_WED_TX_RING_SIZE / 2;
705 int thr = 1;
706
707- if (dev->init_done)
708- return;
709-
710- dev->init_done = true;
711- mtk_wed_set_ext_int(dev, false);
712-
713 if (dev->ver > MTK_WED_V1) {
714- size = MTK_WED_WDMA_RING_SIZE * 2 + dev->buf_ring.size;
715+ size = MTK_WED_WDMA_RING_SIZE * ARRAY_SIZE(dev->tx_wdma) +
716+ dev->buf_ring.size;
717 rev_size = size;
718 thr = 0;
719 }
developerc1b2cd12022-07-28 18:35:24 +0800720@@ -609,13 +914,46 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800721 }
722
723 static void
724-mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale)
725+mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
developerbbca0f92022-07-26 17:26:12 +0800726 {
developer8cb3ac72022-07-04 10:55:14 +0800727+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
developerc1b2cd12022-07-28 18:35:24 +0800728+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
729+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
developer8cb3ac72022-07-04 10:55:14 +0800730+
731+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
732+
733+ mtk_wed_rx_bm_hw_init(dev);
734+ mtk_wed_rro_hw_init(dev);
735+ mtk_wed_route_qm_hw_init(dev);
736+}
737+
738+static void
739+mtk_wed_hw_init(struct mtk_wed_device *dev)
740+{
741+ if (dev->init_done)
742+ return;
743+
744+ dev->init_done = true;
745+ mtk_wed_set_ext_int(dev, false);
746+ mtk_wed_tx_hw_init(dev);
747+ if (dev->ver > MTK_WED_V1)
748+ mtk_wed_rx_hw_init(dev);
749+}
750+
751+static void
752+mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
developerbbca0f92022-07-26 17:26:12 +0800753+{
developer8cb3ac72022-07-04 10:55:14 +0800754+ __le32 ctrl;
755 int i;
756
757+ if (tx)
758+ ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
759+ else
760+ ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST);
761+
762 for (i = 0; i < size; i++) {
763 desc->buf0 = 0;
764- desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
765+ desc->ctrl = ctrl;
766 desc->buf1 = 0;
767 desc->info = 0;
768 desc += scale;
developerc1b2cd12022-07-28 18:35:24 +0800769@@ -674,7 +1012,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800770 if (!desc)
771 continue;
772
773- mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver);
774+ mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver, true);
775 }
776
777 if (mtk_wed_poll_busy(dev))
developerc1b2cd12022-07-28 18:35:24 +0800778@@ -692,6 +1030,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
779 wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
780 wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
781
782+ mtk_wdma_rx_reset(dev);
783+
784 if (busy) {
785 mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
786 mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
787@@ -729,9 +1069,24 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +0800788
789 }
790
791+static int
792+mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
793+ int size)
794+{
795+ ring->desc = dma_alloc_coherent(dev->hw->dev,
796+ size * sizeof(*ring->desc),
797+ &ring->desc_phys, GFP_KERNEL);
798+ if (!ring->desc)
799+ return -ENOMEM;
800+
801+ ring->size = size;
802+ memset(ring->desc, 0, size);
803+ return 0;
804+}
805+
806 static int
807 mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
808- int size, int scale)
809+ int size, int scale, bool tx)
810 {
811 ring->desc = dma_alloc_coherent(dev->hw->dev,
812 size * sizeof(*ring->desc) * scale,
developerc1b2cd12022-07-28 18:35:24 +0800813@@ -740,17 +1095,18 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
developer8cb3ac72022-07-04 10:55:14 +0800814 return -ENOMEM;
815
816 ring->size = size;
817- mtk_wed_ring_reset(ring->desc, size, scale);
818+ mtk_wed_ring_reset(ring->desc, size, scale, tx);
819
820 return 0;
821 }
822
823 static int
824-mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
825+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
826 {
827 struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
828
829- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, dev->ver))
830+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
831+ dev->ver, true))
832 return -ENOMEM;
833
834 wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
developerc1b2cd12022-07-28 18:35:24 +0800835@@ -767,22 +1123,143 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
developer8cb3ac72022-07-04 10:55:14 +0800836 return 0;
837 }
838
839+static int
840+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
841+{
842+ struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
843+
844+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
845+ dev->ver, true))
846+ return -ENOMEM;
847+
848+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
849+ wdma->desc_phys);
850+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT,
851+ size);
852+ wdma_w32(dev,
853+ MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0);
854+ wdma_w32(dev,
855+ MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
856+
857+ if (idx == 0) {
858+ wed_w32(dev, MTK_WED_WDMA_RING_TX
859+ + MTK_WED_RING_OFS_BASE, wdma->desc_phys);
860+ wed_w32(dev, MTK_WED_WDMA_RING_TX
861+ + MTK_WED_RING_OFS_COUNT, size);
862+ wed_w32(dev, MTK_WED_WDMA_RING_TX
863+ + MTK_WED_RING_OFS_CPU_IDX, 0);
864+ wed_w32(dev, MTK_WED_WDMA_RING_TX
865+ + MTK_WED_RING_OFS_DMA_IDX, 0);
866+ }
867+
868+ return 0;
869+}
870+
871+static int
872+mtk_wed_rro_alloc(struct mtk_wed_device *dev)
873+{
874+ struct device_node *np, *node = dev->hw->node;
875+ struct mtk_wed_ring *ring;
876+ struct resource res;
877+ int ret;
878+
879+ np = of_parse_phandle(node, "mediatek,wocpu_dlm", 0);
880+ if (!np)
881+ return -ENODEV;
882+
883+ ret = of_address_to_resource(np, 0, &res);
884+ if (ret)
885+ return ret;
886+
887+ dev->rro.rro_desc = ioremap(res.start, resource_size(&res));
888+
889+ ring = &dev->rro.rro_ring;
890+
891+ dev->rro.miod_desc_phys = res.start;
892+
893+ dev->rro.mcu_view_miod = MTK_WED_WOCPU_VIEW_MIOD_BASE;
894+ dev->rro.fdbk_desc_phys = MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT
895+ + dev->rro.miod_desc_phys;
896+
897+ if (mtk_wed_rro_ring_alloc(dev, ring, MTK_WED_RRO_QUE_CNT))
898+ return -ENOMEM;
899+
900+ return 0;
901+}
902+
903+static int
904+mtk_wed_rro_cfg(struct mtk_wed_device *dev)
905+{
906+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
907+ struct {
908+ struct wo_cmd_ring ring[2];
909+
910+ u32 wed;
911+ u8 ver;
912+ } req = {
913+ .ring = {
914+ [0] = {
915+ .q_base = dev->rro.mcu_view_miod,
916+ .cnt = MTK_WED_MIOD_CNT,
917+ .unit = MTK_WED_MIOD_ENTRY_CNT,
918+ },
919+ [1] = {
920+ .q_base = dev->rro.mcu_view_miod +
921+ MTK_WED_MIOD_ENTRY_CNT *
922+ MTK_WED_MIOD_CNT,
923+ .cnt = MTK_WED_FB_CMD_CNT,
924+ .unit = 4,
925+ },
926+ },
927+ .wed = 0,
928+ };
929+
930+ return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, WO_CMD_WED_CFG,
931+ &req, sizeof(req), true);
932+}
933+
934+static int
935+mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
936+{
937+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
938+
developerf50c1802022-07-05 20:35:53 +0800939+ if (dev->ver == MTK_WED_V1)
940+ return 0;
941+
developer8cb3ac72022-07-04 10:55:14 +0800942+ return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, data, len, true);
943+}
944+
945+static void
946+mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
947+ u32 reason, u32 hash)
948+{
949+ int idx = dev->hw->index;
950+ struct mtk_eth *eth = dev->hw->eth;
951+ struct ethhdr *eh;
952+
953+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
954+ if (!skb)
955+ return;
956+
957+ skb_set_mac_header(skb, 0);
958+ eh = eth_hdr(skb);
959+ skb->protocol = eh->h_proto;
960+ mtk_ppe_check_skb(eth->ppe[idx], skb, hash);
961+ }
962+}
963+
964 static void
965 mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
966 {
967- u32 wdma_mask;
968- int i;
969+ int i, ret;
970
971 for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
972 if (!dev->tx_wdma[i].desc)
973- mtk_wed_wdma_ring_setup(dev, i, 16);
974-
975+ mtk_wed_wdma_rx_ring_setup(dev, i, 16);
976
977 mtk_wed_hw_init(dev);
978
979 mtk_wed_set_int(dev, irq_mask);
980-
981-
982 mtk_wed_set_ext_int(dev, true);
983
984 if (dev->ver == MTK_WED_V1) {
developerc1b2cd12022-07-28 18:35:24 +0800985@@ -797,8 +1274,20 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
developer8cb3ac72022-07-04 10:55:14 +0800986 val |= BIT(0);
987 regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
988 } else {
developerc1b2cd12022-07-28 18:35:24 +0800989- mtk_wed_set_512_support(dev, true);
developer8cb3ac72022-07-04 10:55:14 +0800990+ /* driver set mid ready and only once */
991+ wed_w32(dev, MTK_WED_EXT_INT_MASK1,
992+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
993+ wed_w32(dev, MTK_WED_EXT_INT_MASK2,
994+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
995+
996+ wed_r32(dev, MTK_WED_EXT_INT_MASK1);
997+ wed_r32(dev, MTK_WED_EXT_INT_MASK2);
998+
999+ ret = mtk_wed_rro_cfg(dev);
1000+ if (ret)
1001+ return;
developer8cb3ac72022-07-04 10:55:14 +08001002 }
developerc1b2cd12022-07-28 18:35:24 +08001003+ mtk_wed_set_512_support(dev, true);
developer8cb3ac72022-07-04 10:55:14 +08001004
developerc1b2cd12022-07-28 18:35:24 +08001005 mtk_wed_dma_enable(dev);
1006 dev->running = true;
developerbbca0f92022-07-26 17:26:12 +08001007@@ -809,6 +1298,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
1008 __releases(RCU)
1009 {
1010 struct mtk_wed_hw *hw;
1011+ u16 ver;
1012 int ret = 0;
1013
1014 RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
1015@@ -839,11 +1329,24 @@ mtk_wed_attach(struct mtk_wed_device *dev)
1016
1017 dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
developer8cb3ac72022-07-04 10:55:14 +08001018 wed_r32(dev, MTK_WED_REV_ID));
developerbbca0f92022-07-26 17:26:12 +08001019+ if (dev->ver > MTK_WED_V1)
1020+ ver = FIELD_GET(MTK_WED_REV_ID_MINOR,
1021+ wed_r32(dev, MTK_WED_REV_ID));
1022+
1023+ dev->rev_id = ((dev->ver << 28) | ver << 16);
developer8cb3ac72022-07-04 10:55:14 +08001024
1025 ret = mtk_wed_buffer_alloc(dev);
1026- if (ret) {
1027- mtk_wed_detach(dev);
1028- goto out;
1029+ if (ret)
1030+ goto error;
1031+
1032+ if (dev->ver > MTK_WED_V1) {
1033+ ret = mtk_wed_rx_bm_alloc(dev);
1034+ if (ret)
1035+ goto error;
1036+
1037+ ret = mtk_wed_rro_alloc(dev);
1038+ if (ret)
1039+ goto error;
1040 }
1041
1042 mtk_wed_hw_init_early(dev);
developerbbca0f92022-07-26 17:26:12 +08001043@@ -851,7 +1354,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +08001044 if (dev->ver == MTK_WED_V1)
1045 regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
1046 BIT(hw->index), 0);
1047+ else
1048+ ret = mtk_wed_wo_init(hw);
1049
1050+error:
1051+ if (ret)
1052+ mtk_wed_detach(dev);
1053 out:
1054 mutex_unlock(&hw_lock);
1055
developerbbca0f92022-07-26 17:26:12 +08001056@@ -877,10 +1385,10 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
developer8cb3ac72022-07-04 10:55:14 +08001057
1058 BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
1059
1060- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1))
1061+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1, true))
1062 return -ENOMEM;
1063
1064- if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
1065+ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
1066 return -ENOMEM;
1067
1068 ring->reg_base = MTK_WED_RING_TX(idx);
developerbbca0f92022-07-26 17:26:12 +08001069@@ -927,6 +1435,35 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
developer8cb3ac72022-07-04 10:55:14 +08001070 return 0;
1071 }
1072
1073+static int
1074+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
1075+{
1076+ struct mtk_wed_ring *ring = &dev->rx_ring[idx];
1077+
1078+ BUG_ON(idx > ARRAY_SIZE(dev->rx_ring));
1079+
1080+
1081+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, 1, false))
1082+ return -ENOMEM;
1083+
1084+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
1085+ return -ENOMEM;
1086+
1087+ ring->reg_base = MTK_WED_RING_RX_DATA(idx);
1088+ ring->wpdma = regs;
1089+
1090+ /* WPDMA -> WED */
1091+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
1092+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_RX_RING_SIZE);
1093+
1094+ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_BASE,
1095+ ring->desc_phys);
1096+ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_COUNT,
1097+ MTK_WED_RX_RING_SIZE);
1098+
1099+ return 0;
1100+}
1101+
1102 static u32
1103 mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
1104 {
developerbbca0f92022-07-26 17:26:12 +08001105@@ -1014,6 +1551,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
developer8cb3ac72022-07-04 10:55:14 +08001106 .attach = mtk_wed_attach,
1107 .tx_ring_setup = mtk_wed_tx_ring_setup,
1108 .txfree_ring_setup = mtk_wed_txfree_ring_setup,
1109+ .rx_ring_setup = mtk_wed_rx_ring_setup,
1110+ .msg_update = mtk_wed_send_msg,
1111 .start = mtk_wed_start,
1112 .stop = mtk_wed_stop,
1113 .reset_dma = mtk_wed_reset_dma,
developerbbca0f92022-07-26 17:26:12 +08001114@@ -1022,6 +1561,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
developer8cb3ac72022-07-04 10:55:14 +08001115 .irq_get = mtk_wed_irq_get,
1116 .irq_set_mask = mtk_wed_irq_set_mask,
1117 .detach = mtk_wed_detach,
1118+ .ppe_check = mtk_wed_ppe_check,
1119 };
1120 struct device_node *eth_np = eth->dev->of_node;
1121 struct platform_device *pdev;
developerc1b2cd12022-07-28 18:35:24 +08001122@@ -1077,6 +1617,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
1123 regmap_write(hw->mirror, 0, 0);
1124 regmap_write(hw->mirror, 4, 0);
1125 }
1126+ hw->ver = MTK_WED_V1;
1127 }
1128
1129 mtk_wed_hw_add_debugfs(hw);
developer8cb3ac72022-07-04 10:55:14 +08001130diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
developera3f86ed2022-07-08 14:15:13 +08001131index 9b17b74..8ef5253 100644
developer8cb3ac72022-07-04 10:55:14 +08001132--- a/drivers/net/ethernet/mediatek/mtk_wed.h
1133+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
1134@@ -13,6 +13,7 @@
1135 #define MTK_WED_PKT_SIZE 1900
1136 #define MTK_WED_BUF_SIZE 2048
1137 #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048)
1138+#define MTK_WED_RX_RING_SIZE 1536
1139
1140 #define MTK_WED_TX_RING_SIZE 2048
1141 #define MTK_WED_WDMA_RING_SIZE 512
1142@@ -21,8 +22,15 @@
1143 #define MTK_WED_PER_GROUP_PKT 128
1144
1145 #define MTK_WED_FBUF_SIZE 128
1146+#define MTK_WED_MIOD_CNT 16
1147+#define MTK_WED_FB_CMD_CNT 1024
1148+#define MTK_WED_RRO_QUE_CNT 8192
1149+#define MTK_WED_MIOD_ENTRY_CNT 128
1150+
1151+#define MODULE_ID_WO 1
1152
1153 struct mtk_eth;
1154+struct mtk_wed_wo;
1155
1156 struct mtk_wed_hw {
1157 struct device_node *node;
1158@@ -34,12 +42,14 @@ struct mtk_wed_hw {
1159 struct regmap *mirror;
1160 struct dentry *debugfs_dir;
1161 struct mtk_wed_device *wed_dev;
1162+ struct mtk_wed_wo *wed_wo;
1163 u32 debugfs_reg;
1164 u32 num_flows;
1165 u32 wdma_phy;
1166 char dirname[5];
1167 int irq;
1168 int index;
1169+ u32 ver;
1170 };
1171
1172 struct mtk_wdma_info {
1173@@ -66,6 +76,18 @@ wed_r32(struct mtk_wed_device *dev, u32 reg)
1174 return val;
1175 }
1176
1177+static inline u32
1178+wifi_r32(struct mtk_wed_device *dev, u32 reg)
1179+{
1180+ return readl(dev->wlan.base + reg);
1181+}
1182+
1183+static inline void
1184+wifi_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
1185+{
1186+ writel(val, dev->wlan.base + reg);
1187+}
1188+
1189 static inline void
1190 wdma_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
1191 {
1192@@ -114,6 +136,23 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
1193 writel(val, dev->txfree_ring.wpdma + reg);
1194 }
1195
1196+static inline u32
1197+wpdma_rx_r32(struct mtk_wed_device *dev, int ring, u32 reg)
1198+{
1199+ if (!dev->rx_ring[ring].wpdma)
1200+ return 0;
1201+
1202+ return readl(dev->rx_ring[ring].wpdma + reg);
1203+}
1204+
1205+static inline void
1206+wpdma_rx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val)
1207+{
1208+ if (!dev->rx_ring[ring].wpdma)
1209+ return;
1210+
1211+ writel(val, dev->rx_ring[ring].wpdma + reg);
1212+}
1213 void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
1214 void __iomem *wdma, u32 wdma_phy, int index);
1215 void mtk_wed_exit(void);
developera3f86ed2022-07-08 14:15:13 +08001216@@ -146,4 +185,16 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
developer8cb3ac72022-07-04 10:55:14 +08001217 }
1218 #endif
1219
1220+int wed_wo_hardware_init(struct mtk_wed_wo *wo, irq_handler_t isr);
developera3f86ed2022-07-08 14:15:13 +08001221+void wed_wo_hardware_exit(struct mtk_wed_wo *wo);
developer8cb3ac72022-07-04 10:55:14 +08001222+int wed_wo_mcu_init(struct mtk_wed_wo *wo);
1223+int mtk_wed_exception_init(struct mtk_wed_wo *wo);
1224+void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, struct sk_buff *skb);
1225+int mtk_wed_mcu_cmd_sanity_check(struct mtk_wed_wo *wo, struct sk_buff *skb);
1226+void wed_wo_mcu_debugfs(struct mtk_wed_hw *hw, struct dentry *dir);
1227+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb);
1228+int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo,int to_id, int cmd,
1229+ const void *data, int len, bool wait_resp);
1230+int mtk_wed_wo_rx_poll(struct napi_struct *napi, int budget);
1231+
1232 #endif
1233diff --git a/drivers/net/ethernet/mediatek/mtk_wed_ccif.c b/drivers/net/ethernet/mediatek/mtk_wed_ccif.c
1234new file mode 100644
developera3f86ed2022-07-08 14:15:13 +08001235index 0000000..22ef337
developer8cb3ac72022-07-04 10:55:14 +08001236--- /dev/null
1237+++ b/drivers/net/ethernet/mediatek/mtk_wed_ccif.c
developera3f86ed2022-07-08 14:15:13 +08001238@@ -0,0 +1,133 @@
developer8cb3ac72022-07-04 10:55:14 +08001239+// SPDX-License-Identifier: GPL-2.0-only
1240+
1241+#include <linux/soc/mediatek/mtk_wed.h>
1242+#include <linux/of_address.h>
1243+#include <linux/mfd/syscon.h>
1244+#include <linux/of_irq.h>
1245+#include "mtk_wed_ccif.h"
1246+#include "mtk_wed_regs.h"
1247+#include "mtk_wed_wo.h"
1248+
1249+static inline void woif_set_isr(struct mtk_wed_wo *wo, u32 mask)
1250+{
1251+ woccif_w32(wo, MTK_WED_WO_CCIF_IRQ0_MASK, mask);
1252+}
1253+
1254+static inline u32 woif_get_csr(struct mtk_wed_wo *wo)
1255+{
1256+ u32 val;
1257+
1258+ val = woccif_r32(wo, MTK_WED_WO_CCIF_RCHNUM);
1259+
1260+ return val & MTK_WED_WO_CCIF_RCHNUM_MASK;
1261+}
1262+
1263+static inline void woif_set_ack(struct mtk_wed_wo *wo, u32 mask)
1264+{
1265+ woccif_w32(wo, MTK_WED_WO_CCIF_ACK, mask);
1266+}
1267+
1268+static inline void woif_kickout(struct mtk_wed_wo *wo)
1269+{
1270+ woccif_w32(wo, MTK_WED_WO_CCIF_BUSY, 1 << MTK_WED_WO_TXCH_NUM);
1271+ woccif_w32(wo, MTK_WED_WO_CCIF_TCHNUM, MTK_WED_WO_TXCH_NUM);
1272+}
1273+
1274+static inline void woif_clear_int(struct mtk_wed_wo *wo, u32 mask)
1275+{
1276+ woccif_w32(wo, MTK_WED_WO_CCIF_ACK, mask);
1277+ woccif_r32(wo, MTK_WED_WO_CCIF_RCHNUM);
1278+}
1279+
1280+int wed_wo_hardware_init(struct mtk_wed_wo *wo, irq_handler_t isr)
1281+{
1282+ static const struct wed_wo_drv_ops wo_drv_ops = {
1283+ .kickout = woif_kickout,
1284+ .set_ack = woif_set_ack,
1285+ .set_isr = woif_set_isr,
1286+ .get_csr = woif_get_csr,
1287+ .clear_int = woif_clear_int,
1288+ };
1289+ struct device_node *np, *node = wo->hw->node;
1290+ struct wed_wo_queue_regs queues;
1291+ struct regmap *regs;
1292+ int ret;
1293+
1294+ np = of_parse_phandle(node, "mediatek,ap2woccif", 0);
1295+ if (!np)
1296+ return -ENODEV;
1297+
1298+ regs = syscon_regmap_lookup_by_phandle(np, NULL);
1299+ if (!regs)
1300+ return -ENODEV;
1301+
1302+ wo->drv_ops = &wo_drv_ops;
1303+
1304+ wo->ccif.regs = regs;
1305+ wo->ccif.irq = irq_of_parse_and_map(np, 0);
1306+
1307+ spin_lock_init(&wo->ccif.irq_lock);
1308+
1309+ ret = request_irq(wo->ccif.irq, isr, IRQF_TRIGGER_HIGH,
1310+ "wo_ccif_isr", wo);
1311+ if (ret)
1312+ goto free_irq;
1313+
1314+ queues.desc_base = MTK_WED_WO_CCIF_DUMMY1;
1315+ queues.ring_size = MTK_WED_WO_CCIF_DUMMY2;
1316+ queues.cpu_idx = MTK_WED_WO_CCIF_DUMMY3;
1317+ queues.dma_idx = MTK_WED_WO_CCIF_SHADOW4;
1318+
1319+ ret = mtk_wed_wo_q_alloc(wo, &wo->q_tx, MTK_WED_WO_RING_SIZE,
1320+ MTK_WED_WO_CMD_LEN, MTK_WED_WO_TXCH_NUM,
1321+ &queues);
1322+
1323+ if (ret)
1324+ goto free_irq;
1325+
1326+ queues.desc_base = MTK_WED_WO_CCIF_DUMMY5;
1327+ queues.ring_size = MTK_WED_WO_CCIF_DUMMY6;
1328+ queues.cpu_idx = MTK_WED_WO_CCIF_DUMMY7;
1329+ queues.dma_idx = MTK_WED_WO_CCIF_SHADOW8;
1330+
1331+ ret = mtk_wed_wo_q_alloc(wo, &wo->q_rx, MTK_WED_WO_RING_SIZE,
1332+ MTK_WED_WO_CMD_LEN, MTK_WED_WO_RXCH_NUM,
1333+ &queues);
1334+ if (ret)
1335+ goto free_irq;
1336+
1337+ wo->ccif.q_int_mask = MTK_WED_WO_RXCH_INT_MASK;
1338+
1339+ ret = mtk_wed_wo_q_init(wo, mtk_wed_wo_rx_poll);
1340+ if (ret)
1341+ goto free_irq;
1342+
1343+ wo->ccif.q_exep_mask = MTK_WED_WO_EXCEPTION_INT_MASK;
1344+ wo->ccif.irqmask = MTK_WED_WO_ALL_INT_MASK;
1345+
1346+ /* rx queue irqmask */
1347+ wo->drv_ops->set_isr(wo, wo->ccif.irqmask);
1348+
1349+ return 0;
1350+
1351+free_irq:
developera3f86ed2022-07-08 14:15:13 +08001352+ free_irq(wo->ccif.irq, wo);
developer8cb3ac72022-07-04 10:55:14 +08001353+
1354+ return ret;
1355+}
1356+
developera3f86ed2022-07-08 14:15:13 +08001357+void wed_wo_hardware_exit(struct mtk_wed_wo *wo)
developer8cb3ac72022-07-04 10:55:14 +08001358+{
developera3f86ed2022-07-08 14:15:13 +08001359+ wo->drv_ops->set_isr(wo, 0);
1360+
1361+ disable_irq(wo->ccif.irq);
1362+ free_irq(wo->ccif.irq, wo);
1363+
1364+ tasklet_disable(&wo->irq_tasklet);
1365+ netif_napi_del(&wo->napi);
1366+
1367+ mtk_wed_wo_q_tx_clean(wo, &wo->q_tx, true);
1368+ mtk_wed_wo_q_rx_clean(wo, &wo->q_rx);
1369+ mtk_wed_wo_q_free(wo, &wo->q_tx);
1370+ mtk_wed_wo_q_free(wo, &wo->q_rx);
developer8cb3ac72022-07-04 10:55:14 +08001371+}
1372diff --git a/drivers/net/ethernet/mediatek/mtk_wed_ccif.h b/drivers/net/ethernet/mediatek/mtk_wed_ccif.h
1373new file mode 100644
developera3f86ed2022-07-08 14:15:13 +08001374index 0000000..68ade44
developer8cb3ac72022-07-04 10:55:14 +08001375--- /dev/null
1376+++ b/drivers/net/ethernet/mediatek/mtk_wed_ccif.h
1377@@ -0,0 +1,45 @@
1378+// SPDX-License-Identifier: GPL-2.0-only
1379+
1380+#ifndef __MTK_WED_CCIF_H
1381+#define __MTK_WED_CCIF_H
1382+
1383+#define MTK_WED_WO_RING_SIZE 256
1384+#define MTK_WED_WO_CMD_LEN 1504
1385+
1386+#define MTK_WED_WO_TXCH_NUM 0
1387+#define MTK_WED_WO_RXCH_NUM 1
1388+#define MTK_WED_WO_RXCH_WO_EXCEPTION 7
1389+
1390+#define MTK_WED_WO_TXCH_INT_MASK BIT(0)
1391+#define MTK_WED_WO_RXCH_INT_MASK BIT(1)
1392+#define MTK_WED_WO_EXCEPTION_INT_MASK BIT(7)
1393+#define MTK_WED_WO_ALL_INT_MASK MTK_WED_WO_RXCH_INT_MASK | \
1394+ MTK_WED_WO_EXCEPTION_INT_MASK
1395+
1396+#define MTK_WED_WO_CCIF_BUSY 0x004
1397+#define MTK_WED_WO_CCIF_START 0x008
1398+#define MTK_WED_WO_CCIF_TCHNUM 0x00c
1399+#define MTK_WED_WO_CCIF_RCHNUM 0x010
1400+#define MTK_WED_WO_CCIF_RCHNUM_MASK GENMASK(7, 0)
1401+
1402+#define MTK_WED_WO_CCIF_ACK 0x014
1403+#define MTK_WED_WO_CCIF_IRQ0_MASK 0x018
1404+#define MTK_WED_WO_CCIF_IRQ1_MASK 0x01c
1405+#define MTK_WED_WO_CCIF_DUMMY1 0x020
1406+#define MTK_WED_WO_CCIF_DUMMY2 0x024
1407+#define MTK_WED_WO_CCIF_DUMMY3 0x028
1408+#define MTK_WED_WO_CCIF_DUMMY4 0x02c
1409+#define MTK_WED_WO_CCIF_SHADOW1 0x030
1410+#define MTK_WED_WO_CCIF_SHADOW2 0x034
1411+#define MTK_WED_WO_CCIF_SHADOW3 0x038
1412+#define MTK_WED_WO_CCIF_SHADOW4 0x03c
1413+#define MTK_WED_WO_CCIF_DUMMY5 0x050
1414+#define MTK_WED_WO_CCIF_DUMMY6 0x054
1415+#define MTK_WED_WO_CCIF_DUMMY7 0x058
1416+#define MTK_WED_WO_CCIF_DUMMY8 0x05c
1417+#define MTK_WED_WO_CCIF_SHADOW5 0x060
1418+#define MTK_WED_WO_CCIF_SHADOW6 0x064
1419+#define MTK_WED_WO_CCIF_SHADOW7 0x068
1420+#define MTK_WED_WO_CCIF_SHADOW8 0x06c
1421+
1422+#endif
1423diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
developerc1b2cd12022-07-28 18:35:24 +08001424index f420f18..4a9e684 100644
developer8cb3ac72022-07-04 10:55:14 +08001425--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
1426+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
1427@@ -2,6 +2,7 @@
1428 /* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
1429
1430 #include <linux/seq_file.h>
1431+#include <linux/soc/mediatek/mtk_wed.h>
1432 #include "mtk_wed.h"
1433 #include "mtk_wed_regs.h"
1434
1435@@ -18,6 +19,8 @@ enum {
1436 DUMP_TYPE_WDMA,
1437 DUMP_TYPE_WPDMA_TX,
1438 DUMP_TYPE_WPDMA_TXFREE,
1439+ DUMP_TYPE_WPDMA_RX,
1440+ DUMP_TYPE_WED_RRO,
1441 };
1442
1443 #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
1444@@ -36,6 +39,10 @@ enum {
1445
1446 #define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n)
1447 #define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE)
1448+#define DUMP_WPDMA_RX_RING(_n) DUMP_RING("WPDMA_RX" #_n, 0, DUMP_TYPE_WPDMA_RX, _n)
1449+#define DUMP_WED_RRO_RING(_base)DUMP_RING("WED_RRO_MIOD", MTK_##_base, DUMP_TYPE_WED_RRO)
1450+#define DUMP_WED_RRO_FDBK(_base)DUMP_RING("WED_RRO_FDBK", MTK_##_base, DUMP_TYPE_WED_RRO)
1451+
1452
1453 static void
1454 print_reg_val(struct seq_file *s, const char *name, u32 val)
1455@@ -58,6 +65,7 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
1456 cur->name);
1457 continue;
1458 case DUMP_TYPE_WED:
1459+ case DUMP_TYPE_WED_RRO:
1460 val = wed_r32(dev, cur->offset);
1461 break;
1462 case DUMP_TYPE_WDMA:
1463@@ -69,6 +77,9 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
1464 case DUMP_TYPE_WPDMA_TXFREE:
1465 val = wpdma_txfree_r32(dev, cur->offset);
1466 break;
1467+ case DUMP_TYPE_WPDMA_RX:
1468+ val = wpdma_rx_r32(dev, cur->base, cur->offset);
1469+ break;
1470 }
1471 print_reg_val(s, cur->name, val);
1472 }
1473@@ -132,6 +143,81 @@ wed_txinfo_show(struct seq_file *s, void *data)
1474 }
1475 DEFINE_SHOW_ATTRIBUTE(wed_txinfo);
1476
1477+static int
1478+wed_rxinfo_show(struct seq_file *s, void *data)
1479+{
1480+ static const struct reg_dump regs[] = {
1481+ DUMP_STR("WPDMA RX"),
1482+ DUMP_WPDMA_RX_RING(0),
1483+ DUMP_WPDMA_RX_RING(1),
1484+
1485+ DUMP_STR("WPDMA RX"),
1486+ DUMP_WED(WED_WPDMA_RX_D_MIB(0)),
1487+ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(0)),
1488+ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(0)),
1489+ DUMP_WED(WED_WPDMA_RX_D_MIB(1)),
1490+ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(1)),
1491+ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(1)),
1492+ DUMP_WED(WED_WPDMA_RX_D_COHERENT_MIB),
1493+
1494+ DUMP_STR("WED RX"),
1495+ DUMP_WED_RING(WED_RING_RX_DATA(0)),
1496+ DUMP_WED_RING(WED_RING_RX_DATA(1)),
1497+
1498+ DUMP_STR("WED RRO"),
1499+ DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0),
1500+ DUMP_WED(WED_RROQM_MID_MIB),
1501+ DUMP_WED(WED_RROQM_MOD_MIB),
1502+ DUMP_WED(WED_RROQM_MOD_COHERENT_MIB),
1503+ DUMP_WED_RRO_FDBK(WED_RROQM_FDBK_CTRL0),
1504+ DUMP_WED(WED_RROQM_FDBK_IND_MIB),
1505+ DUMP_WED(WED_RROQM_FDBK_ENQ_MIB),
1506+ DUMP_WED(WED_RROQM_FDBK_ANC_MIB),
1507+ DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB),
1508+
1509+ DUMP_STR("WED Route QM"),
1510+ DUMP_WED(WED_RTQM_R2H_MIB(0)),
1511+ DUMP_WED(WED_RTQM_R2Q_MIB(0)),
1512+ DUMP_WED(WED_RTQM_Q2H_MIB(0)),
1513+ DUMP_WED(WED_RTQM_R2H_MIB(1)),
1514+ DUMP_WED(WED_RTQM_R2Q_MIB(1)),
1515+ DUMP_WED(WED_RTQM_Q2H_MIB(1)),
1516+ DUMP_WED(WED_RTQM_Q2N_MIB),
1517+ DUMP_WED(WED_RTQM_Q2B_MIB),
1518+ DUMP_WED(WED_RTQM_PFDBK_MIB),
1519+
1520+ DUMP_STR("WED WDMA TX"),
1521+ DUMP_WED(WED_WDMA_TX_MIB),
1522+ DUMP_WED_RING(WED_WDMA_RING_TX),
1523+
1524+ DUMP_STR("WDMA TX"),
1525+ DUMP_WDMA(WDMA_GLO_CFG),
1526+ DUMP_WDMA_RING(WDMA_RING_TX(0)),
1527+ DUMP_WDMA_RING(WDMA_RING_TX(1)),
1528+
1529+ DUMP_STR("WED RX BM"),
1530+ DUMP_WED(WED_RX_BM_BASE),
1531+ DUMP_WED(WED_RX_BM_RX_DMAD),
1532+ DUMP_WED(WED_RX_BM_PTR),
1533+ DUMP_WED(WED_RX_BM_TKID_MIB),
1534+ DUMP_WED(WED_RX_BM_BLEN),
1535+ DUMP_WED(WED_RX_BM_STS),
1536+ DUMP_WED(WED_RX_BM_INTF2),
1537+ DUMP_WED(WED_RX_BM_INTF),
1538+ DUMP_WED(WED_RX_BM_ERR_STS),
1539+ };
1540+
1541+ struct mtk_wed_hw *hw = s->private;
1542+ struct mtk_wed_device *dev = hw->wed_dev;
1543+
1544+ if (!dev)
1545+ return 0;
1546+
1547+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
1548+
1549+ return 0;
1550+}
1551+DEFINE_SHOW_ATTRIBUTE(wed_rxinfo);
1552
1553 static int
1554 mtk_wed_reg_set(void *data, u64 val)
1555@@ -175,4 +261,8 @@ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
1556 debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
1557 debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
1558 debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
1559+ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
developerc1b2cd12022-07-28 18:35:24 +08001560+ if (hw->ver != MTK_WED_V1) {
developer8cb3ac72022-07-04 10:55:14 +08001561+ wed_wo_mcu_debugfs(hw, dir);
1562+ }
1563 }
1564diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
1565new file mode 100644
developera3f86ed2022-07-08 14:15:13 +08001566index 0000000..bd1ab95
developer8cb3ac72022-07-04 10:55:14 +08001567--- /dev/null
1568+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
1569@@ -0,0 +1,561 @@
1570+// SPDX-License-Identifier: GPL-2.0-only
1571+
1572+#include <linux/skbuff.h>
1573+#include <linux/debugfs.h>
1574+#include <linux/firmware.h>
1575+#include <linux/of_address.h>
1576+#include <linux/soc/mediatek/mtk_wed.h>
1577+#include "mtk_wed_regs.h"
1578+#include "mtk_wed_mcu.h"
1579+#include "mtk_wed_wo.h"
1580+
1581+struct sk_buff *
1582+mtk_wed_mcu_msg_alloc(struct mtk_wed_wo *wo,
1583+ const void *data, int data_len)
1584+{
1585+ const struct wed_wo_mcu_ops *ops = wo->mcu_ops;
1586+ int length = ops->headroom + data_len;
1587+ struct sk_buff *skb;
1588+
1589+ skb = alloc_skb(length, GFP_KERNEL);
1590+ if (!skb)
1591+ return NULL;
1592+
1593+ memset(skb->head, 0, length);
1594+ skb_reserve(skb, ops->headroom);
1595+
1596+ if (data && data_len)
1597+ skb_put_data(skb, data, data_len);
1598+
1599+ return skb;
1600+}
1601+
1602+struct sk_buff *
1603+mtk_wed_mcu_get_response(struct mtk_wed_wo *wo, unsigned long expires)
1604+{
1605+ unsigned long timeout;
1606+
1607+ if (!time_is_after_jiffies(expires))
1608+ return NULL;
1609+
1610+ timeout = expires - jiffies;
1611+ wait_event_timeout(wo->mcu.wait,
1612+ (!skb_queue_empty(&wo->mcu.res_q)),
1613+ timeout);
1614+
1615+ return skb_dequeue(&wo->mcu.res_q);
1616+}
1617+
1618+int
1619+mtk_wed_mcu_skb_send_and_get_msg(struct mtk_wed_wo *wo,
1620+ int to_id, int cmd, struct sk_buff *skb,
1621+ bool wait_resp, struct sk_buff **ret_skb)
1622+{
1623+ unsigned long expires;
1624+ int ret, seq;
1625+
1626+ if (ret_skb)
1627+ *ret_skb = NULL;
1628+
1629+ mutex_lock(&wo->mcu.mutex);
1630+
1631+ ret = wo->mcu_ops->mcu_skb_send_msg(wo, to_id, cmd, skb, &seq, wait_resp);
1632+ if (ret < 0)
1633+ goto out;
1634+
1635+ if (!wait_resp) {
1636+ ret = 0;
1637+ goto out;
1638+ }
1639+
1640+ expires = jiffies + wo->mcu.timeout;
1641+
1642+ do {
1643+ skb = mtk_wed_mcu_get_response(wo, expires);
1644+ ret = wo->mcu_ops->mcu_parse_response(wo, cmd, skb, seq);
1645+
1646+ if (!ret && ret_skb)
1647+ *ret_skb = skb;
1648+ else
1649+ dev_kfree_skb(skb);
1650+ } while (ret == -EAGAIN);
1651+
1652+out:
1653+ mutex_unlock(&wo->mcu.mutex);
1654+
1655+ return ret;
1656+}
1657+
1658+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo,
1659+ struct sk_buff *skb)
1660+{
1661+ skb_queue_tail(&wo->mcu.res_q, skb);
1662+ wake_up(&wo->mcu.wait);
1663+}
1664+
1665+static int mtk_wed_mcu_send_and_get_msg(struct mtk_wed_wo *wo,
1666+ int to_id, int cmd, const void *data, int len,
1667+ bool wait_resp, struct sk_buff **ret_skb)
1668+{
1669+ struct sk_buff *skb;
1670+
1671+ skb = mtk_wed_mcu_msg_alloc(wo, data, len);
1672+ if (!skb)
1673+ return -ENOMEM;
1674+
1675+ return mtk_wed_mcu_skb_send_and_get_msg(wo, to_id, cmd, skb, wait_resp, ret_skb);
1676+}
1677+
1678+int
1679+mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo,
1680+ int to_id, int cmd,
1681+ const void *data, int len, bool wait_resp)
1682+{
1683+ struct sk_buff *skb = NULL;
1684+ int ret = 0;
1685+
1686+ ret = mtk_wed_mcu_send_and_get_msg(wo, to_id, cmd, data,
1687+ len, wait_resp, &skb);
1688+ if (skb)
1689+ dev_kfree_skb(skb);
1690+
1691+ return ret;
1692+}
1693+
1694+int mtk_wed_exception_init(struct mtk_wed_wo *wo)
1695+{
1696+ struct wed_wo_exception *exp = &wo->exp;
1697+ struct {
1698+ u32 arg0;
1699+ u32 arg1;
1700+ }req;
1701+
1702+ exp->log_size = EXCEPTION_LOG_SIZE;
1703+ exp->log = kmalloc(exp->log_size, GFP_ATOMIC);
1704+ if (!exp->log)
1705+ return -ENOMEM;
1706+
1707+ memset(exp->log, 0, exp->log_size);
1708+ exp->phys = dma_map_single(wo->hw->dev, exp->log, exp->log_size,
1709+ DMA_FROM_DEVICE);
1710+
1711+ if (unlikely(dma_mapping_error(wo->hw->dev, exp->phys))) {
1712+ dev_info(wo->hw->dev, "dma map error\n");
1713+ goto free;
1714+ }
1715+
1716+ req.arg0 = (u32)exp->phys;
1717+ req.arg1 = (u32)exp->log_size;
1718+
1719+ return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, WO_CMD_EXCEPTION_INIT,
1720+ &req, sizeof(req), false);
1721+
1722+free:
1723+ kfree(exp->log);
1724+ return -ENOMEM;
1725+}
1726+
1727+int
1728+mtk_wed_mcu_cmd_sanity_check(struct mtk_wed_wo *wo, struct sk_buff *skb)
1729+{
1730+ struct wed_cmd_hdr *hdr = (struct wed_cmd_hdr *)skb->data;
1731+
1732+ if (hdr->ver != 0)
1733+ return WARP_INVALID_PARA_STATUS;
1734+
1735+ if (skb->len < sizeof(struct wed_cmd_hdr))
1736+ return WARP_INVALID_PARA_STATUS;
1737+
1738+ if (skb->len != hdr->length)
1739+ return WARP_INVALID_PARA_STATUS;
1740+
1741+ return WARP_OK_STATUS;
1742+}
1743+
1744+void
1745+mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, struct sk_buff *skb)
1746+{
1747+ struct wed_cmd_hdr *hdr = (struct wed_cmd_hdr *)skb->data;
1748+ struct wed_wo_log *record;
1749+ char *msg = (char *)(skb->data + sizeof(struct wed_cmd_hdr));
1750+ u16 msg_len = skb->len - sizeof(struct wed_cmd_hdr);
1751+ u32 i, cnt = 0;
1752+
1753+ switch (hdr->cmd_id) {
1754+ case WO_EVT_LOG_DUMP:
1755+ pr_info("[WO LOG]: %s\n", msg);
1756+ break;
1757+ case WO_EVT_PROFILING:
1758+ cnt = msg_len / (sizeof(struct wed_wo_log));
1759+ record = (struct wed_wo_log *) msg;
1760+ dev_info(wo->hw->dev, "[WO Profiling]: %d report arrived!\n", cnt);
1761+
1762+ for (i = 0 ; i < cnt ; i++) {
1763+ //PROFILE_STAT(wo->total, record[i].total);
1764+ //PROFILE_STAT(wo->mod, record[i].mod);
1765+ //PROFILE_STAT(wo->rro, record[i].rro);
1766+
1767+ dev_info(wo->hw->dev, "[WO Profiling]: SN:%u with latency: total=%u, rro:%u, mod:%u\n",
1768+ record[i].sn,
1769+ record[i].total,
1770+ record[i].rro,
1771+ record[i].mod);
1772+ }
1773+ break;
1774+
1775+ default:
1776+ break;
1777+ }
1778+
1779+ dev_kfree_skb(skb);
1780+
1781+}
1782+
1783+static int
1784+mtk_wed_load_firmware(struct mtk_wed_wo *wo)
1785+{
1786+ struct fw_info {
1787+ __le32 decomp_crc;
1788+ __le32 decomp_len;
1789+ __le32 decomp_blk_sz;
1790+ u8 reserved[4];
1791+ __le32 addr;
1792+ __le32 len;
1793+ u8 feature_set;
1794+ u8 reserved1[15];
1795+ } __packed *region;
1796+
1797+ char *mcu;
1798+ const struct mtk_wed_fw_trailer *hdr;
1799+ static u8 shared[MAX_REGION_SIZE] = {0};
1800+ const struct firmware *fw;
1801+ int ret, i;
1802+ u32 ofs = 0;
1803+ u32 boot_cr, val;
1804+
1805+ mcu = wo->hw->index ? MT7986_FIRMWARE_WO_2 : MT7986_FIRMWARE_WO_1;
1806+
1807+ ret = request_firmware(&fw, mcu, wo->hw->dev);
1808+ if (ret)
1809+ return ret;
1810+
1811+ hdr = (const struct mtk_wed_fw_trailer *)(fw->data + fw->size -
1812+ sizeof(*hdr));
1813+
1814+ dev_info(wo->hw->dev, "WO Firmware Version: %.10s, Build Time: %.15s\n",
1815+ hdr->fw_ver, hdr->build_date);
1816+
1817+ for (i = 0; i < hdr->n_region; i++) {
1818+ int j = 0;
1819+ region = (struct fw_info *)(fw->data + fw->size -
1820+ sizeof(*hdr) -
1821+ sizeof(*region) *
1822+ (hdr->n_region - i));
1823+
1824+ while (j < MAX_REGION_SIZE) {
1825+ struct mtk_wed_fw_region *wo_region;
1826+
1827+ wo_region = &wo->region[j];
1828+ if (!wo_region->addr)
1829+ break;
1830+
1831+ if (wo_region->addr_pa == region->addr) {
1832+ if (!wo_region->shared) {
1833+ memcpy(wo_region->addr,
1834+ fw->data + ofs, region->len);
1835+ } else if (!shared[j]) {
1836+ memcpy(wo_region->addr,
1837+ fw->data + ofs, region->len);
1838+ shared[j] = true;
1839+ }
1840+ }
1841+ j++;
1842+ }
1843+
1844+ if (j == __WO_REGION_MAX) {
1845+ ret = -ENOENT;
1846+ goto done;
1847+ }
1848+ ofs += region->len;
1849+ }
1850+
1851+ /* write the start address */
1852+ boot_cr = wo->hw->index ?
1853+ WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
1854+ wo_w32(wo, boot_cr, (wo->region[WO_REGION_EMI].addr_pa >> 16));
1855+
1856+ /* wo firmware reset */
1857+ wo_w32(wo, WOX_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00);
1858+
1859+ val = wo_r32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
1860+
1861+ val |= wo->hw->index ? WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK :
1862+ WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
1863+
1864+ wo_w32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
1865+
1866+done:
1867+ release_firmware(fw);
1868+
1869+ return ret;
1870+}
1871+
1872+static int
1873+mtk_wed_get_firmware_region(struct mtk_wed_wo *wo)
1874+{
1875+ struct device_node *node, *np = wo->hw->node;
1876+ struct mtk_wed_fw_region *region;
1877+ struct resource res;
1878+ const char *compat;
1879+ int i, ret;
1880+
1881+ static const char *const wo_region_compat[__WO_REGION_MAX] = {
1882+ [WO_REGION_EMI] = WOCPU_EMI_DEV_NODE,
1883+ [WO_REGION_ILM] = WOCPU_ILM_DEV_NODE,
1884+ [WO_REGION_DATA] = WOCPU_DATA_DEV_NODE,
1885+ [WO_REGION_BOOT] = WOCPU_BOOT_DEV_NODE,
1886+ };
1887+
1888+ for (i = 0; i < __WO_REGION_MAX; i++) {
1889+ region = &wo->region[i];
1890+ compat = wo_region_compat[i];
1891+
1892+ node = of_parse_phandle(np, compat, 0);
1893+ if (!node)
1894+ return -ENODEV;
1895+
1896+ ret = of_address_to_resource(node, 0, &res);
1897+ if (ret)
1898+ return ret;
1899+
1900+ region->addr_pa = res.start;
1901+ region->size = resource_size(&res);
1902+ region->addr = ioremap(region->addr_pa, region->size);
1903+
1904+ of_property_read_u32_index(node, "shared", 0, &region->shared);
1905+ }
1906+
1907+ return 0;
1908+}
1909+
1910+static int
1911+wo_mcu_send_message(struct mtk_wed_wo *wo,
1912+ int to_id, int cmd, struct sk_buff *skb,
1913+ int *wait_seq, bool wait_resp)
1914+{
1915+ struct wed_cmd_hdr *hdr;
1916+ u8 seq = 0;
1917+
1918+ /* TDO: make dynamic based on msg type */
1919+ wo->mcu.timeout = 20 * HZ;
1920+
1921+ if (wait_resp && wait_seq) {
1922+ seq = wo->mcu.msg_seq++ ;
1923+ *wait_seq = seq;
1924+ }
1925+
1926+ hdr = (struct wed_cmd_hdr *)skb_push(skb, sizeof(*hdr));
1927+
1928+ hdr->cmd_id = cmd;
1929+ hdr->length = cpu_to_le16(skb->len);
1930+ hdr->uni_id = seq;
1931+
1932+ if (to_id == MODULE_ID_WO)
1933+ hdr->flag |= WARP_CMD_FLAG_FROM_TO_WO;
1934+
1935+ if (wait_resp && wait_seq)
1936+ hdr->flag |= WARP_CMD_FLAG_NEED_RSP;
1937+
1938+ return mtk_wed_wo_q_tx_skb(wo, &wo->q_tx, skb);
1939+}
1940+
1941+static int
1942+wo_mcu_parse_response(struct mtk_wed_wo *wo, int cmd,
1943+ struct sk_buff *skb, int seq)
1944+{
1945+ struct wed_cmd_hdr *hdr;
1946+
1947+ if (!skb) {
1948+ dev_err(wo->hw->dev, "Message %08x (seq %d) timeout\n",
1949+ cmd, seq);
1950+ return -ETIMEDOUT;
1951+ }
1952+
1953+ hdr = (struct wed_cmd_hdr *)skb->data;
1954+ if (seq != hdr->uni_id) {
1955+ dev_err(wo->hw->dev, "Message %08x (seq %d) with not match uid(%d)\n",
1956+ cmd, seq, hdr->uni_id);
1957+ return -EAGAIN;
1958+ }
1959+
1960+ //skb_pull(skb, sizeof(struct wed_cmd_hdr));
1961+
1962+ return 0;
1963+}
1964+
1965+int wed_wo_mcu_init(struct mtk_wed_wo *wo)
1966+{
1967+ static const struct wed_wo_mcu_ops wo_mcu_ops = {
1968+ .headroom = sizeof(struct wed_cmd_hdr),
1969+ .mcu_skb_send_msg = wo_mcu_send_message,
1970+ .mcu_parse_response = wo_mcu_parse_response,
1971+ /*TDO .mcu_restart = wo_mcu_restart,*/
1972+ };
1973+ unsigned long timeout = jiffies + FW_DL_TIMEOUT;
1974+ int ret;
1975+ u32 val;
1976+
1977+ wo->mcu_ops = &wo_mcu_ops;
1978+
1979+ ret = mtk_wed_get_firmware_region(wo);
1980+ if (ret)
1981+ return ret;
1982+
1983+ /* set dummy cr */
1984+ wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_FWDL,
1985+ wo->hw->index + 1);
1986+
1987+ ret = mtk_wed_load_firmware(wo);
1988+ if (ret)
1989+ return ret;
1990+
1991+ do {
1992+ /* get dummy cr */
1993+ val = wed_r32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_FWDL);
1994+ } while (val != 0 && !time_after(jiffies, timeout));
1995+
1996+ if (val)
1997+ return -EBUSY;
1998+
1999+ return 0;
2000+}
2001+
2002+static ssize_t
2003+mtk_wed_wo_ctrl(struct file *file,
2004+ const char __user *user_buf,
2005+ size_t count,
2006+ loff_t *ppos)
2007+{
2008+ struct mtk_wed_hw *hw = file->private_data;
2009+ struct mtk_wed_wo *wo = hw->wed_wo;
2010+ char buf[100], *cmd = NULL, *input[11] = {0};
2011+ char msgbuf[128] = {0};
2012+ struct wo_cmd_query *query = (struct wo_cmd_query *)msgbuf;
2013+ u32 cmd_id;
2014+ bool wait = false;
2015+ char *sub_str = NULL;
2016+ int input_idx = 0, input_total = 0, scan_num = 0;
2017+ char *p;
2018+
2019+ if (count > sizeof(buf))
2020+ return -EINVAL;
2021+
2022+ if (copy_from_user(buf, user_buf, count))
2023+ return -EFAULT;
2024+
2025+ if (count && buf[count - 1] == '\n')
2026+ buf[count - 1] = '\0';
2027+ else
2028+ buf[count] = '\0';
2029+
2030+ p = buf;
2031+
2032+ while ((sub_str = strsep(&p, " ")) != NULL) {
2033+ input[input_idx] = sub_str;
2034+ input_idx++;
2035+ input_total++;
2036+ }
2037+ cmd = input[0];
2038+ if (input_total == 1 && cmd) {
2039+ if (strncmp(cmd, "bainfo", strlen(cmd)) == 0) {
2040+ cmd_id = WO_CMD_BA_INFO_DUMP;
2041+ } else if (strncmp(cmd, "bactrl", strlen(cmd)) == 0) {
2042+ cmd_id = WO_CMD_BA_CTRL_DUMP;
2043+ } else if (strncmp(cmd, "fbcmdq", strlen(cmd)) == 0) {
2044+ cmd_id = WO_CMD_FBCMD_Q_DUMP;
2045+ } else if (strncmp(cmd, "logflush", strlen(cmd)) == 0) {
2046+ cmd_id = WO_CMD_LOG_FLUSH;
2047+ } else if (strncmp(cmd, "cpustat.dump", strlen(cmd)) == 0) {
2048+ cmd_id = WO_CMD_CPU_STATS_DUMP;
2049+ } else if (strncmp(cmd, "state", strlen(cmd)) == 0) {
2050+ cmd_id = WO_CMD_WED_RX_STAT;
2051+ } else if (strncmp(cmd, "prof_hit_dump", strlen(cmd)) == 0) {
2052+ //wo_profiling_report();
2053+ return count;
2054+ } else if (strncmp(cmd, "rxcnt_info", strlen(cmd)) == 0) {
2055+ cmd_id = WO_CMD_RXCNT_INFO;
2056+ wait = true;
2057+ } else {
2058+ pr_info("(%s) unknown comand string(%s)!\n", __func__, cmd);
2059+ return count;
2060+ }
2061+ } else if (input_total > 1) {
2062+ for (input_idx = 1 ; input_idx < input_total ; input_idx++) {
2063+ scan_num = sscanf(input[input_idx], "%u", &query->query0+(input_idx - 1));
2064+
2065+ if (scan_num < 1) {
2066+ pr_info("(%s) require more input!\n", __func__);
2067+ return count;
2068+ }
2069+ }
2070+ if(strncmp(cmd, "devinfo", strlen(cmd)) == 0) {
2071+ cmd_id = WO_CMD_DEV_INFO_DUMP;
2072+ } else if (strncmp(cmd, "bssinfo", strlen(cmd)) == 0) {
2073+ cmd_id = WO_CMD_BSS_INFO_DUMP;
2074+ } else if (strncmp(cmd, "starec", strlen(cmd)) == 0) {
2075+ cmd_id = WO_CMD_STA_REC_DUMP;
2076+ } else if (strncmp(cmd, "starec_ba", strlen(cmd)) == 0) {
2077+ cmd_id = WO_CMD_STA_BA_DUMP;
2078+ } else if (strncmp(cmd, "logctrl", strlen(cmd)) == 0) {
2079+ cmd_id = WO_CMD_FW_LOG_CTRL;
2080+ } else if (strncmp(cmd, "cpustat.en", strlen(cmd)) == 0) {
2081+ cmd_id = WO_CMD_CPU_STATS_ENABLE;
2082+ } else if (strncmp(cmd, "prof_conf", strlen(cmd)) == 0) {
2083+ cmd_id = WO_CMD_PROF_CTRL;
2084+ } else if (strncmp(cmd, "rxcnt_ctrl", strlen(cmd)) == 0) {
2085+ cmd_id = WO_CMD_RXCNT_CTRL;
2086+ } else if (strncmp(cmd, "dbg_set", strlen(cmd)) == 0) {
2087+ cmd_id = WO_CMD_DBG_INFO;
2088+ }
2089+ } else {
2090+ dev_info(hw->dev, "usage: echo cmd='cmd_str' > wo_write\n");
2091+ dev_info(hw->dev, "cmd_str value range:\n");
2092+ dev_info(hw->dev, "\tbainfo:\n");
2093+ dev_info(hw->dev, "\tbactrl:\n");
2094+ dev_info(hw->dev, "\tfbcmdq:\n");
2095+ dev_info(hw->dev, "\tlogflush:\n");
2096+ dev_info(hw->dev, "\tcpustat.dump:\n");
2097+ dev_info(hw->dev, "\tprof_hit_dump:\n");
2098+ dev_info(hw->dev, "\trxcnt_info:\n");
2099+ dev_info(hw->dev, "\tdevinfo:\n");
2100+ dev_info(hw->dev, "\tbssinfo:\n");
2101+ dev_info(hw->dev, "\tstarec:\n");
2102+ dev_info(hw->dev, "\tstarec_ba:\n");
2103+ dev_info(hw->dev, "\tlogctrl:\n");
2104+ dev_info(hw->dev, "\tcpustat.en:\n");
2105+ dev_info(hw->dev, "\tprof_conf:\n");
2106+ dev_info(hw->dev, "\trxcnt_ctrl:\n");
2107+ dev_info(hw->dev, "\tdbg_set [level] [category]:\n");
2108+ return count;
2109+ }
2110+
2111+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, (void *)msgbuf, sizeof(struct wo_cmd_query), wait);
2112+
2113+ return count;
2114+
2115+}
2116+
2117+static const struct file_operations fops_wo_ctrl = {
2118+ .write = mtk_wed_wo_ctrl,
2119+ .open = simple_open,
2120+ .llseek = default_llseek,
2121+};
2122+
2123+void wed_wo_mcu_debugfs(struct mtk_wed_hw *hw, struct dentry *dir)
2124+{
2125+ if (!dir)
2126+ return;
2127+
2128+ debugfs_create_file("wo_write", 0600, dir, hw, &fops_wo_ctrl);
2129+}
2130+
2131diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
2132new file mode 100644
developera3f86ed2022-07-08 14:15:13 +08002133index 0000000..6a5ac76
developer8cb3ac72022-07-04 10:55:14 +08002134--- /dev/null
2135+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
2136@@ -0,0 +1,125 @@
2137+// SPDX-License-Identifier: GPL-2.0-only
2138+
2139+#ifndef __MTK_WED_MCU_H
2140+#define __MTK_WED_MCU_H
2141+
2142+#define EXCEPTION_LOG_SIZE 32768
2143+#define WOCPU_MCUSYS_RESET_ADDR 0x15194050
2144+#define WOCPU_WO0_MCUSYS_RESET_MASK 0x20
2145+#define WOCPU_WO1_MCUSYS_RESET_MASK 0x1
2146+
2147+#define WARP_INVALID_LENGTH_STATUS (-2)
2148+#define WARP_NULL_POINTER_STATUS (-3)
2149+#define WARP_INVALID_PARA_STATUS (-4)
2150+#define WARP_NOT_HANDLE_STATUS (-5)
2151+#define WARP_FAIL_STATUS (-1)
2152+#define WARP_OK_STATUS (0)
2153+#define WARP_ALREADY_DONE_STATUS (1)
2154+
2155+#define MT7986_FIRMWARE_WO_1 "mediatek/mt7986_wo_0.bin"
2156+#define MT7986_FIRMWARE_WO_2 "mediatek/mt7986_wo_1.bin"
2157+
2158+#define WOCPU_EMI_DEV_NODE "mediatek,wocpu_emi"
2159+#define WOCPU_ILM_DEV_NODE "mediatek,wocpu_ilm"
2160+#define WOCPU_DLM_DEV_NODE "mediatek,wocpu_dlm"
2161+#define WOCPU_DATA_DEV_NODE "mediatek,wocpu_data"
2162+#define WOCPU_BOOT_DEV_NODE "mediatek,wocpu_boot"
2163+
2164+#define FW_DL_TIMEOUT ((3000 * HZ) / 1000)
2165+#define WOCPU_TIMEOUT ((1000 * HZ) / 1000)
2166+
2167+#define MAX_REGION_SIZE 3
2168+
2169+#define WOX_MCU_CFG_LS_BASE 0 /*0x15194000*/
2170+
2171+#define WOX_MCU_CFG_LS_HW_VER_ADDR (WOX_MCU_CFG_LS_BASE + 0x000) // 4000
2172+#define WOX_MCU_CFG_LS_FW_VER_ADDR (WOX_MCU_CFG_LS_BASE + 0x004) // 4004
2173+#define WOX_MCU_CFG_LS_CFG_DBG1_ADDR (WOX_MCU_CFG_LS_BASE + 0x00C) // 400C
2174+#define WOX_MCU_CFG_LS_CFG_DBG2_ADDR (WOX_MCU_CFG_LS_BASE + 0x010) // 4010
2175+#define WOX_MCU_CFG_LS_WF_MCCR_ADDR (WOX_MCU_CFG_LS_BASE + 0x014) // 4014
2176+#define WOX_MCU_CFG_LS_WF_MCCR_SET_ADDR (WOX_MCU_CFG_LS_BASE + 0x018) // 4018
2177+#define WOX_MCU_CFG_LS_WF_MCCR_CLR_ADDR (WOX_MCU_CFG_LS_BASE + 0x01C) // 401C
2178+#define WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR (WOX_MCU_CFG_LS_BASE + 0x050) // 4050
2179+#define WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR (WOX_MCU_CFG_LS_BASE + 0x060) // 4060
2180+#define WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR (WOX_MCU_CFG_LS_BASE + 0x064) // 4064
2181+
2182+#define WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK BIT(5)
2183+#define WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK BIT(0)
2184+
2185+
2186+enum wo_event_id {
2187+ WO_EVT_LOG_DUMP = 0x1,
2188+ WO_EVT_PROFILING = 0x2,
2189+ WO_EVT_RXCNT_INFO = 0x3
2190+};
2191+
2192+enum wo_cmd_id {
2193+ WO_CMD_WED_CFG = 0,
2194+ WO_CMD_WED_RX_STAT,
2195+ WO_CMD_RRO_SER,
2196+ WO_CMD_DBG_INFO,
2197+ WO_CMD_DEV_INFO,
2198+ WO_CMD_BSS_INFO,
2199+ WO_CMD_STA_REC,
2200+ WO_CMD_DEV_INFO_DUMP,
2201+ WO_CMD_BSS_INFO_DUMP,
2202+ WO_CMD_STA_REC_DUMP,
2203+ WO_CMD_BA_INFO_DUMP,
2204+ WO_CMD_FBCMD_Q_DUMP,
2205+ WO_CMD_FW_LOG_CTRL,
2206+ WO_CMD_LOG_FLUSH,
2207+ WO_CMD_CHANGE_STATE,
2208+ WO_CMD_CPU_STATS_ENABLE,
2209+ WO_CMD_CPU_STATS_DUMP,
2210+ WO_CMD_EXCEPTION_INIT,
2211+ WO_CMD_PROF_CTRL,
2212+ WO_CMD_STA_BA_DUMP,
2213+ WO_CMD_BA_CTRL_DUMP,
2214+ WO_CMD_RXCNT_CTRL,
2215+ WO_CMD_RXCNT_INFO,
2216+ WO_CMD_SET_CAP,
2217+ WO_CMD_CCIF_RING_DUMP,
2218+ WO_CMD_WED_END
2219+};
2220+
2221+enum wo_state {
2222+ WO_STATE_UNDEFINED = 0x0,
2223+ WO_STATE_INIT = 0x1,
2224+ WO_STATE_ENABLE = 0x2,
2225+ WO_STATE_DISABLE = 0x3,
2226+ WO_STATE_HALT = 0x4,
2227+ WO_STATE_GATING = 0x5,
2228+ WO_STATE_SER_RESET = 0x6,
2229+ WO_STATE_WF_RESET = 0x7,
2230+ WO_STATE_END
2231+};
2232+
2233+enum wo_done_state {
2234+ WOIF_UNDEFINED = 0,
2235+ WOIF_DISABLE_DONE = 1,
2236+ WOIF_TRIGGER_ENABLE = 2,
2237+ WOIF_ENABLE_DONE = 3,
2238+ WOIF_TRIGGER_GATING = 4,
2239+ WOIF_GATING_DONE = 5,
2240+ WOIF_TRIGGER_HALT = 6,
2241+ WOIF_HALT_DONE = 7,
2242+};
2243+
2244+enum wed_dummy_cr_idx {
2245+ WED_DUMMY_CR_FWDL = 0,
2246+ WED_DUMMY_CR_WO_STATUS = 1
2247+};
2248+
2249+struct mtk_wed_fw_trailer {
2250+ u8 chip_id;
2251+ u8 eco_code;
2252+ u8 n_region;
2253+ u8 format_ver;
2254+ u8 format_flag;
2255+ u8 reserved[2];
2256+ char fw_ver[10];
2257+ char build_date[15];
2258+ u32 crc;
2259+};
2260+
2261+#endif
2262diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
developerc1b2cd12022-07-28 18:35:24 +08002263index e107de7..9d021e2 100644
developer8cb3ac72022-07-04 10:55:14 +08002264--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
2265+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
2266@@ -4,6 +4,8 @@
2267 #ifndef __MTK_WED_REGS_H
2268 #define __MTK_WED_REGS_H
2269
2270+#define MTK_WFDMA_DESC_CTRL_TO_HOST BIT(8)
2271+
2272 #if defined(CONFIG_MEDIATEK_NETSYS_V2)
2273 #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(13, 0)
2274 #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(14)
2275@@ -16,6 +18,7 @@
2276 #define MTK_WDMA_DESC_CTRL_LEN0 GENMASK(29, 16)
2277 #define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30)
2278 #define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31)
2279+#define MTK_WED_RX_BM_TOKEN GENMASK(31, 16)
2280
2281 struct mtk_wdma_desc {
2282 __le32 buf0;
developerbbca0f92022-07-26 17:26:12 +08002283@@ -31,6 +34,7 @@ struct mtk_wdma_desc {
2284 #define MTK_WED_REV_ID 0x000
2285 #define MTK_WED_REV_ID_MAJOR GENMASK(7, 0)
2286 #endif
2287+#define MTK_WED_REV_ID_MINOR GENMASK(27, 16)
2288
2289 #define MTK_WED_RESET 0x008
2290 #define MTK_WED_RESET_TX_BM BIT(0)
2291@@ -41,6 +45,8 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002292 #define MTK_WED_RESET_WED_TX_DMA BIT(12)
2293 #define MTK_WED_RESET_WDMA_RX_DRV BIT(17)
2294 #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19)
2295+#define MTK_WED_RESET_RX_RRO_QM BIT(20)
2296+#define MTK_WED_RESET_RX_ROUTE_QM BIT(21)
2297 #define MTK_WED_RESET_WED BIT(31)
2298
2299 #define MTK_WED_CTRL 0x00c
developerbbca0f92022-07-26 17:26:12 +08002300@@ -52,8 +58,12 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002301 #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
2302 #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
2303 #define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11)
2304-#define MTK_WED_CTRL_RESERVE_EN BIT(12)
2305-#define MTK_WED_CTRL_RESERVE_BUSY BIT(13)
2306+#define MTK_WED_CTRL_WED_RX_BM_EN BIT(12)
2307+#define MTK_WED_CTRL_WED_RX_BM_BUSY BIT(13)
2308+#define MTK_WED_CTRL_RX_RRO_QM_EN BIT(14)
2309+#define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15)
2310+#define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16)
2311+#define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17)
2312 #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24)
2313 #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25)
2314 #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28)
developerbbca0f92022-07-26 17:26:12 +08002315@@ -68,8 +78,8 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002316 #define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH BIT(10)
2317 #define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH BIT(11)
2318 #endif
2319-#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH BIT(12)
2320-#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH BIT(13)
2321+#define MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY BIT(12)
2322+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER BIT(13)
2323 #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16)
2324 #define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17)
2325 #define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18)
developerbbca0f92022-07-26 17:26:12 +08002326@@ -86,8 +96,8 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002327 #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
2328 MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
2329 MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
2330- MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | \
2331- MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH | \
2332+ MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY | \
2333+ MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER | \
2334 MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
2335 MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
2336 MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | \
developerbbca0f92022-07-26 17:26:12 +08002337@@ -96,6 +106,8 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002338 MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
2339
2340 #define MTK_WED_EXT_INT_MASK 0x028
2341+#define MTK_WED_EXT_INT_MASK1 0x02c
2342+#define MTK_WED_EXT_INT_MASK2 0x030
2343
2344 #define MTK_WED_STATUS 0x060
2345 #define MTK_WED_STATUS_TX GENMASK(15, 8)
developerbbca0f92022-07-26 17:26:12 +08002346@@ -183,6 +195,9 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002347
2348 #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10)
2349
2350+#define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10)
2351+
2352+#define MTK_WED_SCR0 0x3c0
2353 #define MTK_WED_WPDMA_INT_TRIGGER 0x504
2354 #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1)
2355 #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4)
developerbbca0f92022-07-26 17:26:12 +08002356@@ -239,13 +254,19 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002357
2358 #define MTK_WED_WPDMA_INT_CTRL_TX 0x530
2359 #define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN BIT(0)
2360-#define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR BIT(1)
2361+#define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR BIT(1)
2362 #define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_TRIG GENMASK(6, 2)
2363 #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_EN BIT(8)
2364 #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_CLR BIT(9)
2365 #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG GENMASK(14, 10)
2366
2367 #define MTK_WED_WPDMA_INT_CTRL_RX 0x534
2368+#define MTK_WED_WPDMA_INT_CTRL_RX0_EN BIT(0)
2369+#define MTK_WED_WPDMA_INT_CTRL_RX0_CLR BIT(1)
2370+#define MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG GENMASK(6, 2)
2371+#define MTK_WED_WPDMA_INT_CTRL_RX1_EN BIT(8)
2372+#define MTK_WED_WPDMA_INT_CTRL_RX1_CLR BIT(9)
2373+#define MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG GENMASK(14, 10)
2374
2375 #define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538
2376 #define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0)
developerc1b2cd12022-07-28 18:35:24 +08002377@@ -270,13 +291,40 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002378 #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4)
2379 #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4)
2380
2381+#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4)
2382+#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4)
2383+
2384 #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10)
2385 #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10)
developerc1b2cd12022-07-28 18:35:24 +08002386+#define MTK_WED_WPDMA_RING_RX_DATA(_n) (0x730 + (_n) * 0x10)
developer8cb3ac72022-07-04 10:55:14 +08002387+
2388+#define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c
2389+#define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0)
2390+#define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7)
2391+#define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24)
2392+
2393+#define MTK_WED_WPDMA_RX_D_RST_IDX 0x760
developerc1b2cd12022-07-28 18:35:24 +08002394+#define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16)
2395+#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24)
developer8cb3ac72022-07-04 10:55:14 +08002396+
2397+#define MTK_WED_WPDMA_RX_GLO_CFG 0x76c
2398+#define MTK_WED_WPDMA_RX_RING 0x770
2399+
2400+#define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4)
2401+#define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4)
2402+#define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c
2403+
2404+#define MTK_WED_WDMA_RING_TX 0x800
2405+
2406+#define MTK_WED_WDMA_TX_MIB 0x810
2407+
2408+
2409 #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10)
2410 #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4)
2411
2412 #define MTK_WED_WDMA_GLO_CFG 0xa04
2413 #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0)
2414+#define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1)
2415 #define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2)
2416 #define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3)
2417 #define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4)
developerc1b2cd12022-07-28 18:35:24 +08002418@@ -320,6 +368,20 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002419 #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4)
2420 #define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4)
2421
2422+#define MTK_WED_RX_BM_RX_DMAD 0xd80
2423+#define MTK_WED_RX_BM_RX_DMAD_SDL0 GENMASK(13, 0)
2424+
2425+#define MTK_WED_RX_BM_BASE 0xd84
2426+#define MTK_WED_RX_BM_INIT_PTR 0xd88
2427+#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0)
2428+#define MTK_WED_RX_BM_INIT_SW_TAIL BIT(16)
2429+
2430+#define MTK_WED_RX_PTR 0xd8c
2431+
2432+#define MTK_WED_RX_BM_DYN_ALLOC_TH 0xdb4
2433+#define MTK_WED_RX_BM_DYN_ALLOC_TH_H GENMASK(31, 16)
2434+#define MTK_WED_RX_BM_DYN_ALLOC_TH_L GENMASK(15, 0)
2435+
2436 #define MTK_WED_RING_OFS_BASE 0x00
2437 #define MTK_WED_RING_OFS_COUNT 0x04
2438 #define MTK_WED_RING_OFS_CPU_IDX 0x08
developerc1b2cd12022-07-28 18:35:24 +08002439@@ -330,12 +392,13 @@ struct mtk_wdma_desc {
developera3f86ed2022-07-08 14:15:13 +08002440
2441 #define MTK_WDMA_GLO_CFG 0x204
2442 #define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0)
2443+#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1)
2444 #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2)
2445+#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3)
2446 #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26)
2447 #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27)
2448 #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28)
developerc1b2cd12022-07-28 18:35:24 +08002449
2450-
2451 #define MTK_WDMA_RESET_IDX 0x208
2452 #define MTK_WDMA_RESET_IDX_TX GENMASK(3, 0)
2453 #define MTK_WDMA_RESET_IDX_RX GENMASK(17, 16)
2454@@ -359,4 +422,70 @@ struct mtk_wdma_desc {
developer8cb3ac72022-07-04 10:55:14 +08002455 /* DMA channel mapping */
2456 #define HIFSYS_DMA_AG_MAP 0x008
2457
2458+#define MTK_WED_RTQM_GLO_CFG 0xb00
2459+#define MTK_WED_RTQM_BUSY BIT(1)
2460+#define MTK_WED_RTQM_Q_RST BIT(2)
2461+#define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5)
2462+#define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20)
2463+
2464+#define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4)
2465+#define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4)
2466+#define MTK_WED_RTQM_Q2N_MIB 0xb80
2467+#define MTK_WED_RTQM_Q2H_MIB(_n) (0xb84 + (_n) * 0x4)
2468+
2469+#define MTK_WED_RTQM_Q2B_MIB 0xb8c
2470+#define MTK_WED_RTQM_PFDBK_MIB 0xb90
2471+
2472+#define MTK_WED_RROQM_GLO_CFG 0xc04
2473+#define MTK_WED_RROQM_RST_IDX 0xc08
2474+#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0)
2475+#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4)
2476+
2477+#define MTK_WED_RROQM_MIOD_CTRL0 0xc40
2478+#define MTK_WED_RROQM_MIOD_CTRL1 0xc44
2479+#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0)
2480+
2481+#define MTK_WED_RROQM_MIOD_CTRL2 0xc48
2482+#define MTK_WED_RROQM_MIOD_CTRL3 0xc4c
2483+
2484+#define MTK_WED_RROQM_FDBK_CTRL0 0xc50
2485+#define MTK_WED_RROQM_FDBK_CTRL1 0xc54
2486+#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0)
2487+
2488+#define MTK_WED_RROQM_FDBK_CTRL2 0xc58
2489+
2490+#define MTK_WED_RROQ_BASE_L 0xc80
2491+#define MTK_WED_RROQ_BASE_H 0xc84
2492+
developer8cb3ac72022-07-04 10:55:14 +08002493+#define MTK_WED_RROQM_MIOD_CFG 0xc8c
2494+#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0)
2495+#define MTK_WED_RROQM_MIOD_MOD_DW GENMASK(13, 8)
2496+#define MTK_WED_RROQM_MIOD_ENTRY_DW GENMASK(22, 16)
2497+
2498+#define MTK_WED_RROQM_MID_MIB 0xcc0
2499+#define MTK_WED_RROQM_MOD_MIB 0xcc4
2500+#define MTK_WED_RROQM_MOD_COHERENT_MIB 0xcc8
2501+#define MTK_WED_RROQM_FDBK_MIB 0xcd0
2502+#define MTK_WED_RROQM_FDBK_COHERENT_MIB 0xcd4
2503+#define MTK_WED_RROQM_FDBK_IND_MIB 0xce0
2504+#define MTK_WED_RROQM_FDBK_ENQ_MIB 0xce4
2505+#define MTK_WED_RROQM_FDBK_ANC_MIB 0xce8
2506+#define MTK_WED_RROQM_FDBK_ANC2H_MIB 0xcec
2507+
2508+#define MTK_WED_RX_BM_RX_DMAD 0xd80
2509+#define MTK_WED_RX_BM_BASE 0xd84
2510+#define MTK_WED_RX_BM_INIT_PTR 0xd88
2511+#define MTK_WED_RX_BM_PTR 0xd8c
2512+#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16)
2513+#define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0)
2514+
2515+#define MTK_WED_RX_BM_BLEN 0xd90
2516+#define MTK_WED_RX_BM_STS 0xd94
2517+#define MTK_WED_RX_BM_INTF2 0xd98
2518+#define MTK_WED_RX_BM_INTF 0xd9c
2519+#define MTK_WED_RX_BM_ERR_STS 0xda8
2520+
2521+#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000
2522+#define MTK_WED_PCIE_INT_MASK 0x0
2523+
2524 #endif
2525diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.c b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
2526new file mode 100644
developera3f86ed2022-07-08 14:15:13 +08002527index 0000000..e101f17
developer8cb3ac72022-07-04 10:55:14 +08002528--- /dev/null
2529+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
developera3f86ed2022-07-08 14:15:13 +08002530@@ -0,0 +1,588 @@
developer8cb3ac72022-07-04 10:55:14 +08002531+// SPDX-License-Identifier: GPL-2.0-only
2532+
2533+#include <linux/kernel.h>
2534+#include <linux/bitfield.h>
2535+#include <linux/dma-mapping.h>
2536+#include <linux/skbuff.h>
2537+#include <linux/of_platform.h>
2538+#include <linux/interrupt.h>
2539+#include <linux/of_address.h>
2540+#include <linux/iopoll.h>
2541+#include <linux/soc/mediatek/mtk_wed.h>
2542+#include "mtk_wed.h"
2543+#include "mtk_wed_regs.h"
2544+#include "mtk_wed_ccif.h"
2545+#include "mtk_wed_wo.h"
2546+
2547+struct wed_wo_profile_stat profile_total[6] = {
2548+ {1001, 0},
2549+ {1501, 0},
2550+ {3001, 0},
2551+ {5001, 0},
2552+ {10001, 0},
2553+ {0xffffffff, 0}
2554+};
2555+
2556+struct wed_wo_profile_stat profiling_mod[6] = {
2557+ {1001, 0},
2558+ {1501, 0},
2559+ {3001, 0},
2560+ {5001, 0},
2561+ {10001, 0},
2562+ {0xffffffff, 0}
2563+};
2564+
2565+struct wed_wo_profile_stat profiling_rro[6] = {
2566+ {1001, 0},
2567+ {1501, 0},
2568+ {3001, 0},
2569+ {5001, 0},
2570+ {10001, 0},
2571+ {0xffffffff, 0}
2572+};
2573+
2574+static void
2575+woif_q_sync_idx(struct mtk_wed_wo *wo, struct wed_wo_queue *q)
2576+{
2577+ woccif_w32(wo, q->regs->desc_base, q->desc_dma);
2578+ woccif_w32(wo, q->regs->ring_size, q->ndesc);
2579+
2580+ /* wo fw start from 1 */
developera3f86ed2022-07-08 14:15:13 +08002581+ q->tail = q->head = 1;
developer8cb3ac72022-07-04 10:55:14 +08002582+}
2583+
2584+static void
2585+woif_q_reset(struct mtk_wed_wo *dev, struct wed_wo_queue *q)
2586+{
2587+
2588+ if (!q || !q->ndesc)
2589+ return;
2590+
2591+ woccif_w32(dev, q->regs->cpu_idx, 0);
2592+
2593+ woif_q_sync_idx(dev, q);
2594+}
2595+
2596+static void
2597+woif_q_kick(struct mtk_wed_wo *wo, struct wed_wo_queue *q, int offset)
2598+{
2599+ wmb();
2600+ woccif_w32(wo, q->regs->cpu_idx, q->head + offset);
2601+}
2602+
2603+static int
2604+woif_q_rx_fill(struct mtk_wed_wo *wo, struct wed_wo_queue *q)
2605+{
2606+ int len = q->buf_size, frames = 0;
2607+ struct wed_wo_queue_entry *entry;
2608+ struct wed_wo_desc *desc;
2609+ dma_addr_t addr;
2610+ u32 ctrl = 0;
2611+ void *buf;
2612+
2613+ if (!q->ndesc)
2614+ return 0;
2615+
2616+ spin_lock_bh(&q->lock);
2617+
2618+ while (q->queued < q->ndesc - 1) {
2619+
2620+ buf = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC);
2621+ if (!buf)
2622+ break;
2623+
2624+ addr = dma_map_single(wo->hw->dev, buf, len, DMA_FROM_DEVICE);
2625+ if (unlikely(dma_mapping_error(wo->hw->dev, addr))) {
2626+ skb_free_frag(buf);
2627+ break;
2628+ }
2629+ dma_sync_single_for_cpu(wo->hw->dev, addr, len,
2630+ DMA_TO_DEVICE);
2631+ desc = &q->desc[q->head];
2632+ entry = &q->entry[q->head];
2633+
2634+ entry->dma_addr = addr;
2635+ entry->dma_len = len;
2636+
2637+ ctrl = FIELD_PREP(WED_CTL_SD_LEN0, entry->dma_len);
2638+ ctrl |= WED_CTL_LAST_SEC0;
2639+
2640+ WRITE_ONCE(desc->buf0, cpu_to_le32(addr));
2641+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
2642+ dma_sync_single_for_device(wo->hw->dev, addr, len,
2643+ DMA_TO_DEVICE);
2644+ q->queued++;
2645+ q->entry[q->head].buf = buf;
2646+
2647+ q->head = (q->head + 1) % q->ndesc;
2648+ frames++;
2649+ }
2650+
2651+ spin_unlock_bh(&q->lock);
2652+
2653+ return frames;
2654+}
2655+
2656+static void
2657+woif_q_rx_fill_process(struct mtk_wed_wo *wo, struct wed_wo_queue *q)
2658+{
2659+ if(woif_q_rx_fill(wo, q))
2660+ woif_q_kick(wo, q, -1);
2661+}
2662+
2663+static int
2664+woif_q_alloc(struct mtk_wed_wo *dev, struct wed_wo_queue *q,
2665+ int n_desc, int bufsize, int idx,
2666+ struct wed_wo_queue_regs *regs)
2667+{
2668+ struct wed_wo_queue_regs *q_regs;
2669+ int size;
2670+
2671+ spin_lock_init(&q->lock);
2672+ spin_lock_init(&q->cleanup_lock);
2673+
2674+ q_regs = devm_kzalloc(dev->hw->dev, sizeof(*q_regs), GFP_KERNEL);
2675+
2676+ q_regs->desc_base = regs->desc_base;
2677+ q_regs->ring_size = regs->ring_size;
2678+ q_regs->cpu_idx = regs->cpu_idx;
2679+ q_regs->dma_idx = regs->dma_idx;
2680+
2681+ q->regs = q_regs;
2682+ q->ndesc = n_desc;
2683+ q->buf_size = bufsize;
2684+
2685+ size = q->ndesc * sizeof(struct wed_wo_desc);
2686+
2687+ q->desc = dmam_alloc_coherent(dev->hw->dev, size,
2688+ &q->desc_dma, GFP_KERNEL);
2689+ if (!q->desc)
2690+ return -ENOMEM;
2691+
2692+ size = q->ndesc * sizeof(*q->entry);
2693+ q->entry = devm_kzalloc(dev->hw->dev, size, GFP_KERNEL);
2694+ if (!q->entry)
2695+ return -ENOMEM;
2696+
2697+ if (idx == 0)
2698+ woif_q_reset(dev, &dev->q_tx);
2699+
2700+ return 0;
2701+}
2702+
2703+static void
developera3f86ed2022-07-08 14:15:13 +08002704+woif_q_free(struct mtk_wed_wo *dev, struct wed_wo_queue *q)
2705+{
2706+ int size;
2707+
2708+ if (!q)
2709+ return;
2710+
2711+ if (!q->desc)
2712+ return;
2713+
2714+ woccif_w32(dev, q->regs->cpu_idx, 0);
2715+
2716+ size = q->ndesc * sizeof(struct wed_wo_desc);
2717+ dma_free_coherent(dev->hw->dev, size, q->desc, q->desc_dma);
2718+}
2719+
2720+static void
developer8cb3ac72022-07-04 10:55:14 +08002721+woif_q_tx_clean(struct mtk_wed_wo *wo, struct wed_wo_queue *q, bool flush)
2722+{
2723+ int last;
2724+
2725+ if (!q || !q->ndesc)
2726+ return;
2727+
2728+ spin_lock_bh(&q->cleanup_lock);
2729+ if (flush)
2730+ last = -1;
2731+ else
2732+ last = readl(&q->regs->dma_idx);
2733+
2734+ while (q->queued > 0 && q->tail != last) {
2735+ struct wed_wo_queue_entry *e;
2736+
2737+ e = &q->entry[q->tail];
2738+
2739+ dma_unmap_single(wo->hw->dev, e->dma_addr, e->dma_len,
2740+ DMA_TO_DEVICE);
2741+
2742+ if (e->skb)
2743+ dev_kfree_skb(e->skb);
2744+
2745+ memset(e, 0, sizeof(*e));
2746+
2747+ spin_lock_bh(&q->lock);
2748+ q->tail = (q->tail + 1) % q->ndesc;
2749+ q->queued--;
2750+ spin_unlock_bh(&q->lock);
2751+
2752+ if (!flush && q->tail == last)
2753+ last = readl(&q->regs->dma_idx);
2754+ }
2755+ spin_unlock_bh(&q->cleanup_lock);
2756+
2757+ if (flush) {
2758+ spin_lock_bh(&q->lock);
2759+ woif_q_sync_idx(wo, q);
2760+ woif_q_kick(wo, q, 0);
2761+ spin_unlock_bh(&q->lock);
2762+ }
2763+}
2764+
developer8cb3ac72022-07-04 10:55:14 +08002765+static void *
2766+woif_q_deq(struct mtk_wed_wo *wo, struct wed_wo_queue *q, bool flush,
2767+ int *len, u32 *info, bool *more)
2768+{
2769+ int buf_len = SKB_WITH_OVERHEAD(q->buf_size);
2770+ struct wed_wo_queue_entry *e;
2771+ struct wed_wo_desc *desc;
2772+ int idx = q->tail;
2773+ void *buf;
2774+
2775+ *more = false;
2776+ if (!q->queued)
2777+ return NULL;
2778+
2779+ if (flush)
2780+ q->desc[idx].ctrl |= cpu_to_le32(WED_CTL_DMA_DONE);
2781+ else if (!(q->desc[idx].ctrl & cpu_to_le32(WED_CTL_DMA_DONE)))
2782+ return NULL;
2783+
2784+ q->tail = (q->tail + 1) % q->ndesc;
2785+ q->queued--;
2786+
2787+ desc = &q->desc[idx];
2788+ e = &q->entry[idx];
2789+
2790+ buf = e->buf;
2791+ if (len) {
2792+ u32 ctl = le32_to_cpu(READ_ONCE(desc->ctrl));
2793+ *len = FIELD_GET(WED_CTL_SD_LEN0, ctl);
2794+ *more = !(ctl & WED_CTL_LAST_SEC0);
2795+ }
2796+
2797+ if (info)
2798+ *info = le32_to_cpu(desc->info);
2799+ if(buf)
2800+ dma_unmap_single(wo->hw->dev, e->dma_addr, buf_len,
2801+ DMA_FROM_DEVICE);
2802+ e->skb = NULL;
2803+
2804+ return buf;
2805+}
2806+
developera3f86ed2022-07-08 14:15:13 +08002807+static void
2808+woif_q_rx_clean(struct mtk_wed_wo *wo, struct wed_wo_queue *q)
2809+{
2810+ struct page *page;
2811+ void *buf;
2812+ bool more;
2813+
2814+ if (!q->ndesc)
2815+ return;
2816+
2817+ spin_lock_bh(&q->lock);
2818+ do {
2819+ buf = woif_q_deq(wo, q, true, NULL, NULL, &more);
2820+ if (!buf)
2821+ break;
2822+
2823+ skb_free_frag(buf);
2824+ } while (1);
2825+ spin_unlock_bh(&q->lock);
2826+
2827+ if (!q->rx_page.va)
2828+ return;
2829+
2830+ page = virt_to_page(q->rx_page.va);
2831+ __page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
2832+ memset(&q->rx_page, 0, sizeof(q->rx_page));
2833+
2834+}
2835+
developer8cb3ac72022-07-04 10:55:14 +08002836+static int
2837+woif_q_init(struct mtk_wed_wo *dev,
2838+ int (*poll)(struct napi_struct *napi, int budget))
2839+{
2840+ init_dummy_netdev(&dev->napi_dev);
2841+ snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s",
2842+ "woif_q");
2843+
2844+ if (dev->q_rx.ndesc) {
2845+ netif_napi_add(&dev->napi_dev, &dev->napi, poll, 64);
2846+ woif_q_rx_fill(dev, &dev->q_rx);
2847+ woif_q_reset(dev, &dev->q_rx);
2848+ napi_enable(&dev->napi);
2849+ }
2850+
2851+ return 0;
2852+}
2853+
2854+void woif_q_rx_skb(struct mtk_wed_wo *wo, struct sk_buff *skb)
2855+{
2856+ struct wed_cmd_hdr *hdr = (struct wed_cmd_hdr *)skb->data;
2857+ int ret;
2858+
2859+ ret = mtk_wed_mcu_cmd_sanity_check(wo, skb);
2860+ if (ret)
2861+ goto free_skb;
2862+
2863+ if (WED_WO_CMD_FLAG_IS_RSP(hdr))
2864+ mtk_wed_mcu_rx_event(wo, skb);
2865+ else
2866+ mtk_wed_mcu_rx_unsolicited_event(wo, skb);
2867+
2868+ return;
2869+free_skb:
2870+ dev_kfree_skb(skb);
2871+}
2872+
2873+static int
2874+woif_q_tx_skb(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
2875+ struct sk_buff *skb)
2876+{
2877+ struct wed_wo_queue_entry *entry;
2878+ struct wed_wo_desc *desc;
2879+ int len, ret, idx = -1;
2880+ dma_addr_t addr;
2881+ u32 ctrl = 0;
2882+
2883+ len = skb->len;
2884+ addr = dma_map_single(wo->hw->dev, skb->data, len, DMA_TO_DEVICE);
2885+ if (unlikely(dma_mapping_error(wo->hw->dev, addr)))
2886+ goto error;
2887+
2888+ /* packet tx, force trigger tx clean. */
2889+ if (q->queued + MTK_WED_WO_TXQ_FREE_THR >= q->ndesc - 1)
2890+ woif_q_tx_clean(wo, q, false);
2891+
2892+ if (q->queued + 1 >= q->ndesc - 1) {
2893+ ret = -ENOMEM;
2894+ goto error;
2895+ }
2896+
2897+ spin_lock_bh(&q->lock);
2898+
2899+ dma_sync_single_for_device(wo->hw->dev, addr, len,
2900+ DMA_TO_DEVICE);
2901+
2902+ idx = q->head;
2903+
2904+ desc = &q->desc[idx];
2905+ entry = &q->entry[idx];
2906+
2907+ entry->dma_addr = addr;
2908+ entry->dma_len = len;
2909+
2910+ ctrl = FIELD_PREP(WED_CTL_SD_LEN0, len);
2911+ ctrl |= WED_CTL_LAST_SEC0;
2912+ ctrl |= WED_CTL_DMA_DONE;
2913+
2914+ WRITE_ONCE(desc->buf0, cpu_to_le32(addr));
2915+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
2916+
2917+ q->queued++;
2918+ q->entry[idx].skb = skb;
2919+
2920+ woif_q_kick(wo, q, 0);
2921+ wo->drv_ops->kickout(wo);
2922+
2923+ q->head = (q->head + 1) % q->ndesc;
2924+ spin_unlock_bh(&q->lock);
2925+ return 0;
2926+
2927+error:
2928+ dev_kfree_skb(skb);
2929+ return -ENOMEM;
2930+}
2931+
2932+static const struct wed_wo_queue_ops wo_queue_ops = {
2933+ .init = woif_q_init,
2934+ .alloc = woif_q_alloc,
developera3f86ed2022-07-08 14:15:13 +08002935+ .free = woif_q_free,
developer8cb3ac72022-07-04 10:55:14 +08002936+ .reset = woif_q_reset,
2937+ .tx_skb = woif_q_tx_skb,
2938+ .tx_clean = woif_q_tx_clean,
2939+ .rx_clean = woif_q_rx_clean,
2940+ .kick = woif_q_kick,
2941+};
2942+
2943+static int
2944+mtk_wed_wo_rx_process(struct mtk_wed_wo *wo, struct wed_wo_queue *q, int budget)
2945+{
2946+ int len, data_len, done = 0;
2947+ struct sk_buff *skb;
2948+ unsigned char *data;
2949+ bool more;
2950+
2951+ while (done < budget) {
2952+ u32 info;
2953+
2954+ data = woif_q_deq(wo, q, false, &len, &info, &more);
2955+ if (!data)
2956+ break;
2957+
2958+ data_len = SKB_WITH_OVERHEAD(q->buf_size);
2959+
2960+ if (data_len < len) {
2961+ skb_free_frag(data);
2962+ continue;
2963+ }
2964+
2965+ skb = build_skb(data, q->buf_size);
2966+ if (!skb) {
2967+ skb_free_frag(data);
2968+ continue;
2969+ }
2970+
2971+ __skb_put(skb, len);
2972+ done++;
2973+
2974+ woif_q_rx_skb(wo, skb);
2975+ }
2976+
2977+ woif_q_rx_fill_process(wo, q);
2978+
2979+ return done;
2980+}
2981+
2982+void mtk_wed_wo_set_isr_mask(struct mtk_wed_wo *wo, bool set,
2983+ u32 clear, u32 val)
2984+{
2985+ unsigned long flags;
2986+
2987+ spin_lock_irqsave(&wo->ccif.irq_lock, flags);
2988+ wo->ccif.irqmask &= ~clear;
2989+ wo->ccif.irqmask |= val;
2990+ if (set)
2991+ wo->drv_ops->set_isr(wo, wo->ccif.irqmask);
2992+
2993+ spin_unlock_irqrestore(&wo->ccif.irq_lock, flags);
2994+}
2995+
2996+static inline void mtk_wed_wo_set_ack_mask(struct mtk_wed_wo *wo, u32 mask)
2997+{
2998+ wo->drv_ops->set_ack(wo, mask);
2999+}
3000+
3001+static void mtk_wed_wo_poll_complete(struct mtk_wed_wo *wo)
3002+{
3003+ mtk_wed_wo_set_ack_mask(wo, wo->ccif.q_int_mask);
3004+ mtk_wed_wo_isr_enable(wo, wo->ccif.q_int_mask);
3005+}
3006+
3007+int mtk_wed_wo_rx_poll(struct napi_struct *napi, int budget)
3008+{
3009+ struct mtk_wed_wo *wo;
3010+ int done = 0, cur;
3011+
3012+ wo = container_of(napi->dev, struct mtk_wed_wo, napi_dev);
3013+
3014+ rcu_read_lock();
3015+
3016+ do {
3017+ cur = mtk_wed_wo_rx_process(wo, &wo->q_rx, budget - done);
3018+ /* rx packet handle */
3019+ done += cur;
3020+ } while (cur && done < budget);
3021+
3022+ rcu_read_unlock();
3023+
3024+ if (done < budget && napi_complete(napi))
3025+ mtk_wed_wo_poll_complete(wo);
3026+
3027+ return done;
3028+}
3029+
3030+static void mtk_wed_wo_isr_tasklet(unsigned long data)
3031+{
3032+ struct mtk_wed_wo *wo = (struct mtk_wed_wo *)data;
3033+ u32 intr, mask;
3034+
3035+ /* disable isr */
3036+ wo->drv_ops->set_isr(wo, 0);
3037+
3038+ intr = wo->drv_ops->get_csr(wo);
3039+ intr &= wo->ccif.irqmask;
3040+
3041+ mask = intr & (wo->ccif.q_int_mask | wo->ccif.q_exep_mask);
3042+ mtk_wed_wo_isr_disable(wo, mask);
3043+
3044+ if (intr & wo->ccif.q_int_mask)
3045+ napi_schedule(&wo->napi);
3046+
3047+ if (intr & wo->ccif.q_exep_mask) {
3048+ /* todo */
3049+ }
3050+}
3051+
3052+static irqreturn_t mtk_wed_wo_isr_handler(int irq, void *wo_instance)
3053+{
3054+ struct mtk_wed_wo *wo = wo_instance;
3055+
3056+ wo->drv_ops->set_isr(wo, 0);
3057+
3058+ tasklet_schedule(&wo->irq_tasklet);
3059+
3060+ return IRQ_HANDLED;
3061+}
3062+
3063+int mtk_wed_wo_init(struct mtk_wed_hw *hw)
3064+{
3065+ struct mtk_wed_wo *wo;
3066+ int ret = 0;
3067+
3068+ wo = kzalloc(sizeof(struct mtk_wed_wo), GFP_KERNEL);
3069+ if (!wo)
3070+ return -ENOMEM;
3071+
3072+ wo->hw = hw;
3073+ wo->queue_ops = &wo_queue_ops;
3074+ hw->wed_wo = wo;
3075+
3076+ tasklet_init(&wo->irq_tasklet, mtk_wed_wo_isr_tasklet,
3077+ (unsigned long)wo);
3078+
3079+ skb_queue_head_init(&wo->mcu.res_q);
3080+ init_waitqueue_head(&wo->mcu.wait);
3081+ mutex_init(&wo->mcu.mutex);
3082+
3083+ ret = wed_wo_hardware_init(wo, mtk_wed_wo_isr_handler);
3084+ if (ret)
3085+ goto error;
3086+
3087+ /* fw download */
3088+ ret = wed_wo_mcu_init(wo);
3089+ if (ret)
3090+ goto error;
3091+
3092+ ret = mtk_wed_exception_init(wo);
3093+ if (ret)
3094+ goto error;
3095+
3096+ return ret;
3097+
3098+error:
3099+ kfree(wo);
3100+
3101+ return ret;
3102+}
3103+
3104+void mtk_wed_wo_exit(struct mtk_wed_hw *hw)
3105+{
developer8cb3ac72022-07-04 10:55:14 +08003106+ struct mtk_wed_wo *wo = hw->wed_wo;
3107+
developera3f86ed2022-07-08 14:15:13 +08003108+ wed_wo_hardware_exit(wo);
3109+
developer8cb3ac72022-07-04 10:55:14 +08003110+ if (wo->exp.log) {
3111+ dma_unmap_single(wo->hw->dev, wo->exp.phys, wo->exp.log_size, DMA_FROM_DEVICE);
3112+ kfree(wo->exp.log);
3113+ }
3114+
developera3f86ed2022-07-08 14:15:13 +08003115+ wo->hw = NULL;
3116+ memset(wo, 0, sizeof(*wo));
3117+ kfree(wo);
developer8cb3ac72022-07-04 10:55:14 +08003118+}
3119diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
3120new file mode 100644
developera3f86ed2022-07-08 14:15:13 +08003121index 0000000..d962e3a
developer8cb3ac72022-07-04 10:55:14 +08003122--- /dev/null
3123+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
developera3f86ed2022-07-08 14:15:13 +08003124@@ -0,0 +1,336 @@
developer8cb3ac72022-07-04 10:55:14 +08003125+// SPDX-License-Identifier: GPL-2.0-only
3126+/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
3127+
3128+#ifndef __MTK_WED_WO_H
3129+#define __MTK_WED_WO_H
3130+
3131+#include <linux/netdevice.h>
3132+#include <linux/skbuff.h>
3133+#include "mtk_wed.h"
3134+
3135+#define WED_CTL_SD_LEN1 GENMASK(13, 0)
3136+#define WED_CTL_LAST_SEC1 BIT(14)
3137+#define WED_CTL_BURST BIT(15)
3138+#define WED_CTL_SD_LEN0_SHIFT 16
3139+#define WED_CTL_SD_LEN0 GENMASK(29, 16)
3140+#define WED_CTL_LAST_SEC0 BIT(30)
3141+#define WED_CTL_DMA_DONE BIT(31)
3142+#define WED_INFO_WINFO GENMASK(15, 0)
3143+
3144+#define MTK_WED_WO_TXQ_FREE_THR 10
3145+
3146+#define WED_WO_PROFILE_MAX_LVL 6
3147+
3148+
3149+enum mtk_wed_fw_region_id {
3150+ WO_REGION_EMI = 0,
3151+ WO_REGION_ILM,
3152+ WO_REGION_DATA,
3153+ WO_REGION_BOOT,
3154+ __WO_REGION_MAX
3155+};
3156+
3157+struct wed_wo_profile_stat {
3158+ u32 bound;
3159+ u32 record;
3160+};
3161+
3162+#define PROFILE_STAT(record, val) do { \
3163+ u8 lvl = 0; \
3164+ while (lvl < WED_WO_PROFILE_MAX_LVL) { \
3165+ if (val < record[lvl].bound) { \
3166+ record[lvl].record++; \
3167+ break; \
3168+ } \
3169+ lvl++; \
3170+ } \
3171+ } while (0)
3172+
3173+/* align with wo report structure */
3174+struct wed_wo_log {
3175+ u32 sn;
3176+ u32 total;
3177+ u32 rro;
3178+ u32 mod;
3179+};
3180+
3181+struct wed_wo_rxcnt {
3182+ u16 wlan_idx;
3183+ u16 tid;
3184+ u32 rx_pkt_cnt;
3185+ u32 rx_byte_cnt;
3186+ u32 rx_err_cnt;
3187+ u32 rx_drop_cnt;
3188+};
3189+
3190+struct wed_wo_queue {
3191+ struct wed_wo_queue_regs *regs;
3192+
3193+ spinlock_t lock;
3194+ spinlock_t cleanup_lock;
3195+ struct wed_wo_queue_entry *entry;
3196+ struct wed_wo_desc *desc;
3197+
3198+ u16 first;
3199+ u16 head;
3200+ u16 tail;
3201+ int ndesc;
3202+ int queued;
3203+ int buf_size;
3204+
3205+ u8 hw_idx;
3206+ u8 qid;
3207+ u8 flags;
3208+
3209+ dma_addr_t desc_dma;
3210+ struct page_frag_cache rx_page;
3211+};
3212+
3213+
3214+struct wed_wo_mmio {
3215+ struct regmap *regs;
3216+
3217+ spinlock_t irq_lock;
3218+ u8 irq;
3219+ u32 irqmask;
3220+
3221+ u32 q_int_mask;
3222+ u32 q_exep_mask;
3223+};
3224+
3225+struct wed_wo_mcu {
3226+ struct mutex mutex;
3227+ u32 msg_seq;
3228+ int timeout;
3229+
3230+ struct sk_buff_head res_q;
3231+ wait_queue_head_t wait;
3232+};
3233+
3234+struct wed_wo_exception {
3235+ void* log;
3236+ int log_size;
3237+ dma_addr_t phys;
3238+};
3239+
3240+struct wed_wo_queue_regs {
3241+ u32 desc_base;
3242+ u32 ring_size;
3243+ u32 cpu_idx;
3244+ u32 dma_idx;
3245+};
3246+
3247+struct wed_wo_desc {
3248+ __le32 buf0;
3249+ __le32 ctrl;
3250+ __le32 buf1;
3251+ __le32 info;
3252+ __le32 reserved[4];
3253+} __packed __aligned(32);
3254+
3255+struct wed_wo_queue_entry {
3256+ union {
3257+ void *buf;
3258+ struct sk_buff *skb;
3259+ };
3260+
3261+ u32 dma_addr;
3262+ u16 dma_len;
3263+ u16 wcid;
3264+ bool skip_buf0:1;
3265+ bool skip_buf1:1;
3266+ bool done:1;
3267+};
3268+
3269+struct wo_cmd_rxcnt_t {
3270+ u16 wlan_idx;
3271+ u16 tid;
3272+ u32 rx_pkt_cnt;
3273+ u32 rx_byte_cnt;
3274+ u32 rx_err_cnt;
3275+ u32 rx_drop_cnt;
3276+};
3277+
3278+struct wo_cmd_query {
3279+ u32 query0;
3280+ u32 query1;
3281+};
3282+
3283+struct wed_cmd_hdr {
3284+ /*DW0*/
3285+ u8 ver;
3286+ u8 cmd_id;
3287+ u16 length;
3288+
3289+ /*DW1*/
3290+ u16 uni_id;
3291+ u16 flag;
3292+
3293+ /*DW2*/
3294+ int status;
3295+
3296+ /*DW3*/
3297+ u8 reserved[20];
3298+};
3299+
3300+struct mtk_wed_fw_region {
3301+ void *addr;
3302+ u32 addr_pa;
3303+ u32 size;
3304+ u32 shared;
3305+};
3306+
3307+struct wed_wo_queue_ops;
3308+struct wed_wo_drv_ops;
3309+struct wed_wo_mcu_ops;
3310+
3311+struct wo_rx_total_cnt {
3312+ u64 rx_pkt_cnt;
3313+ u64 rx_byte_cnt;
3314+ u64 rx_err_cnt;
3315+ u64 rx_drop_cnt;
3316+};
3317+
3318+struct mtk_wed_wo {
3319+ struct mtk_wed_hw *hw;
3320+
3321+ struct wed_wo_mmio ccif;
3322+ struct wed_wo_mcu mcu;
3323+ struct wed_wo_exception exp;
3324+
3325+ const struct wed_wo_drv_ops *drv_ops;
3326+ const struct wed_wo_mcu_ops *mcu_ops;
3327+ const struct wed_wo_queue_ops *queue_ops;
3328+
3329+ struct net_device napi_dev;
3330+ spinlock_t rx_lock;
3331+ struct napi_struct napi;
3332+ struct sk_buff_head rx_skb;
3333+ struct wed_wo_queue q_rx;
3334+ struct tasklet_struct irq_tasklet;
3335+
3336+ struct wed_wo_queue q_tx;
3337+
3338+ struct mtk_wed_fw_region region[__WO_REGION_MAX];
3339+
3340+ struct wed_wo_profile_stat total[WED_WO_PROFILE_MAX_LVL];
3341+ struct wed_wo_profile_stat mod[WED_WO_PROFILE_MAX_LVL];
3342+ struct wed_wo_profile_stat rro[WED_WO_PROFILE_MAX_LVL];
3343+ char dirname[4];
3344+ struct wo_rx_total_cnt wo_rxcnt[8][544];
3345+};
3346+
3347+struct wed_wo_queue_ops {
3348+ int (*init)(struct mtk_wed_wo *wo,
3349+ int (*poll)(struct napi_struct *napi, int budget));
3350+
3351+ int (*alloc)(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
3352+ int idx, int n_desc, int bufsize,
3353+ struct wed_wo_queue_regs *regs);
developera3f86ed2022-07-08 14:15:13 +08003354+ void (*free)(struct mtk_wed_wo *wo, struct wed_wo_queue *q);
developer8cb3ac72022-07-04 10:55:14 +08003355+ void (*reset)(struct mtk_wed_wo *wo, struct wed_wo_queue *q);
3356+
3357+ int (*tx_skb)(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
3358+ struct sk_buff *skb);
3359+ int (*tx_skb1)(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
3360+ u8 *msg, u32 msg_len);
3361+ void (*tx_clean)(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
3362+ bool flush);
3363+
3364+ void (*rx_clean)(struct mtk_wed_wo *wo, struct wed_wo_queue *q);
3365+
3366+ void (*kick)(struct mtk_wed_wo *wo, struct wed_wo_queue *q, int offset);
3367+};
3368+
3369+struct wed_wo_drv_ops {
3370+ void (*kickout)(struct mtk_wed_wo *wo);
3371+ void (*set_ack)(struct mtk_wed_wo *wo, u32 mask);
3372+ void (*set_isr)(struct mtk_wed_wo *wo, u32 mask);
3373+ u32 (*get_csr)(struct mtk_wed_wo *wo);
3374+ int (*tx_prepare_skb)(struct mtk_wed_wo *wo);
3375+ bool (*check_excpetion)(struct mtk_wed_wo *wo);
3376+ void (*clear_int)(struct mtk_wed_wo *wo, u32 mask);
3377+};
3378+
3379+struct wed_wo_mcu_ops {
3380+ u32 headroom;
3381+
3382+ int (*mcu_skb_send_msg)(struct mtk_wed_wo *wo, int to_id,
3383+ int cmd, struct sk_buff *skb,
3384+ int *seq, bool wait_resp);
3385+
3386+ int (*mcu_parse_response)(struct mtk_wed_wo *wo, int cmd,
3387+ struct sk_buff *skb, int seq);
3388+
3389+ int (*mcu_restart)(struct mtk_wed_wo *wo);
3390+};
3391+
3392+#define mtk_wed_wo_q_init(wo, ...) (wo)->queue_ops->init((wo), __VA_ARGS__)
3393+#define mtk_wed_wo_q_alloc(wo, ...) (wo)->queue_ops->alloc((wo), __VA_ARGS__)
developera3f86ed2022-07-08 14:15:13 +08003394+#define mtk_wed_wo_q_free(wo, ...) (wo)->queue_ops->free((wo), __VA_ARGS__)
3395+#define mtk_wed_wo_q_reset(wo, ...) (wo)->queue_ops->reset((wo), __VA_ARGS__)
developer8cb3ac72022-07-04 10:55:14 +08003396+#define mtk_wed_wo_q_tx_skb(wo, ...) (wo)->queue_ops->tx_skb((wo), __VA_ARGS__)
3397+#define mtk_wed_wo_q_tx_skb1(wo, ...) (wo)->queue_ops->tx_skb1((wo), __VA_ARGS__)
3398+#define mtk_wed_wo_q_tx_clean(wo, ...) (wo)->queue_ops->tx_clean((wo), __VA_ARGS__)
3399+#define mtk_wed_wo_q_rx_clean(wo, ...) (wo)->queue_ops->rx_clean((wo), __VA_ARGS__)
3400+#define mtk_wed_wo_q_kick(wo, ...) (wo)->queue_ops->kick((wo), __VA_ARGS__)
3401+
3402+enum {
3403+ WARP_CMD_FLAG_RSP = 1 << 0, /* is responce*/
3404+ WARP_CMD_FLAG_NEED_RSP = 1 << 1, /* need responce */
3405+ WARP_CMD_FLAG_FROM_TO_WO = 1 << 2, /* send between host and wo */
3406+};
3407+
3408+#define WED_WO_CMD_FLAG_IS_RSP(_hdr) ((_hdr)->flag & (WARP_CMD_FLAG_RSP))
3409+#define WED_WO_CMD_FLAG_SET_RSP(_hdr) ((_hdr)->flag |= (WARP_CMD_FLAG_RSP))
3410+#define WED_WO_CMD_FLAG_IS_NEED_RSP(_hdr) ((_hdr)->flag & (WARP_CMD_FLAG_NEED_RSP))
3411+#define WED_WO_CMD_FLAG_SET_NEED_RSP(_hdr) ((_hdr)->flag |= (WARP_CMD_FLAG_NEED_RSP))
3412+#define WED_WO_CMD_FLAG_IS_FROM_TO_WO(_hdr) ((_hdr)->flag & (WARP_CMD_FLAG_FROM_TO_WO))
3413+#define WED_WO_CMD_FLAG_SET_FROM_TO_WO(_hdr) ((_hdr)->flag |= (WARP_CMD_FLAG_FROM_TO_WO))
3414+
3415+void mtk_wed_wo_set_isr_mask(struct mtk_wed_wo *wo, bool set,
3416+ u32 clear, u32 val);
3417+
3418+static inline void mtk_wed_wo_isr_enable(struct mtk_wed_wo *wo, u32 mask)
3419+{
3420+ mtk_wed_wo_set_isr_mask(wo, false, 0, mask);
3421+
3422+ tasklet_schedule(&wo->irq_tasklet);
3423+}
3424+
3425+static inline void mtk_wed_wo_isr_disable(struct mtk_wed_wo *wo, u32 mask)
3426+{
3427+ mtk_wed_wo_set_isr_mask(wo, true, mask, 0);
3428+}
3429+
3430+static inline void
3431+wo_w32(struct mtk_wed_wo *dev, u32 reg, u32 val)
3432+{
3433+ writel(val, dev->region[WO_REGION_BOOT].addr + reg);
3434+}
3435+
3436+static inline u32
3437+wo_r32(struct mtk_wed_wo *dev, u32 reg)
3438+{
3439+ return readl(dev->region[WO_REGION_BOOT].addr + reg);
3440+}
3441+static inline void
3442+woccif_w32(struct mtk_wed_wo *dev, u32 reg, u32 val)
3443+{
3444+ regmap_write(dev->ccif.regs, reg, val);
3445+}
3446+
3447+static inline u32
3448+woccif_r32(struct mtk_wed_wo *dev, u32 reg)
3449+{
3450+ unsigned int val;
3451+
3452+ regmap_read(dev->ccif.regs, reg, &val);
3453+
3454+ return val;
3455+}
3456+
3457+int mtk_wed_wo_init(struct mtk_wed_hw *hw);
developera3f86ed2022-07-08 14:15:13 +08003458+void mtk_wed_wo_exit(struct mtk_wed_hw *hw);
developer8cb3ac72022-07-04 10:55:14 +08003459+#endif
3460+
3461diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
developerc1b2cd12022-07-28 18:35:24 +08003462index ffd547a..9a9cc1b 100644
developer8cb3ac72022-07-04 10:55:14 +08003463--- a/include/linux/soc/mediatek/mtk_wed.h
3464+++ b/include/linux/soc/mediatek/mtk_wed.h
3465@@ -7,6 +7,9 @@
3466 #include <linux/pci.h>
3467
3468 #define MTK_WED_TX_QUEUES 2
3469+#define MTK_WED_RX_QUEUES 2
3470+
3471+#define WED_WO_STA_REC 0x6
3472
3473 enum {
3474 MTK_NO_WED,
3475@@ -33,6 +36,24 @@ struct mtk_wed_ring {
3476 void __iomem *wpdma;
3477 };
3478
3479+struct mtk_rxbm_desc {
3480+ __le32 buf0;
3481+ __le32 token;
3482+} __packed __aligned(4);
3483+
3484+struct dma_buf {
3485+ int size;
3486+ void **pages;
3487+ struct mtk_wdma_desc *desc;
3488+ dma_addr_t desc_phys;
3489+};
3490+
3491+struct dma_entry {
3492+ int size;
3493+ struct mtk_rxbm_desc *desc;
3494+ dma_addr_t desc_phys;
3495+};
3496+
3497 struct mtk_wed_device {
3498 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
3499 const struct mtk_wed_ops *ops;
developerbbca0f92022-07-26 17:26:12 +08003500@@ -42,39 +63,57 @@ struct mtk_wed_device {
3501 int wdma_idx;
3502 int irq;
3503 u8 ver;
3504+ u32 rev_id;
3505
developer8cb3ac72022-07-04 10:55:14 +08003506 struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
3507 struct mtk_wed_ring txfree_ring;
3508 struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES];
3509+ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
3510+ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
3511+
3512+ struct dma_buf buf_ring;
3513+ struct dma_entry rx_buf_ring;
3514+ struct page_frag_cache rx_page;
3515
3516 struct {
3517- int size;
3518- void **pages;
3519- struct mtk_wdma_desc *desc;
3520- dma_addr_t desc_phys;
3521- } buf_ring;
3522+ struct mtk_wed_ring rro_ring;
3523+ void __iomem *rro_desc;
3524+ dma_addr_t miod_desc_phys;
3525+ dma_addr_t fdbk_desc_phys;
3526+ u32 mcu_view_miod;
3527+ } rro;
3528
3529 /* filled by driver: */
3530 struct {
3531 struct pci_dev *pci_dev;
3532 void __iomem *base;
3533 u32 bus_type;
3534+ u32 phy_base;
3535
developerbbca0f92022-07-26 17:26:12 +08003536 u32 wpdma_phys;
3537 u32 wpdma_int;
developer8cb3ac72022-07-04 10:55:14 +08003538 u32 wpdma_mask;
3539 u32 wpdma_tx;
3540 u32 wpdma_txfree;
3541+ u32 wpdma_rx_glo;
3542+ u32 wpdma_rx;
3543
3544 u8 tx_tbit[MTK_WED_TX_QUEUES];
3545+ u8 rx_tbit[MTK_WED_RX_QUEUES];
3546 u8 txfree_tbit;
3547
3548 u16 token_start;
3549 unsigned int nbuf;
3550+ unsigned int rx_nbuf;
3551+ unsigned int rx_pkt;
3552+ unsigned int rx_pkt_size;
3553
3554 u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
3555 int (*offload_enable)(struct mtk_wed_device *wed);
3556 void (*offload_disable)(struct mtk_wed_device *wed);
3557+ u32 (*init_rx_buf)(struct mtk_wed_device *wed,
3558+ int pkt_num);
3559+ void (*release_rx_buf)(struct mtk_wed_device *wed);
3560 } wlan;
3561 #endif
3562 };
developerbbca0f92022-07-26 17:26:12 +08003563@@ -85,6 +124,10 @@ struct mtk_wed_ops {
developer8cb3ac72022-07-04 10:55:14 +08003564 void __iomem *regs);
3565 int (*txfree_ring_setup)(struct mtk_wed_device *dev,
3566 void __iomem *regs);
3567+ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
3568+ void __iomem *regs);
3569+ int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
3570+ void *data, int len);
3571 void (*detach)(struct mtk_wed_device *dev);
3572
3573 void (*stop)(struct mtk_wed_device *dev);
developerbbca0f92022-07-26 17:26:12 +08003574@@ -96,6 +139,8 @@ struct mtk_wed_ops {
developer8cb3ac72022-07-04 10:55:14 +08003575
3576 u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
3577 void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
developerbbca0f92022-07-26 17:26:12 +08003578+ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
developer8cb3ac72022-07-04 10:55:14 +08003579+ u32 reason, u32 hash);
3580 };
3581
3582 extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
developerbbca0f92022-07-26 17:26:12 +08003583@@ -128,6 +173,10 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +08003584 (_dev)->ops->tx_ring_setup(_dev, _ring, _regs)
3585 #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
3586 (_dev)->ops->txfree_ring_setup(_dev, _regs)
3587+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
3588+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
3589+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
3590+ (_dev)->ops->msg_update(_dev, _id, _msg, _len)
3591 #define mtk_wed_device_reg_read(_dev, _reg) \
3592 (_dev)->ops->reg_read(_dev, _reg)
3593 #define mtk_wed_device_reg_write(_dev, _reg, _val) \
developerbbca0f92022-07-26 17:26:12 +08003594@@ -136,6 +185,8 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +08003595 (_dev)->ops->irq_get(_dev, _mask)
3596 #define mtk_wed_device_irq_set_mask(_dev, _mask) \
3597 (_dev)->ops->irq_set_mask(_dev, _mask)
3598+#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
3599+ (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
3600 #else
3601 static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
3602 {
developerbbca0f92022-07-26 17:26:12 +08003603@@ -145,10 +196,13 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
developer8cb3ac72022-07-04 10:55:14 +08003604 #define mtk_wed_device_start(_dev, _mask) do {} while (0)
3605 #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV
3606 #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
3607+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
3608+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
3609 #define mtk_wed_device_reg_read(_dev, _reg) 0
3610 #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
3611 #define mtk_wed_device_irq_get(_dev, _mask) 0
3612 #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
3613+#define mtk_wed_device_ppe_check(_dev, _hash) do {} while (0)
3614 #endif
3615
3616 #endif
3617--
36182.18.0
3619