From 0b416eb17c14d9da642f9c8af2b815d71ee022f9 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Fri, 15 Apr 2022 12:44:36 +0800
Subject: [PATCH] mt76:add mt7896 wed tx support

Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
 mt7915/dma.c    | 19 +++++++++----
 mt7915/mac.c    |  4 +--
 mt7915/mac.h    |  1 +
 mt7915/main.c   |  9 +++++--
 mt7915/mcu.c    |  2 +-
 mt7915/mmio.c   | 63 ++++++++++++++++++++++++++++++++++++++++++-
 mt7915/mt7915.h |  2 ++
 mt7915/pci.c    | 72 +------------------------------------------------
 mt7915/regs.h   |  3 +++
 mt7915/soc.c    | 16 ++++++++---
 10 files changed, 105 insertions(+), 86 deletions(-)

diff --git a/mt7915/dma.c b/mt7915/dma.c
index 219b440f..2f46e107 100644
--- a/mt7915/dma.c
+++ b/mt7915/dma.c
@@ -12,7 +12,10 @@ mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base
 	int i, err;
 
 	if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
-		ring_base = MT_WED_TX_RING_BASE;
+		if(is_mt7915(&dev->mt76))
+			ring_base = MT_WED_TX_RING_BASE;
+		else
+			ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
 		idx -= MT_TXQ_ID(0);
 	}
 
@@ -330,7 +333,10 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
 		u32 wed_irq_mask = irq_mask;
 
 		wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
-		mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
+		if (is_mt7915(&dev->mt76))
+			mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
+		else
+			mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
 		mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
 	}
 
@@ -355,7 +361,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
 
 	mt7915_dma_disable(dev, true);
 
-	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(mdev)) {
 		mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
 
 		mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
@@ -363,7 +369,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
 			FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
 			FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1));
 	} else {
-		mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
+		//mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
 	}
 
 	/* init tx queue */
@@ -417,7 +423,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
 		return ret;
 
 	/* event from WA */
