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