0001
0002
0003
0004
0005
0006
0007 #include <linux/module.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/of_device.h>
0010 #include <linux/of.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/of_address.h>
0013 #include <linux/iommu.h>
0014 #include "ahb.h"
0015 #include "debug.h"
0016 #include "hif.h"
0017 #include <linux/remoteproc.h>
0018 #include "pcic.h"
0019
0020 static const struct of_device_id ath11k_ahb_of_match[] = {
0021
0022
0023
0024 { .compatible = "qcom,ipq8074-wifi",
0025 .data = (void *)ATH11K_HW_IPQ8074,
0026 },
0027 { .compatible = "qcom,ipq6018-wifi",
0028 .data = (void *)ATH11K_HW_IPQ6018_HW10,
0029 },
0030 { .compatible = "qcom,wcn6750-wifi",
0031 .data = (void *)ATH11K_HW_WCN6750_HW10,
0032 },
0033 { }
0034 };
0035
0036 MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
0037
0038 #define ATH11K_IRQ_CE0_OFFSET 4
0039
0040 static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
0041 "misc-pulse1",
0042 "misc-latch",
0043 "sw-exception",
0044 "watchdog",
0045 "ce0",
0046 "ce1",
0047 "ce2",
0048 "ce3",
0049 "ce4",
0050 "ce5",
0051 "ce6",
0052 "ce7",
0053 "ce8",
0054 "ce9",
0055 "ce10",
0056 "ce11",
0057 "host2wbm-desc-feed",
0058 "host2reo-re-injection",
0059 "host2reo-command",
0060 "host2rxdma-monitor-ring3",
0061 "host2rxdma-monitor-ring2",
0062 "host2rxdma-monitor-ring1",
0063 "reo2ost-exception",
0064 "wbm2host-rx-release",
0065 "reo2host-status",
0066 "reo2host-destination-ring4",
0067 "reo2host-destination-ring3",
0068 "reo2host-destination-ring2",
0069 "reo2host-destination-ring1",
0070 "rxdma2host-monitor-destination-mac3",
0071 "rxdma2host-monitor-destination-mac2",
0072 "rxdma2host-monitor-destination-mac1",
0073 "ppdu-end-interrupts-mac3",
0074 "ppdu-end-interrupts-mac2",
0075 "ppdu-end-interrupts-mac1",
0076 "rxdma2host-monitor-status-ring-mac3",
0077 "rxdma2host-monitor-status-ring-mac2",
0078 "rxdma2host-monitor-status-ring-mac1",
0079 "host2rxdma-host-buf-ring-mac3",
0080 "host2rxdma-host-buf-ring-mac2",
0081 "host2rxdma-host-buf-ring-mac1",
0082 "rxdma2host-destination-ring-mac3",
0083 "rxdma2host-destination-ring-mac2",
0084 "rxdma2host-destination-ring-mac1",
0085 "host2tcl-input-ring4",
0086 "host2tcl-input-ring3",
0087 "host2tcl-input-ring2",
0088 "host2tcl-input-ring1",
0089 "wbm2host-tx-completions-ring3",
0090 "wbm2host-tx-completions-ring2",
0091 "wbm2host-tx-completions-ring1",
0092 "tcl2host-status-ring",
0093 };
0094
0095
0096
0097
0098 enum ext_irq_num {
0099 host2wbm_desc_feed = 16,
0100 host2reo_re_injection,
0101 host2reo_command,
0102 host2rxdma_monitor_ring3,
0103 host2rxdma_monitor_ring2,
0104 host2rxdma_monitor_ring1,
0105 reo2host_exception,
0106 wbm2host_rx_release,
0107 reo2host_status,
0108 reo2host_destination_ring4,
0109 reo2host_destination_ring3,
0110 reo2host_destination_ring2,
0111 reo2host_destination_ring1,
0112 rxdma2host_monitor_destination_mac3,
0113 rxdma2host_monitor_destination_mac2,
0114 rxdma2host_monitor_destination_mac1,
0115 ppdu_end_interrupts_mac3,
0116 ppdu_end_interrupts_mac2,
0117 ppdu_end_interrupts_mac1,
0118 rxdma2host_monitor_status_ring_mac3,
0119 rxdma2host_monitor_status_ring_mac2,
0120 rxdma2host_monitor_status_ring_mac1,
0121 host2rxdma_host_buf_ring_mac3,
0122 host2rxdma_host_buf_ring_mac2,
0123 host2rxdma_host_buf_ring_mac1,
0124 rxdma2host_destination_ring_mac3,
0125 rxdma2host_destination_ring_mac2,
0126 rxdma2host_destination_ring_mac1,
0127 host2tcl_input_ring4,
0128 host2tcl_input_ring3,
0129 host2tcl_input_ring2,
0130 host2tcl_input_ring1,
0131 wbm2host_tx_completions_ring3,
0132 wbm2host_tx_completions_ring2,
0133 wbm2host_tx_completions_ring1,
0134 tcl2host_status_ring,
0135 };
0136
0137 static int
0138 ath11k_ahb_get_msi_irq_wcn6750(struct ath11k_base *ab, unsigned int vector)
0139 {
0140 return ab->pci.msi.irqs[vector];
0141 }
0142
0143 static inline u32
0144 ath11k_ahb_get_window_start_wcn6750(struct ath11k_base *ab, u32 offset)
0145 {
0146 u32 window_start = 0;
0147
0148
0149 if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK)
0150 window_start = ATH11K_PCI_WINDOW_START;
0151
0152 else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) <
0153 ATH11K_PCI_WINDOW_RANGE_MASK)
0154 window_start = 2 * ATH11K_PCI_WINDOW_START;
0155
0156 return window_start;
0157 }
0158
0159 static void
0160 ath11k_ahb_window_write32_wcn6750(struct ath11k_base *ab, u32 offset, u32 value)
0161 {
0162 u32 window_start;
0163
0164
0165 window_start = ath11k_ahb_get_window_start_wcn6750(ab, offset);
0166
0167 iowrite32(value, ab->mem + window_start +
0168 (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
0169 }
0170
0171 static u32 ath11k_ahb_window_read32_wcn6750(struct ath11k_base *ab, u32 offset)
0172 {
0173 u32 window_start;
0174 u32 val;
0175
0176
0177 window_start = ath11k_ahb_get_window_start_wcn6750(ab, offset);
0178
0179 val = ioread32(ab->mem + window_start +
0180 (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
0181 return val;
0182 }
0183
0184 static const struct ath11k_pci_ops ath11k_ahb_pci_ops_wcn6750 = {
0185 .wakeup = NULL,
0186 .release = NULL,
0187 .get_msi_irq = ath11k_ahb_get_msi_irq_wcn6750,
0188 .window_write32 = ath11k_ahb_window_write32_wcn6750,
0189 .window_read32 = ath11k_ahb_window_read32_wcn6750,
0190 };
0191
0192 static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
0193 {
0194 return ioread32(ab->mem + offset);
0195 }
0196
0197 static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
0198 {
0199 iowrite32(value, ab->mem + offset);
0200 }
0201
0202 static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
0203 {
0204 int i;
0205
0206 for (i = 0; i < ab->hw_params.ce_count; i++) {
0207 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
0208
0209 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
0210 continue;
0211
0212 tasklet_kill(&ce_pipe->intr_tq);
0213 }
0214 }
0215
0216 static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
0217 {
0218 int i;
0219
0220 for (i = 0; i < irq_grp->num_irq; i++)
0221 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
0222 }
0223
0224 static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
0225 {
0226 int i;
0227
0228 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
0229 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
0230
0231 ath11k_ahb_ext_grp_disable(irq_grp);
0232
0233 if (irq_grp->napi_enabled) {
0234 napi_synchronize(&irq_grp->napi);
0235 napi_disable(&irq_grp->napi);
0236 irq_grp->napi_enabled = false;
0237 }
0238 }
0239 }
0240
0241 static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
0242 {
0243 int i;
0244
0245 for (i = 0; i < irq_grp->num_irq; i++)
0246 enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
0247 }
0248
0249 static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset)
0250 {
0251 u32 val;
0252
0253 val = ath11k_ahb_read32(ab, offset);
0254 ath11k_ahb_write32(ab, offset, val | BIT(bit));
0255 }
0256
0257 static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
0258 {
0259 u32 val;
0260
0261 val = ath11k_ahb_read32(ab, offset);
0262 ath11k_ahb_write32(ab, offset, val & ~BIT(bit));
0263 }
0264
0265 static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
0266 {
0267 const struct ce_attr *ce_attr;
0268
0269 ce_attr = &ab->hw_params.host_ce_config[ce_id];
0270 if (ce_attr->src_nentries)
0271 ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
0272
0273 if (ce_attr->dest_nentries) {
0274 ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
0275 ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
0276 CE_HOST_IE_3_ADDRESS);
0277 }
0278 }
0279
0280 static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
0281 {
0282 const struct ce_attr *ce_attr;
0283
0284 ce_attr = &ab->hw_params.host_ce_config[ce_id];
0285 if (ce_attr->src_nentries)
0286 ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
0287
0288 if (ce_attr->dest_nentries) {
0289 ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
0290 ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
0291 CE_HOST_IE_3_ADDRESS);
0292 }
0293 }
0294
0295 static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
0296 {
0297 int i;
0298 int irq_idx;
0299
0300 for (i = 0; i < ab->hw_params.ce_count; i++) {
0301 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
0302 continue;
0303
0304 irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
0305 synchronize_irq(ab->irq_num[irq_idx]);
0306 }
0307 }
0308
0309 static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab)
0310 {
0311 int i, j;
0312 int irq_idx;
0313
0314 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
0315 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
0316
0317 for (j = 0; j < irq_grp->num_irq; j++) {
0318 irq_idx = irq_grp->irqs[j];
0319 synchronize_irq(ab->irq_num[irq_idx]);
0320 }
0321 }
0322 }
0323
0324 static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
0325 {
0326 int i;
0327
0328 for (i = 0; i < ab->hw_params.ce_count; i++) {
0329 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
0330 continue;
0331 ath11k_ahb_ce_irq_enable(ab, i);
0332 }
0333 }
0334
0335 static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
0336 {
0337 int i;
0338
0339 for (i = 0; i < ab->hw_params.ce_count; i++) {
0340 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
0341 continue;
0342 ath11k_ahb_ce_irq_disable(ab, i);
0343 }
0344 }
0345
0346 static int ath11k_ahb_start(struct ath11k_base *ab)
0347 {
0348 ath11k_ahb_ce_irqs_enable(ab);
0349 ath11k_ce_rx_post_buf(ab);
0350
0351 return 0;
0352 }
0353
0354 static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
0355 {
0356 int i;
0357
0358 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
0359 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
0360
0361 if (!irq_grp->napi_enabled) {
0362 napi_enable(&irq_grp->napi);
0363 irq_grp->napi_enabled = true;
0364 }
0365 ath11k_ahb_ext_grp_enable(irq_grp);
0366 }
0367 }
0368
0369 static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
0370 {
0371 __ath11k_ahb_ext_irq_disable(ab);
0372 ath11k_ahb_sync_ext_irqs(ab);
0373 }
0374
0375 static void ath11k_ahb_stop(struct ath11k_base *ab)
0376 {
0377 if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
0378 ath11k_ahb_ce_irqs_disable(ab);
0379 ath11k_ahb_sync_ce_irqs(ab);
0380 ath11k_ahb_kill_tasklets(ab);
0381 del_timer_sync(&ab->rx_replenish_retry);
0382 ath11k_ce_cleanup_pipes(ab);
0383 }
0384
0385 static int ath11k_ahb_power_up(struct ath11k_base *ab)
0386 {
0387 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
0388 int ret;
0389
0390 ret = rproc_boot(ab_ahb->tgt_rproc);
0391 if (ret)
0392 ath11k_err(ab, "failed to boot the remote processor Q6\n");
0393
0394 return ret;
0395 }
0396
0397 static void ath11k_ahb_power_down(struct ath11k_base *ab)
0398 {
0399 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
0400
0401 rproc_shutdown(ab_ahb->tgt_rproc);
0402 }
0403
0404 static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab)
0405 {
0406 int timeout;
0407
0408 if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done ||
0409 ab->hw_params.cold_boot_calib == 0)
0410 return 0;
0411
0412 ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n");
0413 timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
0414 (ab->qmi.cal_done == 1),
0415 ATH11K_COLD_BOOT_FW_RESET_DELAY);
0416 if (timeout <= 0) {
0417 ath11k_cold_boot_cal = 0;
0418 ath11k_warn(ab, "Coldboot Calibration failed timed out\n");
0419 }
0420
0421
0422 ath11k_ahb_power_down(ab);
0423 ath11k_ahb_power_up(ab);
0424
0425 ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n");
0426 return 0;
0427 }
0428
0429 static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
0430 {
0431 struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
0432
0433 cfg->tgt_ce_len = ab->hw_params.target_ce_count;
0434 cfg->tgt_ce = ab->hw_params.target_ce_config;
0435 cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
0436 cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
0437 ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
0438 }
0439
0440 static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
0441 {
0442 int i, j;
0443
0444 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
0445 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
0446
0447 for (j = 0; j < irq_grp->num_irq; j++)
0448 free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
0449
0450 netif_napi_del(&irq_grp->napi);
0451 }
0452 }
0453
0454 static void ath11k_ahb_free_irq(struct ath11k_base *ab)
0455 {
0456 int irq_idx;
0457 int i;
0458
0459 if (ab->hw_params.hybrid_bus_type)
0460 return ath11k_pcic_free_irq(ab);
0461
0462 for (i = 0; i < ab->hw_params.ce_count; i++) {
0463 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
0464 continue;
0465 irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
0466 free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
0467 }
0468
0469 ath11k_ahb_free_ext_irq(ab);
0470 }
0471
0472 static void ath11k_ahb_ce_tasklet(struct tasklet_struct *t)
0473 {
0474 struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
0475
0476 ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
0477
0478 ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
0479 }
0480
0481 static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
0482 {
0483 struct ath11k_ce_pipe *ce_pipe = arg;
0484
0485
0486 ce_pipe->timestamp = jiffies;
0487
0488 ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
0489
0490 tasklet_schedule(&ce_pipe->intr_tq);
0491
0492 return IRQ_HANDLED;
0493 }
0494
0495 static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
0496 {
0497 struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
0498 struct ath11k_ext_irq_grp,
0499 napi);
0500 struct ath11k_base *ab = irq_grp->ab;
0501 int work_done;
0502
0503 work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
0504 if (work_done < budget) {
0505 napi_complete_done(napi, work_done);
0506 ath11k_ahb_ext_grp_enable(irq_grp);
0507 }
0508
0509 if (work_done > budget)
0510 work_done = budget;
0511
0512 return work_done;
0513 }
0514
0515 static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
0516 {
0517 struct ath11k_ext_irq_grp *irq_grp = arg;
0518
0519
0520 irq_grp->timestamp = jiffies;
0521
0522 ath11k_ahb_ext_grp_disable(irq_grp);
0523
0524 napi_schedule(&irq_grp->napi);
0525
0526 return IRQ_HANDLED;
0527 }
0528
0529 static int ath11k_ahb_config_ext_irq(struct ath11k_base *ab)
0530 {
0531 struct ath11k_hw_params *hw = &ab->hw_params;
0532 int i, j;
0533 int irq;
0534 int ret;
0535
0536 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
0537 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
0538 u32 num_irq = 0;
0539
0540 irq_grp->ab = ab;
0541 irq_grp->grp_id = i;
0542 init_dummy_netdev(&irq_grp->napi_ndev);
0543 netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
0544 ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
0545
0546 for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
0547 if (ab->hw_params.ring_mask->tx[i] & BIT(j)) {
0548 irq_grp->irqs[num_irq++] =
0549 wbm2host_tx_completions_ring1 - j;
0550 }
0551
0552 if (ab->hw_params.ring_mask->rx[i] & BIT(j)) {
0553 irq_grp->irqs[num_irq++] =
0554 reo2host_destination_ring1 - j;
0555 }
0556
0557 if (ab->hw_params.ring_mask->rx_err[i] & BIT(j))
0558 irq_grp->irqs[num_irq++] = reo2host_exception;
0559
0560 if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j))
0561 irq_grp->irqs[num_irq++] = wbm2host_rx_release;
0562
0563 if (ab->hw_params.ring_mask->reo_status[i] & BIT(j))
0564 irq_grp->irqs[num_irq++] = reo2host_status;
0565
0566 if (j < ab->hw_params.max_radios) {
0567 if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
0568 irq_grp->irqs[num_irq++] =
0569 rxdma2host_destination_ring_mac1 -
0570 ath11k_hw_get_mac_from_pdev_id(hw, j);
0571 }
0572
0573 if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) {
0574 irq_grp->irqs[num_irq++] =
0575 host2rxdma_host_buf_ring_mac1 -
0576 ath11k_hw_get_mac_from_pdev_id(hw, j);
0577 }
0578
0579 if (ab->hw_params.ring_mask->rx_mon_status[i] & BIT(j)) {
0580 irq_grp->irqs[num_irq++] =
0581 ppdu_end_interrupts_mac1 -
0582 ath11k_hw_get_mac_from_pdev_id(hw, j);
0583 irq_grp->irqs[num_irq++] =
0584 rxdma2host_monitor_status_ring_mac1 -
0585 ath11k_hw_get_mac_from_pdev_id(hw, j);
0586 }
0587 }
0588 }
0589 irq_grp->num_irq = num_irq;
0590
0591 for (j = 0; j < irq_grp->num_irq; j++) {
0592 int irq_idx = irq_grp->irqs[j];
0593
0594 irq = platform_get_irq_byname(ab->pdev,
0595 irq_name[irq_idx]);
0596 ab->irq_num[irq_idx] = irq;
0597 irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
0598 ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler,
0599 IRQF_TRIGGER_RISING,
0600 irq_name[irq_idx], irq_grp);
0601 if (ret) {
0602 ath11k_err(ab, "failed request_irq for %d\n",
0603 irq);
0604 }
0605 }
0606 }
0607
0608 return 0;
0609 }
0610
0611 static int ath11k_ahb_config_irq(struct ath11k_base *ab)
0612 {
0613 int irq, irq_idx, i;
0614 int ret;
0615
0616 if (ab->hw_params.hybrid_bus_type)
0617 return ath11k_pcic_config_irq(ab);
0618
0619
0620 for (i = 0; i < ab->hw_params.ce_count; i++) {
0621 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
0622
0623 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
0624 continue;
0625
0626 irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
0627
0628 tasklet_setup(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet);
0629 irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
0630 ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
0631 IRQF_TRIGGER_RISING, irq_name[irq_idx],
0632 ce_pipe);
0633 if (ret)
0634 return ret;
0635
0636 ab->irq_num[irq_idx] = irq;
0637 }
0638
0639
0640 ret = ath11k_ahb_config_ext_irq(ab);
0641
0642 return ret;
0643 }
0644
0645 static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
0646 u8 *ul_pipe, u8 *dl_pipe)
0647 {
0648 const struct service_to_pipe *entry;
0649 bool ul_set = false, dl_set = false;
0650 int i;
0651
0652 for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
0653 entry = &ab->hw_params.svc_to_ce_map[i];
0654
0655 if (__le32_to_cpu(entry->service_id) != service_id)
0656 continue;
0657
0658 switch (__le32_to_cpu(entry->pipedir)) {
0659 case PIPEDIR_NONE:
0660 break;
0661 case PIPEDIR_IN:
0662 WARN_ON(dl_set);
0663 *dl_pipe = __le32_to_cpu(entry->pipenum);
0664 dl_set = true;
0665 break;
0666 case PIPEDIR_OUT:
0667 WARN_ON(ul_set);
0668 *ul_pipe = __le32_to_cpu(entry->pipenum);
0669 ul_set = true;
0670 break;
0671 case PIPEDIR_INOUT:
0672 WARN_ON(dl_set);
0673 WARN_ON(ul_set);
0674 *dl_pipe = __le32_to_cpu(entry->pipenum);
0675 *ul_pipe = __le32_to_cpu(entry->pipenum);
0676 dl_set = true;
0677 ul_set = true;
0678 break;
0679 }
0680 }
0681
0682 if (WARN_ON(!ul_set || !dl_set))
0683 return -ENOENT;
0684
0685 return 0;
0686 }
0687
0688 static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = {
0689 .start = ath11k_ahb_start,
0690 .stop = ath11k_ahb_stop,
0691 .read32 = ath11k_ahb_read32,
0692 .write32 = ath11k_ahb_write32,
0693 .irq_enable = ath11k_ahb_ext_irq_enable,
0694 .irq_disable = ath11k_ahb_ext_irq_disable,
0695 .map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
0696 .power_down = ath11k_ahb_power_down,
0697 .power_up = ath11k_ahb_power_up,
0698 };
0699
0700 static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = {
0701 .start = ath11k_pcic_start,
0702 .stop = ath11k_pcic_stop,
0703 .read32 = ath11k_pcic_read32,
0704 .write32 = ath11k_pcic_write32,
0705 .irq_enable = ath11k_pcic_ext_irq_enable,
0706 .irq_disable = ath11k_pcic_ext_irq_disable,
0707 .get_msi_address = ath11k_pcic_get_msi_address,
0708 .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment,
0709 .map_service_to_pipe = ath11k_pcic_map_service_to_pipe,
0710 .power_down = ath11k_ahb_power_down,
0711 .power_up = ath11k_ahb_power_up,
0712 };
0713
0714 static int ath11k_core_get_rproc(struct ath11k_base *ab)
0715 {
0716 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
0717 struct device *dev = ab->dev;
0718 struct rproc *prproc;
0719 phandle rproc_phandle;
0720
0721 if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
0722 ath11k_err(ab, "failed to get q6_rproc handle\n");
0723 return -ENOENT;
0724 }
0725
0726 prproc = rproc_get_by_phandle(rproc_phandle);
0727 if (!prproc) {
0728 ath11k_err(ab, "failed to get rproc\n");
0729 return -EINVAL;
0730 }
0731 ab_ahb->tgt_rproc = prproc;
0732
0733 return 0;
0734 }
0735
0736 static int ath11k_ahb_setup_msi_resources(struct ath11k_base *ab)
0737 {
0738 struct platform_device *pdev = ab->pdev;
0739 phys_addr_t msi_addr_pa;
0740 dma_addr_t msi_addr_iova;
0741 struct resource *res;
0742 int int_prop;
0743 int ret;
0744 int i;
0745
0746 ret = ath11k_pcic_init_msi_config(ab);
0747 if (ret) {
0748 ath11k_err(ab, "failed to init msi config: %d\n", ret);
0749 return ret;
0750 }
0751
0752 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0753 if (!res) {
0754 ath11k_err(ab, "failed to fetch msi_addr\n");
0755 return -ENOENT;
0756 }
0757
0758 msi_addr_pa = res->start;
0759 msi_addr_iova = dma_map_resource(ab->dev, msi_addr_pa, PAGE_SIZE,
0760 DMA_FROM_DEVICE, 0);
0761 if (dma_mapping_error(ab->dev, msi_addr_iova))
0762 return -ENOMEM;
0763
0764 ab->pci.msi.addr_lo = lower_32_bits(msi_addr_iova);
0765 ab->pci.msi.addr_hi = upper_32_bits(msi_addr_iova);
0766
0767 ret = of_property_read_u32_index(ab->dev->of_node, "interrupts", 1, &int_prop);
0768 if (ret)
0769 return ret;
0770
0771 ab->pci.msi.ep_base_data = int_prop + 32;
0772
0773 for (i = 0; i < ab->pci.msi.config->total_vectors; i++) {
0774 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
0775 if (!res)
0776 return -ENODEV;
0777
0778 ab->pci.msi.irqs[i] = res->start;
0779 }
0780
0781 set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
0782
0783 return 0;
0784 }
0785
0786 static int ath11k_ahb_setup_resources(struct ath11k_base *ab)
0787 {
0788 struct platform_device *pdev = ab->pdev;
0789 struct resource *mem_res;
0790 void __iomem *mem;
0791
0792 if (ab->hw_params.hybrid_bus_type)
0793 return ath11k_ahb_setup_msi_resources(ab);
0794
0795 mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
0796 if (IS_ERR(mem)) {
0797 dev_err(&pdev->dev, "ioremap error\n");
0798 return PTR_ERR(mem);
0799 }
0800
0801 ab->mem = mem;
0802 ab->mem_len = resource_size(mem_res);
0803
0804 return 0;
0805 }
0806
0807 static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
0808 {
0809 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
0810 struct device *dev = ab->dev;
0811 struct device_node *node;
0812 struct resource r;
0813 int ret;
0814
0815 node = of_parse_phandle(dev->of_node, "memory-region", 0);
0816 if (!node)
0817 return -ENOENT;
0818
0819 ret = of_address_to_resource(node, 0, &r);
0820 of_node_put(node);
0821 if (ret) {
0822 dev_err(dev, "failed to resolve msa fixed region\n");
0823 return ret;
0824 }
0825
0826 ab_ahb->fw.msa_paddr = r.start;
0827 ab_ahb->fw.msa_size = resource_size(&r);
0828
0829 node = of_parse_phandle(dev->of_node, "memory-region", 1);
0830 if (!node)
0831 return -ENOENT;
0832
0833 ret = of_address_to_resource(node, 0, &r);
0834 of_node_put(node);
0835 if (ret) {
0836 dev_err(dev, "failed to resolve ce fixed region\n");
0837 return ret;
0838 }
0839
0840 ab_ahb->fw.ce_paddr = r.start;
0841 ab_ahb->fw.ce_size = resource_size(&r);
0842
0843 return 0;
0844 }
0845
0846 static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
0847 {
0848 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
0849 struct device *host_dev = ab->dev;
0850 struct platform_device_info info = {0};
0851 struct iommu_domain *iommu_dom;
0852 struct platform_device *pdev;
0853 struct device_node *node;
0854 int ret;
0855
0856
0857
0858
0859 if (!ab->hw_params.fixed_fw_mem)
0860 return 0;
0861
0862 ret = ath11k_ahb_setup_msa_resources(ab);
0863 if (ret) {
0864 ath11k_err(ab, "failed to setup msa resources\n");
0865 return ret;
0866 }
0867
0868 node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
0869 if (!node) {
0870 ab_ahb->fw.use_tz = true;
0871 return 0;
0872 }
0873
0874 info.fwnode = &node->fwnode;
0875 info.parent = host_dev;
0876 info.name = node->name;
0877 info.dma_mask = DMA_BIT_MASK(32);
0878
0879 pdev = platform_device_register_full(&info);
0880 if (IS_ERR(pdev)) {
0881 of_node_put(node);
0882 return PTR_ERR(pdev);
0883 }
0884
0885 ret = of_dma_configure(&pdev->dev, node, true);
0886 if (ret) {
0887 ath11k_err(ab, "dma configure fail: %d\n", ret);
0888 goto err_unregister;
0889 }
0890
0891 ab_ahb->fw.dev = &pdev->dev;
0892
0893 iommu_dom = iommu_domain_alloc(&platform_bus_type);
0894 if (!iommu_dom) {
0895 ath11k_err(ab, "failed to allocate iommu domain\n");
0896 ret = -ENOMEM;
0897 goto err_unregister;
0898 }
0899
0900 ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev);
0901 if (ret) {
0902 ath11k_err(ab, "could not attach device: %d\n", ret);
0903 goto err_iommu_free;
0904 }
0905
0906 ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr,
0907 ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size,
0908 IOMMU_READ | IOMMU_WRITE);
0909 if (ret) {
0910 ath11k_err(ab, "failed to map firmware region: %d\n", ret);
0911 goto err_iommu_detach;
0912 }
0913
0914 ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr,
0915 ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size,
0916 IOMMU_READ | IOMMU_WRITE);
0917 if (ret) {
0918 ath11k_err(ab, "failed to map firmware CE region: %d\n", ret);
0919 goto err_iommu_unmap;
0920 }
0921
0922 ab_ahb->fw.use_tz = false;
0923 ab_ahb->fw.iommu_domain = iommu_dom;
0924 of_node_put(node);
0925
0926 return 0;
0927
0928 err_iommu_unmap:
0929 iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
0930
0931 err_iommu_detach:
0932 iommu_detach_device(iommu_dom, ab_ahb->fw.dev);
0933
0934 err_iommu_free:
0935 iommu_domain_free(iommu_dom);
0936
0937 err_unregister:
0938 platform_device_unregister(pdev);
0939 of_node_put(node);
0940
0941 return ret;
0942 }
0943
0944 static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
0945 {
0946 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
0947 struct iommu_domain *iommu;
0948 size_t unmapped_size;
0949
0950 if (ab_ahb->fw.use_tz)
0951 return 0;
0952
0953 iommu = ab_ahb->fw.iommu_domain;
0954
0955 unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
0956 if (unmapped_size != ab_ahb->fw.msa_size)
0957 ath11k_err(ab, "failed to unmap firmware: %zu\n",
0958 unmapped_size);
0959
0960 unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size);
0961 if (unmapped_size != ab_ahb->fw.ce_size)
0962 ath11k_err(ab, "failed to unmap firmware CE memory: %zu\n",
0963 unmapped_size);
0964
0965 iommu_detach_device(iommu, ab_ahb->fw.dev);
0966 iommu_domain_free(iommu);
0967
0968 platform_device_unregister(to_platform_device(ab_ahb->fw.dev));
0969
0970 return 0;
0971 }
0972
0973 static int ath11k_ahb_probe(struct platform_device *pdev)
0974 {
0975 struct ath11k_base *ab;
0976 const struct of_device_id *of_id;
0977 const struct ath11k_hif_ops *hif_ops;
0978 const struct ath11k_pci_ops *pci_ops;
0979 enum ath11k_hw_rev hw_rev;
0980 int ret;
0981
0982 of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
0983 if (!of_id) {
0984 dev_err(&pdev->dev, "failed to find matching device tree id\n");
0985 return -EINVAL;
0986 }
0987
0988 hw_rev = (enum ath11k_hw_rev)of_id->data;
0989
0990 switch (hw_rev) {
0991 case ATH11K_HW_IPQ8074:
0992 case ATH11K_HW_IPQ6018_HW10:
0993 hif_ops = &ath11k_ahb_hif_ops_ipq8074;
0994 pci_ops = NULL;
0995 break;
0996 case ATH11K_HW_WCN6750_HW10:
0997 hif_ops = &ath11k_ahb_hif_ops_wcn6750;
0998 pci_ops = &ath11k_ahb_pci_ops_wcn6750;
0999 break;
1000 default:
1001 dev_err(&pdev->dev, "unsupported device type %d\n", hw_rev);
1002 return -EOPNOTSUPP;
1003 }
1004
1005 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
1006 if (ret) {
1007 dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
1008 return ret;
1009 }
1010
1011 ab = ath11k_core_alloc(&pdev->dev, sizeof(struct ath11k_ahb),
1012 ATH11K_BUS_AHB);
1013 if (!ab) {
1014 dev_err(&pdev->dev, "failed to allocate ath11k base\n");
1015 return -ENOMEM;
1016 }
1017
1018 ab->hif.ops = hif_ops;
1019 ab->pdev = pdev;
1020 ab->hw_rev = hw_rev;
1021 platform_set_drvdata(pdev, ab);
1022
1023 ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
1024 if (ret) {
1025 ath11k_err(ab, "failed to register PCI ops: %d\n", ret);
1026 goto err_core_free;
1027 }
1028
1029 ret = ath11k_core_pre_init(ab);
1030 if (ret)
1031 goto err_core_free;
1032
1033 ret = ath11k_ahb_setup_resources(ab);
1034 if (ret)
1035 goto err_core_free;
1036
1037 ret = ath11k_ahb_fw_resources_init(ab);
1038 if (ret)
1039 goto err_core_free;
1040
1041 ret = ath11k_hal_srng_init(ab);
1042 if (ret)
1043 goto err_fw_deinit;
1044
1045 ret = ath11k_ce_alloc_pipes(ab);
1046 if (ret) {
1047 ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
1048 goto err_hal_srng_deinit;
1049 }
1050
1051 ath11k_ahb_init_qmi_ce_config(ab);
1052
1053 ret = ath11k_core_get_rproc(ab);
1054 if (ret) {
1055 ath11k_err(ab, "failed to get rproc: %d\n", ret);
1056 goto err_ce_free;
1057 }
1058
1059 ret = ath11k_core_init(ab);
1060 if (ret) {
1061 ath11k_err(ab, "failed to init core: %d\n", ret);
1062 goto err_ce_free;
1063 }
1064
1065 ret = ath11k_ahb_config_irq(ab);
1066 if (ret) {
1067 ath11k_err(ab, "failed to configure irq: %d\n", ret);
1068 goto err_ce_free;
1069 }
1070
1071 ath11k_ahb_fwreset_from_cold_boot(ab);
1072
1073 return 0;
1074
1075 err_ce_free:
1076 ath11k_ce_free_pipes(ab);
1077
1078 err_hal_srng_deinit:
1079 ath11k_hal_srng_deinit(ab);
1080
1081 err_fw_deinit:
1082 ath11k_ahb_fw_resource_deinit(ab);
1083
1084 err_core_free:
1085 ath11k_core_free(ab);
1086 platform_set_drvdata(pdev, NULL);
1087
1088 return ret;
1089 }
1090
1091 static int ath11k_ahb_remove(struct platform_device *pdev)
1092 {
1093 struct ath11k_base *ab = platform_get_drvdata(pdev);
1094 unsigned long left;
1095
1096 if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
1097 ath11k_ahb_power_down(ab);
1098 ath11k_debugfs_soc_destroy(ab);
1099 ath11k_qmi_deinit_service(ab);
1100 goto qmi_fail;
1101 }
1102
1103 reinit_completion(&ab->driver_recovery);
1104
1105 if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) {
1106 left = wait_for_completion_timeout(&ab->driver_recovery,
1107 ATH11K_AHB_RECOVERY_TIMEOUT);
1108 if (!left)
1109 ath11k_warn(ab, "failed to receive recovery response completion\n");
1110 }
1111
1112 set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
1113 cancel_work_sync(&ab->restart_work);
1114
1115 ath11k_core_deinit(ab);
1116 qmi_fail:
1117 ath11k_ahb_free_irq(ab);
1118 ath11k_hal_srng_deinit(ab);
1119 ath11k_ahb_fw_resource_deinit(ab);
1120 ath11k_ce_free_pipes(ab);
1121 ath11k_core_free(ab);
1122 platform_set_drvdata(pdev, NULL);
1123
1124 return 0;
1125 }
1126
1127 static struct platform_driver ath11k_ahb_driver = {
1128 .driver = {
1129 .name = "ath11k",
1130 .of_match_table = ath11k_ahb_of_match,
1131 },
1132 .probe = ath11k_ahb_probe,
1133 .remove = ath11k_ahb_remove,
1134 };
1135
1136 static int ath11k_ahb_init(void)
1137 {
1138 return platform_driver_register(&ath11k_ahb_driver);
1139 }
1140 module_init(ath11k_ahb_init);
1141
1142 static void ath11k_ahb_exit(void)
1143 {
1144 platform_driver_unregister(&ath11k_ahb_driver);
1145 }
1146 module_exit(ath11k_ahb_exit);
1147
1148 MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices");
1149 MODULE_LICENSE("Dual BSD/GPL");