1901 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (c) 2018 The Linux Foundation. All rights reserved.4 */5 6#include <linux/bits.h>7#include <linux/clk.h>8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/of_device.h>12#include <linux/platform_device.h>13#include <linux/property.h>14#include <linux/regulator/consumer.h>15#include <linux/remoteproc/qcom_rproc.h>16#include <linux/of_address.h>17#include <linux/iommu.h>18 19#include "ce.h"20#include "coredump.h"21#include "debug.h"22#include "hif.h"23#include "htc.h"24#include "snoc.h"25 26#define ATH10K_SNOC_RX_POST_RETRY_MS 5027#define CE_POLL_PIPE 428#define ATH10K_SNOC_WAKE_IRQ 229 30static char *const ce_name[] = {31 "WLAN_CE_0",32 "WLAN_CE_1",33 "WLAN_CE_2",34 "WLAN_CE_3",35 "WLAN_CE_4",36 "WLAN_CE_5",37 "WLAN_CE_6",38 "WLAN_CE_7",39 "WLAN_CE_8",40 "WLAN_CE_9",41 "WLAN_CE_10",42 "WLAN_CE_11",43};44 45static const char * const ath10k_regulators[] = {46 "vdd-0.8-cx-mx",47 "vdd-1.8-xo",48 "vdd-1.3-rfa",49 "vdd-3.3-ch0",50 "vdd-3.3-ch1",51};52 53static const char * const ath10k_clocks[] = {54 "cxo_ref_clk_pin", "qdss",55};56 57static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);58static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state);59static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state);60static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state);61static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state);62static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);63 64static const struct ath10k_snoc_drv_priv drv_priv = {65 .hw_rev = ATH10K_HW_WCN3990,66 .dma_mask = DMA_BIT_MASK(35),67 .msa_size = 0x100000,68};69 70#define WCN3990_SRC_WR_IDX_OFFSET 0x3C71#define WCN3990_DST_WR_IDX_OFFSET 0x4072 73static struct ath10k_shadow_reg_cfg target_shadow_reg_cfg_map[] = {74 {75 .ce_id = __cpu_to_le16(0),76 .reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),77 },78 79 {80 .ce_id = __cpu_to_le16(3),81 .reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),82 },83 84 {85 .ce_id = __cpu_to_le16(4),86 .reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),87 },88 89 {90 .ce_id = __cpu_to_le16(5),91 .reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),92 },93 94 {95 .ce_id = __cpu_to_le16(7),96 .reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),97 },98 99 {100 .ce_id = __cpu_to_le16(1),101 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),102 },103 104 {105 .ce_id = __cpu_to_le16(2),106 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),107 },108 109 {110 .ce_id = __cpu_to_le16(7),111 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),112 },113 114 {115 .ce_id = __cpu_to_le16(8),116 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),117 },118 119 {120 .ce_id = __cpu_to_le16(9),121 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),122 },123 124 {125 .ce_id = __cpu_to_le16(10),126 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),127 },128 129 {130 .ce_id = __cpu_to_le16(11),131 .reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),132 },133};134 135static struct ce_attr host_ce_config_wlan[] = {136 /* CE0: host->target HTC control streams */137 {138 .flags = CE_ATTR_FLAGS,139 .src_nentries = 16,140 .src_sz_max = 2048,141 .dest_nentries = 0,142 .send_cb = ath10k_snoc_htc_tx_cb,143 },144 145 /* CE1: target->host HTT + HTC control */146 {147 .flags = CE_ATTR_FLAGS,148 .src_nentries = 0,149 .src_sz_max = 2048,150 .dest_nentries = 512,151 .recv_cb = ath10k_snoc_htt_htc_rx_cb,152 },153 154 /* CE2: target->host WMI */155 {156 .flags = CE_ATTR_FLAGS,157 .src_nentries = 0,158 .src_sz_max = 2048,159 .dest_nentries = 64,160 .recv_cb = ath10k_snoc_htc_rx_cb,161 },162 163 /* CE3: host->target WMI */164 {165 .flags = CE_ATTR_FLAGS,166 .src_nentries = 32,167 .src_sz_max = 2048,168 .dest_nentries = 0,169 .send_cb = ath10k_snoc_htc_tx_cb,170 },171 172 /* CE4: host->target HTT */173 {174 .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,175 .src_nentries = 2048,176 .src_sz_max = 256,177 .dest_nentries = 0,178 .send_cb = ath10k_snoc_htt_tx_cb,179 },180 181 /* CE5: target->host HTT (ipa_uc->target ) */182 {183 .flags = CE_ATTR_FLAGS,184 .src_nentries = 0,185 .src_sz_max = 512,186 .dest_nentries = 512,187 .recv_cb = ath10k_snoc_htt_rx_cb,188 },189 190 /* CE6: target autonomous hif_memcpy */191 {192 .flags = CE_ATTR_FLAGS,193 .src_nentries = 0,194 .src_sz_max = 0,195 .dest_nentries = 0,196 },197 198 /* CE7: ce_diag, the Diagnostic Window */199 {200 .flags = CE_ATTR_FLAGS,201 .src_nentries = 2,202 .src_sz_max = 2048,203 .dest_nentries = 2,204 },205 206 /* CE8: Target to uMC */207 {208 .flags = CE_ATTR_FLAGS,209 .src_nentries = 0,210 .src_sz_max = 2048,211 .dest_nentries = 128,212 },213 214 /* CE9 target->host HTT */215 {216 .flags = CE_ATTR_FLAGS,217 .src_nentries = 0,218 .src_sz_max = 2048,219 .dest_nentries = 512,220 .recv_cb = ath10k_snoc_htt_htc_rx_cb,221 },222 223 /* CE10: target->host HTT */224 {225 .flags = CE_ATTR_FLAGS,226 .src_nentries = 0,227 .src_sz_max = 2048,228 .dest_nentries = 512,229 .recv_cb = ath10k_snoc_htt_htc_rx_cb,230 },231 232 /* CE11: target -> host PKTLOG */233 {234 .flags = CE_ATTR_FLAGS,235 .src_nentries = 0,236 .src_sz_max = 2048,237 .dest_nentries = 512,238 .recv_cb = ath10k_snoc_pktlog_rx_cb,239 },240};241 242static struct ce_pipe_config target_ce_config_wlan[] = {243 /* CE0: host->target HTC control and raw streams */244 {245 .pipenum = __cpu_to_le32(0),246 .pipedir = __cpu_to_le32(PIPEDIR_OUT),247 .nentries = __cpu_to_le32(32),248 .nbytes_max = __cpu_to_le32(2048),249 .flags = __cpu_to_le32(CE_ATTR_FLAGS),250 .reserved = __cpu_to_le32(0),251 },252 253 /* CE1: target->host HTT + HTC control */254 {255 .pipenum = __cpu_to_le32(1),256 .pipedir = __cpu_to_le32(PIPEDIR_IN),257 .nentries = __cpu_to_le32(32),258 .nbytes_max = __cpu_to_le32(2048),259 .flags = __cpu_to_le32(CE_ATTR_FLAGS),260 .reserved = __cpu_to_le32(0),261 },262 263 /* CE2: target->host WMI */264 {265 .pipenum = __cpu_to_le32(2),266 .pipedir = __cpu_to_le32(PIPEDIR_IN),267 .nentries = __cpu_to_le32(64),268 .nbytes_max = __cpu_to_le32(2048),269 .flags = __cpu_to_le32(CE_ATTR_FLAGS),270 .reserved = __cpu_to_le32(0),271 },272 273 /* CE3: host->target WMI */274 {275 .pipenum = __cpu_to_le32(3),276 .pipedir = __cpu_to_le32(PIPEDIR_OUT),277 .nentries = __cpu_to_le32(32),278 .nbytes_max = __cpu_to_le32(2048),279 .flags = __cpu_to_le32(CE_ATTR_FLAGS),280 .reserved = __cpu_to_le32(0),281 },282 283 /* CE4: host->target HTT */284 {285 .pipenum = __cpu_to_le32(4),286 .pipedir = __cpu_to_le32(PIPEDIR_OUT),287 .nentries = __cpu_to_le32(256),288 .nbytes_max = __cpu_to_le32(256),289 .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),290 .reserved = __cpu_to_le32(0),291 },292 293 /* CE5: target->host HTT (HIF->HTT) */294 {295 .pipenum = __cpu_to_le32(5),296 .pipedir = __cpu_to_le32(PIPEDIR_OUT),297 .nentries = __cpu_to_le32(1024),298 .nbytes_max = __cpu_to_le32(64),299 .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),300 .reserved = __cpu_to_le32(0),301 },302 303 /* CE6: Reserved for target autonomous hif_memcpy */304 {305 .pipenum = __cpu_to_le32(6),306 .pipedir = __cpu_to_le32(PIPEDIR_INOUT),307 .nentries = __cpu_to_le32(32),308 .nbytes_max = __cpu_to_le32(16384),309 .flags = __cpu_to_le32(CE_ATTR_FLAGS),310 .reserved = __cpu_to_le32(0),311 },312 313 /* CE7 used only by Host */314 {315 .pipenum = __cpu_to_le32(7),316 .pipedir = __cpu_to_le32(4),317 .nentries = __cpu_to_le32(0),318 .nbytes_max = __cpu_to_le32(0),319 .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),320 .reserved = __cpu_to_le32(0),321 },322 323 /* CE8 Target to uMC */324 {325 .pipenum = __cpu_to_le32(8),326 .pipedir = __cpu_to_le32(PIPEDIR_IN),327 .nentries = __cpu_to_le32(32),328 .nbytes_max = __cpu_to_le32(2048),329 .flags = __cpu_to_le32(0),330 .reserved = __cpu_to_le32(0),331 },332 333 /* CE9 target->host HTT */334 {335 .pipenum = __cpu_to_le32(9),336 .pipedir = __cpu_to_le32(PIPEDIR_IN),337 .nentries = __cpu_to_le32(32),338 .nbytes_max = __cpu_to_le32(2048),339 .flags = __cpu_to_le32(CE_ATTR_FLAGS),340 .reserved = __cpu_to_le32(0),341 },342 343 /* CE10 target->host HTT */344 {345 .pipenum = __cpu_to_le32(10),346 .pipedir = __cpu_to_le32(PIPEDIR_IN),347 .nentries = __cpu_to_le32(32),348 .nbytes_max = __cpu_to_le32(2048),349 .flags = __cpu_to_le32(CE_ATTR_FLAGS),350 .reserved = __cpu_to_le32(0),351 },352 353 /* CE11 target autonomous qcache memcpy */354 {355 .pipenum = __cpu_to_le32(11),356 .pipedir = __cpu_to_le32(PIPEDIR_IN),357 .nentries = __cpu_to_le32(32),358 .nbytes_max = __cpu_to_le32(2048),359 .flags = __cpu_to_le32(CE_ATTR_FLAGS),360 .reserved = __cpu_to_le32(0),361 },362};363 364static struct ce_service_to_pipe target_service_to_ce_map_wlan[] = {365 {366 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),367 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */368 __cpu_to_le32(3),369 },370 {371 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),372 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */373 __cpu_to_le32(2),374 },375 {376 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),377 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */378 __cpu_to_le32(3),379 },380 {381 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),382 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */383 __cpu_to_le32(2),384 },385 {386 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),387 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */388 __cpu_to_le32(3),389 },390 {391 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),392 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */393 __cpu_to_le32(2),394 },395 {396 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),397 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */398 __cpu_to_le32(3),399 },400 {401 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),402 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */403 __cpu_to_le32(2),404 },405 {406 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),407 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */408 __cpu_to_le32(3),409 },410 {411 __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),412 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */413 __cpu_to_le32(2),414 },415 {416 __cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),417 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */418 __cpu_to_le32(0),419 },420 {421 __cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),422 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */423 __cpu_to_le32(2),424 },425 { /* not used */426 __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),427 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */428 __cpu_to_le32(0),429 },430 { /* not used */431 __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),432 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */433 __cpu_to_le32(2),434 },435 {436 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),437 __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */438 __cpu_to_le32(4),439 },440 {441 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),442 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */443 __cpu_to_le32(1),444 },445 { /* not used */446 __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),447 __cpu_to_le32(PIPEDIR_OUT),448 __cpu_to_le32(5),449 },450 { /* in = DL = target -> host */451 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA2_MSG),452 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */453 __cpu_to_le32(9),454 },455 { /* in = DL = target -> host */456 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA3_MSG),457 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */458 __cpu_to_le32(10),459 },460 { /* in = DL = target -> host pktlog */461 __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_LOG_MSG),462 __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */463 __cpu_to_le32(11),464 },465 /* (Additions here) */466 467 { /* must be last */468 __cpu_to_le32(0),469 __cpu_to_le32(0),470 __cpu_to_le32(0),471 },472};473 474static void ath10k_snoc_write32(struct ath10k *ar, u32 offset, u32 value)475{476 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);477 478 iowrite32(value, ar_snoc->mem + offset);479}480 481static u32 ath10k_snoc_read32(struct ath10k *ar, u32 offset)482{483 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);484 u32 val;485 486 val = ioread32(ar_snoc->mem + offset);487 488 return val;489}490 491static int __ath10k_snoc_rx_post_buf(struct ath10k_snoc_pipe *pipe)492{493 struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;494 struct ath10k *ar = pipe->hif_ce_state;495 struct ath10k_ce *ce = ath10k_ce_priv(ar);496 struct sk_buff *skb;497 dma_addr_t paddr;498 int ret;499 500 skb = dev_alloc_skb(pipe->buf_sz);501 if (!skb)502 return -ENOMEM;503 504 WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");505 506 paddr = dma_map_single(ar->dev, skb->data,507 skb->len + skb_tailroom(skb),508 DMA_FROM_DEVICE);509 if (unlikely(dma_mapping_error(ar->dev, paddr))) {510 ath10k_warn(ar, "failed to dma map snoc rx buf\n");511 dev_kfree_skb_any(skb);512 return -EIO;513 }514 515 ATH10K_SKB_RXCB(skb)->paddr = paddr;516 517 spin_lock_bh(&ce->ce_lock);518 ret = ce_pipe->ops->ce_rx_post_buf(ce_pipe, skb, paddr);519 spin_unlock_bh(&ce->ce_lock);520 if (ret) {521 dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb),522 DMA_FROM_DEVICE);523 dev_kfree_skb_any(skb);524 return ret;525 }526 527 return 0;528}529 530static void ath10k_snoc_rx_post_pipe(struct ath10k_snoc_pipe *pipe)531{532 struct ath10k *ar = pipe->hif_ce_state;533 struct ath10k_ce *ce = ath10k_ce_priv(ar);534 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);535 struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;536 int ret, num;537 538 if (pipe->buf_sz == 0)539 return;540 541 if (!ce_pipe->dest_ring)542 return;543 544 spin_lock_bh(&ce->ce_lock);545 num = __ath10k_ce_rx_num_free_bufs(ce_pipe);546 spin_unlock_bh(&ce->ce_lock);547 while (num--) {548 ret = __ath10k_snoc_rx_post_buf(pipe);549 if (ret) {550 if (ret == -ENOSPC)551 break;552 ath10k_warn(ar, "failed to post rx buf: %d\n", ret);553 mod_timer(&ar_snoc->rx_post_retry, jiffies +554 ATH10K_SNOC_RX_POST_RETRY_MS);555 break;556 }557 }558}559 560static void ath10k_snoc_rx_post(struct ath10k *ar)561{562 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);563 int i;564 565 for (i = 0; i < CE_COUNT; i++)566 ath10k_snoc_rx_post_pipe(&ar_snoc->pipe_info[i]);567}568 569static void ath10k_snoc_process_rx_cb(struct ath10k_ce_pipe *ce_state,570 void (*callback)(struct ath10k *ar,571 struct sk_buff *skb))572{573 struct ath10k *ar = ce_state->ar;574 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);575 struct ath10k_snoc_pipe *pipe_info = &ar_snoc->pipe_info[ce_state->id];576 struct sk_buff *skb;577 struct sk_buff_head list;578 void *transfer_context;579 unsigned int nbytes, max_nbytes;580 581 __skb_queue_head_init(&list);582 while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,583 &nbytes) == 0) {584 skb = transfer_context;585 max_nbytes = skb->len + skb_tailroom(skb);586 dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,587 max_nbytes, DMA_FROM_DEVICE);588 589 if (unlikely(max_nbytes < nbytes)) {590 ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)\n",591 nbytes, max_nbytes);592 dev_kfree_skb_any(skb);593 continue;594 }595 596 skb_put(skb, nbytes);597 __skb_queue_tail(&list, skb);598 }599 600 while ((skb = __skb_dequeue(&list))) {601 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc rx ce pipe %d len %d\n",602 ce_state->id, skb->len);603 604 callback(ar, skb);605 }606 607 ath10k_snoc_rx_post_pipe(pipe_info);608}609 610static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state)611{612 ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);613}614 615static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state)616{617 /* CE4 polling needs to be done whenever CE pipe which transports618 * HTT Rx (target->host) is processed.619 */620 ath10k_ce_per_engine_service(ce_state->ar, CE_POLL_PIPE);621 622 ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);623}624 625/* Called by lower (CE) layer when data is received from the Target.626 * WCN3990 firmware uses separate CE(CE11) to transfer pktlog data.627 */628static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state)629{630 ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);631}632 633static void ath10k_snoc_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb)634{635 skb_pull(skb, sizeof(struct ath10k_htc_hdr));636 ath10k_htt_t2h_msg_handler(ar, skb);637}638 639static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state)640{641 ath10k_ce_per_engine_service(ce_state->ar, CE_POLL_PIPE);642 ath10k_snoc_process_rx_cb(ce_state, ath10k_snoc_htt_rx_deliver);643}644 645static void ath10k_snoc_rx_replenish_retry(struct timer_list *t)646{647 struct ath10k_snoc *ar_snoc = from_timer(ar_snoc, t, rx_post_retry);648 struct ath10k *ar = ar_snoc->ar;649 650 ath10k_snoc_rx_post(ar);651}652 653static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state)654{655 struct ath10k *ar = ce_state->ar;656 struct sk_buff_head list;657 struct sk_buff *skb;658 659 __skb_queue_head_init(&list);660 while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {661 if (!skb)662 continue;663 664 __skb_queue_tail(&list, skb);665 }666 667 while ((skb = __skb_dequeue(&list)))668 ath10k_htc_tx_completion_handler(ar, skb);669}670 671static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state)672{673 struct ath10k *ar = ce_state->ar;674 struct sk_buff *skb;675 676 while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {677 if (!skb)678 continue;679 680 dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,681 skb->len, DMA_TO_DEVICE);682 ath10k_htt_hif_tx_complete(ar, skb);683 }684}685 686static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id,687 struct ath10k_hif_sg_item *items, int n_items)688{689 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);690 struct ath10k_ce *ce = ath10k_ce_priv(ar);691 struct ath10k_snoc_pipe *snoc_pipe;692 struct ath10k_ce_pipe *ce_pipe;693 int err, i = 0;694 695 snoc_pipe = &ar_snoc->pipe_info[pipe_id];696 ce_pipe = snoc_pipe->ce_hdl;697 spin_lock_bh(&ce->ce_lock);698 699 for (i = 0; i < n_items - 1; i++) {700 ath10k_dbg(ar, ATH10K_DBG_SNOC,701 "snoc tx item %d paddr %pad len %d n_items %d\n",702 i, &items[i].paddr, items[i].len, n_items);703 704 err = ath10k_ce_send_nolock(ce_pipe,705 items[i].transfer_context,706 items[i].paddr,707 items[i].len,708 items[i].transfer_id,709 CE_SEND_FLAG_GATHER);710 if (err)711 goto err;712 }713 714 ath10k_dbg(ar, ATH10K_DBG_SNOC,715 "snoc tx item %d paddr %pad len %d n_items %d\n",716 i, &items[i].paddr, items[i].len, n_items);717 718 err = ath10k_ce_send_nolock(ce_pipe,719 items[i].transfer_context,720 items[i].paddr,721 items[i].len,722 items[i].transfer_id,723 0);724 if (err)725 goto err;726 727 spin_unlock_bh(&ce->ce_lock);728 729 return 0;730 731err:732 for (; i > 0; i--)733 __ath10k_ce_send_revert(ce_pipe);734 735 spin_unlock_bh(&ce->ce_lock);736 return err;737}738 739static int ath10k_snoc_hif_get_target_info(struct ath10k *ar,740 struct bmi_target_info *target_info)741{742 target_info->version = ATH10K_HW_WCN3990;743 target_info->type = ATH10K_HW_WCN3990;744 745 return 0;746}747 748static u16 ath10k_snoc_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)749{750 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);751 752 ath10k_dbg(ar, ATH10K_DBG_SNOC, "hif get free queue number\n");753 754 return ath10k_ce_num_free_src_entries(ar_snoc->pipe_info[pipe].ce_hdl);755}756 757static void ath10k_snoc_hif_send_complete_check(struct ath10k *ar, u8 pipe,758 int force)759{760 int resources;761 762 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc hif send complete check\n");763 764 if (!force) {765 resources = ath10k_snoc_hif_get_free_queue_number(ar, pipe);766 767 if (resources > (host_ce_config_wlan[pipe].src_nentries >> 1))768 return;769 }770 ath10k_ce_per_engine_service(ar, pipe);771}772 773static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,774 u16 service_id,775 u8 *ul_pipe, u8 *dl_pipe)776{777 const struct ce_service_to_pipe *entry;778 bool ul_set = false, dl_set = false;779 int i;780 781 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc hif map service\n");782 783 for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {784 entry = &target_service_to_ce_map_wlan[i];785 786 if (__le32_to_cpu(entry->service_id) != service_id)787 continue;788 789 switch (__le32_to_cpu(entry->pipedir)) {790 case PIPEDIR_NONE:791 break;792 case PIPEDIR_IN:793 WARN_ON(dl_set);794 *dl_pipe = __le32_to_cpu(entry->pipenum);795 dl_set = true;796 break;797 case PIPEDIR_OUT:798 WARN_ON(ul_set);799 *ul_pipe = __le32_to_cpu(entry->pipenum);800 ul_set = true;801 break;802 case PIPEDIR_INOUT:803 WARN_ON(dl_set);804 WARN_ON(ul_set);805 *dl_pipe = __le32_to_cpu(entry->pipenum);806 *ul_pipe = __le32_to_cpu(entry->pipenum);807 dl_set = true;808 ul_set = true;809 break;810 }811 }812 813 if (!ul_set || !dl_set)814 return -ENOENT;815 816 return 0;817}818 819static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,820 u8 *ul_pipe, u8 *dl_pipe)821{822 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc hif get default pipe\n");823 824 (void)ath10k_snoc_hif_map_service_to_pipe(ar,825 ATH10K_HTC_SVC_ID_RSVD_CTRL,826 ul_pipe, dl_pipe);827}828 829static inline void ath10k_snoc_irq_disable(struct ath10k *ar)830{831 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);832 int id;833 834 for (id = 0; id < CE_COUNT_MAX; id++)835 disable_irq(ar_snoc->ce_irqs[id].irq_line);836}837 838static inline void ath10k_snoc_irq_enable(struct ath10k *ar)839{840 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);841 int id;842 843 for (id = 0; id < CE_COUNT_MAX; id++)844 enable_irq(ar_snoc->ce_irqs[id].irq_line);845}846 847static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)848{849 struct ath10k_ce_pipe *ce_pipe;850 struct ath10k_ce_ring *ce_ring;851 struct sk_buff *skb;852 struct ath10k *ar;853 int i;854 855 ar = snoc_pipe->hif_ce_state;856 ce_pipe = snoc_pipe->ce_hdl;857 ce_ring = ce_pipe->dest_ring;858 859 if (!ce_ring)860 return;861 862 if (!snoc_pipe->buf_sz)863 return;864 865 for (i = 0; i < ce_ring->nentries; i++) {866 skb = ce_ring->per_transfer_context[i];867 if (!skb)868 continue;869 870 ce_ring->per_transfer_context[i] = NULL;871 872 dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,873 skb->len + skb_tailroom(skb),874 DMA_FROM_DEVICE);875 dev_kfree_skb_any(skb);876 }877}878 879static void ath10k_snoc_tx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)880{881 struct ath10k_ce_pipe *ce_pipe;882 struct ath10k_ce_ring *ce_ring;883 struct sk_buff *skb;884 struct ath10k *ar;885 int i;886 887 ar = snoc_pipe->hif_ce_state;888 ce_pipe = snoc_pipe->ce_hdl;889 ce_ring = ce_pipe->src_ring;890 891 if (!ce_ring)892 return;893 894 if (!snoc_pipe->buf_sz)895 return;896 897 for (i = 0; i < ce_ring->nentries; i++) {898 skb = ce_ring->per_transfer_context[i];899 if (!skb)900 continue;901 902 ce_ring->per_transfer_context[i] = NULL;903 904 ath10k_htc_tx_completion_handler(ar, skb);905 }906}907 908static void ath10k_snoc_buffer_cleanup(struct ath10k *ar)909{910 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);911 struct ath10k_snoc_pipe *pipe_info;912 int pipe_num;913 914 del_timer_sync(&ar_snoc->rx_post_retry);915 for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {916 pipe_info = &ar_snoc->pipe_info[pipe_num];917 ath10k_snoc_rx_pipe_cleanup(pipe_info);918 ath10k_snoc_tx_pipe_cleanup(pipe_info);919 }920}921 922static void ath10k_snoc_hif_stop(struct ath10k *ar)923{924 if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))925 ath10k_snoc_irq_disable(ar);926 927 ath10k_core_napi_sync_disable(ar);928 ath10k_snoc_buffer_cleanup(ar);929 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");930}931 932static int ath10k_snoc_hif_start(struct ath10k *ar)933{934 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);935 936 bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);937 938 dev_set_threaded(ar->napi_dev, true);939 ath10k_core_napi_enable(ar);940 ath10k_snoc_irq_enable(ar);941 ath10k_snoc_rx_post(ar);942 943 clear_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags);944 945 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");946 947 return 0;948}949 950static int ath10k_snoc_init_pipes(struct ath10k *ar)951{952 int i, ret;953 954 for (i = 0; i < CE_COUNT; i++) {955 ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]);956 if (ret) {957 ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n",958 i, ret);959 return ret;960 }961 }962 963 return 0;964}965 966static int ath10k_snoc_wlan_enable(struct ath10k *ar,967 enum ath10k_firmware_mode fw_mode)968{969 struct ath10k_tgt_pipe_cfg tgt_cfg[CE_COUNT_MAX];970 struct ath10k_qmi_wlan_enable_cfg cfg;971 enum wlfw_driver_mode_enum_v01 mode;972 int pipe_num;973 974 for (pipe_num = 0; pipe_num < CE_COUNT_MAX; pipe_num++) {975 tgt_cfg[pipe_num].pipe_num =976 target_ce_config_wlan[pipe_num].pipenum;977 tgt_cfg[pipe_num].pipe_dir =978 target_ce_config_wlan[pipe_num].pipedir;979 tgt_cfg[pipe_num].nentries =980 target_ce_config_wlan[pipe_num].nentries;981 tgt_cfg[pipe_num].nbytes_max =982 target_ce_config_wlan[pipe_num].nbytes_max;983 tgt_cfg[pipe_num].flags =984 target_ce_config_wlan[pipe_num].flags;985 tgt_cfg[pipe_num].reserved = 0;986 }987 988 cfg.num_ce_tgt_cfg = sizeof(target_ce_config_wlan) /989 sizeof(struct ath10k_tgt_pipe_cfg);990 cfg.ce_tgt_cfg = (struct ath10k_tgt_pipe_cfg *)991 &tgt_cfg;992 cfg.num_ce_svc_pipe_cfg = sizeof(target_service_to_ce_map_wlan) /993 sizeof(struct ath10k_svc_pipe_cfg);994 cfg.ce_svc_cfg = (struct ath10k_svc_pipe_cfg *)995 &target_service_to_ce_map_wlan;996 cfg.num_shadow_reg_cfg = ARRAY_SIZE(target_shadow_reg_cfg_map);997 cfg.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *)998 &target_shadow_reg_cfg_map;999 1000 switch (fw_mode) {1001 case ATH10K_FIRMWARE_MODE_NORMAL:1002 mode = QMI_WLFW_MISSION_V01;1003 break;1004 case ATH10K_FIRMWARE_MODE_UTF:1005 mode = QMI_WLFW_FTM_V01;1006 break;1007 default:1008 ath10k_err(ar, "invalid firmware mode %d\n", fw_mode);1009 return -EINVAL;1010 }1011 1012 return ath10k_qmi_wlan_enable(ar, &cfg, mode,1013 NULL);1014}1015 1016static int ath10k_hw_power_on(struct ath10k *ar)1017{1018 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1019 int ret;1020 1021 ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");1022 1023 ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);1024 if (ret)1025 return ret;1026 1027 ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);1028 if (ret)1029 goto vreg_off;1030 1031 return ret;1032 1033vreg_off:1034 regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);1035 return ret;1036}1037 1038static int ath10k_hw_power_off(struct ath10k *ar)1039{1040 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1041 1042 ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");1043 1044 clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);1045 1046 return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);1047}1048 1049static void ath10k_snoc_wlan_disable(struct ath10k *ar)1050{1051 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1052 1053 /* If both ATH10K_FLAG_CRASH_FLUSH and ATH10K_SNOC_FLAG_RECOVERY1054 * flags are not set, it means that the driver has restarted1055 * due to a crash inject via debugfs. In this case, the driver1056 * needs to restart the firmware and hence send qmi wlan disable,1057 * during the driver restart sequence.1058 */1059 if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags) ||1060 !test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags))1061 ath10k_qmi_wlan_disable(ar);1062}1063 1064static void ath10k_snoc_hif_power_down(struct ath10k *ar)1065{1066 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n");1067 1068 ath10k_snoc_wlan_disable(ar);1069 ath10k_ce_free_rri(ar);1070 ath10k_hw_power_off(ar);1071}1072 1073static int ath10k_snoc_hif_power_up(struct ath10k *ar,1074 enum ath10k_firmware_mode fw_mode)1075{1076 int ret;1077 1078 ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 driver state = %d\n",1079 __func__, ar->state);1080 1081 ret = ath10k_hw_power_on(ar);1082 if (ret) {1083 ath10k_err(ar, "failed to power on device: %d\n", ret);1084 return ret;1085 }1086 1087 ret = ath10k_snoc_wlan_enable(ar, fw_mode);1088 if (ret) {1089 ath10k_err(ar, "failed to enable wcn3990: %d\n", ret);1090 goto err_hw_power_off;1091 }1092 1093 ath10k_ce_alloc_rri(ar);1094 1095 ret = ath10k_snoc_init_pipes(ar);1096 if (ret) {1097 ath10k_err(ar, "failed to initialize CE: %d\n", ret);1098 goto err_free_rri;1099 }1100 1101 ath10k_ce_enable_interrupts(ar);1102 1103 return 0;1104 1105err_free_rri:1106 ath10k_ce_free_rri(ar);1107 ath10k_snoc_wlan_disable(ar);1108 1109err_hw_power_off:1110 ath10k_hw_power_off(ar);1111 1112 return ret;1113}1114 1115static int ath10k_snoc_hif_set_target_log_mode(struct ath10k *ar,1116 u8 fw_log_mode)1117{1118 u8 fw_dbg_mode;1119 1120 if (fw_log_mode)1121 fw_dbg_mode = ATH10K_ENABLE_FW_LOG_CE;1122 else1123 fw_dbg_mode = ATH10K_ENABLE_FW_LOG_DIAG;1124 1125 return ath10k_qmi_set_fw_log_mode(ar, fw_dbg_mode);1126}1127 1128#ifdef CONFIG_PM1129static int ath10k_snoc_hif_suspend(struct ath10k *ar)1130{1131 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1132 int ret;1133 1134 if (!device_may_wakeup(ar->dev))1135 return -EPERM;1136 1137 ret = enable_irq_wake(ar_snoc->ce_irqs[ATH10K_SNOC_WAKE_IRQ].irq_line);1138 if (ret) {1139 ath10k_err(ar, "failed to enable wakeup irq :%d\n", ret);1140 return ret;1141 }1142 1143 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc device suspended\n");1144 1145 return ret;1146}1147 1148static int ath10k_snoc_hif_resume(struct ath10k *ar)1149{1150 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1151 int ret;1152 1153 if (!device_may_wakeup(ar->dev))1154 return -EPERM;1155 1156 ret = disable_irq_wake(ar_snoc->ce_irqs[ATH10K_SNOC_WAKE_IRQ].irq_line);1157 if (ret) {1158 ath10k_err(ar, "failed to disable wakeup irq: %d\n", ret);1159 return ret;1160 }1161 1162 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc device resumed\n");1163 1164 return ret;1165}1166#endif1167 1168static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {1169 .read32 = ath10k_snoc_read32,1170 .write32 = ath10k_snoc_write32,1171 .start = ath10k_snoc_hif_start,1172 .stop = ath10k_snoc_hif_stop,1173 .map_service_to_pipe = ath10k_snoc_hif_map_service_to_pipe,1174 .get_default_pipe = ath10k_snoc_hif_get_default_pipe,1175 .power_up = ath10k_snoc_hif_power_up,1176 .power_down = ath10k_snoc_hif_power_down,1177 .tx_sg = ath10k_snoc_hif_tx_sg,1178 .send_complete_check = ath10k_snoc_hif_send_complete_check,1179 .get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,1180 .get_target_info = ath10k_snoc_hif_get_target_info,1181 .set_target_log_mode = ath10k_snoc_hif_set_target_log_mode,1182 1183#ifdef CONFIG_PM1184 .suspend = ath10k_snoc_hif_suspend,1185 .resume = ath10k_snoc_hif_resume,1186#endif1187};1188 1189static const struct ath10k_bus_ops ath10k_snoc_bus_ops = {1190 .read32 = ath10k_snoc_read32,1191 .write32 = ath10k_snoc_write32,1192};1193 1194static int ath10k_snoc_get_ce_id_from_irq(struct ath10k *ar, int irq)1195{1196 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1197 int i;1198 1199 for (i = 0; i < CE_COUNT_MAX; i++) {1200 if (ar_snoc->ce_irqs[i].irq_line == irq)1201 return i;1202 }1203 ath10k_err(ar, "No matching CE id for irq %d\n", irq);1204 1205 return -EINVAL;1206}1207 1208static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg)1209{1210 struct ath10k *ar = arg;1211 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1212 int ce_id = ath10k_snoc_get_ce_id_from_irq(ar, irq);1213 1214 if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_snoc->pipe_info)) {1215 ath10k_warn(ar, "unexpected/invalid irq %d ce_id %d\n", irq,1216 ce_id);1217 return IRQ_HANDLED;1218 }1219 1220 ath10k_ce_disable_interrupt(ar, ce_id);1221 set_bit(ce_id, ar_snoc->pending_ce_irqs);1222 1223 napi_schedule(&ar->napi);1224 1225 return IRQ_HANDLED;1226}1227 1228static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)1229{1230 struct ath10k *ar = container_of(ctx, struct ath10k, napi);1231 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1232 int done = 0;1233 int ce_id;1234 1235 if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {1236 napi_complete(ctx);1237 return done;1238 }1239 1240 for (ce_id = 0; ce_id < CE_COUNT; ce_id++)1241 if (test_and_clear_bit(ce_id, ar_snoc->pending_ce_irqs)) {1242 ath10k_ce_per_engine_service(ar, ce_id);1243 ath10k_ce_enable_interrupt(ar, ce_id);1244 }1245 1246 done = ath10k_htt_txrx_compl_task(ar, budget);1247 1248 if (done < budget)1249 napi_complete(ctx);1250 1251 return done;1252}1253 1254static void ath10k_snoc_init_napi(struct ath10k *ar)1255{1256 netif_napi_add(ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll);1257}1258 1259static int ath10k_snoc_request_irq(struct ath10k *ar)1260{1261 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1262 int ret, id;1263 1264 for (id = 0; id < CE_COUNT_MAX; id++) {1265 ret = request_irq(ar_snoc->ce_irqs[id].irq_line,1266 ath10k_snoc_per_engine_handler,1267 IRQF_NO_AUTOEN, ce_name[id], ar);1268 if (ret) {1269 ath10k_err(ar,1270 "failed to register IRQ handler for CE %d: %d\n",1271 id, ret);1272 goto err_irq;1273 }1274 }1275 1276 return 0;1277 1278err_irq:1279 for (id -= 1; id >= 0; id--)1280 free_irq(ar_snoc->ce_irqs[id].irq_line, ar);1281 1282 return ret;1283}1284 1285static void ath10k_snoc_free_irq(struct ath10k *ar)1286{1287 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1288 int id;1289 1290 for (id = 0; id < CE_COUNT_MAX; id++)1291 free_irq(ar_snoc->ce_irqs[id].irq_line, ar);1292}1293 1294static int ath10k_snoc_resource_init(struct ath10k *ar)1295{1296 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1297 struct platform_device *pdev;1298 struct resource *res;1299 int i, ret = 0;1300 1301 pdev = ar_snoc->dev;1302 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "membase");1303 if (!res) {1304 ath10k_err(ar, "Memory base not found in DT\n");1305 return -EINVAL;1306 }1307 1308 ar_snoc->mem_pa = res->start;1309 ar_snoc->mem = devm_ioremap(&pdev->dev, ar_snoc->mem_pa,1310 resource_size(res));1311 if (!ar_snoc->mem) {1312 ath10k_err(ar, "Memory base ioremap failed with physical address %pa\n",1313 &ar_snoc->mem_pa);1314 return -EINVAL;1315 }1316 1317 for (i = 0; i < CE_COUNT; i++) {1318 ret = platform_get_irq(ar_snoc->dev, i);1319 if (ret < 0)1320 return ret;1321 ar_snoc->ce_irqs[i].irq_line = ret;1322 }1323 1324 ret = device_property_read_u32(&pdev->dev, "qcom,xo-cal-data",1325 &ar_snoc->xo_cal_data);1326 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc xo-cal-data return %d\n", ret);1327 if (ret == 0) {1328 ar_snoc->xo_cal_supported = true;1329 ath10k_dbg(ar, ATH10K_DBG_SNOC, "xo cal data %x\n",1330 ar_snoc->xo_cal_data);1331 }1332 1333 return 0;1334}1335 1336static void ath10k_snoc_quirks_init(struct ath10k *ar)1337{1338 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1339 struct device *dev = &ar_snoc->dev->dev;1340 1341 /* ignore errors, keep NULL if there is no property */1342 of_property_read_string(dev->of_node, "firmware-name", &ar->board_name);1343 1344 if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))1345 set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);1346}1347 1348int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)1349{1350 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1351 struct ath10k_bus_params bus_params = {};1352 int ret;1353 1354 if (test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))1355 return 0;1356 1357 switch (type) {1358 case ATH10K_QMI_EVENT_FW_READY_IND:1359 if (test_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags)) {1360 ath10k_core_start_recovery(ar);1361 break;1362 }1363 1364 bus_params.dev_type = ATH10K_DEV_TYPE_LL;1365 bus_params.chip_id = ar_snoc->target_info.soc_version;1366 ret = ath10k_core_register(ar, &bus_params);1367 if (ret) {1368 ath10k_err(ar, "Failed to register driver core: %d\n",1369 ret);1370 return ret;1371 }1372 set_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags);1373 break;1374 case ATH10K_QMI_EVENT_FW_DOWN_IND:1375 set_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags);1376 set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);1377 break;1378 default:1379 ath10k_err(ar, "invalid fw indication: %llx\n", type);1380 return -EINVAL;1381 }1382 1383 return 0;1384}1385 1386static int ath10k_snoc_setup_resource(struct ath10k *ar)1387{1388 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1389 struct ath10k_ce *ce = ath10k_ce_priv(ar);1390 struct ath10k_snoc_pipe *pipe;1391 int i, ret;1392 1393 timer_setup(&ar_snoc->rx_post_retry, ath10k_snoc_rx_replenish_retry, 0);1394 spin_lock_init(&ce->ce_lock);1395 for (i = 0; i < CE_COUNT; i++) {1396 pipe = &ar_snoc->pipe_info[i];1397 pipe->ce_hdl = &ce->ce_states[i];1398 pipe->pipe_num = i;1399 pipe->hif_ce_state = ar;1400 1401 ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);1402 if (ret) {1403 ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",1404 i, ret);1405 return ret;1406 }1407 1408 pipe->buf_sz = host_ce_config_wlan[i].src_sz_max;1409 }1410 ath10k_snoc_init_napi(ar);1411 1412 return 0;1413}1414 1415static void ath10k_snoc_release_resource(struct ath10k *ar)1416{1417 int i;1418 1419 netif_napi_del(&ar->napi);1420 for (i = 0; i < CE_COUNT; i++)1421 ath10k_ce_free_pipe(ar, i);1422}1423 1424static void ath10k_msa_dump_memory(struct ath10k *ar,1425 struct ath10k_fw_crash_data *crash_data)1426{1427 const struct ath10k_hw_mem_layout *mem_layout;1428 const struct ath10k_mem_region *current_region;1429 struct ath10k_dump_ram_data_hdr *hdr;1430 size_t buf_len;1431 u8 *buf;1432 1433 if (!crash_data || !crash_data->ramdump_buf)1434 return;1435 1436 mem_layout = ath10k_coredump_get_mem_layout(ar);1437 if (!mem_layout)1438 return;1439 1440 current_region = &mem_layout->region_table.regions[0];1441 1442 buf = crash_data->ramdump_buf;1443 buf_len = crash_data->ramdump_buf_len;1444 memset(buf, 0, buf_len);1445 1446 /* Reserve space for the header. */1447 hdr = (void *)buf;1448 buf += sizeof(*hdr);1449 buf_len -= sizeof(*hdr);1450 1451 hdr->region_type = cpu_to_le32(current_region->type);1452 hdr->start = cpu_to_le32((unsigned long)ar->msa.vaddr);1453 hdr->length = cpu_to_le32(ar->msa.mem_size);1454 1455 if (current_region->len < ar->msa.mem_size) {1456 memcpy(buf, ar->msa.vaddr, current_region->len);1457 ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",1458 current_region->len, ar->msa.mem_size);1459 } else {1460 memcpy(buf, ar->msa.vaddr, ar->msa.mem_size);1461 }1462}1463 1464void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)1465{1466 struct ath10k_fw_crash_data *crash_data;1467 char guid[UUID_STRING_LEN + 1];1468 1469 mutex_lock(&ar->dump_mutex);1470 1471 spin_lock_bh(&ar->data_lock);1472 ar->stats.fw_crash_counter++;1473 spin_unlock_bh(&ar->data_lock);1474 1475 crash_data = ath10k_coredump_new(ar);1476 1477 if (crash_data)1478 scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);1479 else1480 scnprintf(guid, sizeof(guid), "n/a");1481 1482 ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);1483 ath10k_print_driver_info(ar);1484 ath10k_msa_dump_memory(ar, crash_data);1485 mutex_unlock(&ar->dump_mutex);1486}1487 1488static int ath10k_snoc_modem_notify(struct notifier_block *nb, unsigned long action,1489 void *data)1490{1491 struct ath10k_snoc *ar_snoc = container_of(nb, struct ath10k_snoc, nb);1492 struct ath10k *ar = ar_snoc->ar;1493 struct qcom_ssr_notify_data *notify_data = data;1494 1495 switch (action) {1496 case QCOM_SSR_BEFORE_POWERUP:1497 ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem starting event\n");1498 clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags);1499 break;1500 1501 case QCOM_SSR_AFTER_POWERUP:1502 ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem running event\n");1503 break;1504 1505 case QCOM_SSR_BEFORE_SHUTDOWN:1506 ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem %s event\n",1507 notify_data->crashed ? "crashed" : "stopping");1508 if (!notify_data->crashed)1509 set_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags);1510 else1511 clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags);1512 break;1513 1514 case QCOM_SSR_AFTER_SHUTDOWN:1515 ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem offline event\n");1516 break;1517 1518 default:1519 ath10k_err(ar, "received unrecognized event %lu\n", action);1520 break;1521 }1522 1523 return NOTIFY_OK;1524}1525 1526static int ath10k_modem_init(struct ath10k *ar)1527{1528 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1529 void *notifier;1530 int ret;1531 1532 ar_snoc->nb.notifier_call = ath10k_snoc_modem_notify;1533 1534 notifier = qcom_register_ssr_notifier("mpss", &ar_snoc->nb);1535 if (IS_ERR(notifier)) {1536 ret = PTR_ERR(notifier);1537 ath10k_err(ar, "failed to initialize modem notifier: %d\n", ret);1538 return ret;1539 }1540 1541 ar_snoc->notifier = notifier;1542 1543 return 0;1544}1545 1546static void ath10k_modem_deinit(struct ath10k *ar)1547{1548 int ret;1549 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1550 1551 ret = qcom_unregister_ssr_notifier(ar_snoc->notifier, &ar_snoc->nb);1552 if (ret)1553 ath10k_err(ar, "error %d unregistering notifier\n", ret);1554}1555 1556static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size)1557{1558 struct device *dev = ar->dev;1559 struct device_node *node;1560 struct resource r;1561 int ret;1562 1563 node = of_parse_phandle(dev->of_node, "memory-region", 0);1564 if (node) {1565 ret = of_address_to_resource(node, 0, &r);1566 of_node_put(node);1567 if (ret) {1568 dev_err(dev, "failed to resolve msa fixed region\n");1569 return ret;1570 }1571 1572 ar->msa.paddr = r.start;1573 ar->msa.mem_size = resource_size(&r);1574 ar->msa.vaddr = devm_memremap(dev, ar->msa.paddr,1575 ar->msa.mem_size,1576 MEMREMAP_WT);1577 if (IS_ERR(ar->msa.vaddr)) {1578 dev_err(dev, "failed to map memory region: %pa\n",1579 &r.start);1580 return PTR_ERR(ar->msa.vaddr);1581 }1582 } else {1583 ar->msa.vaddr = dmam_alloc_coherent(dev, msa_size,1584 &ar->msa.paddr,1585 GFP_KERNEL);1586 if (!ar->msa.vaddr) {1587 ath10k_err(ar, "failed to allocate dma memory for msa region\n");1588 return -ENOMEM;1589 }1590 ar->msa.mem_size = msa_size;1591 }1592 1593 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa.paddr: %pad , msa.vaddr: 0x%p\n",1594 &ar->msa.paddr,1595 ar->msa.vaddr);1596 1597 return 0;1598}1599 1600static int ath10k_fw_init(struct ath10k *ar)1601{1602 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1603 struct device *host_dev = &ar_snoc->dev->dev;1604 struct platform_device_info info;1605 struct iommu_domain *iommu_dom;1606 struct platform_device *pdev;1607 struct device_node *node;1608 int ret;1609 1610 node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");1611 if (!node) {1612 ar_snoc->use_tz = true;1613 return 0;1614 }1615 1616 memset(&info, 0, sizeof(info));1617 info.fwnode = &node->fwnode;1618 info.parent = host_dev;1619 info.name = node->name;1620 info.dma_mask = DMA_BIT_MASK(32);1621 1622 pdev = platform_device_register_full(&info);1623 if (IS_ERR(pdev)) {1624 of_node_put(node);1625 return PTR_ERR(pdev);1626 }1627 1628 pdev->dev.of_node = node;1629 1630 ret = of_dma_configure(&pdev->dev, node, true);1631 if (ret) {1632 ath10k_err(ar, "dma configure fail: %d\n", ret);1633 goto err_unregister;1634 }1635 1636 ar_snoc->fw.dev = &pdev->dev;1637 1638 iommu_dom = iommu_paging_domain_alloc(ar_snoc->fw.dev);1639 if (IS_ERR(iommu_dom)) {1640 ath10k_err(ar, "failed to allocate iommu domain\n");1641 ret = PTR_ERR(iommu_dom);1642 goto err_unregister;1643 }1644 1645 ret = iommu_attach_device(iommu_dom, ar_snoc->fw.dev);1646 if (ret) {1647 ath10k_err(ar, "could not attach device: %d\n", ret);1648 goto err_iommu_free;1649 }1650 1651 ar_snoc->fw.iommu_domain = iommu_dom;1652 ar_snoc->fw.fw_start_addr = ar->msa.paddr;1653 1654 ret = iommu_map(iommu_dom, ar_snoc->fw.fw_start_addr,1655 ar->msa.paddr, ar->msa.mem_size,1656 IOMMU_READ | IOMMU_WRITE, GFP_KERNEL);1657 if (ret) {1658 ath10k_err(ar, "failed to map firmware region: %d\n", ret);1659 goto err_iommu_detach;1660 }1661 1662 of_node_put(node);1663 1664 return 0;1665 1666err_iommu_detach:1667 iommu_detach_device(iommu_dom, ar_snoc->fw.dev);1668 1669err_iommu_free:1670 iommu_domain_free(iommu_dom);1671 1672err_unregister:1673 platform_device_unregister(pdev);1674 of_node_put(node);1675 1676 return ret;1677}1678 1679static int ath10k_fw_deinit(struct ath10k *ar)1680{1681 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1682 const size_t mapped_size = ar_snoc->fw.mapped_mem_size;1683 struct iommu_domain *iommu;1684 size_t unmapped_size;1685 1686 if (ar_snoc->use_tz)1687 return 0;1688 1689 iommu = ar_snoc->fw.iommu_domain;1690 1691 unmapped_size = iommu_unmap(iommu, ar_snoc->fw.fw_start_addr,1692 mapped_size);1693 if (unmapped_size != mapped_size)1694 ath10k_err(ar, "failed to unmap firmware: %zu\n",1695 unmapped_size);1696 1697 iommu_detach_device(iommu, ar_snoc->fw.dev);1698 iommu_domain_free(iommu);1699 1700 platform_device_unregister(to_platform_device(ar_snoc->fw.dev));1701 1702 return 0;1703}1704 1705static const struct of_device_id ath10k_snoc_dt_match[] = {1706 { .compatible = "qcom,wcn3990-wifi",1707 .data = &drv_priv,1708 },1709 { }1710};1711MODULE_DEVICE_TABLE(of, ath10k_snoc_dt_match);1712 1713static int ath10k_snoc_probe(struct platform_device *pdev)1714{1715 const struct ath10k_snoc_drv_priv *drv_data;1716 struct ath10k_snoc *ar_snoc;1717 struct device *dev;1718 struct ath10k *ar;1719 u32 msa_size;1720 int ret;1721 u32 i;1722 1723 dev = &pdev->dev;1724 drv_data = device_get_match_data(dev);1725 if (!drv_data) {1726 dev_err(dev, "failed to find matching device tree id\n");1727 return -EINVAL;1728 }1729 1730 ret = dma_set_mask_and_coherent(dev, drv_data->dma_mask);1731 if (ret) {1732 dev_err(dev, "failed to set dma mask: %d\n", ret);1733 return ret;1734 }1735 1736 ar = ath10k_core_create(sizeof(*ar_snoc), dev, ATH10K_BUS_SNOC,1737 drv_data->hw_rev, &ath10k_snoc_hif_ops);1738 if (!ar) {1739 dev_err(dev, "failed to allocate core\n");1740 return -ENOMEM;1741 }1742 1743 ar_snoc = ath10k_snoc_priv(ar);1744 ar_snoc->dev = pdev;1745 platform_set_drvdata(pdev, ar);1746 ar_snoc->ar = ar;1747 ar_snoc->ce.bus_ops = &ath10k_snoc_bus_ops;1748 ar->ce_priv = &ar_snoc->ce;1749 msa_size = drv_data->msa_size;1750 1751 ath10k_snoc_quirks_init(ar);1752 1753 ret = ath10k_snoc_resource_init(ar);1754 if (ret) {1755 ath10k_warn(ar, "failed to initialize resource: %d\n", ret);1756 goto err_core_destroy;1757 }1758 1759 ret = ath10k_snoc_setup_resource(ar);1760 if (ret) {1761 ath10k_warn(ar, "failed to setup resource: %d\n", ret);1762 goto err_core_destroy;1763 }1764 ret = ath10k_snoc_request_irq(ar);1765 if (ret) {1766 ath10k_warn(ar, "failed to request irqs: %d\n", ret);1767 goto err_release_resource;1768 }1769 1770 ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);1771 ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,1772 sizeof(*ar_snoc->vregs), GFP_KERNEL);1773 if (!ar_snoc->vregs) {1774 ret = -ENOMEM;1775 goto err_free_irq;1776 }1777 for (i = 0; i < ar_snoc->num_vregs; i++)1778 ar_snoc->vregs[i].supply = ath10k_regulators[i];1779 1780 ret = devm_regulator_bulk_get(&pdev->dev, ar_snoc->num_vregs,1781 ar_snoc->vregs);1782 if (ret < 0)1783 goto err_free_irq;1784 1785 ar_snoc->num_clks = ARRAY_SIZE(ath10k_clocks);1786 ar_snoc->clks = devm_kcalloc(&pdev->dev, ar_snoc->num_clks,1787 sizeof(*ar_snoc->clks), GFP_KERNEL);1788 if (!ar_snoc->clks) {1789 ret = -ENOMEM;1790 goto err_free_irq;1791 }1792 1793 for (i = 0; i < ar_snoc->num_clks; i++)1794 ar_snoc->clks[i].id = ath10k_clocks[i];1795 1796 ret = devm_clk_bulk_get_optional(&pdev->dev, ar_snoc->num_clks,1797 ar_snoc->clks);1798 if (ret)1799 goto err_free_irq;1800 1801 ret = ath10k_setup_msa_resources(ar, msa_size);1802 if (ret) {1803 ath10k_warn(ar, "failed to setup msa resources: %d\n", ret);1804 goto err_free_irq;1805 }1806 1807 ret = ath10k_fw_init(ar);1808 if (ret) {1809 ath10k_err(ar, "failed to initialize firmware: %d\n", ret);1810 goto err_free_irq;1811 }1812 1813 ret = ath10k_qmi_init(ar, msa_size);1814 if (ret) {1815 ath10k_warn(ar, "failed to register wlfw qmi client: %d\n", ret);1816 goto err_fw_deinit;1817 }1818 1819 ret = ath10k_modem_init(ar);1820 if (ret)1821 goto err_qmi_deinit;1822 1823 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");1824 1825 return 0;1826 1827err_qmi_deinit:1828 ath10k_qmi_deinit(ar);1829 1830err_fw_deinit:1831 ath10k_fw_deinit(ar);1832 1833err_free_irq:1834 ath10k_snoc_free_irq(ar);1835 1836err_release_resource:1837 ath10k_snoc_release_resource(ar);1838 1839err_core_destroy:1840 ath10k_core_destroy(ar);1841 1842 return ret;1843}1844 1845static int ath10k_snoc_free_resources(struct ath10k *ar)1846{1847 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1848 1849 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc free resources\n");1850 1851 set_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags);1852 1853 ath10k_core_unregister(ar);1854 ath10k_fw_deinit(ar);1855 ath10k_snoc_free_irq(ar);1856 ath10k_snoc_release_resource(ar);1857 ath10k_modem_deinit(ar);1858 ath10k_qmi_deinit(ar);1859 ath10k_core_destroy(ar);1860 1861 return 0;1862}1863 1864static void ath10k_snoc_remove(struct platform_device *pdev)1865{1866 struct ath10k *ar = platform_get_drvdata(pdev);1867 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);1868 1869 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc remove\n");1870 1871 reinit_completion(&ar->driver_recovery);1872 1873 if (test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags))1874 wait_for_completion_timeout(&ar->driver_recovery, 3 * HZ);1875 1876 ath10k_snoc_free_resources(ar);1877}1878 1879static void ath10k_snoc_shutdown(struct platform_device *pdev)1880{1881 struct ath10k *ar = platform_get_drvdata(pdev);1882 1883 ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc shutdown\n");1884 ath10k_snoc_free_resources(ar);1885}1886 1887static struct platform_driver ath10k_snoc_driver = {1888 .probe = ath10k_snoc_probe,1889 .remove_new = ath10k_snoc_remove,1890 .shutdown = ath10k_snoc_shutdown,1891 .driver = {1892 .name = "ath10k_snoc",1893 .of_match_table = ath10k_snoc_dt_match,1894 },1895};1896module_platform_driver(ath10k_snoc_driver);1897 1898MODULE_AUTHOR("Qualcomm");1899MODULE_LICENSE("Dual BSD/GPL");1900MODULE_DESCRIPTION("Driver support for Atheros WCN3990 SNOC devices");1901