xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/ahb.c (revision 56970454)
1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d5c65159SKalle Valo /*
3d5c65159SKalle Valo  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4d5c65159SKalle Valo  */
5d5c65159SKalle Valo 
6d5c65159SKalle Valo #include <linux/module.h>
7d5c65159SKalle Valo #include <linux/platform_device.h>
8d5c65159SKalle Valo #include <linux/of_device.h>
9d5c65159SKalle Valo #include <linux/of.h>
10d5c65159SKalle Valo #include <linux/dma-mapping.h>
11d5c65159SKalle Valo #include "ahb.h"
12d5c65159SKalle Valo #include "debug.h"
1331858805SGovind Singh #include "hif.h"
14d5c65159SKalle Valo #include <linux/remoteproc.h>
15d5c65159SKalle Valo 
16d5c65159SKalle Valo static const struct of_device_id ath11k_ahb_of_match[] = {
17d5c65159SKalle Valo 	/* TODO: Should we change the compatible string to something similar
18d5c65159SKalle Valo 	 * to one that ath10k uses?
19d5c65159SKalle Valo 	 */
20d5c65159SKalle Valo 	{ .compatible = "qcom,ipq8074-wifi",
21d5c65159SKalle Valo 	  .data = (void *)ATH11K_HW_IPQ8074,
22d5c65159SKalle Valo 	},
23d5c65159SKalle Valo 	{ }
24d5c65159SKalle Valo };
25d5c65159SKalle Valo 
26d5c65159SKalle Valo MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
27d5c65159SKalle Valo 
281ff8ed78SGovind Singh static const struct ath11k_bus_params ath11k_ahb_bus_params = {
291ff8ed78SGovind Singh 	.mhi_support = false,
3056970454SGovind Singh 	.m3_fw_support = false,
311ff8ed78SGovind Singh };
321ff8ed78SGovind Singh 
33d5c65159SKalle Valo /* Target firmware's Copy Engine configuration. */
34d5c65159SKalle Valo static const struct ce_pipe_config target_ce_config_wlan[] = {
35d5c65159SKalle Valo 	/* CE0: host->target HTC control and raw streams */
36d5c65159SKalle Valo 	{
37d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
38d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
39d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
40d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
41d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
42d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
43d5c65159SKalle Valo 	},
44d5c65159SKalle Valo 
45d5c65159SKalle Valo 	/* CE1: target->host HTT + HTC control */
46d5c65159SKalle Valo 	{
47d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
48d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
49d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
50d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
51d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
52d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
53d5c65159SKalle Valo 	},
54d5c65159SKalle Valo 
55d5c65159SKalle Valo 	/* CE2: target->host WMI */
56d5c65159SKalle Valo 	{
57d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
58d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
59d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
60d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
61d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
62d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
63d5c65159SKalle Valo 	},
64d5c65159SKalle Valo 
65d5c65159SKalle Valo 	/* CE3: host->target WMI */
66d5c65159SKalle Valo 	{
67d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
68d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
69d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
70d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
71d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
72d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
73d5c65159SKalle Valo 	},
74d5c65159SKalle Valo 
75d5c65159SKalle Valo 	/* CE4: host->target HTT */
76d5c65159SKalle Valo 	{
77d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(4),
78d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
79d5c65159SKalle Valo 		.nentries = __cpu_to_le32(256),
80d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(256),
81d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
82d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
83d5c65159SKalle Valo 	},
84d5c65159SKalle Valo 
85d5c65159SKalle Valo 	/* CE5: target->host Pktlog */
86d5c65159SKalle Valo 	{
87d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(5),
88d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
89d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
90d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
91d5c65159SKalle Valo 		.flags = __cpu_to_le32(0),
92d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
93d5c65159SKalle Valo 	},
94d5c65159SKalle Valo 
95d5c65159SKalle Valo 	/* CE6: Reserved for target autonomous hif_memcpy */
96d5c65159SKalle Valo 	{
97d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(6),
98d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
99d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
100d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(65535),
101d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
102d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
103d5c65159SKalle Valo 	},
104d5c65159SKalle Valo 
105d5c65159SKalle Valo 	/* CE7 used only by Host */
106d5c65159SKalle Valo 	{
107d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(7),
108d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
109d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
110d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
111d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
112d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
113d5c65159SKalle Valo 	},
114d5c65159SKalle Valo 
115d5c65159SKalle Valo 	/* CE8 target->host used only by IPA */
116d5c65159SKalle Valo 	{
117d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(8),
118d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
119d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
120d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(65535),
121d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
122d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
123d5c65159SKalle Valo 	},
124d5c65159SKalle Valo 
125d5c65159SKalle Valo 	/* CE9 host->target HTT */
126d5c65159SKalle Valo 	{
127d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(9),
128d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
129d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
130d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
131d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
132d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
133d5c65159SKalle Valo 	},
134d5c65159SKalle Valo 
135d5c65159SKalle Valo 	/* CE10 target->host HTT */
136d5c65159SKalle Valo 	{
137d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(10),
138d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
139d5c65159SKalle Valo 		.nentries = __cpu_to_le32(0),
140d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(0),
141d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
142d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
143d5c65159SKalle Valo 	},
144d5c65159SKalle Valo 
145d5c65159SKalle Valo 	/* CE11 Not used */
146d5c65159SKalle Valo 	{
147d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
148d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(0),
149d5c65159SKalle Valo 		.nentries = __cpu_to_le32(0),
150d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(0),
151d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
152d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
153d5c65159SKalle Valo 	},
154d5c65159SKalle Valo };
155d5c65159SKalle Valo 
156d5c65159SKalle Valo /* Map from service/endpoint to Copy Engine.
157d5c65159SKalle Valo  * This table is derived from the CE_PCI TABLE, above.
158d5c65159SKalle Valo  * It is passed to the Target at startup for use by firmware.
159d5c65159SKalle Valo  */
160d5c65159SKalle Valo static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
161d5c65159SKalle Valo 	{
162d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
163d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
164d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
165d5c65159SKalle Valo 	},
166d5c65159SKalle Valo 	{
167d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
168d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
169d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
170d5c65159SKalle Valo 	},
171d5c65159SKalle Valo 	{
172d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
173d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
174d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
175d5c65159SKalle Valo 	},
176d5c65159SKalle Valo 	{
177d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
178d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
179d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
180d5c65159SKalle Valo 	},
181d5c65159SKalle Valo 	{
182d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
183d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
184d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
185d5c65159SKalle Valo 	},
186d5c65159SKalle Valo 	{
187d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
188d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
189d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
190d5c65159SKalle Valo 	},
191d5c65159SKalle Valo 	{
192d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
193d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
194d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
195d5c65159SKalle Valo 	},
196d5c65159SKalle Valo 	{
197d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
198d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
199d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
200d5c65159SKalle Valo 	},
201d5c65159SKalle Valo 	{
202d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
203d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
204d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
205d5c65159SKalle Valo 	},
206d5c65159SKalle Valo 	{
207d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
208d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
209d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
210d5c65159SKalle Valo 	},
211d5c65159SKalle Valo 	{
212d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
213d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
214d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(7),
215d5c65159SKalle Valo 	},
216d5c65159SKalle Valo 	{
217d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
218d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
219d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
220d5c65159SKalle Valo 	},
221d5c65159SKalle Valo 	{
222d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
223d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
224d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(9),
225d5c65159SKalle Valo 	},
226d5c65159SKalle Valo 	{
227d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
228d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
229d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
230d5c65159SKalle Valo 	},
231d5c65159SKalle Valo 	{
232d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
233d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
234d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
235d5c65159SKalle Valo 	},
236d5c65159SKalle Valo 	{
237d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
238d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
239d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
240d5c65159SKalle Valo 	},
241d5c65159SKalle Valo 	{ /* not used */
242d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
243d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
244d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
245d5c65159SKalle Valo 	},
246d5c65159SKalle Valo 	{ /* not used */
247d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
248d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
249d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
250d5c65159SKalle Valo 	},
251d5c65159SKalle Valo 	{
252d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
253d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
254d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(4),
255d5c65159SKalle Valo 	},
256d5c65159SKalle Valo 	{
257d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
258d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
259d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
260d5c65159SKalle Valo 	},
261d5c65159SKalle Valo 	{
262d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
263d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
264d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(5),
265d5c65159SKalle Valo 	},
266d5c65159SKalle Valo 
267d5c65159SKalle Valo 	/* (Additions here) */
268d5c65159SKalle Valo 
269d5c65159SKalle Valo 	{ /* terminator entry */ }
270d5c65159SKalle Valo };
271d5c65159SKalle Valo 
272d5c65159SKalle Valo #define ATH11K_IRQ_CE0_OFFSET 4
273d5c65159SKalle Valo 
274d5c65159SKalle Valo static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
275d5c65159SKalle Valo 	"misc-pulse1",
276d5c65159SKalle Valo 	"misc-latch",
277d5c65159SKalle Valo 	"sw-exception",
278d5c65159SKalle Valo 	"watchdog",
279d5c65159SKalle Valo 	"ce0",
280d5c65159SKalle Valo 	"ce1",
281d5c65159SKalle Valo 	"ce2",
282d5c65159SKalle Valo 	"ce3",
283d5c65159SKalle Valo 	"ce4",
284d5c65159SKalle Valo 	"ce5",
285d5c65159SKalle Valo 	"ce6",
286d5c65159SKalle Valo 	"ce7",
287d5c65159SKalle Valo 	"ce8",
288d5c65159SKalle Valo 	"ce9",
289d5c65159SKalle Valo 	"ce10",
290d5c65159SKalle Valo 	"ce11",
291d5c65159SKalle Valo 	"host2wbm-desc-feed",
292d5c65159SKalle Valo 	"host2reo-re-injection",
293d5c65159SKalle Valo 	"host2reo-command",
294d5c65159SKalle Valo 	"host2rxdma-monitor-ring3",
295d5c65159SKalle Valo 	"host2rxdma-monitor-ring2",
296d5c65159SKalle Valo 	"host2rxdma-monitor-ring1",
297d5c65159SKalle Valo 	"reo2ost-exception",
298d5c65159SKalle Valo 	"wbm2host-rx-release",
299d5c65159SKalle Valo 	"reo2host-status",
300d5c65159SKalle Valo 	"reo2host-destination-ring4",
301d5c65159SKalle Valo 	"reo2host-destination-ring3",
302d5c65159SKalle Valo 	"reo2host-destination-ring2",
303d5c65159SKalle Valo 	"reo2host-destination-ring1",
304d5c65159SKalle Valo 	"rxdma2host-monitor-destination-mac3",
305d5c65159SKalle Valo 	"rxdma2host-monitor-destination-mac2",
306d5c65159SKalle Valo 	"rxdma2host-monitor-destination-mac1",
307d5c65159SKalle Valo 	"ppdu-end-interrupts-mac3",
308d5c65159SKalle Valo 	"ppdu-end-interrupts-mac2",
309d5c65159SKalle Valo 	"ppdu-end-interrupts-mac1",
310d5c65159SKalle Valo 	"rxdma2host-monitor-status-ring-mac3",
311d5c65159SKalle Valo 	"rxdma2host-monitor-status-ring-mac2",
312d5c65159SKalle Valo 	"rxdma2host-monitor-status-ring-mac1",
313d5c65159SKalle Valo 	"host2rxdma-host-buf-ring-mac3",
314d5c65159SKalle Valo 	"host2rxdma-host-buf-ring-mac2",
315d5c65159SKalle Valo 	"host2rxdma-host-buf-ring-mac1",
316d5c65159SKalle Valo 	"rxdma2host-destination-ring-mac3",
317d5c65159SKalle Valo 	"rxdma2host-destination-ring-mac2",
318d5c65159SKalle Valo 	"rxdma2host-destination-ring-mac1",
319d5c65159SKalle Valo 	"host2tcl-input-ring4",
320d5c65159SKalle Valo 	"host2tcl-input-ring3",
321d5c65159SKalle Valo 	"host2tcl-input-ring2",
322d5c65159SKalle Valo 	"host2tcl-input-ring1",
323d5c65159SKalle Valo 	"wbm2host-tx-completions-ring3",
324d5c65159SKalle Valo 	"wbm2host-tx-completions-ring2",
325d5c65159SKalle Valo 	"wbm2host-tx-completions-ring1",
326d5c65159SKalle Valo 	"tcl2host-status-ring",
327d5c65159SKalle Valo };
328d5c65159SKalle Valo 
329d5c65159SKalle Valo /* enum ext_irq_num - irq numbers that can be used by external modules
330d5c65159SKalle Valo  * like datapath
331d5c65159SKalle Valo  */
332d5c65159SKalle Valo enum ext_irq_num {
333d5c65159SKalle Valo 	host2wbm_desc_feed = 16,
334d5c65159SKalle Valo 	host2reo_re_injection,
335d5c65159SKalle Valo 	host2reo_command,
336d5c65159SKalle Valo 	host2rxdma_monitor_ring3,
337d5c65159SKalle Valo 	host2rxdma_monitor_ring2,
338d5c65159SKalle Valo 	host2rxdma_monitor_ring1,
339d5c65159SKalle Valo 	reo2host_exception,
340d5c65159SKalle Valo 	wbm2host_rx_release,
341d5c65159SKalle Valo 	reo2host_status,
342d5c65159SKalle Valo 	reo2host_destination_ring4,
343d5c65159SKalle Valo 	reo2host_destination_ring3,
344d5c65159SKalle Valo 	reo2host_destination_ring2,
345d5c65159SKalle Valo 	reo2host_destination_ring1,
346d5c65159SKalle Valo 	rxdma2host_monitor_destination_mac3,
347d5c65159SKalle Valo 	rxdma2host_monitor_destination_mac2,
348d5c65159SKalle Valo 	rxdma2host_monitor_destination_mac1,
349d5c65159SKalle Valo 	ppdu_end_interrupts_mac3,
350d5c65159SKalle Valo 	ppdu_end_interrupts_mac2,
351d5c65159SKalle Valo 	ppdu_end_interrupts_mac1,
352d5c65159SKalle Valo 	rxdma2host_monitor_status_ring_mac3,
353d5c65159SKalle Valo 	rxdma2host_monitor_status_ring_mac2,
354d5c65159SKalle Valo 	rxdma2host_monitor_status_ring_mac1,
355d5c65159SKalle Valo 	host2rxdma_host_buf_ring_mac3,
356d5c65159SKalle Valo 	host2rxdma_host_buf_ring_mac2,
357d5c65159SKalle Valo 	host2rxdma_host_buf_ring_mac1,
358d5c65159SKalle Valo 	rxdma2host_destination_ring_mac3,
359d5c65159SKalle Valo 	rxdma2host_destination_ring_mac2,
360d5c65159SKalle Valo 	rxdma2host_destination_ring_mac1,
361d5c65159SKalle Valo 	host2tcl_input_ring4,
362d5c65159SKalle Valo 	host2tcl_input_ring3,
363d5c65159SKalle Valo 	host2tcl_input_ring2,
364d5c65159SKalle Valo 	host2tcl_input_ring1,
365d5c65159SKalle Valo 	wbm2host_tx_completions_ring3,
366d5c65159SKalle Valo 	wbm2host_tx_completions_ring2,
367d5c65159SKalle Valo 	wbm2host_tx_completions_ring1,
368d5c65159SKalle Valo 	tcl2host_status_ring,
369d5c65159SKalle Valo };
370d5c65159SKalle Valo 
37131858805SGovind Singh static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
37231858805SGovind Singh {
37331858805SGovind Singh 	return ioread32(ab->mem + offset);
37431858805SGovind Singh }
37531858805SGovind Singh 
37631858805SGovind Singh static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
37731858805SGovind Singh {
37831858805SGovind Singh 	iowrite32(value, ab->mem + offset);
37931858805SGovind Singh }
38031858805SGovind Singh 
381d5c65159SKalle Valo static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
382d5c65159SKalle Valo {
383d5c65159SKalle Valo 	int i;
384d5c65159SKalle Valo 
385d5c65159SKalle Valo 	for (i = 0; i < CE_COUNT; i++) {
386d5c65159SKalle Valo 		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
387d5c65159SKalle Valo 
388d5c65159SKalle Valo 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
389d5c65159SKalle Valo 			continue;
390d5c65159SKalle Valo 
391d5c65159SKalle Valo 		tasklet_kill(&ce_pipe->intr_tq);
392d5c65159SKalle Valo 	}
393d5c65159SKalle Valo }
394d5c65159SKalle Valo 
395d5c65159SKalle Valo static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
396d5c65159SKalle Valo {
397d5c65159SKalle Valo 	int i;
398d5c65159SKalle Valo 
399d5c65159SKalle Valo 	for (i = 0; i < irq_grp->num_irq; i++)
400d5c65159SKalle Valo 		disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
401d5c65159SKalle Valo }
402d5c65159SKalle Valo 
403d5c65159SKalle Valo static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
404d5c65159SKalle Valo {
405d5c65159SKalle Valo 	int i;
406d5c65159SKalle Valo 
407d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
408d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
409d5c65159SKalle Valo 
410d5c65159SKalle Valo 		ath11k_ahb_ext_grp_disable(irq_grp);
411d5c65159SKalle Valo 
412d5c65159SKalle Valo 		napi_synchronize(&irq_grp->napi);
413d5c65159SKalle Valo 		napi_disable(&irq_grp->napi);
414d5c65159SKalle Valo 	}
415d5c65159SKalle Valo }
416d5c65159SKalle Valo 
417d5c65159SKalle Valo static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
418d5c65159SKalle Valo {
419d5c65159SKalle Valo 	int i;
420d5c65159SKalle Valo 
421d5c65159SKalle Valo 	for (i = 0; i < irq_grp->num_irq; i++)
422d5c65159SKalle Valo 		enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
423d5c65159SKalle Valo }
424d5c65159SKalle Valo 
425d5c65159SKalle Valo static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset)
426d5c65159SKalle Valo {
427d5c65159SKalle Valo 	u32 val;
428d5c65159SKalle Valo 
429d5c65159SKalle Valo 	val = ath11k_ahb_read32(ab, offset);
430d5c65159SKalle Valo 	ath11k_ahb_write32(ab, offset, val | BIT(bit));
431d5c65159SKalle Valo }
432d5c65159SKalle Valo 
433d5c65159SKalle Valo static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
434d5c65159SKalle Valo {
435d5c65159SKalle Valo 	u32 val;
436d5c65159SKalle Valo 
437d5c65159SKalle Valo 	val = ath11k_ahb_read32(ab, offset);
438d5c65159SKalle Valo 	ath11k_ahb_write32(ab, offset, val & ~BIT(bit));
439d5c65159SKalle Valo }
440d5c65159SKalle Valo 
441d5c65159SKalle Valo static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
442d5c65159SKalle Valo {
443d5c65159SKalle Valo 	const struct ce_pipe_config *ce_config;
444d5c65159SKalle Valo 
445d5c65159SKalle Valo 	ce_config = &target_ce_config_wlan[ce_id];
446d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
447d5c65159SKalle Valo 		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
448d5c65159SKalle Valo 
449d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
450d5c65159SKalle Valo 		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
451d5c65159SKalle Valo 		ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
452d5c65159SKalle Valo 				    CE_HOST_IE_3_ADDRESS);
453d5c65159SKalle Valo 	}
454d5c65159SKalle Valo }
455d5c65159SKalle Valo 
456d5c65159SKalle Valo static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
457d5c65159SKalle Valo {
458d5c65159SKalle Valo 	const struct ce_pipe_config *ce_config;
459d5c65159SKalle Valo 
460d5c65159SKalle Valo 	ce_config = &target_ce_config_wlan[ce_id];
461d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
462d5c65159SKalle Valo 		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
463d5c65159SKalle Valo 
464d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
465d5c65159SKalle Valo 		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
466d5c65159SKalle Valo 		ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
467d5c65159SKalle Valo 				      CE_HOST_IE_3_ADDRESS);
468d5c65159SKalle Valo 	}
469d5c65159SKalle Valo }
470d5c65159SKalle Valo 
471d5c65159SKalle Valo static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
472d5c65159SKalle Valo {
473d5c65159SKalle Valo 	int i;
474d5c65159SKalle Valo 	int irq_idx;
475d5c65159SKalle Valo 
476d5c65159SKalle Valo 	for (i = 0; i < CE_COUNT; i++) {
477d5c65159SKalle Valo 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
478d5c65159SKalle Valo 			continue;
479d5c65159SKalle Valo 
480d5c65159SKalle Valo 		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
481d5c65159SKalle Valo 		synchronize_irq(ab->irq_num[irq_idx]);
482d5c65159SKalle Valo 	}
483d5c65159SKalle Valo }
484d5c65159SKalle Valo 
485d5c65159SKalle Valo static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab)
486d5c65159SKalle Valo {
487d5c65159SKalle Valo 	int i, j;
488d5c65159SKalle Valo 	int irq_idx;
489d5c65159SKalle Valo 
490d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
491d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
492d5c65159SKalle Valo 
493d5c65159SKalle Valo 		for (j = 0; j < irq_grp->num_irq; j++) {
494d5c65159SKalle Valo 			irq_idx = irq_grp->irqs[j];
495d5c65159SKalle Valo 			synchronize_irq(ab->irq_num[irq_idx]);
496d5c65159SKalle Valo 		}
497d5c65159SKalle Valo 	}
498d5c65159SKalle Valo }
499d5c65159SKalle Valo 
500d5c65159SKalle Valo static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
501d5c65159SKalle Valo {
502d5c65159SKalle Valo 	int i;
503d5c65159SKalle Valo 
504d5c65159SKalle Valo 	for (i = 0; i < CE_COUNT; i++) {
505d5c65159SKalle Valo 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
506d5c65159SKalle Valo 			continue;
507d5c65159SKalle Valo 		ath11k_ahb_ce_irq_enable(ab, i);
508d5c65159SKalle Valo 	}
509d5c65159SKalle Valo }
510d5c65159SKalle Valo 
511d5c65159SKalle Valo static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
512d5c65159SKalle Valo {
513d5c65159SKalle Valo 	int i;
514d5c65159SKalle Valo 
515d5c65159SKalle Valo 	for (i = 0; i < CE_COUNT; i++) {
516d5c65159SKalle Valo 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
517d5c65159SKalle Valo 			continue;
518d5c65159SKalle Valo 		ath11k_ahb_ce_irq_disable(ab, i);
519d5c65159SKalle Valo 	}
520d5c65159SKalle Valo }
521d5c65159SKalle Valo 
52231858805SGovind Singh static int ath11k_ahb_start(struct ath11k_base *ab)
523d5c65159SKalle Valo {
524d5c65159SKalle Valo 	ath11k_ahb_ce_irqs_enable(ab);
525d5c65159SKalle Valo 	ath11k_ce_rx_post_buf(ab);
526d5c65159SKalle Valo 
527d5c65159SKalle Valo 	return 0;
528d5c65159SKalle Valo }
529d5c65159SKalle Valo 
53031858805SGovind Singh static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
531d5c65159SKalle Valo {
532d5c65159SKalle Valo 	int i;
533d5c65159SKalle Valo 
534d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
535d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
536d5c65159SKalle Valo 
537d5c65159SKalle Valo 		napi_enable(&irq_grp->napi);
538d5c65159SKalle Valo 		ath11k_ahb_ext_grp_enable(irq_grp);
539d5c65159SKalle Valo 	}
540d5c65159SKalle Valo }
541d5c65159SKalle Valo 
54231858805SGovind Singh static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
543d5c65159SKalle Valo {
544d5c65159SKalle Valo 	__ath11k_ahb_ext_irq_disable(ab);
545d5c65159SKalle Valo 	ath11k_ahb_sync_ext_irqs(ab);
546d5c65159SKalle Valo }
547d5c65159SKalle Valo 
54831858805SGovind Singh static void ath11k_ahb_stop(struct ath11k_base *ab)
549d5c65159SKalle Valo {
550d5c65159SKalle Valo 	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
551d5c65159SKalle Valo 		ath11k_ahb_ce_irqs_disable(ab);
552d5c65159SKalle Valo 	ath11k_ahb_sync_ce_irqs(ab);
553d5c65159SKalle Valo 	ath11k_ahb_kill_tasklets(ab);
554d5c65159SKalle Valo 	del_timer_sync(&ab->rx_replenish_retry);
555d5c65159SKalle Valo 	ath11k_ce_cleanup_pipes(ab);
556d5c65159SKalle Valo }
557d5c65159SKalle Valo 
55831858805SGovind Singh static int ath11k_ahb_power_up(struct ath11k_base *ab)
559d5c65159SKalle Valo {
560d5c65159SKalle Valo 	int ret;
561d5c65159SKalle Valo 
562d5c65159SKalle Valo 	ret = rproc_boot(ab->tgt_rproc);
563d5c65159SKalle Valo 	if (ret)
564d5c65159SKalle Valo 		ath11k_err(ab, "failed to boot the remote processor Q6\n");
565d5c65159SKalle Valo 
566d5c65159SKalle Valo 	return ret;
567d5c65159SKalle Valo }
568d5c65159SKalle Valo 
56931858805SGovind Singh static void ath11k_ahb_power_down(struct ath11k_base *ab)
570d5c65159SKalle Valo {
571d5c65159SKalle Valo 	rproc_shutdown(ab->tgt_rproc);
572d5c65159SKalle Valo }
573d5c65159SKalle Valo 
574d5c65159SKalle Valo static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
575d5c65159SKalle Valo {
576d5c65159SKalle Valo 	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
577d5c65159SKalle Valo 
578d6af906dSAnilkumar Kolli 	cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan) - 1;
579d6af906dSAnilkumar Kolli 	cfg->tgt_ce = target_ce_config_wlan;
580d6af906dSAnilkumar Kolli 	cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan);
581d6af906dSAnilkumar Kolli 	cfg->svc_to_ce_map = target_service_to_ce_map_wlan;
582d5c65159SKalle Valo }
583d5c65159SKalle Valo 
584d5c65159SKalle Valo static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
585d5c65159SKalle Valo {
586d5c65159SKalle Valo 	int i, j;
587d5c65159SKalle Valo 
588d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
589d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
590d5c65159SKalle Valo 
591d5c65159SKalle Valo 		for (j = 0; j < irq_grp->num_irq; j++)
592d5c65159SKalle Valo 			free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
593d5c65159SKalle Valo 	}
594d5c65159SKalle Valo }
595d5c65159SKalle Valo 
596d5c65159SKalle Valo static void ath11k_ahb_free_irq(struct ath11k_base *ab)
597d5c65159SKalle Valo {
598d5c65159SKalle Valo 	int irq_idx;
599d5c65159SKalle Valo 	int i;
600d5c65159SKalle Valo 
601d5c65159SKalle Valo 	for (i = 0; i < CE_COUNT; i++) {
602d5c65159SKalle Valo 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
603d5c65159SKalle Valo 			continue;
604d5c65159SKalle Valo 		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
605d5c65159SKalle Valo 		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
606d5c65159SKalle Valo 	}
607d5c65159SKalle Valo 
608d5c65159SKalle Valo 	ath11k_ahb_free_ext_irq(ab);
609d5c65159SKalle Valo }
610d5c65159SKalle Valo 
611d5c65159SKalle Valo static void ath11k_ahb_ce_tasklet(unsigned long data)
612d5c65159SKalle Valo {
613d5c65159SKalle Valo 	struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
614d5c65159SKalle Valo 
615d5c65159SKalle Valo 	ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
616d5c65159SKalle Valo 
617d5c65159SKalle Valo 	ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
618d5c65159SKalle Valo }
619d5c65159SKalle Valo 
620d5c65159SKalle Valo static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
621d5c65159SKalle Valo {
622d5c65159SKalle Valo 	struct ath11k_ce_pipe *ce_pipe = arg;
623d5c65159SKalle Valo 
6245118935bSManikanta Pubbisetty 	/* last interrupt received for this CE */
6255118935bSManikanta Pubbisetty 	ce_pipe->timestamp = jiffies;
6265118935bSManikanta Pubbisetty 
627d5c65159SKalle Valo 	ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
628d5c65159SKalle Valo 
629d5c65159SKalle Valo 	tasklet_schedule(&ce_pipe->intr_tq);
630d5c65159SKalle Valo 
631d5c65159SKalle Valo 	return IRQ_HANDLED;
632d5c65159SKalle Valo }
633d5c65159SKalle Valo 
634d5c65159SKalle Valo static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
635d5c65159SKalle Valo {
636d5c65159SKalle Valo 	struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
637d5c65159SKalle Valo 						struct ath11k_ext_irq_grp,
638d5c65159SKalle Valo 						napi);
639d5c65159SKalle Valo 	struct ath11k_base *ab = irq_grp->ab;
640d5c65159SKalle Valo 	int work_done;
641d5c65159SKalle Valo 
642d5c65159SKalle Valo 	work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
643d5c65159SKalle Valo 	if (work_done < budget) {
644d5c65159SKalle Valo 		napi_complete_done(napi, work_done);
645d5c65159SKalle Valo 		ath11k_ahb_ext_grp_enable(irq_grp);
646d5c65159SKalle Valo 	}
647d5c65159SKalle Valo 
648d5c65159SKalle Valo 	if (work_done > budget)
649d5c65159SKalle Valo 		work_done = budget;
650d5c65159SKalle Valo 
651d5c65159SKalle Valo 	return work_done;
652d5c65159SKalle Valo }
653d5c65159SKalle Valo 
654d5c65159SKalle Valo static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
655d5c65159SKalle Valo {
656d5c65159SKalle Valo 	struct ath11k_ext_irq_grp *irq_grp = arg;
657d5c65159SKalle Valo 
6585118935bSManikanta Pubbisetty 	/* last interrupt received for this group */
6595118935bSManikanta Pubbisetty 	irq_grp->timestamp = jiffies;
6605118935bSManikanta Pubbisetty 
661d5c65159SKalle Valo 	ath11k_ahb_ext_grp_disable(irq_grp);
662d5c65159SKalle Valo 
663d5c65159SKalle Valo 	napi_schedule(&irq_grp->napi);
664d5c65159SKalle Valo 
665d5c65159SKalle Valo 	return IRQ_HANDLED;
666d5c65159SKalle Valo }
667d5c65159SKalle Valo 
668d5c65159SKalle Valo static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
669d5c65159SKalle Valo {
670d547ca4cSAnilkumar Kolli 	struct ath11k_hw_params *hw = &ab->hw_params;
671d5c65159SKalle Valo 	int i, j;
672d5c65159SKalle Valo 	int irq;
673d5c65159SKalle Valo 	int ret;
674d5c65159SKalle Valo 
675d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
676d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
677d5c65159SKalle Valo 		u32 num_irq = 0;
678d5c65159SKalle Valo 
679d5c65159SKalle Valo 		irq_grp->ab = ab;
680d5c65159SKalle Valo 		irq_grp->grp_id = i;
681d5c65159SKalle Valo 		init_dummy_netdev(&irq_grp->napi_ndev);
682d5c65159SKalle Valo 		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
683d5c65159SKalle Valo 			       ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
684d5c65159SKalle Valo 
685d5c65159SKalle Valo 		for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
68634d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->tx[i] & BIT(j)) {
687d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] =
688d5c65159SKalle Valo 					wbm2host_tx_completions_ring1 - j;
689d5c65159SKalle Valo 			}
690d5c65159SKalle Valo 
69134d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->rx[i] & BIT(j)) {
692d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] =
693d5c65159SKalle Valo 					reo2host_destination_ring1 - j;
694d5c65159SKalle Valo 			}
695d5c65159SKalle Valo 
69634d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->rx_err[i] & BIT(j))
697d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] = reo2host_exception;
698d5c65159SKalle Valo 
69934d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j))
700d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] = wbm2host_rx_release;
701d5c65159SKalle Valo 
70234d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->reo_status[i] & BIT(j))
703d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] = reo2host_status;
704d5c65159SKalle Valo 
705d547ca4cSAnilkumar Kolli 			if (j < ab->hw_params.max_radios) {
70634d5a3a8SKalle Valo 				if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
707d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
708d547ca4cSAnilkumar Kolli 						rxdma2host_destination_ring_mac1 -
709d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
710d5c65159SKalle Valo 				}
711d5c65159SKalle Valo 
71234d5a3a8SKalle Valo 				if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) {
713d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
714d547ca4cSAnilkumar Kolli 						host2rxdma_host_buf_ring_mac1 -
715d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
716d5c65159SKalle Valo 				}
717d5c65159SKalle Valo 
71834d5a3a8SKalle Valo 				if (ab->hw_params.ring_mask->rx_mon_status[i] & BIT(j)) {
719d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
720d5c65159SKalle Valo 						ppdu_end_interrupts_mac1 -
721d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
722d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
723d5c65159SKalle Valo 						rxdma2host_monitor_status_ring_mac1 -
724d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
725d5c65159SKalle Valo 				}
726d5c65159SKalle Valo 			}
727d5c65159SKalle Valo 		}
728d5c65159SKalle Valo 		irq_grp->num_irq = num_irq;
729d5c65159SKalle Valo 
730d5c65159SKalle Valo 		for (j = 0; j < irq_grp->num_irq; j++) {
731d5c65159SKalle Valo 			int irq_idx = irq_grp->irqs[j];
732d5c65159SKalle Valo 
733d5c65159SKalle Valo 			irq = platform_get_irq_byname(ab->pdev,
734d5c65159SKalle Valo 						      irq_name[irq_idx]);
735d5c65159SKalle Valo 			ab->irq_num[irq_idx] = irq;
73605090864SManikanta Pubbisetty 			irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
737d5c65159SKalle Valo 			ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler,
738d5c65159SKalle Valo 					  IRQF_TRIGGER_RISING,
739d5c65159SKalle Valo 					  irq_name[irq_idx], irq_grp);
740d5c65159SKalle Valo 			if (ret) {
741d5c65159SKalle Valo 				ath11k_err(ab, "failed request_irq for %d\n",
742d5c65159SKalle Valo 					   irq);
743d5c65159SKalle Valo 			}
744d5c65159SKalle Valo 		}
745d5c65159SKalle Valo 	}
746d5c65159SKalle Valo 
747d5c65159SKalle Valo 	return 0;
748d5c65159SKalle Valo }
749d5c65159SKalle Valo 
750d5c65159SKalle Valo static int ath11k_ahb_config_irq(struct ath11k_base *ab)
751d5c65159SKalle Valo {
752d5c65159SKalle Valo 	int irq, irq_idx, i;
753d5c65159SKalle Valo 	int ret;
754d5c65159SKalle Valo 
755d5c65159SKalle Valo 	/* Configure CE irqs */
756d5c65159SKalle Valo 	for (i = 0; i < CE_COUNT; i++) {
757d5c65159SKalle Valo 		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
758d5c65159SKalle Valo 
759d5c65159SKalle Valo 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
760d5c65159SKalle Valo 			continue;
761d5c65159SKalle Valo 
762d5c65159SKalle Valo 		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
763d5c65159SKalle Valo 
764d5c65159SKalle Valo 		tasklet_init(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet,
765d5c65159SKalle Valo 			     (unsigned long)ce_pipe);
766d5c65159SKalle Valo 		irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
767d5c65159SKalle Valo 		ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
768d5c65159SKalle Valo 				  IRQF_TRIGGER_RISING, irq_name[irq_idx],
769d5c65159SKalle Valo 				  ce_pipe);
770d5c65159SKalle Valo 		if (ret)
771d5c65159SKalle Valo 			return ret;
772d5c65159SKalle Valo 
773d5c65159SKalle Valo 		ab->irq_num[irq_idx] = irq;
774d5c65159SKalle Valo 	}
775d5c65159SKalle Valo 
776d5c65159SKalle Valo 	/* Configure external interrupts */
777d5c65159SKalle Valo 	ret = ath11k_ahb_ext_irq_config(ab);
778d5c65159SKalle Valo 
779d5c65159SKalle Valo 	return ret;
780d5c65159SKalle Valo }
781d5c65159SKalle Valo 
78231858805SGovind Singh static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
783d5c65159SKalle Valo 					  u8 *ul_pipe, u8 *dl_pipe)
784d5c65159SKalle Valo {
785d5c65159SKalle Valo 	const struct service_to_pipe *entry;
786d5c65159SKalle Valo 	bool ul_set = false, dl_set = false;
787d5c65159SKalle Valo 	int i;
788d5c65159SKalle Valo 
789d5c65159SKalle Valo 	for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
790d5c65159SKalle Valo 		entry = &target_service_to_ce_map_wlan[i];
791d5c65159SKalle Valo 
792d5c65159SKalle Valo 		if (__le32_to_cpu(entry->service_id) != service_id)
793d5c65159SKalle Valo 			continue;
794d5c65159SKalle Valo 
795d5c65159SKalle Valo 		switch (__le32_to_cpu(entry->pipedir)) {
796d5c65159SKalle Valo 		case PIPEDIR_NONE:
797d5c65159SKalle Valo 			break;
798d5c65159SKalle Valo 		case PIPEDIR_IN:
799d5c65159SKalle Valo 			WARN_ON(dl_set);
800d5c65159SKalle Valo 			*dl_pipe = __le32_to_cpu(entry->pipenum);
801d5c65159SKalle Valo 			dl_set = true;
802d5c65159SKalle Valo 			break;
803d5c65159SKalle Valo 		case PIPEDIR_OUT:
804d5c65159SKalle Valo 			WARN_ON(ul_set);
805d5c65159SKalle Valo 			*ul_pipe = __le32_to_cpu(entry->pipenum);
806d5c65159SKalle Valo 			ul_set = true;
807d5c65159SKalle Valo 			break;
808d5c65159SKalle Valo 		case PIPEDIR_INOUT:
809d5c65159SKalle Valo 			WARN_ON(dl_set);
810d5c65159SKalle Valo 			WARN_ON(ul_set);
811d5c65159SKalle Valo 			*dl_pipe = __le32_to_cpu(entry->pipenum);
812d5c65159SKalle Valo 			*ul_pipe = __le32_to_cpu(entry->pipenum);
813d5c65159SKalle Valo 			dl_set = true;
814d5c65159SKalle Valo 			ul_set = true;
815d5c65159SKalle Valo 			break;
816d5c65159SKalle Valo 		}
817d5c65159SKalle Valo 	}
818d5c65159SKalle Valo 
819d5c65159SKalle Valo 	if (WARN_ON(!ul_set || !dl_set))
820d5c65159SKalle Valo 		return -ENOENT;
821d5c65159SKalle Valo 
822d5c65159SKalle Valo 	return 0;
823d5c65159SKalle Valo }
824d5c65159SKalle Valo 
82531858805SGovind Singh static const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
82631858805SGovind Singh 	.start = ath11k_ahb_start,
82731858805SGovind Singh 	.stop = ath11k_ahb_stop,
82831858805SGovind Singh 	.read32 = ath11k_ahb_read32,
82931858805SGovind Singh 	.write32 = ath11k_ahb_write32,
83031858805SGovind Singh 	.irq_enable = ath11k_ahb_ext_irq_enable,
83131858805SGovind Singh 	.irq_disable = ath11k_ahb_ext_irq_disable,
83231858805SGovind Singh 	.map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
83331858805SGovind Singh 	.power_down = ath11k_ahb_power_down,
83431858805SGovind Singh 	.power_up = ath11k_ahb_power_up,
83531858805SGovind Singh };
83631858805SGovind Singh 
837d5c65159SKalle Valo static int ath11k_ahb_probe(struct platform_device *pdev)
838d5c65159SKalle Valo {
839d5c65159SKalle Valo 	struct ath11k_base *ab;
840d5c65159SKalle Valo 	const struct of_device_id *of_id;
841d5c65159SKalle Valo 	struct resource *mem_res;
842d5c65159SKalle Valo 	void __iomem *mem;
843d5c65159SKalle Valo 	int ret;
844d5c65159SKalle Valo 
845d5c65159SKalle Valo 	of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
846d5c65159SKalle Valo 	if (!of_id) {
847d5c65159SKalle Valo 		dev_err(&pdev->dev, "failed to find matching device tree id\n");
848d5c65159SKalle Valo 		return -EINVAL;
849d5c65159SKalle Valo 	}
850d5c65159SKalle Valo 
851c8ffcd12SWei Yongjun 	mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
852d5c65159SKalle Valo 	if (IS_ERR(mem)) {
853d5c65159SKalle Valo 		dev_err(&pdev->dev, "ioremap error\n");
854d5c65159SKalle Valo 		return PTR_ERR(mem);
855d5c65159SKalle Valo 	}
856d5c65159SKalle Valo 
857d5c65159SKalle Valo 	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
858d5c65159SKalle Valo 	if (ret) {
859d5c65159SKalle Valo 		dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
860d5c65159SKalle Valo 		return ret;
861d5c65159SKalle Valo 	}
862d5c65159SKalle Valo 
8631ff8ed78SGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB, &ath11k_ahb_bus_params);
864d5c65159SKalle Valo 	if (!ab) {
865d5c65159SKalle Valo 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
866d5c65159SKalle Valo 		return -ENOMEM;
867d5c65159SKalle Valo 	}
868d5c65159SKalle Valo 
86931858805SGovind Singh 	ab->hif.ops = &ath11k_ahb_hif_ops;
870d5c65159SKalle Valo 	ab->pdev = pdev;
871d5c65159SKalle Valo 	ab->hw_rev = (enum ath11k_hw_rev)of_id->data;
872d5c65159SKalle Valo 	ab->mem = mem;
873d5c65159SKalle Valo 	ab->mem_len = resource_size(mem_res);
874d5c65159SKalle Valo 	platform_set_drvdata(pdev, ab);
875d5c65159SKalle Valo 
876b8246f88SKalle Valo 	ret = ath11k_core_pre_init(ab);
877b8246f88SKalle Valo 	if (ret)
878b8246f88SKalle Valo 		goto err_core_free;
879b8246f88SKalle Valo 
880d5c65159SKalle Valo 	ret = ath11k_hal_srng_init(ab);
881d5c65159SKalle Valo 	if (ret)
882d5c65159SKalle Valo 		goto err_core_free;
883d5c65159SKalle Valo 
884d5c65159SKalle Valo 	ret = ath11k_ce_alloc_pipes(ab);
885d5c65159SKalle Valo 	if (ret) {
886d5c65159SKalle Valo 		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
887d5c65159SKalle Valo 		goto err_hal_srng_deinit;
888d5c65159SKalle Valo 	}
889d5c65159SKalle Valo 
890d5c65159SKalle Valo 	ath11k_ahb_init_qmi_ce_config(ab);
891d5c65159SKalle Valo 
892d5c65159SKalle Valo 	ret = ath11k_core_init(ab);
893d5c65159SKalle Valo 	if (ret) {
894d5c65159SKalle Valo 		ath11k_err(ab, "failed to init core: %d\n", ret);
895d5c65159SKalle Valo 		goto err_ce_free;
896d5c65159SKalle Valo 	}
897d5c65159SKalle Valo 
898166e22b3SAnilkumar Kolli 	ret = ath11k_ahb_config_irq(ab);
899166e22b3SAnilkumar Kolli 	if (ret) {
900166e22b3SAnilkumar Kolli 		ath11k_err(ab, "failed to configure irq: %d\n", ret);
901166e22b3SAnilkumar Kolli 		goto err_ce_free;
902166e22b3SAnilkumar Kolli 	}
903166e22b3SAnilkumar Kolli 
904d5c65159SKalle Valo 	return 0;
905d5c65159SKalle Valo 
906d5c65159SKalle Valo err_ce_free:
907d5c65159SKalle Valo 	ath11k_ce_free_pipes(ab);
908d5c65159SKalle Valo 
909d5c65159SKalle Valo err_hal_srng_deinit:
910d5c65159SKalle Valo 	ath11k_hal_srng_deinit(ab);
911d5c65159SKalle Valo 
912d5c65159SKalle Valo err_core_free:
913d5c65159SKalle Valo 	ath11k_core_free(ab);
914d5c65159SKalle Valo 	platform_set_drvdata(pdev, NULL);
915d5c65159SKalle Valo 
916d5c65159SKalle Valo 	return ret;
917d5c65159SKalle Valo }
918d5c65159SKalle Valo 
919d5c65159SKalle Valo static int ath11k_ahb_remove(struct platform_device *pdev)
920d5c65159SKalle Valo {
921d5c65159SKalle Valo 	struct ath11k_base *ab = platform_get_drvdata(pdev);
922d5c65159SKalle Valo 
923d5c65159SKalle Valo 	reinit_completion(&ab->driver_recovery);
924d5c65159SKalle Valo 
925d5c65159SKalle Valo 	if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags))
926d5c65159SKalle Valo 		wait_for_completion_timeout(&ab->driver_recovery,
927d5c65159SKalle Valo 					    ATH11K_AHB_RECOVERY_TIMEOUT);
928d5c65159SKalle Valo 
929d5c65159SKalle Valo 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
930d5c65159SKalle Valo 	cancel_work_sync(&ab->restart_work);
931d5c65159SKalle Valo 
932d5c65159SKalle Valo 	ath11k_core_deinit(ab);
933d5c65159SKalle Valo 	ath11k_ahb_free_irq(ab);
934d5c65159SKalle Valo 
935d5c65159SKalle Valo 	ath11k_hal_srng_deinit(ab);
936d5c65159SKalle Valo 	ath11k_ce_free_pipes(ab);
937d5c65159SKalle Valo 	ath11k_core_free(ab);
938d5c65159SKalle Valo 	platform_set_drvdata(pdev, NULL);
939d5c65159SKalle Valo 
940d5c65159SKalle Valo 	return 0;
941d5c65159SKalle Valo }
942d5c65159SKalle Valo 
943d5c65159SKalle Valo static struct platform_driver ath11k_ahb_driver = {
944d5c65159SKalle Valo 	.driver         = {
945d5c65159SKalle Valo 		.name   = "ath11k",
946d5c65159SKalle Valo 		.of_match_table = ath11k_ahb_of_match,
947d5c65159SKalle Valo 	},
948d5c65159SKalle Valo 	.probe  = ath11k_ahb_probe,
949d5c65159SKalle Valo 	.remove = ath11k_ahb_remove,
950d5c65159SKalle Valo };
951d5c65159SKalle Valo 
95231858805SGovind Singh static int ath11k_ahb_init(void)
953d5c65159SKalle Valo {
954d5c65159SKalle Valo 	return platform_driver_register(&ath11k_ahb_driver);
955d5c65159SKalle Valo }
95631858805SGovind Singh module_init(ath11k_ahb_init);
957d5c65159SKalle Valo 
95831858805SGovind Singh static void ath11k_ahb_exit(void)
959d5c65159SKalle Valo {
960d5c65159SKalle Valo 	platform_driver_unregister(&ath11k_ahb_driver);
961d5c65159SKalle Valo }
96231858805SGovind Singh module_exit(ath11k_ahb_exit);
96331858805SGovind Singh 
9646e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices");
96531858805SGovind Singh MODULE_LICENSE("Dual BSD/GPL");
966