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