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