xref: /linux/drivers/net/wireless/mediatek/mt76/mt7996/npu.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1377aa17dSLorenzo Bianconi // SPDX-License-Identifier: GPL-2.0-only
2377aa17dSLorenzo Bianconi /*
3377aa17dSLorenzo Bianconi  * Copyright (c) 2025 AIROHA Inc
4377aa17dSLorenzo Bianconi  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5377aa17dSLorenzo Bianconi  */
6377aa17dSLorenzo Bianconi #include <linux/kernel.h>
7377aa17dSLorenzo Bianconi #include <linux/soc/airoha/airoha_offload.h>
8377aa17dSLorenzo Bianconi 
9377aa17dSLorenzo Bianconi #include "mt7996.h"
10377aa17dSLorenzo Bianconi 
11a9ac8f83SLorenzo Bianconi static int mt7992_npu_txrx_offload_init(struct mt7996_dev *dev,
12377aa17dSLorenzo Bianconi 					struct airoha_npu *npu)
13377aa17dSLorenzo Bianconi {
14a9ac8f83SLorenzo Bianconi 	u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
15377aa17dSLorenzo Bianconi 	phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
16a9ac8f83SLorenzo Bianconi 	u32 dma_addr;
17377aa17dSLorenzo Bianconi 	int i, err;
18377aa17dSLorenzo Bianconi 
19377aa17dSLorenzo Bianconi 	for (i = MT_BAND0; i < MT_BAND2; i++) {
20377aa17dSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,
21377aa17dSLorenzo Bianconi 					MT7996_RX_RING_SIZE, GFP_KERNEL);
22377aa17dSLorenzo Bianconi 		if (err) {
23377aa17dSLorenzo Bianconi 			dev_warn(dev->mt76.dev,
24a9ac8f83SLorenzo Bianconi 				 "failed setting NPU wlan rx desc size\n");
25377aa17dSLorenzo Bianconi 			return err;
26377aa17dSLorenzo Bianconi 		}
27377aa17dSLorenzo Bianconi 
28377aa17dSLorenzo Bianconi 		dma_addr = phy_addr;
29377aa17dSLorenzo Bianconi 		if (i)
30377aa17dSLorenzo Bianconi 			dma_addr += MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
31377aa17dSLorenzo Bianconi 		else
32377aa17dSLorenzo Bianconi 			dma_addr += MT_TXQ_RING_BASE(0) + 0x120;
33377aa17dSLorenzo Bianconi 
34377aa17dSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, i,
35377aa17dSLorenzo Bianconi 					WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
36377aa17dSLorenzo Bianconi 					dma_addr, GFP_KERNEL);
37377aa17dSLorenzo Bianconi 		if (err) {
38377aa17dSLorenzo Bianconi 			dev_warn(dev->mt76.dev,
39377aa17dSLorenzo Bianconi 				 "failed setting NPU wlan tx desc addr\n");
40377aa17dSLorenzo Bianconi 			return err;
41377aa17dSLorenzo Bianconi 		}
42377aa17dSLorenzo Bianconi 	}
43377aa17dSLorenzo Bianconi 
44377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
45377aa17dSLorenzo Bianconi 				phy_addr + MT_RXQ_RRO_AP_RING_BASE,
46377aa17dSLorenzo Bianconi 				GFP_KERNEL);
47377aa17dSLorenzo Bianconi 	if (err) {
48377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
49377aa17dSLorenzo Bianconi 			 "failed setting NPU wlan rxdmad_c addr\n");
50377aa17dSLorenzo Bianconi 		return err;
51377aa17dSLorenzo Bianconi 	}
52377aa17dSLorenzo Bianconi 
53377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 9, WLAN_FUNC_SET_WAIT_DESC,
54377aa17dSLorenzo Bianconi 				MT7996_RX_RING_SIZE, GFP_KERNEL);
55377aa17dSLorenzo Bianconi 	if (err) {
56377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
57377aa17dSLorenzo Bianconi 			 "failed setting NPU wlan rxdmad_c desc size\n");
58377aa17dSLorenzo Bianconi 		return err;
59377aa17dSLorenzo Bianconi 	}
60377aa17dSLorenzo Bianconi 
61377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
62377aa17dSLorenzo Bianconi 				phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
63377aa17dSLorenzo Bianconi 	if (err) {
64377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
65a9ac8f83SLorenzo Bianconi 			 "failed setting NPU wlan tx desc addr\n");
66377aa17dSLorenzo Bianconi 		return err;
67377aa17dSLorenzo Bianconi 	}
68377aa17dSLorenzo Bianconi 
69a9ac8f83SLorenzo Bianconi 	return 0;
70a9ac8f83SLorenzo Bianconi }
71a9ac8f83SLorenzo Bianconi 
72880f4e3eSLorenzo Bianconi static int mt7996_npu_txrx_offload_init(struct mt7996_dev *dev,
73880f4e3eSLorenzo Bianconi 					struct airoha_npu *npu)
74880f4e3eSLorenzo Bianconi {
75880f4e3eSLorenzo Bianconi 	u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
76880f4e3eSLorenzo Bianconi 	phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
77880f4e3eSLorenzo Bianconi 	u32 dma_addr;
78880f4e3eSLorenzo Bianconi 	int err;
79880f4e3eSLorenzo Bianconi 
80880f4e3eSLorenzo Bianconi 	/* npu rx rro ring0 */
81880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_DESC,
82880f4e3eSLorenzo Bianconi 				MT7996_RX_RING_SIZE, GFP_KERNEL);
83880f4e3eSLorenzo Bianconi 	if (err) {
84880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
85880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan rx desc size\n");
86880f4e3eSLorenzo Bianconi 		return err;
87880f4e3eSLorenzo Bianconi 	}
88880f4e3eSLorenzo Bianconi 
89880f4e3eSLorenzo Bianconi 	/* npu rx rro ring1 */
90880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_DESC,
91880f4e3eSLorenzo Bianconi 				MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
92880f4e3eSLorenzo Bianconi 	if (err) {
93880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
94880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan rx desc size\n");
95880f4e3eSLorenzo Bianconi 		return err;
96880f4e3eSLorenzo Bianconi 	}
97880f4e3eSLorenzo Bianconi 
98880f4e3eSLorenzo Bianconi 	/* msdu pg  2GHz */
99880f4e3eSLorenzo Bianconi 	dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0) + 0xa0;
100880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
101880f4e3eSLorenzo Bianconi 				dma_addr, GFP_KERNEL);
102880f4e3eSLorenzo Bianconi 	if (err) {
103880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
104880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
105880f4e3eSLorenzo Bianconi 		return err;
106880f4e3eSLorenzo Bianconi 	}
107880f4e3eSLorenzo Bianconi 
108880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_DESC,
109880f4e3eSLorenzo Bianconi 				MT7996_NPU_RX_RING_SIZE / 4, GFP_KERNEL);
110880f4e3eSLorenzo Bianconi 	if (err) {
111880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
112880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan rx desc size\n");
113880f4e3eSLorenzo Bianconi 		return err;
114880f4e3eSLorenzo Bianconi 	}
115880f4e3eSLorenzo Bianconi 
116880f4e3eSLorenzo Bianconi 	/* msdu pg 5GHz */
117880f4e3eSLorenzo Bianconi 	dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1) + 0xb0;
118880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
119880f4e3eSLorenzo Bianconi 				dma_addr, GFP_KERNEL);
120880f4e3eSLorenzo Bianconi 	if (err) {
121880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
122880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
123880f4e3eSLorenzo Bianconi 		return err;
124880f4e3eSLorenzo Bianconi 	}
125880f4e3eSLorenzo Bianconi 
126880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_DESC,
127880f4e3eSLorenzo Bianconi 				MT7996_NPU_RX_RING_SIZE / 2, GFP_KERNEL);
128880f4e3eSLorenzo Bianconi 	if (err) {
129880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
130880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan rx desc size\n");
131880f4e3eSLorenzo Bianconi 		return err;
132880f4e3eSLorenzo Bianconi 	}
133880f4e3eSLorenzo Bianconi 
134880f4e3eSLorenzo Bianconi 	/* msdu pg 6GHz */
135880f4e3eSLorenzo Bianconi 	dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2) + 0xc0;
136880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
137880f4e3eSLorenzo Bianconi 				dma_addr, GFP_KERNEL);
138880f4e3eSLorenzo Bianconi 	if (err) {
139880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
140880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
141880f4e3eSLorenzo Bianconi 		return err;
142880f4e3eSLorenzo Bianconi 	}
143880f4e3eSLorenzo Bianconi 
144880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_DESC,
145880f4e3eSLorenzo Bianconi 				MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
146880f4e3eSLorenzo Bianconi 	if (err) {
147880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
148880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan rx desc size\n");
149880f4e3eSLorenzo Bianconi 		return err;
150880f4e3eSLorenzo Bianconi 	}
151880f4e3eSLorenzo Bianconi 
152880f4e3eSLorenzo Bianconi 	/* ind cmd ring */
153880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
154880f4e3eSLorenzo Bianconi 				phy_addr + MT_RXQ_RRO_IND_RING_BASE,
155880f4e3eSLorenzo Bianconi 				GFP_KERNEL);
156880f4e3eSLorenzo Bianconi 	if (err) {
157880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
158880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
159880f4e3eSLorenzo Bianconi 		return err;
160880f4e3eSLorenzo Bianconi 	}
161880f4e3eSLorenzo Bianconi 
162880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_DESC,
163880f4e3eSLorenzo Bianconi 				MT7996_RX_RING_SIZE, GFP_KERNEL);
164880f4e3eSLorenzo Bianconi 	if (err) {
165880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
166880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan rx desc size\n");
167880f4e3eSLorenzo Bianconi 		return err;
168880f4e3eSLorenzo Bianconi 	}
169880f4e3eSLorenzo Bianconi 
170880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 3, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
171880f4e3eSLorenzo Bianconi 				phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
172880f4e3eSLorenzo Bianconi 	if (err) {
173880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
174880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan tx desc addr\n");
175880f4e3eSLorenzo Bianconi 		return err;
176880f4e3eSLorenzo Bianconi 	}
177880f4e3eSLorenzo Bianconi 
178880f4e3eSLorenzo Bianconi 	/* npu tx */
179880f4e3eSLorenzo Bianconi 	dma_addr = phy_addr + MT_TXQ_RING_BASE(1) + 0x120;
180880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
181880f4e3eSLorenzo Bianconi 				dma_addr, GFP_KERNEL);
182880f4e3eSLorenzo Bianconi 	if (err) {
183880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
184880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan tx desc addr\n");
185880f4e3eSLorenzo Bianconi 		return err;
186880f4e3eSLorenzo Bianconi 	}
187880f4e3eSLorenzo Bianconi 
188880f4e3eSLorenzo Bianconi 	dma_addr = phy_addr + MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
189880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
190880f4e3eSLorenzo Bianconi 				dma_addr, GFP_KERNEL);
191880f4e3eSLorenzo Bianconi 	if (err) {
192880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
193880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan tx desc addr\n");
194880f4e3eSLorenzo Bianconi 		return err;
195880f4e3eSLorenzo Bianconi 	}
196880f4e3eSLorenzo Bianconi 
197880f4e3eSLorenzo Bianconi 	return 0;
198880f4e3eSLorenzo Bianconi }
199880f4e3eSLorenzo Bianconi 
200a9ac8f83SLorenzo Bianconi static int mt7996_npu_offload_init(struct mt7996_dev *dev,
201a9ac8f83SLorenzo Bianconi 				   struct airoha_npu *npu)
202a9ac8f83SLorenzo Bianconi {
203a9ac8f83SLorenzo Bianconi 	u32 val;
204a9ac8f83SLorenzo Bianconi 	int err;
205a9ac8f83SLorenzo Bianconi 
206a9ac8f83SLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
207a9ac8f83SLorenzo Bianconi 			       &val, GFP_KERNEL);
208a9ac8f83SLorenzo Bianconi 	if (err) {
209a9ac8f83SLorenzo Bianconi 		dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
210a9ac8f83SLorenzo Bianconi 		return err;
211a9ac8f83SLorenzo Bianconi 	}
212a9ac8f83SLorenzo Bianconi 
213a9ac8f83SLorenzo Bianconi 	dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
214a9ac8f83SLorenzo Bianconi 		 (val >> 16) & 0xffff, val & 0xffff);
215a9ac8f83SLorenzo Bianconi 
216a9ac8f83SLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
217a9ac8f83SLorenzo Bianconi 				dev->mt76.mmio.npu_type, GFP_KERNEL);
218a9ac8f83SLorenzo Bianconi 	if (err) {
219a9ac8f83SLorenzo Bianconi 		dev_warn(dev->mt76.dev,
220a9ac8f83SLorenzo Bianconi 			 "failed setting NPU wlan PCIe port type\n");
221a9ac8f83SLorenzo Bianconi 		return err;
222a9ac8f83SLorenzo Bianconi 	}
223a9ac8f83SLorenzo Bianconi 
224880f4e3eSLorenzo Bianconi 	if (is_mt7996(&dev->mt76))
225880f4e3eSLorenzo Bianconi 		err = mt7996_npu_txrx_offload_init(dev, npu);
226880f4e3eSLorenzo Bianconi 	else
227a9ac8f83SLorenzo Bianconi 		err = mt7992_npu_txrx_offload_init(dev, npu);
228880f4e3eSLorenzo Bianconi 
229a9ac8f83SLorenzo Bianconi 	if (err)
230a9ac8f83SLorenzo Bianconi 		return err;
231a9ac8f83SLorenzo Bianconi 
232377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
233377aa17dSLorenzo Bianconi 				MT7996_HW_TOKEN_SIZE, GFP_KERNEL);
234377aa17dSLorenzo Bianconi 	if (err)
235377aa17dSLorenzo Bianconi 		return err;
236377aa17dSLorenzo Bianconi 
237377aa17dSLorenzo Bianconi 	dev->mt76.token_start = MT7996_HW_TOKEN_SIZE;
238377aa17dSLorenzo Bianconi 
239377aa17dSLorenzo Bianconi 	return 0;
240377aa17dSLorenzo Bianconi }
241377aa17dSLorenzo Bianconi 
242c93e2fbdSLorenzo Bianconi static int mt7992_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
243377aa17dSLorenzo Bianconi {
244377aa17dSLorenzo Bianconi 	u32 val;
245377aa17dSLorenzo Bianconi 	int err;
246377aa17dSLorenzo Bianconi 
247377aa17dSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
248377aa17dSLorenzo Bianconi 			       &val, GFP_KERNEL);
249377aa17dSLorenzo Bianconi 	if (err) {
250377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
2510cd776fdSColin Ian King 			 "failed retrieving NPU wlan rx ring0 addr\n");
252377aa17dSLorenzo Bianconi 		return err;
253377aa17dSLorenzo Bianconi 	}
254377aa17dSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
255377aa17dSLorenzo Bianconi 
256377aa17dSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 1, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
257377aa17dSLorenzo Bianconi 			       &val, GFP_KERNEL);
258377aa17dSLorenzo Bianconi 	if (err) {
259377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
2600cd776fdSColin Ian King 			 "failed retrieving NPU wlan rx ring1 addr\n");
261377aa17dSLorenzo Bianconi 		return err;
262377aa17dSLorenzo Bianconi 	}
263377aa17dSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);
264377aa17dSLorenzo Bianconi 
265377aa17dSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 9, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
266377aa17dSLorenzo Bianconi 			       &val, GFP_KERNEL);
267377aa17dSLorenzo Bianconi 	if (err) {
268377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
2690cd776fdSColin Ian King 			 "failed retrieving NPU wlan rxdmad_c ring addr\n");
270377aa17dSLorenzo Bianconi 		return err;
271377aa17dSLorenzo Bianconi 	}
272377aa17dSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);
273377aa17dSLorenzo Bianconi 
274377aa17dSLorenzo Bianconi 	return 0;
275377aa17dSLorenzo Bianconi }
276377aa17dSLorenzo Bianconi 
277880f4e3eSLorenzo Bianconi static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
278880f4e3eSLorenzo Bianconi {
279880f4e3eSLorenzo Bianconi 	u32 val;
280880f4e3eSLorenzo Bianconi 	int err;
281880f4e3eSLorenzo Bianconi 
282880f4e3eSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
283880f4e3eSLorenzo Bianconi 			       &val, GFP_KERNEL);
284880f4e3eSLorenzo Bianconi 	if (err) {
285880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
286880f4e3eSLorenzo Bianconi 			 "failed retriving NPU wlan rx ring0 addr\n");
287880f4e3eSLorenzo Bianconi 		return err;
288880f4e3eSLorenzo Bianconi 	}
289880f4e3eSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
290880f4e3eSLorenzo Bianconi 
291880f4e3eSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 2, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
292880f4e3eSLorenzo Bianconi 			       &val, GFP_KERNEL);
293880f4e3eSLorenzo Bianconi 	if (err) {
294880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
295880f4e3eSLorenzo Bianconi 			 "failed retriving NPU wlan rx ring2 addr\n");
296880f4e3eSLorenzo Bianconi 		return err;
297880f4e3eSLorenzo Bianconi 	}
298880f4e3eSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2].regs->desc_base);
299880f4e3eSLorenzo Bianconi 
300880f4e3eSLorenzo Bianconi 	/* msdu pg ring */
301880f4e3eSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 10, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
302880f4e3eSLorenzo Bianconi 			       &val, GFP_KERNEL);
303880f4e3eSLorenzo Bianconi 	if (err) {
304880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
305880f4e3eSLorenzo Bianconi 			 "failed retriving NPU wlan msdu pg ring addr\n");
306880f4e3eSLorenzo Bianconi 		return err;
307880f4e3eSLorenzo Bianconi 	}
308880f4e3eSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].regs->desc_base);
309880f4e3eSLorenzo Bianconi 
310880f4e3eSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 11, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
311880f4e3eSLorenzo Bianconi 			       &val, GFP_KERNEL);
312880f4e3eSLorenzo Bianconi 	if (err) {
313880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
314880f4e3eSLorenzo Bianconi 			 "failed retriving NPU wlan msdu pg ring addr\n");
315880f4e3eSLorenzo Bianconi 		return err;
316880f4e3eSLorenzo Bianconi 	}
317880f4e3eSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].regs->desc_base);
318880f4e3eSLorenzo Bianconi 
319880f4e3eSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 12, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
320880f4e3eSLorenzo Bianconi 			       &val, GFP_KERNEL);
321880f4e3eSLorenzo Bianconi 	if (err) {
322880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
323880f4e3eSLorenzo Bianconi 			 "failed retriving NPU wlan msdu pg ring addr\n");
324880f4e3eSLorenzo Bianconi 		return err;
325880f4e3eSLorenzo Bianconi 	}
326880f4e3eSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].regs->desc_base);
327880f4e3eSLorenzo Bianconi 
328880f4e3eSLorenzo Bianconi 	/* ind_cmd ring */
329880f4e3eSLorenzo Bianconi 	err = mt76_npu_get_msg(npu, 8, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
330880f4e3eSLorenzo Bianconi 			       &val, GFP_KERNEL);
331880f4e3eSLorenzo Bianconi 	if (err) {
332880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
333880f4e3eSLorenzo Bianconi 			 "failed retriving NPU wlan ind_cmd ring addr\n");
334880f4e3eSLorenzo Bianconi 		return err;
335880f4e3eSLorenzo Bianconi 	}
336880f4e3eSLorenzo Bianconi 	writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_IND].regs->desc_base);
337880f4e3eSLorenzo Bianconi 
338880f4e3eSLorenzo Bianconi 	return 0;
339880f4e3eSLorenzo Bianconi }
340880f4e3eSLorenzo Bianconi 
341377aa17dSLorenzo Bianconi static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
342377aa17dSLorenzo Bianconi {
343880f4e3eSLorenzo Bianconi 	const enum mt76_band_id band_list[] = {
344880f4e3eSLorenzo Bianconi 		MT_BAND0,
345880f4e3eSLorenzo Bianconi 		is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND1,
346880f4e3eSLorenzo Bianconi 	};
347*c2efd5feSLorenzo Bianconi 	int i, index = 0;
348*c2efd5feSLorenzo Bianconi 
349*c2efd5feSLorenzo Bianconi 	BUILD_BUG_ON(ARRAY_SIZE(band_list) * 3 !=
350*c2efd5feSLorenzo Bianconi 		     ARRAY_SIZE(dev->npu_txd_addr));
351377aa17dSLorenzo Bianconi 
352880f4e3eSLorenzo Bianconi 	for (i = 0; i < ARRAY_SIZE(band_list); i++) {
353880f4e3eSLorenzo Bianconi 		int err, band = band_list[i], phy_id;
354*c2efd5feSLorenzo Bianconi 		u32 val;
355377aa17dSLorenzo Bianconi 
356880f4e3eSLorenzo Bianconi 		err = mt76_npu_get_msg(npu, band + 5,
357377aa17dSLorenzo Bianconi 				       WLAN_FUNC_GET_WAIT_RXDESC_BASE,
358377aa17dSLorenzo Bianconi 				       &val, GFP_KERNEL);
359377aa17dSLorenzo Bianconi 		if (err) {
360377aa17dSLorenzo Bianconi 			dev_warn(dev->mt76.dev,
3610cd776fdSColin Ian King 				 "failed retrieving NPU wlan tx ring addr\n");
362377aa17dSLorenzo Bianconi 			return err;
363377aa17dSLorenzo Bianconi 		}
364377aa17dSLorenzo Bianconi 
365880f4e3eSLorenzo Bianconi 		phy_id = is_mt7996(&dev->mt76) ? band == MT_BAND0 ? 1 : 0
366880f4e3eSLorenzo Bianconi 					       : band;
367880f4e3eSLorenzo Bianconi 		writel(val, &dev->mt76.phys[phy_id]->q_tx[0]->regs->desc_base);
368880f4e3eSLorenzo Bianconi 
369880f4e3eSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, band,
370377aa17dSLorenzo Bianconi 					WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
371*c2efd5feSLorenzo Bianconi 					dev->npu_txd_addr[index++], GFP_KERNEL);
372377aa17dSLorenzo Bianconi 		if (err) {
373377aa17dSLorenzo Bianconi 			dev_warn(dev->mt76.dev,
374377aa17dSLorenzo Bianconi 				 "failed setting NPU wlan queue buf addr\n");
375377aa17dSLorenzo Bianconi 			return err;
376377aa17dSLorenzo Bianconi 		}
377377aa17dSLorenzo Bianconi 
378880f4e3eSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, band + 5,
379377aa17dSLorenzo Bianconi 					WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
380*c2efd5feSLorenzo Bianconi 					dev->npu_txd_addr[index++],
381*c2efd5feSLorenzo Bianconi 					GFP_KERNEL);
382377aa17dSLorenzo Bianconi 		if (err) {
383377aa17dSLorenzo Bianconi 			dev_warn(dev->mt76.dev,
384377aa17dSLorenzo Bianconi 				 "failed setting NPU wlan tx buf addr\n");
385377aa17dSLorenzo Bianconi 			return err;
386377aa17dSLorenzo Bianconi 		}
387377aa17dSLorenzo Bianconi 
388880f4e3eSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, band + 10,
389377aa17dSLorenzo Bianconi 					WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
390*c2efd5feSLorenzo Bianconi 					dev->npu_txd_addr[index++],
391*c2efd5feSLorenzo Bianconi 					GFP_KERNEL);
392377aa17dSLorenzo Bianconi 		if (err) {
393377aa17dSLorenzo Bianconi 			dev_warn(dev->mt76.dev,
394377aa17dSLorenzo Bianconi 				 "failed setting NPU wlan tx buf base\n");
395377aa17dSLorenzo Bianconi 			return err;
396377aa17dSLorenzo Bianconi 		}
397377aa17dSLorenzo Bianconi 	}
398377aa17dSLorenzo Bianconi 
399377aa17dSLorenzo Bianconi 	return 0;
400377aa17dSLorenzo Bianconi }
401377aa17dSLorenzo Bianconi 
402377aa17dSLorenzo Bianconi static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
403377aa17dSLorenzo Bianconi 				    struct airoha_npu *npu)
404377aa17dSLorenzo Bianconi {
405880f4e3eSLorenzo Bianconi 	int qid = is_mt7996(&dev->mt76) ? MT_RXQ_TXFREE_BAND0 : MT_RXQ_MAIN_WA;
406377aa17dSLorenzo Bianconi 	phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
407880f4e3eSLorenzo Bianconi 	struct mt76_queue *q = &dev->mt76.q_rx[qid];
408377aa17dSLorenzo Bianconi 	int err;
409377aa17dSLorenzo Bianconi 
410377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 0,
411377aa17dSLorenzo Bianconi 				WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE,
412377aa17dSLorenzo Bianconi 				q->desc_dma, GFP_KERNEL);
413377aa17dSLorenzo Bianconi 	if (err) {
414377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
415377aa17dSLorenzo Bianconi 			 "failed setting NPU wlan tx-done ring\n");
416377aa17dSLorenzo Bianconi 		return err;
417377aa17dSLorenzo Bianconi 	}
418377aa17dSLorenzo Bianconi 
419377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_DESC,
420377aa17dSLorenzo Bianconi 				MT7996_RX_MCU_RING_SIZE, GFP_KERNEL);
421377aa17dSLorenzo Bianconi 	if (err) {
422377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
423377aa17dSLorenzo Bianconi 			 "failed setting NPU wlan descriptors\n");
424377aa17dSLorenzo Bianconi 		return err;
425377aa17dSLorenzo Bianconi 	}
426377aa17dSLorenzo Bianconi 
427880f4e3eSLorenzo Bianconi 	phy_addr += MT_RXQ_RING_BASE(qid);
428880f4e3eSLorenzo Bianconi 	phy_addr += is_mt7996(&dev->mt76) ? 0x90 : 0x20;
429377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
430377aa17dSLorenzo Bianconi 				phy_addr, GFP_KERNEL);
431377aa17dSLorenzo Bianconi 	if (err)
432377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
433377aa17dSLorenzo Bianconi 			 "failed setting NPU wlan rx pcie address\n");
434377aa17dSLorenzo Bianconi 	return err;
435377aa17dSLorenzo Bianconi }
436377aa17dSLorenzo Bianconi 
437880f4e3eSLorenzo Bianconi static int mt7996_npu_set_pcie_addr(struct mt7996_dev *dev,
438880f4e3eSLorenzo Bianconi 				    struct airoha_npu *npu)
439880f4e3eSLorenzo Bianconi {
440880f4e3eSLorenzo Bianconi 	u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
441880f4e3eSLorenzo Bianconi 	dma_addr_t dma_addr = dev->mt76.mmio.phy_addr;
442880f4e3eSLorenzo Bianconi 	int err;
443880f4e3eSLorenzo Bianconi 
444880f4e3eSLorenzo Bianconi 	dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
445880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
446880f4e3eSLorenzo Bianconi 				dma_addr, GFP_KERNEL);
447880f4e3eSLorenzo Bianconi 	if (err) {
448880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
449880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
450880f4e3eSLorenzo Bianconi 		return err;
451880f4e3eSLorenzo Bianconi 	}
452880f4e3eSLorenzo Bianconi 
453880f4e3eSLorenzo Bianconi 	dma_addr = dev->mt76.mmio.phy_addr + hif1_ofs;
454880f4e3eSLorenzo Bianconi 	if (is_mt7996(&dev->mt76)) {
455880f4e3eSLorenzo Bianconi 		dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + 0x60;
456880f4e3eSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
457880f4e3eSLorenzo Bianconi 					dma_addr, GFP_KERNEL);
458880f4e3eSLorenzo Bianconi 	} else {
459880f4e3eSLorenzo Bianconi 		dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90;
460880f4e3eSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, 1, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
461880f4e3eSLorenzo Bianconi 					dma_addr, GFP_KERNEL);
462880f4e3eSLorenzo Bianconi 	}
463880f4e3eSLorenzo Bianconi 
464880f4e3eSLorenzo Bianconi 	if (err)
465880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
466880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
467880f4e3eSLorenzo Bianconi 
468880f4e3eSLorenzo Bianconi 	return err;
469880f4e3eSLorenzo Bianconi }
470880f4e3eSLorenzo Bianconi 
471377aa17dSLorenzo Bianconi static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,
472377aa17dSLorenzo Bianconi 				   struct airoha_npu *npu)
473377aa17dSLorenzo Bianconi {
474377aa17dSLorenzo Bianconi 	int err;
475377aa17dSLorenzo Bianconi 
476880f4e3eSLorenzo Bianconi 	/* rro ring cpu idx */
477880f4e3eSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 15, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
478880f4e3eSLorenzo Bianconi 				0, GFP_KERNEL);
479880f4e3eSLorenzo Bianconi 	if (err) {
480880f4e3eSLorenzo Bianconi 		dev_warn(dev->mt76.dev,
481880f4e3eSLorenzo Bianconi 			 "failed setting NPU wlan PCIe desc addr\n");
482880f4e3eSLorenzo Bianconi 		return err;
483880f4e3eSLorenzo Bianconi 	}
484880f4e3eSLorenzo Bianconi 
485377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
486377aa17dSLorenzo Bianconi 				0, GFP_KERNEL);
487377aa17dSLorenzo Bianconi 	if (err) {
488377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr2\n");
489377aa17dSLorenzo Bianconi 		return err;
490377aa17dSLorenzo Bianconi 	}
491377aa17dSLorenzo Bianconi 
492377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
493377aa17dSLorenzo Bianconi 				0, GFP_KERNEL);
494377aa17dSLorenzo Bianconi 	if (err)
495377aa17dSLorenzo Bianconi 		dev_warn(dev->mt76.dev, "failed setting NPU wlan txrx addr7\n");
496377aa17dSLorenzo Bianconi 
497377aa17dSLorenzo Bianconi 	return err;
498377aa17dSLorenzo Bianconi }
499377aa17dSLorenzo Bianconi 
500377aa17dSLorenzo Bianconi int mt7996_npu_rx_queues_init(struct mt7996_dev *dev)
501377aa17dSLorenzo Bianconi {
502377aa17dSLorenzo Bianconi 	int err;
503377aa17dSLorenzo Bianconi 
504377aa17dSLorenzo Bianconi 	if (!mt76_npu_device_active(&dev->mt76))
505377aa17dSLorenzo Bianconi 		return 0;
506377aa17dSLorenzo Bianconi 
507377aa17dSLorenzo Bianconi 	err = mt76_npu_rx_queue_init(&dev->mt76,
508377aa17dSLorenzo Bianconi 				     &dev->mt76.q_rx[MT_RXQ_NPU0]);
509377aa17dSLorenzo Bianconi 	if (err)
510377aa17dSLorenzo Bianconi 		return err;
511377aa17dSLorenzo Bianconi 
512377aa17dSLorenzo Bianconi 	return mt76_npu_rx_queue_init(&dev->mt76,
513377aa17dSLorenzo Bianconi 				      &dev->mt76.q_rx[MT_RXQ_NPU1]);
514377aa17dSLorenzo Bianconi }
515377aa17dSLorenzo Bianconi 
51693e24914SLorenzo Bianconi int __mt7996_npu_hw_init(struct mt7996_dev *dev)
517377aa17dSLorenzo Bianconi {
518377aa17dSLorenzo Bianconi 	struct airoha_npu *npu;
51993e24914SLorenzo Bianconi 	int i, err;
520377aa17dSLorenzo Bianconi 
521377aa17dSLorenzo Bianconi 	npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
522377aa17dSLorenzo Bianconi 	if (!npu)
52393e24914SLorenzo Bianconi 		return 0;
524377aa17dSLorenzo Bianconi 
525377aa17dSLorenzo Bianconi 	err = mt7996_npu_offload_init(dev, npu);
526377aa17dSLorenzo Bianconi 	if (err)
52793e24914SLorenzo Bianconi 		return err;
528377aa17dSLorenzo Bianconi 
529880f4e3eSLorenzo Bianconi 	if (is_mt7996(&dev->mt76))
530880f4e3eSLorenzo Bianconi 		err = mt7996_npu_rxd_init(dev, npu);
531880f4e3eSLorenzo Bianconi 	else
532c93e2fbdSLorenzo Bianconi 		err = mt7992_npu_rxd_init(dev, npu);
533880f4e3eSLorenzo Bianconi 
534377aa17dSLorenzo Bianconi 	if (err)
53593e24914SLorenzo Bianconi 		return err;
536377aa17dSLorenzo Bianconi 
537377aa17dSLorenzo Bianconi 	err = mt7996_npu_txd_init(dev, npu);
538377aa17dSLorenzo Bianconi 	if (err)
53993e24914SLorenzo Bianconi 		return err;
540377aa17dSLorenzo Bianconi 
541377aa17dSLorenzo Bianconi 	err = mt7996_npu_rx_event_init(dev, npu);
542377aa17dSLorenzo Bianconi 	if (err)
54393e24914SLorenzo Bianconi 		return err;
544377aa17dSLorenzo Bianconi 
545880f4e3eSLorenzo Bianconi 	err = mt7996_npu_set_pcie_addr(dev, npu);
546880f4e3eSLorenzo Bianconi 	if (err)
54793e24914SLorenzo Bianconi 		return err;
548880f4e3eSLorenzo Bianconi 
549377aa17dSLorenzo Bianconi 	err = mt7996_npu_tx_done_init(dev, npu);
550377aa17dSLorenzo Bianconi 	if (err)
55193e24914SLorenzo Bianconi 		return err;
552377aa17dSLorenzo Bianconi 
553377aa17dSLorenzo Bianconi 	for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)
554377aa17dSLorenzo Bianconi 		airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);
55593e24914SLorenzo Bianconi 
55693e24914SLorenzo Bianconi 	return 0;
55793e24914SLorenzo Bianconi }
55893e24914SLorenzo Bianconi 
55993e24914SLorenzo Bianconi int mt7996_npu_hw_init(struct mt7996_dev *dev)
56093e24914SLorenzo Bianconi {
561*c2efd5feSLorenzo Bianconi 	int i, err;
562*c2efd5feSLorenzo Bianconi 
563*c2efd5feSLorenzo Bianconi 	BUILD_BUG_ON(ARRAY_SIZE(dev->npu_txd_addr) % 3);
564*c2efd5feSLorenzo Bianconi 
565*c2efd5feSLorenzo Bianconi 	for (i = 0; i < ARRAY_SIZE(dev->npu_txd_addr); i += 3) {
566*c2efd5feSLorenzo Bianconi 		int band = i && is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND0;
567*c2efd5feSLorenzo Bianconi 		u32 size = is_mt7996(&dev->mt76) ? band == MT_BAND2
568*c2efd5feSLorenzo Bianconi 						 ? MT7996_NPU_TX_RING_SIZE
569*c2efd5feSLorenzo Bianconi 						 : MT7996_NPU_RX_RING_SIZE / 2
570*c2efd5feSLorenzo Bianconi 						 : MT7996_TX_RING_SIZE;
571*c2efd5feSLorenzo Bianconi 
572*c2efd5feSLorenzo Bianconi 		if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
573*c2efd5feSLorenzo Bianconi 					 &dev->npu_txd_addr[i], GFP_KERNEL))
574*c2efd5feSLorenzo Bianconi 			return -ENOMEM;
575*c2efd5feSLorenzo Bianconi 
576*c2efd5feSLorenzo Bianconi 		if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
577*c2efd5feSLorenzo Bianconi 					 &dev->npu_txd_addr[i + 1],
578*c2efd5feSLorenzo Bianconi 					 GFP_KERNEL))
579*c2efd5feSLorenzo Bianconi 			return -ENOMEM;
580*c2efd5feSLorenzo Bianconi 
581*c2efd5feSLorenzo Bianconi 		if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
582*c2efd5feSLorenzo Bianconi 					 &dev->npu_txd_addr[i + 2],
583*c2efd5feSLorenzo Bianconi 					 GFP_KERNEL))
584*c2efd5feSLorenzo Bianconi 			return -ENOMEM;
585*c2efd5feSLorenzo Bianconi 	}
58693e24914SLorenzo Bianconi 
58793e24914SLorenzo Bianconi 	mutex_lock(&dev->mt76.mutex);
58893e24914SLorenzo Bianconi 	err = __mt7996_npu_hw_init(dev);
589377aa17dSLorenzo Bianconi 	mutex_unlock(&dev->mt76.mutex);
590377aa17dSLorenzo Bianconi 
591377aa17dSLorenzo Bianconi 	return err;
592377aa17dSLorenzo Bianconi }
593377aa17dSLorenzo Bianconi 
594377aa17dSLorenzo Bianconi int mt7996_npu_hw_stop(struct mt7996_dev *dev)
595377aa17dSLorenzo Bianconi {
596377aa17dSLorenzo Bianconi 	struct airoha_npu *npu;
5977aed20bdSLorenzo Bianconi 	int i, err = 0;
598377aa17dSLorenzo Bianconi 	u32 info;
599377aa17dSLorenzo Bianconi 
6007aed20bdSLorenzo Bianconi 	mutex_lock(&dev->mt76.mutex);
6017aed20bdSLorenzo Bianconi 
602377aa17dSLorenzo Bianconi 	npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
603377aa17dSLorenzo Bianconi 	if (!npu)
6047aed20bdSLorenzo Bianconi 		goto unlock;
605377aa17dSLorenzo Bianconi 
606377aa17dSLorenzo Bianconi 	err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
607377aa17dSLorenzo Bianconi 				0, GFP_KERNEL);
608377aa17dSLorenzo Bianconi 	if (err)
6097aed20bdSLorenzo Bianconi 		goto unlock;
610377aa17dSLorenzo Bianconi 
611377aa17dSLorenzo Bianconi 	for (i = 0; i < 10; i++) {
612377aa17dSLorenzo Bianconi 		err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,
613377aa17dSLorenzo Bianconi 				       &info, GFP_KERNEL);
6147aed20bdSLorenzo Bianconi 		if (!err && !info)
6157aed20bdSLorenzo Bianconi 			break;
616377aa17dSLorenzo Bianconi 
617377aa17dSLorenzo Bianconi 		err = -ETIMEDOUT;
6187aed20bdSLorenzo Bianconi 		usleep_range(10000, 15000);
619377aa17dSLorenzo Bianconi 	}
620377aa17dSLorenzo Bianconi 
621377aa17dSLorenzo Bianconi 	if (!err)
622377aa17dSLorenzo Bianconi 		err = mt76_npu_send_msg(npu, 6,
623377aa17dSLorenzo Bianconi 					WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
624377aa17dSLorenzo Bianconi 					0, GFP_KERNEL);
6257aed20bdSLorenzo Bianconi 	else
6267aed20bdSLorenzo Bianconi 		dev_err(dev->mt76.dev, "npu stop failed\n");
6277aed20bdSLorenzo Bianconi unlock:
6287aed20bdSLorenzo Bianconi 	mutex_unlock(&dev->mt76.mutex);
6297aed20bdSLorenzo Bianconi 
630377aa17dSLorenzo Bianconi 	return err;
631377aa17dSLorenzo Bianconi }
632