xref: /linux/drivers/net/wireless/mediatek/mt76/mt7996/npu.c (revision cc4adab164b772a34b3340d644b7c4728498581e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2025 AIROHA Inc
4  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5  */
6 #include <linux/kernel.h>
7 #include <linux/soc/airoha/airoha_offload.h>
8 
9 #include "mt7996.h"
10 
11 static int mt7996_npu_offload_init(struct mt7996_dev *dev,
12 				   struct airoha_npu *npu)
13 {
14 	phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
15 	u32 val, hif1_ofs = 0, dma_addr;
16 	int i, err;
17 
18 	err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
19 			       &val, GFP_KERNEL);
20 	if (err) {
21 		dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
22 		return err;
23 	}
24 
25 	dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
26 		 (val >> 16) & 0xffff, val & 0xffff);
27 
28 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
29 				dev->mt76.mmio.npu_type, GFP_KERNEL);
30 	if (err) {
31 		dev_warn(dev->mt76.dev,
32 			 "failed setting NPU wlan PCIe port type\n");
33 		return err;
34 	}
35 
36 	if (dev->hif2)
37 		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
38 
39 	for (i = MT_BAND0; i < MT_BAND2; i++) {
40 		dma_addr = phy_addr;
41 		if (i)
42 			dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90 +
43 				    hif1_ofs;
44 		else
45 			dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
46 
47 		err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
48 					dma_addr, GFP_KERNEL);
49 		if (err) {
50 			dev_warn(dev->mt76.dev,
51 				 "failed setting NPU wlan PCIe desc addr\n");
52 			return err;
53 		}
54 
55 		err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,
56 					MT7996_RX_RING_SIZE, GFP_KERNEL);
57 		if (err) {
58 			dev_warn(dev->mt76.dev,
59 				 "failed setting NPU wlan PCIe desc size\n");
60 			return err;
61 		}
62 
63 		dma_addr = phy_addr;
64 		if (i)
65 			dma_addr += MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
66 		else
67 			dma_addr += MT_TXQ_RING_BASE(0) + 0x120;
68 
69 		err = mt76_npu_send_msg(npu, i,
70 					WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
71 					dma_addr, GFP_KERNEL);
72 		if (err) {
73 			dev_warn(dev->mt76.dev,
74 				 "failed setting NPU wlan tx desc addr\n");
75 			return err;
76 		}
77 	}
78 
79 	err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
80 				phy_addr + MT_RXQ_RRO_AP_RING_BASE,
81 				GFP_KERNEL);
82 	if (err) {
83 		dev_warn(dev->mt76.dev,
84 			 "failed setting NPU wlan rxdmad_c addr\n");
85 		return err;
86 	}
87 
88 	err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_DESC,
89 				MT7996_RX_RING_SIZE, GFP_KERNEL);
90 	if (err) {
91 		dev_warn(dev->mt76.dev,
92 			 "failed setting NPU wlan rxdmad_c desc size\n");
93 		return err;
94 	}
95 
96 	err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
97 				phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
98 	if (err) {
99 		dev_warn(dev->mt76.dev,
100 			 "failed setting NPU wlan rro_ack_sn desc addr\n");
101 		return err;
102 	}
103 
104 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
105 				MT7996_HW_TOKEN_SIZE, GFP_KERNEL);
106 	if (err)
107 		return err;
108 
109 	dev->mt76.token_start = MT7996_HW_TOKEN_SIZE;
110 
111 	return 0;
112 }
113 
114 static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
115 {
116 	u32 val;
117 	int err;
118 
119 	err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
120 			       &val, GFP_KERNEL);
121 	if (err) {
122 		dev_warn(dev->mt76.dev,
123 			 "failed retriving NPU wlan rx ring0 addr\n");
124 		return err;
125 	}
126 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
127 
128 	err = mt76_npu_get_msg(npu, 1, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
129 			       &val, GFP_KERNEL);
130 	if (err) {
131 		dev_warn(dev->mt76.dev,
132 			 "failed retriving NPU wlan rx ring1 addr\n");
133 		return err;
134 	}
135 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);
136 
137 	err = mt76_npu_get_msg(npu, 9, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
138 			       &val, GFP_KERNEL);
139 	if (err) {
140 		dev_warn(dev->mt76.dev,
141 			 "failed retriving NPU wlan rxdmad_c ring addr\n");
142 		return err;
143 	}
144 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);
145 
146 	return 0;
147 }
148 
149 static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
150 {
151 	int i, err;
152 
153 	for (i = MT_BAND0; i < MT_BAND2; i++) {
154 		dma_addr_t dma_addr;
155 		u32 val;
156 
157 		err = mt76_npu_get_msg(npu, i + 5,
158 				       WLAN_FUNC_GET_WAIT_RXDESC_BASE,
159 				       &val, GFP_KERNEL);
160 		if (err) {
161 			dev_warn(dev->mt76.dev,
162 				 "failed retriving NPU wlan tx ring addr\n");
163 			return err;
164 		}
165 		writel(val, &dev->mt76.phys[i]->q_tx[0]->regs->desc_base);
166 
167 		if (!dmam_alloc_coherent(dev->mt76.dma_dev,
168 					 256 * MT7996_TX_RING_SIZE,
169 					 &dma_addr, GFP_KERNEL))
170 			return -ENOMEM;
171 
172 		err = mt76_npu_send_msg(npu, i,
173 					WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
174 					dma_addr, GFP_KERNEL);
175 		if (err) {
176 			dev_warn(dev->mt76.dev,
177 				 "failed setting NPU wlan queue buf addr\n");
178 			return err;
179 		}
180 
181 		if (!dmam_alloc_coherent(dev->mt76.dma_dev,
182 					 256 * MT7996_TX_RING_SIZE,
183 					 &dma_addr, GFP_KERNEL))
184 			return -ENOMEM;
185 
186 		err = mt76_npu_send_msg(npu, i + 5,
187 					WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
188 					dma_addr, GFP_KERNEL);
189 		if (err) {
190 			dev_warn(dev->mt76.dev,
191 				 "failed setting NPU wlan tx buf addr\n");
192 			return err;
193 		}
194 
195 		if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
196 					 &dma_addr, GFP_KERNEL))
197 			return -ENOMEM;
198 
199 		err = mt76_npu_send_msg(npu, i + 10,
200 					WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
201 					dma_addr, GFP_KERNEL);
202 		if (err) {
203 			dev_warn(dev->mt76.dev,
204 				 "failed setting NPU wlan tx buf base\n");
205 			return err;
206 		}
207 	}
208 
209 	return 0;
210 }
211 
212 static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
213 				    struct airoha_npu *npu)
214 {
215 	struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MAIN_WA];
216 	phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
217 	int err;
218 
219 	err = mt76_npu_send_msg(npu, 0,
220 				WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE,
221 				q->desc_dma, GFP_KERNEL);
222 	if (err) {
223 		dev_warn(dev->mt76.dev,
224 			 "failed setting NPU wlan tx-done ring\n");
225 		return err;
226 	}
227 
228 	err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_DESC,
229 				MT7996_RX_MCU_RING_SIZE, GFP_KERNEL);
230 	if (err) {
231 		dev_warn(dev->mt76.dev,
232 			 "failed setting NPU wlan descriptors\n");
233 		return err;
234 	}
235 
236 	phy_addr += MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA) + 0x20;
237 	err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
238 				phy_addr, GFP_KERNEL);
239 	if (err)
240 		dev_warn(dev->mt76.dev,
241 			 "failed setting NPU wlan rx pcie address\n");
242 	return err;
243 }
244 
245 static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,
246 				   struct airoha_npu *npu)
247 {
248 	int err;
249 
250 	err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
251 				0, GFP_KERNEL);
252 	if (err) {
253 		dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr2\n");
254 		return err;
255 	}
256 
257 	err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
258 				0, GFP_KERNEL);
259 	if (err)
260 		dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr7\n");
261 
262 	return err;
263 }
264 
265 int mt7996_npu_rx_queues_init(struct mt7996_dev *dev)
266 {
267 	int err;
268 
269 	if (!mt76_npu_device_active(&dev->mt76))
270 		return 0;
271 
272 	err = mt76_npu_rx_queue_init(&dev->mt76,
273 				     &dev->mt76.q_rx[MT_RXQ_NPU0]);
274 	if (err)
275 		return err;
276 
277 	return mt76_npu_rx_queue_init(&dev->mt76,
278 				      &dev->mt76.q_rx[MT_RXQ_NPU1]);
279 }
280 
281 int mt7996_npu_hw_init(struct mt7996_dev *dev)
282 {
283 	struct airoha_npu *npu;
284 	int i, err = 0;
285 
286 	mutex_lock(&dev->mt76.mutex);
287 
288 	npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
289 	if (!npu)
290 		goto unlock;
291 
292 	err = mt7996_npu_offload_init(dev, npu);
293 	if (err)
294 		goto unlock;
295 
296 	err = mt7996_npu_rxd_init(dev, npu);
297 	if (err)
298 		goto unlock;
299 
300 	err = mt7996_npu_txd_init(dev, npu);
301 	if (err)
302 		goto unlock;
303 
304 	err = mt7996_npu_rx_event_init(dev, npu);
305 	if (err)
306 		goto unlock;
307 
308 	err = mt7996_npu_tx_done_init(dev, npu);
309 	if (err)
310 		goto unlock;
311 
312 	for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)
313 		airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);
314 unlock:
315 	mutex_unlock(&dev->mt76.mutex);
316 
317 	return err;
318 }
319 
320 int mt7996_npu_hw_stop(struct mt7996_dev *dev)
321 {
322 	struct airoha_npu *npu;
323 	int i, err;
324 	u32 info;
325 
326 	npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
327 	if (!npu)
328 		return 0;
329 
330 	err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
331 				0, GFP_KERNEL);
332 	if (err)
333 		return err;
334 
335 	for (i = 0; i < 10; i++) {
336 		err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,
337 				       &info, GFP_KERNEL);
338 		if (err)
339 			continue;
340 
341 		if (info) {
342 			err = -ETIMEDOUT;
343 			continue;
344 		}
345 	}
346 
347 	if (!err)
348 		err = mt76_npu_send_msg(npu, 6,
349 					WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
350 					0, GFP_KERNEL);
351 	return err;
352 }
353