1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/of_device.h>
10 #include <linux/dma-mapping.h>
14 #include <linux/remoteproc.h>
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?
20 { .compatible = "qcom,ipq8074-wifi",
21 .data = (void *)ATH11K_HW_IPQ8074,
26 MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
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 */
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),
40 /* CE1: target->host HTT + HTC control */
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),
50 /* CE2: target->host WMI */
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),
60 /* CE3: host->target WMI */
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),
70 /* CE4: host->target HTT */
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),
80 /* CE5: target->host Pktlog */
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),
90 /* CE6: Reserved for target autonomous hif_memcpy */
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),
100 /* CE7 used only by Host */
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),
110 /* CE8 target->host used only by IPA */
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),
120 /* CE9 host->target HTT */
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),
130 /* CE10 target->host HTT */
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),
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),
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.
155 static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
262 /* (Additions here) */
264 { /* terminator entry */ }
267 #define ATH11K_IRQ_CE0_OFFSET 4
269 static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
286 "host2wbm-desc-feed",
287 "host2reo-re-injection",
289 "host2rxdma-monitor-ring3",
290 "host2rxdma-monitor-ring2",
291 "host2rxdma-monitor-ring1",
293 "wbm2host-rx-release",
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",
324 #define ATH11K_TX_RING_MASK_0 0x1
325 #define ATH11K_TX_RING_MASK_1 0x2
326 #define ATH11K_TX_RING_MASK_2 0x4
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
333 #define ATH11K_RX_ERR_RING_MASK_0 0x1
335 #define ATH11K_RX_WBM_REL_RING_MASK_0 0x1
337 #define ATH11K_REO_STATUS_RING_MASK_0 0x1
339 #define ATH11K_RXDMA2HOST_RING_MASK_0 0x1
340 #define ATH11K_RXDMA2HOST_RING_MASK_1 0x2
341 #define ATH11K_RXDMA2HOST_RING_MASK_2 0x4
343 #define ATH11K_HOST2RXDMA_RING_MASK_0 0x1
344 #define ATH11K_HOST2RXDMA_RING_MASK_1 0x2
345 #define ATH11K_HOST2RXDMA_RING_MASK_2 0x4
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
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,
357 const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
359 ATH11K_RX_MON_STATUS_RING_MASK_0,
360 ATH11K_RX_MON_STATUS_RING_MASK_1,
361 ATH11K_RX_MON_STATUS_RING_MASK_2,
364 const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
366 ATH11K_RX_RING_MASK_0,
367 ATH11K_RX_RING_MASK_1,
368 ATH11K_RX_RING_MASK_2,
369 ATH11K_RX_RING_MASK_3,
372 const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
373 ATH11K_RX_ERR_RING_MASK_0,
376 const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
377 ATH11K_RX_WBM_REL_RING_MASK_0,
380 const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
381 ATH11K_REO_STATUS_RING_MASK_0,
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,
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,
396 /* enum ext_irq_num - irq numbers that can be used by external modules
400 host2wbm_desc_feed = 16,
401 host2reo_re_injection,
403 host2rxdma_monitor_ring3,
404 host2rxdma_monitor_ring2,
405 host2rxdma_monitor_ring1,
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,
438 static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
440 return ioread32(ab->mem + offset);
443 static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
445 iowrite32(value, ab->mem + offset);
448 static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
452 for (i = 0; i < CE_COUNT; i++) {
453 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
455 if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
458 tasklet_kill(&ce_pipe->intr_tq);
462 static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
466 for (i = 0; i < irq_grp->num_irq; i++)
467 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
470 static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
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];
477 ath11k_ahb_ext_grp_disable(irq_grp);
479 napi_synchronize(&irq_grp->napi);
480 napi_disable(&irq_grp->napi);
484 static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
488 for (i = 0; i < irq_grp->num_irq; i++)
489 enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
492 static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset)
496 val = ath11k_ahb_read32(ab, offset);
497 ath11k_ahb_write32(ab, offset, val | BIT(bit));
500 static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
504 val = ath11k_ahb_read32(ab, offset);
505 ath11k_ahb_write32(ab, offset, val & ~BIT(bit));
508 static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
510 const struct ce_pipe_config *ce_config;
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);
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);
523 static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
525 const struct ce_pipe_config *ce_config;
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);
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);
538 static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
543 for (i = 0; i < CE_COUNT; i++) {
544 if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
547 irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
548 synchronize_irq(ab->irq_num[irq_idx]);
552 static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab)
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];
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]);
567 static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
571 for (i = 0; i < CE_COUNT; i++) {
572 if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
574 ath11k_ahb_ce_irq_enable(ab, i);
578 static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
582 for (i = 0; i < CE_COUNT; i++) {
583 if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
585 ath11k_ahb_ce_irq_disable(ab, i);
589 static int ath11k_ahb_start(struct ath11k_base *ab)
591 ath11k_ahb_ce_irqs_enable(ab);
592 ath11k_ce_rx_post_buf(ab);
597 static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
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];
604 napi_enable(&irq_grp->napi);
605 ath11k_ahb_ext_grp_enable(irq_grp);
609 static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
611 __ath11k_ahb_ext_irq_disable(ab);
612 ath11k_ahb_sync_ext_irqs(ab);
615 static void ath11k_ahb_stop(struct ath11k_base *ab)
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);
625 static int ath11k_ahb_power_up(struct ath11k_base *ab)
629 ret = rproc_boot(ab->tgt_rproc);
631 ath11k_err(ab, "failed to boot the remote processor Q6\n");
636 static void ath11k_ahb_power_down(struct ath11k_base *ab)
638 rproc_shutdown(ab->tgt_rproc);
641 static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
643 struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
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;
651 static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
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];
658 for (j = 0; j < irq_grp->num_irq; j++)
659 free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
663 static void ath11k_ahb_free_irq(struct ath11k_base *ab)
668 for (i = 0; i < CE_COUNT; i++) {
669 if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
671 irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
672 free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
675 ath11k_ahb_free_ext_irq(ab);
678 static void ath11k_ahb_ce_tasklet(unsigned long data)
680 struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
682 ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
684 ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
687 static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
689 struct ath11k_ce_pipe *ce_pipe = arg;
691 /* last interrupt received for this CE */
692 ce_pipe->timestamp = jiffies;
694 ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
696 tasklet_schedule(&ce_pipe->intr_tq);
701 static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
703 struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
704 struct ath11k_ext_irq_grp,
706 struct ath11k_base *ab = irq_grp->ab;
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);
715 if (work_done > budget)
721 static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
723 struct ath11k_ext_irq_grp *irq_grp = arg;
725 /* last interrupt received for this group */
726 irq_grp->timestamp = jiffies;
728 ath11k_ahb_ext_grp_disable(irq_grp);
730 napi_schedule(&irq_grp->napi);
735 static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
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];
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);
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;
757 if (ath11k_rx_ring_mask[i] & BIT(j)) {
758 irq_grp->irqs[num_irq++] =
759 reo2host_destination_ring1 - j;
762 if (ath11k_rx_err_ring_mask[i] & BIT(j))
763 irq_grp->irqs[num_irq++] = reo2host_exception;
765 if (ath11k_rx_wbm_rel_ring_mask[i] & BIT(j))
766 irq_grp->irqs[num_irq++] = wbm2host_rx_release;
768 if (ath11k_reo_status_ring_mask[i] & BIT(j))
769 irq_grp->irqs[num_irq++] = reo2host_status;
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);
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);
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);
794 irq_grp->num_irq = num_irq;
796 for (j = 0; j < irq_grp->num_irq; j++) {
797 int irq_idx = irq_grp->irqs[j];
799 irq = platform_get_irq_byname(ab->pdev,
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,
805 irq_name[irq_idx], irq_grp);
807 ath11k_err(ab, "failed request_irq for %d\n",
816 static int ath11k_ahb_config_irq(struct ath11k_base *ab)
821 /* Configure CE irqs */
822 for (i = 0; i < CE_COUNT; i++) {
823 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
825 if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
828 irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
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],
839 ab->irq_num[irq_idx] = irq;
842 /* Configure external interrupts */
843 ret = ath11k_ahb_ext_irq_config(ab);
848 static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
849 u8 *ul_pipe, u8 *dl_pipe)
851 const struct service_to_pipe *entry;
852 bool ul_set = false, dl_set = false;
855 for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
856 entry = &target_service_to_ce_map_wlan[i];
858 if (__le32_to_cpu(entry->service_id) != service_id)
861 switch (__le32_to_cpu(entry->pipedir)) {
866 *dl_pipe = __le32_to_cpu(entry->pipenum);
871 *ul_pipe = __le32_to_cpu(entry->pipenum);
877 *dl_pipe = __le32_to_cpu(entry->pipenum);
878 *ul_pipe = __le32_to_cpu(entry->pipenum);
885 if (WARN_ON(!ul_set || !dl_set))
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,
903 static int ath11k_ahb_probe(struct platform_device *pdev)
905 struct ath11k_base *ab;
906 const struct of_device_id *of_id;
907 struct resource *mem_res;
911 of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
913 dev_err(&pdev->dev, "failed to find matching device tree id\n");
917 mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
919 dev_err(&pdev->dev, "ioremap error\n");
923 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
925 dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
929 ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB);
931 dev_err(&pdev->dev, "failed to allocate ath11k base\n");
935 ab->hif.ops = &ath11k_ahb_hif_ops;
937 ab->hw_rev = (enum ath11k_hw_rev)of_id->data;
939 ab->mem_len = resource_size(mem_res);
940 platform_set_drvdata(pdev, ab);
942 ret = ath11k_hal_srng_init(ab);
946 ret = ath11k_ce_alloc_pipes(ab);
948 ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
949 goto err_hal_srng_deinit;
952 ath11k_ahb_init_qmi_ce_config(ab);
954 ret = ath11k_ahb_config_irq(ab);
956 ath11k_err(ab, "failed to configure irq: %d\n", ret);
960 ret = ath11k_core_init(ab);
962 ath11k_err(ab, "failed to init core: %d\n", ret);
969 ath11k_ce_free_pipes(ab);
972 ath11k_hal_srng_deinit(ab);
975 ath11k_core_free(ab);
976 platform_set_drvdata(pdev, NULL);
981 static int ath11k_ahb_remove(struct platform_device *pdev)
983 struct ath11k_base *ab = platform_get_drvdata(pdev);
985 reinit_completion(&ab->driver_recovery);
987 if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags))
988 wait_for_completion_timeout(&ab->driver_recovery,
989 ATH11K_AHB_RECOVERY_TIMEOUT);
991 set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
992 cancel_work_sync(&ab->restart_work);
994 ath11k_core_deinit(ab);
995 ath11k_ahb_free_irq(ab);
997 ath11k_hal_srng_deinit(ab);
998 ath11k_ce_free_pipes(ab);
999 ath11k_core_free(ab);
1000 platform_set_drvdata(pdev, NULL);
1005 static struct platform_driver ath11k_ahb_driver = {
1008 .of_match_table = ath11k_ahb_of_match,
1010 .probe = ath11k_ahb_probe,
1011 .remove = ath11k_ahb_remove,
1014 static int ath11k_ahb_init(void)
1016 return platform_driver_register(&ath11k_ahb_driver);
1018 module_init(ath11k_ahb_init);
1020 static void ath11k_ahb_exit(void)
1022 platform_driver_unregister(&ath11k_ahb_driver);
1024 module_exit(ath11k_ahb_exit);
1026 MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax wireless chip");
1027 MODULE_LICENSE("Dual BSD/GPL");