2 * Copyright (c) 2018 The Linux Foundation. All rights reserved.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/module.h>
18 #include <linux/kernel.h>
25 #include <linux/of_device.h>
26 #include <linux/platform_device.h>
27 #define WCN3990_CE_ATTR_FLAGS 0
28 #define ATH10K_SNOC_RX_POST_RETRY_MS 50
29 #define CE_POLL_PIPE 4
31 static char *const ce_name[] = {
46 static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
47 static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
48 static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
49 static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
50 static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
52 static const struct ath10k_snoc_drv_priv drv_priv = {
53 .hw_rev = ATH10K_HW_WCN3990,
54 .dma_mask = DMA_BIT_MASK(37),
57 static struct ce_attr host_ce_config_wlan[] = {
58 /* CE0: host->target HTC control streams */
60 .flags = CE_ATTR_FLAGS,
64 .send_cb = ath10k_snoc_htc_tx_cb,
67 /* CE1: target->host HTT + HTC control */
69 .flags = CE_ATTR_FLAGS,
73 .recv_cb = ath10k_snoc_htt_htc_rx_cb,
76 /* CE2: target->host WMI */
78 .flags = CE_ATTR_FLAGS,
82 .recv_cb = ath10k_snoc_htc_rx_cb,
85 /* CE3: host->target WMI */
87 .flags = CE_ATTR_FLAGS,
91 .send_cb = ath10k_snoc_htc_tx_cb,
94 /* CE4: host->target HTT */
96 .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
100 .send_cb = ath10k_snoc_htt_tx_cb,
103 /* CE5: target->host HTT (ipa_uc->target ) */
105 .flags = CE_ATTR_FLAGS,
108 .dest_nentries = 512,
109 .recv_cb = ath10k_snoc_htt_rx_cb,
112 /* CE6: target autonomous hif_memcpy */
114 .flags = CE_ATTR_FLAGS,
120 /* CE7: ce_diag, the Diagnostic Window */
122 .flags = CE_ATTR_FLAGS,
128 /* CE8: Target to uMC */
130 .flags = CE_ATTR_FLAGS,
133 .dest_nentries = 128,
136 /* CE9 target->host HTT */
138 .flags = CE_ATTR_FLAGS,
141 .dest_nentries = 512,
142 .recv_cb = ath10k_snoc_htt_htc_rx_cb,
145 /* CE10: target->host HTT */
147 .flags = CE_ATTR_FLAGS,
150 .dest_nentries = 512,
151 .recv_cb = ath10k_snoc_htt_htc_rx_cb,
154 /* CE11: target -> host PKTLOG */
156 .flags = CE_ATTR_FLAGS,
159 .dest_nentries = 512,
160 .recv_cb = ath10k_snoc_htt_htc_rx_cb,
164 static struct service_to_pipe target_service_to_ce_map_wlan[] = {
166 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
167 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
171 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
172 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
176 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),
177 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
181 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),
182 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
186 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),
187 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
191 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),
192 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
196 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),
197 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
201 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),
202 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
206 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),
207 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
211 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),
212 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
216 __cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),
217 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
221 __cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),
222 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
226 __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
227 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
231 __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
232 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
236 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
237 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
241 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
242 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
246 __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
247 __cpu_to_le32(PIPEDIR_OUT),
250 { /* in = DL = target -> host */
251 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA2_MSG),
252 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
255 { /* in = DL = target -> host */
256 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA3_MSG),
257 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
260 { /* in = DL = target -> host pktlog */
261 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_LOG_MSG),
262 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
265 /* (Additions here) */
274 void ath10k_snoc_write32(struct ath10k *ar, u32 offset, u32 value)
276 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
278 iowrite32(value, ar_snoc->mem + offset);
281 u32 ath10k_snoc_read32(struct ath10k *ar, u32 offset)
283 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
286 val = ioread32(ar_snoc->mem + offset);
291 static int __ath10k_snoc_rx_post_buf(struct ath10k_snoc_pipe *pipe)
293 struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
294 struct ath10k *ar = pipe->hif_ce_state;
295 struct ath10k_ce *ce = ath10k_ce_priv(ar);
300 skb = dev_alloc_skb(pipe->buf_sz);
304 WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
306 paddr = dma_map_single(ar->dev, skb->data,
307 skb->len + skb_tailroom(skb),
309 if (unlikely(dma_mapping_error(ar->dev, paddr))) {
310 ath10k_warn(ar, "failed to dma map snoc rx buf\n");
311 dev_kfree_skb_any(skb);
315 ATH10K_SKB_RXCB(skb)->paddr = paddr;
317 spin_lock_bh(&ce->ce_lock);
318 ret = ce_pipe->ops->ce_rx_post_buf(ce_pipe, skb, paddr);
319 spin_unlock_bh(&ce->ce_lock);
321 dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb),
323 dev_kfree_skb_any(skb);
330 static void ath10k_snoc_rx_post_pipe(struct ath10k_snoc_pipe *pipe)
332 struct ath10k *ar = pipe->hif_ce_state;
333 struct ath10k_ce *ce = ath10k_ce_priv(ar);
334 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
335 struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
338 if (pipe->buf_sz == 0)
341 if (!ce_pipe->dest_ring)
344 spin_lock_bh(&ce->ce_lock);
345 num = __ath10k_ce_rx_num_free_bufs(ce_pipe);
346 spin_unlock_bh(&ce->ce_lock);
348 ret = __ath10k_snoc_rx_post_buf(pipe);
352 ath10k_warn(ar, "failed to post rx buf: %d\n", ret);
353 mod_timer(&ar_snoc->rx_post_retry, jiffies +
354 ATH10K_SNOC_RX_POST_RETRY_MS);
360 static void ath10k_snoc_rx_post(struct ath10k *ar)
362 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
365 for (i = 0; i < CE_COUNT; i++)
366 ath10k_snoc_rx_post_pipe(&ar_snoc->pipe_info[i]);
369 static void ath10k_snoc_process_rx_cb(struct ath10k_ce_pipe *ce_state,
370 void (*callback)(struct ath10k *ar,
371 struct sk_buff *skb))
373 struct ath10k *ar = ce_state->ar;
374 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
375 struct ath10k_snoc_pipe *pipe_info = &ar_snoc->pipe_info[ce_state->id];
377 struct sk_buff_head list;
378 void *transfer_context;
379 unsigned int nbytes, max_nbytes;
381 __skb_queue_head_init(&list);
382 while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
384 skb = transfer_context;
385 max_nbytes = skb->len + skb_tailroom(skb);
386 dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
387 max_nbytes, DMA_FROM_DEVICE);
389 if (unlikely(max_nbytes < nbytes)) {
390 ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)",
392 dev_kfree_skb_any(skb);
396 skb_put(skb, nbytes);
397 __skb_queue_tail(&list, skb);
400 while ((skb = __skb_dequeue(&list))) {
401 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc rx ce pipe %d len %d\n",
402 ce_state->id, skb->len);
407 ath10k_snoc_rx_post_pipe(pipe_info);
410 static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
412 ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
415 static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
417 /* CE4 polling needs to be done whenever CE pipe which transports
418 * HTT Rx (target->host) is processed.
420 ath10k_ce_per_engine_service(ce_state->ar, CE_POLL_PIPE);
422 ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
425 static void ath10k_snoc_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb)
427 skb_pull(skb, sizeof(struct ath10k_htc_hdr));
428 ath10k_htt_t2h_msg_handler(ar, skb);
431 static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state)
433 ath10k_ce_per_engine_service(ce_state->ar, CE_POLL_PIPE);
434 ath10k_snoc_process_rx_cb(ce_state, ath10k_snoc_htt_rx_deliver);
437 static void ath10k_snoc_rx_replenish_retry(struct timer_list *t)
439 struct ath10k_pci *ar_snoc = from_timer(ar_snoc, t, rx_post_retry);
440 struct ath10k *ar = ar_snoc->ar;
442 ath10k_snoc_rx_post(ar);
445 static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state)
447 struct ath10k *ar = ce_state->ar;
448 struct sk_buff_head list;
451 __skb_queue_head_init(&list);
452 while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
456 __skb_queue_tail(&list, skb);
459 while ((skb = __skb_dequeue(&list)))
460 ath10k_htc_tx_completion_handler(ar, skb);
463 static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
465 struct ath10k *ar = ce_state->ar;
468 while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
472 dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
473 skb->len, DMA_TO_DEVICE);
474 ath10k_htt_hif_tx_complete(ar, skb);
478 static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
479 struct ath10k_hif_sg_item *items, int n_items)
481 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
482 struct ath10k_ce *ce = ath10k_ce_priv(ar);
483 struct ath10k_snoc_pipe *snoc_pipe;
484 struct ath10k_ce_pipe *ce_pipe;
487 snoc_pipe = &ar_snoc->pipe_info[pipe_id];
488 ce_pipe = snoc_pipe->ce_hdl;
489 spin_lock_bh(&ce->ce_lock);
491 for (i = 0; i < n_items - 1; i++) {
492 ath10k_dbg(ar, ATH10K_DBG_SNOC,
493 "snoc tx item %d paddr %pad len %d n_items %d\n",
494 i, &items[i].paddr, items[i].len, n_items);
496 err = ath10k_ce_send_nolock(ce_pipe,
497 items[i].transfer_context,
500 items[i].transfer_id,
501 CE_SEND_FLAG_GATHER);
506 ath10k_dbg(ar, ATH10K_DBG_SNOC,
507 "snoc tx item %d paddr %pad len %d n_items %d\n",
508 i, &items[i].paddr, items[i].len, n_items);
510 err = ath10k_ce_send_nolock(ce_pipe,
511 items[i].transfer_context,
514 items[i].transfer_id,
519 spin_unlock_bh(&ce->ce_lock);
525 __ath10k_ce_send_revert(ce_pipe);
527 spin_unlock_bh(&ce->ce_lock);
531 static int ath10k_snoc_hif_get_target_info(struct ath10k *ar,
532 struct bmi_target_info *target_info)
534 target_info->version = ATH10K_HW_WCN3990;
535 target_info->type = ATH10K_HW_WCN3990;
540 static u16 ath10k_snoc_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
542 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
544 ath10k_dbg(ar, ATH10K_DBG_SNOC, "hif get free queue number\n");
546 return ath10k_ce_num_free_src_entries(ar_snoc->pipe_info[pipe].ce_hdl);
549 static void ath10k_snoc_hif_send_complete_check(struct ath10k *ar, u8 pipe,
554 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc hif send complete check\n");
557 resources = ath10k_snoc_hif_get_free_queue_number(ar, pipe);
559 if (resources > (host_ce_config_wlan[pipe].src_nentries >> 1))
562 ath10k_ce_per_engine_service(ar, pipe);
565 static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,
567 u8 *ul_pipe, u8 *dl_pipe)
569 const struct service_to_pipe *entry;
570 bool ul_set = false, dl_set = false;
573 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc hif map service\n");
575 for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
576 entry = &target_service_to_ce_map_wlan[i];
578 if (__le32_to_cpu(entry->service_id) != service_id)
581 switch (__le32_to_cpu(entry->pipedir)) {
586 *dl_pipe = __le32_to_cpu(entry->pipenum);
591 *ul_pipe = __le32_to_cpu(entry->pipenum);
597 *dl_pipe = __le32_to_cpu(entry->pipenum);
598 *ul_pipe = __le32_to_cpu(entry->pipenum);
605 if (WARN_ON(!ul_set || !dl_set))
611 static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,
612 u8 *ul_pipe, u8 *dl_pipe)
614 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc hif get default pipe\n");
616 (void)ath10k_snoc_hif_map_service_to_pipe(ar,
617 ATH10K_HTC_SVC_ID_RSVD_CTRL,
621 static inline void ath10k_snoc_irq_disable(struct ath10k *ar)
623 ath10k_ce_disable_interrupts(ar);
626 static inline void ath10k_snoc_irq_enable(struct ath10k *ar)
628 ath10k_ce_enable_interrupts(ar);
631 static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
633 struct ath10k_ce_pipe *ce_pipe;
634 struct ath10k_ce_ring *ce_ring;
639 ar = snoc_pipe->hif_ce_state;
640 ce_pipe = snoc_pipe->ce_hdl;
641 ce_ring = ce_pipe->dest_ring;
646 if (!snoc_pipe->buf_sz)
649 for (i = 0; i < ce_ring->nentries; i++) {
650 skb = ce_ring->per_transfer_context[i];
654 ce_ring->per_transfer_context[i] = NULL;
656 dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
657 skb->len + skb_tailroom(skb),
659 dev_kfree_skb_any(skb);
663 static void ath10k_snoc_tx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
665 struct ath10k_ce_pipe *ce_pipe;
666 struct ath10k_ce_ring *ce_ring;
667 struct ath10k_snoc *ar_snoc;
672 ar = snoc_pipe->hif_ce_state;
673 ar_snoc = ath10k_snoc_priv(ar);
674 ce_pipe = snoc_pipe->ce_hdl;
675 ce_ring = ce_pipe->src_ring;
680 if (!snoc_pipe->buf_sz)
683 for (i = 0; i < ce_ring->nentries; i++) {
684 skb = ce_ring->per_transfer_context[i];
688 ce_ring->per_transfer_context[i] = NULL;
690 ath10k_htc_tx_completion_handler(ar, skb);
694 static void ath10k_snoc_buffer_cleanup(struct ath10k *ar)
696 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
697 struct ath10k_snoc_pipe *pipe_info;
700 del_timer_sync(&ar_snoc->rx_post_retry);
701 for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
702 pipe_info = &ar_snoc->pipe_info[pipe_num];
703 ath10k_snoc_rx_pipe_cleanup(pipe_info);
704 ath10k_snoc_tx_pipe_cleanup(pipe_info);
708 static void ath10k_snoc_hif_stop(struct ath10k *ar)
710 ath10k_snoc_irq_disable(ar);
711 ath10k_snoc_buffer_cleanup(ar);
712 napi_synchronize(&ar->napi);
713 napi_disable(&ar->napi);
714 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
717 static int ath10k_snoc_hif_start(struct ath10k *ar)
719 ath10k_snoc_irq_enable(ar);
720 ath10k_snoc_rx_post(ar);
722 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
727 static int ath10k_snoc_init_pipes(struct ath10k *ar)
731 for (i = 0; i < CE_COUNT; i++) {
732 ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]);
734 ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n",
743 static int ath10k_snoc_wlan_enable(struct ath10k *ar)
748 static void ath10k_snoc_wlan_disable(struct ath10k *ar)
752 static void ath10k_snoc_hif_power_down(struct ath10k *ar)
754 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n");
756 ath10k_snoc_wlan_disable(ar);
759 static int ath10k_snoc_hif_power_up(struct ath10k *ar)
763 ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 driver state = %d\n",
764 __func__, ar->state);
766 ret = ath10k_snoc_wlan_enable(ar);
768 ath10k_err(ar, "failed to enable wcn3990: %d\n", ret);
772 ret = ath10k_snoc_init_pipes(ar);
774 ath10k_err(ar, "failed to initialize CE: %d\n", ret);
775 goto err_wlan_enable;
778 napi_enable(&ar->napi);
782 ath10k_snoc_wlan_disable(ar);
787 static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
788 .read32 = ath10k_snoc_read32,
789 .write32 = ath10k_snoc_write32,
790 .start = ath10k_snoc_hif_start,
791 .stop = ath10k_snoc_hif_stop,
792 .map_service_to_pipe = ath10k_snoc_hif_map_service_to_pipe,
793 .get_default_pipe = ath10k_snoc_hif_get_default_pipe,
794 .power_up = ath10k_snoc_hif_power_up,
795 .power_down = ath10k_snoc_hif_power_down,
796 .tx_sg = ath10k_snoc_hif_tx_sg,
797 .send_complete_check = ath10k_snoc_hif_send_complete_check,
798 .get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,
799 .get_target_info = ath10k_snoc_hif_get_target_info,
802 static const struct ath10k_bus_ops ath10k_snoc_bus_ops = {
803 .read32 = ath10k_snoc_read32,
804 .write32 = ath10k_snoc_write32,
807 int ath10k_snoc_get_ce_id_from_irq(struct ath10k *ar, int irq)
809 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
812 for (i = 0; i < CE_COUNT_MAX; i++) {
813 if (ar_snoc->ce_irqs[i].irq_line == irq)
816 ath10k_err(ar, "No matching CE id for irq %d\n", irq);
821 static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg)
823 struct ath10k *ar = arg;
824 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
825 int ce_id = ath10k_snoc_get_ce_id_from_irq(ar, irq);
827 if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_snoc->pipe_info)) {
828 ath10k_warn(ar, "unexpected/invalid irq %d ce_id %d\n", irq,
833 ath10k_snoc_irq_disable(ar);
834 napi_schedule(&ar->napi);
839 static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)
841 struct ath10k *ar = container_of(ctx, struct ath10k, napi);
844 ath10k_ce_per_engine_service_any(ar);
845 done = ath10k_htt_txrx_compl_task(ar, budget);
849 ath10k_snoc_irq_enable(ar);
855 void ath10k_snoc_init_napi(struct ath10k *ar)
857 netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll,
861 static int ath10k_snoc_request_irq(struct ath10k *ar)
863 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
864 int irqflags = IRQF_TRIGGER_RISING;
867 for (id = 0; id < CE_COUNT_MAX; id++) {
868 ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
869 ath10k_snoc_per_engine_handler,
870 irqflags, ce_name[id], ar);
873 "failed to register IRQ handler for CE %d: %d",
882 for (id -= 1; id >= 0; id--)
883 free_irq(ar_snoc->ce_irqs[id].irq_line, ar);
888 static void ath10k_snoc_free_irq(struct ath10k *ar)
890 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
893 for (id = 0; id < CE_COUNT_MAX; id++)
894 free_irq(ar_snoc->ce_irqs[id].irq_line, ar);
897 static int ath10k_snoc_resource_init(struct ath10k *ar)
899 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
900 struct platform_device *pdev;
901 struct resource *res;
905 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "membase");
907 ath10k_err(ar, "Memory base not found in DT\n");
911 ar_snoc->mem_pa = res->start;
912 ar_snoc->mem = devm_ioremap(&pdev->dev, ar_snoc->mem_pa,
915 ath10k_err(ar, "Memory base ioremap failed with physical address %pa\n",
920 for (i = 0; i < CE_COUNT; i++) {
921 res = platform_get_resource(ar_snoc->dev, IORESOURCE_IRQ, i);
923 ath10k_err(ar, "failed to get IRQ%d\n", i);
927 ar_snoc->ce_irqs[i].irq_line = res->start;
934 static int ath10k_snoc_setup_resource(struct ath10k *ar)
936 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
937 struct ath10k_ce *ce = ath10k_ce_priv(ar);
938 struct ath10k_snoc_pipe *pipe;
941 timer_setup(&ar_snoc->rx_post_retry, ath10k_snoc_rx_replenish_retry, 0);
942 spin_lock_init(&ce->ce_lock);
943 for (i = 0; i < CE_COUNT; i++) {
944 pipe = &ar_snoc->pipe_info[i];
945 pipe->ce_hdl = &ce->ce_states[i];
947 pipe->hif_ce_state = ar;
949 ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);
951 ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",
956 pipe->buf_sz = host_ce_config_wlan[i].src_sz_max;
958 ath10k_snoc_init_napi(ar);
963 static void ath10k_snoc_release_resource(struct ath10k *ar)
967 netif_napi_del(&ar->napi);
968 for (i = 0; i < CE_COUNT; i++)
969 ath10k_ce_free_pipe(ar, i);
972 static const struct of_device_id ath10k_snoc_dt_match[] = {
973 { .compatible = "qcom,wcn3990-wifi",
978 MODULE_DEVICE_TABLE(of, ath10k_snoc_dt_match);
980 static int ath10k_snoc_probe(struct platform_device *pdev)
982 const struct ath10k_snoc_drv_priv *drv_data;
983 const struct of_device_id *of_id;
984 struct ath10k_snoc *ar_snoc;
989 of_id = of_match_device(ath10k_snoc_dt_match, &pdev->dev);
991 dev_err(&pdev->dev, "failed to find matching device tree id\n");
995 drv_data = of_id->data;
998 ret = dma_set_mask_and_coherent(dev, drv_data->dma_mask);
1000 dev_err(dev, "failed to set dma mask: %d", ret);
1004 ar = ath10k_core_create(sizeof(*ar_snoc), dev, ATH10K_BUS_SNOC,
1005 drv_data->hw_rev, &ath10k_snoc_hif_ops);
1007 dev_err(dev, "failed to allocate core\n");
1011 ar_snoc = ath10k_snoc_priv(ar);
1012 ar_snoc->dev = pdev;
1013 platform_set_drvdata(pdev, ar);
1015 ar_snoc->ce.bus_ops = &ath10k_snoc_bus_ops;
1016 ar->ce_priv = &ar_snoc->ce;
1018 ath10k_snoc_resource_init(ar);
1020 ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
1021 goto err_core_destroy;
1024 ath10k_snoc_setup_resource(ar);
1026 ath10k_warn(ar, "failed to setup resource: %d\n", ret);
1027 goto err_core_destroy;
1029 ret = ath10k_snoc_request_irq(ar);
1031 ath10k_warn(ar, "failed to request irqs: %d\n", ret);
1032 goto err_release_resource;
1034 ret = ath10k_core_register(ar, drv_data->hw_rev);
1036 ath10k_err(ar, "failed to register driver core: %d\n", ret);
1039 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
1040 ath10k_warn(ar, "Warning: SNOC support is still work-in-progress, it will not work properly!");
1045 ath10k_snoc_free_irq(ar);
1047 err_release_resource:
1048 ath10k_snoc_release_resource(ar);
1051 ath10k_core_destroy(ar);
1056 static int ath10k_snoc_remove(struct platform_device *pdev)
1058 struct ath10k *ar = platform_get_drvdata(pdev);
1060 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc remove\n");
1061 ath10k_core_unregister(ar);
1062 ath10k_snoc_free_irq(ar);
1063 ath10k_snoc_release_resource(ar);
1064 ath10k_core_destroy(ar);
1069 static struct platform_driver ath10k_snoc_driver = {
1070 .probe = ath10k_snoc_probe,
1071 .remove = ath10k_snoc_remove,
1073 .name = "ath10k_snoc",
1074 .owner = THIS_MODULE,
1075 .of_match_table = ath10k_snoc_dt_match,
1079 static int __init ath10k_snoc_init(void)
1083 ret = platform_driver_register(&ath10k_snoc_driver);
1085 pr_err("failed to register ath10k snoc driver: %d\n",
1090 module_init(ath10k_snoc_init);
1092 static void __exit ath10k_snoc_exit(void)
1094 platform_driver_unregister(&ath10k_snoc_driver);
1096 module_exit(ath10k_snoc_exit);
1098 MODULE_AUTHOR("Qualcomm");
1099 MODULE_LICENSE("Dual BSD/GPL");
1100 MODULE_DESCRIPTION("Driver support for Atheros WCN3990 SNOC devices");