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