-	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(mdev)) {
 		wa_rx_base = MT_WED_RX_RING_BASE;
 		wa_rx_idx = MT7915_RXQ_MCU_WA;
 		dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
@@ -444,6 +450,9 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
 
 	/* tx free notify event from WA for band0 */
 	if (!is_mt7915(mdev)) {
+		if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+			dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
+
 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
 				       MT_RXQ_ID(MT_RXQ_MAIN_WA),
 				       MT7915_RX_MCU_RING_SIZE,
diff --git a/mt7915/mac.c b/mt7915/mac.c
index 64ef061f..94c45b47 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -1402,9 +1402,9 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
 
 	txp->token = cpu_to_le16(token_id);
 	txp->nbuf = 1;
-	txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
+	txp->buf[0] = cpu_to_le32(phys + MT_TXD_TXP_BUF_SIZE);
 
-	return MT_TXD_SIZE + sizeof(*txp);
+	return MT_TXD_TXP_BUF_SIZE;
 }
 
 static void
diff --git a/mt7915/mac.h b/mt7915/mac.h
index c5fd1a61..1914f244 100644
--- a/mt7915/mac.h
+++ b/mt7915/mac.h
@@ -292,6 +292,7 @@ enum tx_mcu_port_q_idx {
 #define MT_TX_RATE_IDX			GENMASK(5, 0)
 
 #define MT_TXP_MAX_BUF_NUM		6
+#define MT_TXD_TXP_BUF_SIZE		128
 
 struct mt7915_txp {
 	__le16 flags;
diff --git a/mt7915/main.c b/mt7915/main.c
index 12efb120..0d58d89e 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -1429,14 +1429,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (msta->wcid.idx > 0xff)
+	if (msta->wcid.idx > MT7915_WTBL_STA)
 		return -EIO;
 
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
 	path->mtk_wdma.bss = mvif->mt76.idx;
-	path->mtk_wdma.wcid = msta->wcid.idx;
+	/* fw will find the wcid by dest addr */
+	if(is_mt7915(&dev->mt76))
+		path->mtk_wdma.wcid = 0xff;
+	else
+		path->mtk_wdma.wcid = 0x3ff;
+
 	path->mtk_wdma.queue = phy != &dev->phy;
 
 	ctx->dev = NULL;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
index 289360b5..2aaa5bbd 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -2527,7 +2527,7 @@ int mt7915_run_firmware(struct mt7915_dev *dev)
 	if (ret)
 		return ret;
 
-	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76))
 		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
 
 	ret = mt7915_mcu_set_mwds(dev, 1);
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
index f07b0565..70a3f9f3 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -10,6 +10,9 @@
 #include "mac.h"
 #include "../trace.h"
 
+static bool wed_enable = true;
+module_param(wed_enable, bool, 0644);
+
 static const u32 mt7915_reg[] = {
 	[INT_SOURCE_CSR]	= 0xd7010,
 	[INT_MASK_CSR]		= 0xd7014,
@@ -536,7 +539,11 @@ void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev,
 	mdev->mmio.irqmask |= set;
 
 	if (write_reg) {
-		mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
+		if (mtk_wed_device_active(&mdev->mmio.wed))
+			mtk_wed_device_irq_set_mask(&mdev->mmio.wed,
+						    mdev->mmio.irqmask);
+		else
+			mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
 		mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
 	}
 
@@ -560,6 +567,8 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
 
 	if (mtk_wed_device_active(wed)) {
 		mtk_wed_device_irq_set_mask(wed, 0);
+		if (dev->hif2)
+			mt76_wr(dev, MT_INT1_MASK_CSR, 0);
 		intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
 	} else {
 		mt76_wr(dev, MT_INT_MASK_CSR, 0);
@@ -642,6 +651,58 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
 	return IRQ_HANDLED;
 }
 
+int
+mt7915_pci_wed_init(struct mt7915_dev *dev, struct device *pdev, int *irq)
+{
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+	struct mt76_dev *mdev = &dev->mt76;
+	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+	u32 base;
+	int ret;
+
+	if (!wed_enable)
+		return 0;
+
+	if (dev_is_pci(pdev)) {
+		struct pci_dev *pci_dev;
+
+		pci_dev = container_of(pdev, struct pci_dev, dev);
+		base = pci_resource_start(pci_dev, 0);
+
+		wed->wlan.pci_dev = pci_dev;
+		wed->wlan.wpdma_phys = base + MT_WFDMA_EXT_CSR_BASE;
+	} else {
+		struct platform_device *plat_dev;
+		struct resource *res;
+
+		plat_dev = to_platform_device(pdev);
+		res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
+		base = res->start;
+
+		wed->wlan.wpdma_phys = base + MT_INT_SOURCE_CSR;
+		wed->wlan.wpdma_tx = res->start + MT_TXQ_WED_RING_BASE;
+		wed->wlan.wpdma_txfree = res->start + MT_RXQ_WED_RING_BASE;
+	}
+
+	wed->wlan.nbuf = 7168;
+	wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
+	wed->wlan.init_buf = mt7915_wed_init_buf;
+
+	if (mtk_wed_device_attach(wed) != 0)
+		return 0;
+
+	*irq = wed->irq;
+	dev->mt76.dma_dev = wed->dev;
+	ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
+	if (ret)
+		return ret;
+
+	return 1;
+#else
+	return 0;
+#endif
+}
+
 struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
 				     void __iomem *mem_base, u32 device_id)
 {
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
index 0ed02537..de40e417 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -511,6 +511,8 @@ static inline void mt7986_wmac_disable(struct mt7915_dev *dev)
 {
 }
 #endif
+int mt7915_pci_wed_init(struct mt7915_dev *dev,
+			struct device *pdev, int *irq);
 struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
 				     void __iomem *mem_base, u32 device_id);
 void mt7915_wfsys_reset(struct mt7915_dev *dev);
diff --git a/mt7915/pci.c b/mt7915/pci.c
index f6222ef1..72369a2d 100644
--- a/mt7915/pci.c
+++ b/mt7915/pci.c
@@ -12,9 +12,6 @@
 #include "mac.h"
 #include "../trace.h"
 
-static bool wed_enable = false;
-module_param(wed_enable, bool, 0644);
-
 static LIST_HEAD(hif_list);
 static DEFINE_SPINLOCK(hif_lock);
 static u32 hif_idx;
@@ -95,73 +92,6 @@ static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
-{
-	struct mt7915_dev *dev;
-	int ret;
-
-	dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
-
-	spin_lock_bh(&dev->mt76.token_lock);
-	dev->mt76.token_size = wed->wlan.token_start;
-	spin_unlock_bh(&dev->mt76.token_lock);
-
-	ret = wait_event_timeout(dev->mt76.tx_wait,
-				 !dev->mt76.wed_token_count, HZ);
-	if (!ret)
-		return -EAGAIN;
-
-	return 0;
-}
-
-static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
-{
-	struct mt7915_dev *dev;
-
-	dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
-
-	spin_lock_bh(&dev->mt76.token_lock);
-	dev->mt76.token_size = MT7915_TOKEN_SIZE;
-	spin_unlock_bh(&dev->mt76.token_lock);
-}
-#endif
-
-static int
-mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
-{
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-	int ret;
-
-	if (!wed_enable)
-		return 0;
-
-	wed->wlan.pci_dev = pdev;
-	wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
-			       MT_WFDMA_EXT_CSR_BASE;
-	wed->wlan.nbuf = 4096;
-	wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
-	wed->wlan.init_buf = mt7915_wed_init_buf;
-	wed->wlan.offload_enable = mt7915_wed_offload_enable;
-	wed->wlan.offload_disable = mt7915_wed_offload_disable;
-
-	if (mtk_wed_device_attach(wed) != 0)
-		return 0;
-
-	*irq = wed->irq;
-	dev->mt76.dma_dev = wed->dev;
-
-	ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
-	if (ret)
-		return ret;
-
-	return 1;
-#else
-	return 0;
-#endif
-}
-
 static int mt7915_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *id)
 {
@@ -199,7 +129,7 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
 	mt7915_wfsys_reset(dev);
 	hif2 = mt7915_pci_init_hif2(pdev);
 
-	ret = mt7915_pci_wed_init(dev, pdev, &irq);
+	ret = mt7915_pci_wed_init(dev, &pdev->dev, &irq);
 	if (ret < 0)
 		goto free_wed_or_irq_vector;
 
diff --git a/mt7915/regs.h b/mt7915/regs.h
index a3b9bf4c..0b0fe611 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
@@ -657,6 +657,9 @@ enum offs_rev {
 #define MT_TXQ_EXT_CTRL(q)		(MT_Q_BASE(__TXQ(q)) + 0x600 +	\
 					 MT_TXQ_ID(q)* 0x4)
 
+#define MT_TXQ_WED_RING_BASE		(is_mt7915(mdev)? 0xd7420 : 0x24420)
+#define MT_RXQ_WED_RING_BASE		(is_mt7915(mdev)? 0xd7520 : 0x24520)
+
 #define MT_INT_SOURCE_CSR		__REG(INT_SOURCE_CSR)
 #define MT_INT_MASK_CSR			__REG(INT_MASK_CSR)
 
diff --git a/mt7915/soc.c b/mt7915/soc.c
index 99fc3d3a..9f4cab36 100644
--- a/mt7915/soc.c
+++ b/mt7915/soc.c
@@ -1160,10 +1160,6 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
 
 	chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
 	mem_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(mem_base)) {
 		dev_err(&pdev->dev, "Failed to get memory resource\n");
@@ -1175,6 +1171,16 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
 		return PTR_ERR(dev);
 
 	mdev = &dev->mt76;
+	ret = mt7915_pci_wed_init(dev, &pdev->dev, &irq);
+	if (ret < 0)
+		goto free_device;
+
+	if (!ret) {
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return irq;;
+	}
+
 	ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
 			       IRQF_SHARED, KBUILD_MODNAME, dev);
 	if (ret)
@@ -1197,6 +1203,8 @@ free_irq:
 	devm_free_irq(mdev->dev, irq, dev);
 
 free_device:
+	if (mtk_wed_device_active(&mdev->mmio.wed))
+		mtk_wed_device_detach(&mdev->mmio.wed);
 	mt76_free_device(&dev->mt76);
 
 	return ret;
-- 
2.18.0

