1e57b7901SRyder Lee // SPDX-License-Identifier: ISC
2e57b7901SRyder Lee /* Copyright (C) 2020 MediaTek Inc. */
3e57b7901SRyder Lee 
4e57b7901SRyder Lee #include "mt7915.h"
5e57b7901SRyder Lee #include "../dma.h"
6e57b7901SRyder Lee #include "mac.h"
7e57b7901SRyder Lee 
8e57b7901SRyder Lee static int
9e57b7901SRyder Lee mt7915_init_tx_queues(struct mt7915_dev *dev, int n_desc)
10e57b7901SRyder Lee {
11e57b7901SRyder Lee 	struct mt76_sw_queue *q;
12e57b7901SRyder Lee 	struct mt76_queue *hwq;
13e57b7901SRyder Lee 	int err, i;
14e57b7901SRyder Lee 
15e57b7901SRyder Lee 	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL);
16e57b7901SRyder Lee 	if (!hwq)
17e57b7901SRyder Lee 		return -ENOMEM;
18e57b7901SRyder Lee 
19e57b7901SRyder Lee 	err = mt76_queue_alloc(dev, hwq, MT7915_TXQ_BAND0, n_desc, 0,
20e57b7901SRyder Lee 			       MT_TX_RING_BASE);
21e57b7901SRyder Lee 	if (err < 0)
22e57b7901SRyder Lee 		return err;
23e57b7901SRyder Lee 
24e57b7901SRyder Lee 	for (i = 0; i < MT_TXQ_MCU; i++) {
25e57b7901SRyder Lee 		q = &dev->mt76.q_tx[i];
26e57b7901SRyder Lee 		INIT_LIST_HEAD(&q->swq);
27e57b7901SRyder Lee 		q->q = hwq;
28e57b7901SRyder Lee 	}
29e57b7901SRyder Lee 
30e57b7901SRyder Lee 	return 0;
31e57b7901SRyder Lee }
32e57b7901SRyder Lee 
33e57b7901SRyder Lee static int
34e57b7901SRyder Lee mt7915_init_mcu_queue(struct mt7915_dev *dev, struct mt76_sw_queue *q,
35e57b7901SRyder Lee 		      int idx, int n_desc)
36e57b7901SRyder Lee {
37e57b7901SRyder Lee 	struct mt76_queue *hwq;
38e57b7901SRyder Lee 	int err;
39e57b7901SRyder Lee 
40e57b7901SRyder Lee 	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL);
41e57b7901SRyder Lee 	if (!hwq)
42e57b7901SRyder Lee 		return -ENOMEM;
43e57b7901SRyder Lee 
44e57b7901SRyder Lee 	err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE);
45e57b7901SRyder Lee 	if (err < 0)
46e57b7901SRyder Lee 		return err;
47e57b7901SRyder Lee 
48e57b7901SRyder Lee 	INIT_LIST_HEAD(&q->swq);
49e57b7901SRyder Lee 	q->q = hwq;
50e57b7901SRyder Lee 
51e57b7901SRyder Lee 	return 0;
52e57b7901SRyder Lee }
53e57b7901SRyder Lee 
54e57b7901SRyder Lee void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
55e57b7901SRyder Lee 			 struct sk_buff *skb)
56e57b7901SRyder Lee {
57e57b7901SRyder Lee 	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
58e57b7901SRyder Lee 	__le32 *rxd = (__le32 *)skb->data;
59e57b7901SRyder Lee 	enum rx_pkt_type type;
60e57b7901SRyder Lee 
61e57b7901SRyder Lee 	type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
62e57b7901SRyder Lee 
63e57b7901SRyder Lee 	switch (type) {
64e57b7901SRyder Lee 	case PKT_TYPE_TXRX_NOTIFY:
65e57b7901SRyder Lee 		mt7915_mac_tx_free(dev, skb);
66e57b7901SRyder Lee 		break;
67e57b7901SRyder Lee 	case PKT_TYPE_RX_EVENT:
68e57b7901SRyder Lee 		mt7915_mcu_rx_event(dev, skb);
69e57b7901SRyder Lee 		break;
70e57b7901SRyder Lee 	case PKT_TYPE_NORMAL:
71e57b7901SRyder Lee 		if (!mt7915_mac_fill_rx(dev, skb)) {
72e57b7901SRyder Lee 			mt76_rx(&dev->mt76, q, skb);
73e57b7901SRyder Lee 			return;
74e57b7901SRyder Lee 		}
75e57b7901SRyder Lee 		/* fall through */
76e57b7901SRyder Lee 	default:
77e57b7901SRyder Lee 		dev_kfree_skb(skb);
78e57b7901SRyder Lee 		break;
79e57b7901SRyder Lee 	}
80e57b7901SRyder Lee }
81e57b7901SRyder Lee 
82dc076af5SRyder Lee static void
83dc076af5SRyder Lee mt7915_tx_cleanup(struct mt7915_dev *dev)
84dc076af5SRyder Lee {
85dc076af5SRyder Lee 	mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false);
86dc076af5SRyder Lee 	mt76_queue_tx_cleanup(dev, MT_TXQ_MCU_WA, false);
87dc076af5SRyder Lee 	mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false);
88dc076af5SRyder Lee 	mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
89dc076af5SRyder Lee }
90dc076af5SRyder Lee 
91e57b7901SRyder Lee static int mt7915_poll_tx(struct napi_struct *napi, int budget)
92e57b7901SRyder Lee {
93e57b7901SRyder Lee 	struct mt7915_dev *dev;
94e57b7901SRyder Lee 
95e57b7901SRyder Lee 	dev = container_of(napi, struct mt7915_dev, mt76.tx_napi);
96e57b7901SRyder Lee 
97dc076af5SRyder Lee 	mt7915_tx_cleanup(dev);
98e57b7901SRyder Lee 	mt7915_mac_sta_poll(dev);
99e57b7901SRyder Lee 
100e57b7901SRyder Lee 	tasklet_schedule(&dev->mt76.tx_tasklet);
101e57b7901SRyder Lee 
10238b04398SFelix Fietkau 	if (napi_complete_done(napi, 0))
10338b04398SFelix Fietkau 		mt7915_irq_enable(dev, MT_INT_TX_DONE_ALL);
10438b04398SFelix Fietkau 
105e57b7901SRyder Lee 	return 0;
106e57b7901SRyder Lee }
107e57b7901SRyder Lee 
108e57b7901SRyder Lee void mt7915_dma_prefetch(struct mt7915_dev *dev)
109e57b7901SRyder Lee {
110e57b7901SRyder Lee #define PREFETCH(base, depth)	((base) << 16 | (depth))
111e57b7901SRyder Lee 
112e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
113e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x40, 0x4));
114e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x80, 0x0));
115e57b7901SRyder Lee 
116e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING0_EXT_CTRL, PREFETCH(0x80, 0x4));
117e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING1_EXT_CTRL, PREFETCH(0xc0, 0x4));
118e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING2_EXT_CTRL, PREFETCH(0x100, 0x4));
119e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING3_EXT_CTRL, PREFETCH(0x140, 0x4));
120e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING4_EXT_CTRL, PREFETCH(0x180, 0x4));
121e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING5_EXT_CTRL, PREFETCH(0x1c0, 0x4));
122e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING6_EXT_CTRL, PREFETCH(0x200, 0x4));
123e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING7_EXT_CTRL, PREFETCH(0x240, 0x4));
124e57b7901SRyder Lee 
125e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING16_EXT_CTRL, PREFETCH(0x280, 0x4));
126e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING17_EXT_CTRL, PREFETCH(0x2c0, 0x4));
127e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING18_EXT_CTRL, PREFETCH(0x300, 0x4));
128e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING19_EXT_CTRL, PREFETCH(0x340, 0x4));
129e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING20_EXT_CTRL, PREFETCH(0x380, 0x4));
130e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_TX_RING21_EXT_CTRL, PREFETCH(0x3c0, 0x0));
131e57b7901SRyder Lee 
132e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_RX_RING0_EXT_CTRL, PREFETCH(0x3c0, 0x4));
133e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_RX_RING1_EXT_CTRL, PREFETCH(0x400, 0x4));
134e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_RX_RING2_EXT_CTRL, PREFETCH(0x440, 0x4));
135e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_RX_RING3_EXT_CTRL, PREFETCH(0x480, 0x0));
136e57b7901SRyder Lee }
137e57b7901SRyder Lee 
138e57b7901SRyder Lee int mt7915_dma_init(struct mt7915_dev *dev)
139e57b7901SRyder Lee {
140e57b7901SRyder Lee 	/* Increase buffer size to receive large VHT/HE MPDUs */
141e57b7901SRyder Lee 	int rx_buf_size = MT_RX_BUF_SIZE * 2;
142e57b7901SRyder Lee 	int ret;
143e57b7901SRyder Lee 
144e57b7901SRyder Lee 	mt76_dma_attach(&dev->mt76);
145e57b7901SRyder Lee 
146e57b7901SRyder Lee 	/* configure global setting */
147e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA1_GLO_CFG,
148e57b7901SRyder Lee 		 MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
149e57b7901SRyder Lee 		 MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
150e57b7901SRyder Lee 
151e57b7901SRyder Lee 	/* configure perfetch settings */
152e57b7901SRyder Lee 	mt7915_dma_prefetch(dev);
153e57b7901SRyder Lee 
154e57b7901SRyder Lee 	/* reset dma idx */
155e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
156e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR, ~0);
157e57b7901SRyder Lee 
158e57b7901SRyder Lee 	/* configure delay interrupt */
159e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
160e57b7901SRyder Lee 	mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0);
161e57b7901SRyder Lee 
162e57b7901SRyder Lee 	/* init tx queue */
163e57b7901SRyder Lee 	ret = mt7915_init_tx_queues(dev, MT7915_TX_RING_SIZE);
164e57b7901SRyder Lee 	if (ret)
165e57b7901SRyder Lee 		return ret;
166e57b7901SRyder Lee 
167e57b7901SRyder Lee 	/* command to WM */
168e57b7901SRyder Lee 	ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
169e57b7901SRyder Lee 				    MT7915_TXQ_MCU_WM,
170e57b7901SRyder Lee 				    MT7915_TX_MCU_RING_SIZE);
171e57b7901SRyder Lee 	if (ret)
172e57b7901SRyder Lee 		return ret;
173e57b7901SRyder Lee 
174e57b7901SRyder Lee 	/* command to WA */
175e57b7901SRyder Lee 	ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU_WA],
176e57b7901SRyder Lee 				    MT7915_TXQ_MCU_WA,
177e57b7901SRyder Lee 				    MT7915_TX_MCU_RING_SIZE);
178e57b7901SRyder Lee 	if (ret)
179e57b7901SRyder Lee 		return ret;
180e57b7901SRyder Lee 
181e57b7901SRyder Lee 	/* firmware download */
182e57b7901SRyder Lee 	ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL],
183e57b7901SRyder Lee 				    MT7915_TXQ_FWDL,
184e57b7901SRyder Lee 				    MT7915_TX_FWDL_RING_SIZE);
185e57b7901SRyder Lee 	if (ret)
186e57b7901SRyder Lee 		return ret;
187e57b7901SRyder Lee 
188e57b7901SRyder Lee 	/* event from WM */
189e57b7901SRyder Lee 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
190e57b7901SRyder Lee 			       MT7915_RXQ_MCU_WM, MT7915_RX_MCU_RING_SIZE,
191e57b7901SRyder Lee 			       rx_buf_size, MT_RX_EVENT_RING_BASE);
192e57b7901SRyder Lee 	if (ret)
193e57b7901SRyder Lee 		return ret;
194e57b7901SRyder Lee 
195e57b7901SRyder Lee 	/* event from WA */
196e57b7901SRyder Lee 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
197e57b7901SRyder Lee 			       MT7915_RXQ_MCU_WA, MT7915_RX_MCU_RING_SIZE,
198e57b7901SRyder Lee 			       rx_buf_size, MT_RX_EVENT_RING_BASE);
199e57b7901SRyder Lee 	if (ret)
200e57b7901SRyder Lee 		return ret;
201e57b7901SRyder Lee 
202e57b7901SRyder Lee 	/* rx data */
203e57b7901SRyder Lee 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
204e57b7901SRyder Lee 			       MT7915_RX_RING_SIZE, rx_buf_size,
205e57b7901SRyder Lee 			       MT_RX_DATA_RING_BASE);
206e57b7901SRyder Lee 	if (ret)
207e57b7901SRyder Lee 		return ret;
208e57b7901SRyder Lee 
209e57b7901SRyder Lee 	ret = mt76_init_queues(dev);
210e57b7901SRyder Lee 	if (ret < 0)
211e57b7901SRyder Lee 		return ret;
212e57b7901SRyder Lee 
213e57b7901SRyder Lee 	netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
214e57b7901SRyder Lee 			  mt7915_poll_tx, NAPI_POLL_WEIGHT);
215e57b7901SRyder Lee 	napi_enable(&dev->mt76.tx_napi);
216e57b7901SRyder Lee 
217e57b7901SRyder Lee 	/* hif wait WFDMA idle */
218e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA0_BUSY_ENA,
219e57b7901SRyder Lee 		 MT_WFDMA0_BUSY_ENA_TX_FIFO0 |
220e57b7901SRyder Lee 		 MT_WFDMA0_BUSY_ENA_TX_FIFO1 |
221e57b7901SRyder Lee 		 MT_WFDMA0_BUSY_ENA_RX_FIFO);
222e57b7901SRyder Lee 
223e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA1_BUSY_ENA,
224e57b7901SRyder Lee 		 MT_WFDMA1_BUSY_ENA_TX_FIFO0 |
225e57b7901SRyder Lee 		 MT_WFDMA1_BUSY_ENA_TX_FIFO1 |
226e57b7901SRyder Lee 		 MT_WFDMA1_BUSY_ENA_RX_FIFO);
227e57b7901SRyder Lee 
228e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA0_PCIE1_BUSY_ENA,
229e57b7901SRyder Lee 		 MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 |
230e57b7901SRyder Lee 		 MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 |
231e57b7901SRyder Lee 		 MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO);
232e57b7901SRyder Lee 
233e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA1_PCIE1_BUSY_ENA,
234e57b7901SRyder Lee 		 MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO0 |
235e57b7901SRyder Lee 		 MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 |
236e57b7901SRyder Lee 		 MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO);
237e57b7901SRyder Lee 
238e57b7901SRyder Lee 	mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC,
239e57b7901SRyder Lee 		  MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000);
240e57b7901SRyder Lee 
241e57b7901SRyder Lee 	/* set WFDMA Tx/Rx */
242e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA0_GLO_CFG,
243e57b7901SRyder Lee 		 MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
244e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA1_GLO_CFG,
245e57b7901SRyder Lee 		 MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
246e57b7901SRyder Lee 
247e57b7901SRyder Lee 	/* enable interrupts for TX/RX rings */
248e57b7901SRyder Lee 	mt7915_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
249e57b7901SRyder Lee 			  MT_INT_MCU_CMD);
250e57b7901SRyder Lee 
251e57b7901SRyder Lee 	return 0;
252e57b7901SRyder Lee }
253e57b7901SRyder Lee 
254e57b7901SRyder Lee void mt7915_dma_cleanup(struct mt7915_dev *dev)
255e57b7901SRyder Lee {
256e57b7901SRyder Lee 	/* disable */
257e57b7901SRyder Lee 	mt76_clear(dev, MT_WFDMA0_GLO_CFG,
258e57b7901SRyder Lee 		   MT_WFDMA0_GLO_CFG_TX_DMA_EN |
259e57b7901SRyder Lee 		   MT_WFDMA0_GLO_CFG_RX_DMA_EN);
260e57b7901SRyder Lee 	mt76_clear(dev, MT_WFDMA1_GLO_CFG,
261e57b7901SRyder Lee 		   MT_WFDMA1_GLO_CFG_TX_DMA_EN |
262e57b7901SRyder Lee 		   MT_WFDMA1_GLO_CFG_RX_DMA_EN);
263e57b7901SRyder Lee 
264e57b7901SRyder Lee 	/* reset */
265e57b7901SRyder Lee 	mt76_clear(dev, MT_WFDMA1_RST,
266e57b7901SRyder Lee 		   MT_WFDMA1_RST_DMASHDL_ALL_RST |
267e57b7901SRyder Lee 		   MT_WFDMA1_RST_LOGIC_RST);
268e57b7901SRyder Lee 
269e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA1_RST,
270e57b7901SRyder Lee 		 MT_WFDMA1_RST_DMASHDL_ALL_RST |
271e57b7901SRyder Lee 		 MT_WFDMA1_RST_LOGIC_RST);
272e57b7901SRyder Lee 
273e57b7901SRyder Lee 	mt76_clear(dev, MT_WFDMA0_RST,
274e57b7901SRyder Lee 		   MT_WFDMA0_RST_DMASHDL_ALL_RST |
275e57b7901SRyder Lee 		   MT_WFDMA0_RST_LOGIC_RST);
276e57b7901SRyder Lee 
277e57b7901SRyder Lee 	mt76_set(dev, MT_WFDMA0_RST,
278e57b7901SRyder Lee 		 MT_WFDMA0_RST_DMASHDL_ALL_RST |
279e57b7901SRyder Lee 		 MT_WFDMA0_RST_LOGIC_RST);
280e57b7901SRyder Lee 
281e57b7901SRyder Lee 	tasklet_kill(&dev->mt76.tx_tasklet);
282e57b7901SRyder Lee 	mt76_dma_cleanup(&dev->mt76);
283e57b7901SRyder Lee }
284