1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 5 */ 6 7 #include <linux/module.h> 8 #include <linux/platform_device.h> 9 #include <linux/of_device.h> 10 #include <linux/of.h> 11 #include <linux/dma-mapping.h> 12 #include <linux/of_address.h> 13 #include <linux/iommu.h> 14 #include "ahb.h" 15 #include "debug.h" 16 #include "hif.h" 17 #include <linux/remoteproc.h> 18 #include "pcic.h" 19 #include <linux/soc/qcom/smem.h> 20 #include <linux/soc/qcom/smem_state.h> 21 22 static const struct of_device_id ath11k_ahb_of_match[] = { 23 /* TODO: Should we change the compatible string to something similar 24 * to one that ath10k uses? 25 */ 26 { .compatible = "qcom,ipq8074-wifi", 27 .data = (void *)ATH11K_HW_IPQ8074, 28 }, 29 { .compatible = "qcom,ipq6018-wifi", 30 .data = (void *)ATH11K_HW_IPQ6018_HW10, 31 }, 32 { .compatible = "qcom,wcn6750-wifi", 33 .data = (void *)ATH11K_HW_WCN6750_HW10, 34 }, 35 { } 36 }; 37 38 MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match); 39 40 #define ATH11K_IRQ_CE0_OFFSET 4 41 42 static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { 43 "misc-pulse1", 44 "misc-latch", 45 "sw-exception", 46 "watchdog", 47 "ce0", 48 "ce1", 49 "ce2", 50 "ce3", 51 "ce4", 52 "ce5", 53 "ce6", 54 "ce7", 55 "ce8", 56 "ce9", 57 "ce10", 58 "ce11", 59 "host2wbm-desc-feed", 60 "host2reo-re-injection", 61 "host2reo-command", 62 "host2rxdma-monitor-ring3", 63 "host2rxdma-monitor-ring2", 64 "host2rxdma-monitor-ring1", 65 "reo2ost-exception", 66 "wbm2host-rx-release", 67 "reo2host-status", 68 "reo2host-destination-ring4", 69 "reo2host-destination-ring3", 70 "reo2host-destination-ring2", 71 "reo2host-destination-ring1", 72 "rxdma2host-monitor-destination-mac3", 73 "rxdma2host-monitor-destination-mac2", 74 "rxdma2host-monitor-destination-mac1", 75 "ppdu-end-interrupts-mac3", 76 "ppdu-end-interrupts-mac2", 77 "ppdu-end-interrupts-mac1", 78 "rxdma2host-monitor-status-ring-mac3", 79 "rxdma2host-monitor-status-ring-mac2", 80 "rxdma2host-monitor-status-ring-mac1", 81 "host2rxdma-host-buf-ring-mac3", 82 "host2rxdma-host-buf-ring-mac2", 83 "host2rxdma-host-buf-ring-mac1", 84 "rxdma2host-destination-ring-mac3", 85 "rxdma2host-destination-ring-mac2", 86 "rxdma2host-destination-ring-mac1", 87 "host2tcl-input-ring4", 88 "host2tcl-input-ring3", 89 "host2tcl-input-ring2", 90 "host2tcl-input-ring1", 91 "wbm2host-tx-completions-ring3", 92 "wbm2host-tx-completions-ring2", 93 "wbm2host-tx-completions-ring1", 94 "tcl2host-status-ring", 95 }; 96 97 /* enum ext_irq_num - irq numbers that can be used by external modules 98 * like datapath 99 */ 100 enum ext_irq_num { 101 host2wbm_desc_feed = 16, 102 host2reo_re_injection, 103 host2reo_command, 104 host2rxdma_monitor_ring3, 105 host2rxdma_monitor_ring2, 106 host2rxdma_monitor_ring1, 107 reo2host_exception, 108 wbm2host_rx_release, 109 reo2host_status, 110 reo2host_destination_ring4, 111 reo2host_destination_ring3, 112 reo2host_destination_ring2, 113 reo2host_destination_ring1, 114 rxdma2host_monitor_destination_mac3, 115 rxdma2host_monitor_destination_mac2, 116 rxdma2host_monitor_destination_mac1, 117 ppdu_end_interrupts_mac3, 118 ppdu_end_interrupts_mac2, 119 ppdu_end_interrupts_mac1, 120 rxdma2host_monitor_status_ring_mac3, 121 rxdma2host_monitor_status_ring_mac2, 122 rxdma2host_monitor_status_ring_mac1, 123 host2rxdma_host_buf_ring_mac3, 124 host2rxdma_host_buf_ring_mac2, 125 host2rxdma_host_buf_ring_mac1, 126 rxdma2host_destination_ring_mac3, 127 rxdma2host_destination_ring_mac2, 128 rxdma2host_destination_ring_mac1, 129 host2tcl_input_ring4, 130 host2tcl_input_ring3, 131 host2tcl_input_ring2, 132 host2tcl_input_ring1, 133 wbm2host_tx_completions_ring3, 134 wbm2host_tx_completions_ring2, 135 wbm2host_tx_completions_ring1, 136 tcl2host_status_ring, 137 }; 138 139 static int 140 ath11k_ahb_get_msi_irq_wcn6750(struct ath11k_base *ab, unsigned int vector) 141 { 142 return ab->pci.msi.irqs[vector]; 143 } 144 145 static inline u32 146 ath11k_ahb_get_window_start_wcn6750(struct ath11k_base *ab, u32 offset) 147 { 148 u32 window_start = 0; 149 150 /* If offset lies within DP register range, use 1st window */ 151 if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK) 152 window_start = ATH11K_PCI_WINDOW_START; 153 /* If offset lies within CE register range, use 2nd window */ 154 else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < 155 ATH11K_PCI_WINDOW_RANGE_MASK) 156 window_start = 2 * ATH11K_PCI_WINDOW_START; 157 158 return window_start; 159 } 160 161 static void 162 ath11k_ahb_window_write32_wcn6750(struct ath11k_base *ab, u32 offset, u32 value) 163 { 164 u32 window_start; 165 166 /* WCN6750 uses static window based register access*/ 167 window_start = ath11k_ahb_get_window_start_wcn6750(ab, offset); 168 169 iowrite32(value, ab->mem + window_start + 170 (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); 171 } 172 173 static u32 ath11k_ahb_window_read32_wcn6750(struct ath11k_base *ab, u32 offset) 174 { 175 u32 window_start; 176 u32 val; 177 178 /* WCN6750 uses static window based register access */ 179 window_start = ath11k_ahb_get_window_start_wcn6750(ab, offset); 180 181 val = ioread32(ab->mem + window_start + 182 (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); 183 return val; 184 } 185 186 static const struct ath11k_pci_ops ath11k_ahb_pci_ops_wcn6750 = { 187 .wakeup = NULL, 188 .release = NULL, 189 .get_msi_irq = ath11k_ahb_get_msi_irq_wcn6750, 190 .window_write32 = ath11k_ahb_window_write32_wcn6750, 191 .window_read32 = ath11k_ahb_window_read32_wcn6750, 192 }; 193 194 static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset) 195 { 196 return ioread32(ab->mem + offset); 197 } 198 199 static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value) 200 { 201 iowrite32(value, ab->mem + offset); 202 } 203 204 static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab) 205 { 206 int i; 207 208 for (i = 0; i < ab->hw_params.ce_count; i++) { 209 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; 210 211 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) 212 continue; 213 214 tasklet_kill(&ce_pipe->intr_tq); 215 } 216 } 217 218 static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp) 219 { 220 int i; 221 222 for (i = 0; i < irq_grp->num_irq; i++) 223 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); 224 } 225 226 static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) 227 { 228 int i; 229 230 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 231 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 232 233 ath11k_ahb_ext_grp_disable(irq_grp); 234 235 if (irq_grp->napi_enabled) { 236 napi_synchronize(&irq_grp->napi); 237 napi_disable(&irq_grp->napi); 238 irq_grp->napi_enabled = false; 239 } 240 } 241 } 242 243 static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp) 244 { 245 int i; 246 247 for (i = 0; i < irq_grp->num_irq; i++) 248 enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); 249 } 250 251 static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset) 252 { 253 u32 val; 254 255 val = ath11k_ahb_read32(ab, offset); 256 ath11k_ahb_write32(ab, offset, val | BIT(bit)); 257 } 258 259 static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset) 260 { 261 u32 val; 262 263 val = ath11k_ahb_read32(ab, offset); 264 ath11k_ahb_write32(ab, offset, val & ~BIT(bit)); 265 } 266 267 static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) 268 { 269 const struct ce_attr *ce_attr; 270 271 ce_attr = &ab->hw_params.host_ce_config[ce_id]; 272 if (ce_attr->src_nentries) 273 ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS); 274 275 if (ce_attr->dest_nentries) { 276 ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); 277 ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, 278 CE_HOST_IE_3_ADDRESS); 279 } 280 } 281 282 static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) 283 { 284 const struct ce_attr *ce_attr; 285 286 ce_attr = &ab->hw_params.host_ce_config[ce_id]; 287 if (ce_attr->src_nentries) 288 ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS); 289 290 if (ce_attr->dest_nentries) { 291 ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); 292 ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, 293 CE_HOST_IE_3_ADDRESS); 294 } 295 } 296 297 static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab) 298 { 299 int i; 300 int irq_idx; 301 302 for (i = 0; i < ab->hw_params.ce_count; i++) { 303 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) 304 continue; 305 306 irq_idx = ATH11K_IRQ_CE0_OFFSET + i; 307 synchronize_irq(ab->irq_num[irq_idx]); 308 } 309 } 310 311 static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab) 312 { 313 int i, j; 314 int irq_idx; 315 316 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 317 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 318 319 for (j = 0; j < irq_grp->num_irq; j++) { 320 irq_idx = irq_grp->irqs[j]; 321 synchronize_irq(ab->irq_num[irq_idx]); 322 } 323 } 324 } 325 326 static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab) 327 { 328 int i; 329 330 for (i = 0; i < ab->hw_params.ce_count; i++) { 331 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) 332 continue; 333 ath11k_ahb_ce_irq_enable(ab, i); 334 } 335 } 336 337 static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab) 338 { 339 int i; 340 341 for (i = 0; i < ab->hw_params.ce_count; i++) { 342 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) 343 continue; 344 ath11k_ahb_ce_irq_disable(ab, i); 345 } 346 } 347 348 static int ath11k_ahb_start(struct ath11k_base *ab) 349 { 350 ath11k_ahb_ce_irqs_enable(ab); 351 ath11k_ce_rx_post_buf(ab); 352 353 return 0; 354 } 355 356 static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) 357 { 358 int i; 359 360 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 361 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 362 363 if (!irq_grp->napi_enabled) { 364 dev_set_threaded(&irq_grp->napi_ndev, true); 365 napi_enable(&irq_grp->napi); 366 irq_grp->napi_enabled = true; 367 } 368 ath11k_ahb_ext_grp_enable(irq_grp); 369 } 370 } 371 372 static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) 373 { 374 __ath11k_ahb_ext_irq_disable(ab); 375 ath11k_ahb_sync_ext_irqs(ab); 376 } 377 378 static void ath11k_ahb_stop(struct ath11k_base *ab) 379 { 380 if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) 381 ath11k_ahb_ce_irqs_disable(ab); 382 ath11k_ahb_sync_ce_irqs(ab); 383 ath11k_ahb_kill_tasklets(ab); 384 del_timer_sync(&ab->rx_replenish_retry); 385 ath11k_ce_cleanup_pipes(ab); 386 } 387 388 static int ath11k_ahb_power_up(struct ath11k_base *ab) 389 { 390 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 391 int ret; 392 393 ret = rproc_boot(ab_ahb->tgt_rproc); 394 if (ret) 395 ath11k_err(ab, "failed to boot the remote processor Q6\n"); 396 397 return ret; 398 } 399 400 static void ath11k_ahb_power_down(struct ath11k_base *ab) 401 { 402 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 403 404 rproc_shutdown(ab_ahb->tgt_rproc); 405 } 406 407 static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab) 408 { 409 int timeout; 410 411 if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done || 412 ab->hw_params.cold_boot_calib == 0 || 413 ab->hw_params.cbcal_restart_fw == 0) 414 return 0; 415 416 ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n"); 417 timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, 418 (ab->qmi.cal_done == 1), 419 ATH11K_COLD_BOOT_FW_RESET_DELAY); 420 if (timeout <= 0) { 421 ath11k_cold_boot_cal = 0; 422 ath11k_warn(ab, "Coldboot Calibration failed timed out\n"); 423 } 424 425 /* reset the firmware */ 426 ath11k_ahb_power_down(ab); 427 ath11k_ahb_power_up(ab); 428 429 ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n"); 430 return 0; 431 } 432 433 static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) 434 { 435 struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; 436 437 cfg->tgt_ce_len = ab->hw_params.target_ce_count; 438 cfg->tgt_ce = ab->hw_params.target_ce_config; 439 cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len; 440 cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map; 441 ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; 442 } 443 444 static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) 445 { 446 int i, j; 447 448 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 449 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 450 451 for (j = 0; j < irq_grp->num_irq; j++) 452 free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); 453 454 netif_napi_del(&irq_grp->napi); 455 } 456 } 457 458 static void ath11k_ahb_free_irq(struct ath11k_base *ab) 459 { 460 int irq_idx; 461 int i; 462 463 if (ab->hw_params.hybrid_bus_type) 464 return ath11k_pcic_free_irq(ab); 465 466 for (i = 0; i < ab->hw_params.ce_count; i++) { 467 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) 468 continue; 469 irq_idx = ATH11K_IRQ_CE0_OFFSET + i; 470 free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); 471 } 472 473 ath11k_ahb_free_ext_irq(ab); 474 } 475 476 static void ath11k_ahb_ce_tasklet(struct tasklet_struct *t) 477 { 478 struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); 479 480 ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); 481 482 ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num); 483 } 484 485 static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg) 486 { 487 struct ath11k_ce_pipe *ce_pipe = arg; 488 489 /* last interrupt received for this CE */ 490 ce_pipe->timestamp = jiffies; 491 492 ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num); 493 494 tasklet_schedule(&ce_pipe->intr_tq); 495 496 return IRQ_HANDLED; 497 } 498 499 static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget) 500 { 501 struct ath11k_ext_irq_grp *irq_grp = container_of(napi, 502 struct ath11k_ext_irq_grp, 503 napi); 504 struct ath11k_base *ab = irq_grp->ab; 505 int work_done; 506 507 work_done = ath11k_dp_service_srng(ab, irq_grp, budget); 508 if (work_done < budget) { 509 napi_complete_done(napi, work_done); 510 ath11k_ahb_ext_grp_enable(irq_grp); 511 } 512 513 if (work_done > budget) 514 work_done = budget; 515 516 return work_done; 517 } 518 519 static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg) 520 { 521 struct ath11k_ext_irq_grp *irq_grp = arg; 522 523 /* last interrupt received for this group */ 524 irq_grp->timestamp = jiffies; 525 526 ath11k_ahb_ext_grp_disable(irq_grp); 527 528 napi_schedule(&irq_grp->napi); 529 530 return IRQ_HANDLED; 531 } 532 533 static int ath11k_ahb_config_ext_irq(struct ath11k_base *ab) 534 { 535 struct ath11k_hw_params *hw = &ab->hw_params; 536 int i, j; 537 int irq; 538 int ret; 539 540 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 541 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 542 u32 num_irq = 0; 543 544 irq_grp->ab = ab; 545 irq_grp->grp_id = i; 546 init_dummy_netdev(&irq_grp->napi_ndev); 547 netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, 548 ath11k_ahb_ext_grp_napi_poll); 549 550 for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) { 551 if (ab->hw_params.ring_mask->tx[i] & BIT(j)) { 552 irq_grp->irqs[num_irq++] = 553 wbm2host_tx_completions_ring1 - j; 554 } 555 556 if (ab->hw_params.ring_mask->rx[i] & BIT(j)) { 557 irq_grp->irqs[num_irq++] = 558 reo2host_destination_ring1 - j; 559 } 560 561 if (ab->hw_params.ring_mask->rx_err[i] & BIT(j)) 562 irq_grp->irqs[num_irq++] = reo2host_exception; 563 564 if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j)) 565 irq_grp->irqs[num_irq++] = wbm2host_rx_release; 566 567 if (ab->hw_params.ring_mask->reo_status[i] & BIT(j)) 568 irq_grp->irqs[num_irq++] = reo2host_status; 569 570 if (j < ab->hw_params.max_radios) { 571 if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) { 572 irq_grp->irqs[num_irq++] = 573 rxdma2host_destination_ring_mac1 - 574 ath11k_hw_get_mac_from_pdev_id(hw, j); 575 } 576 577 if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) { 578 irq_grp->irqs[num_irq++] = 579 host2rxdma_host_buf_ring_mac1 - 580 ath11k_hw_get_mac_from_pdev_id(hw, j); 581 } 582 583 if (ab->hw_params.ring_mask->rx_mon_status[i] & BIT(j)) { 584 irq_grp->irqs[num_irq++] = 585 ppdu_end_interrupts_mac1 - 586 ath11k_hw_get_mac_from_pdev_id(hw, j); 587 irq_grp->irqs[num_irq++] = 588 rxdma2host_monitor_status_ring_mac1 - 589 ath11k_hw_get_mac_from_pdev_id(hw, j); 590 } 591 } 592 } 593 irq_grp->num_irq = num_irq; 594 595 for (j = 0; j < irq_grp->num_irq; j++) { 596 int irq_idx = irq_grp->irqs[j]; 597 598 irq = platform_get_irq_byname(ab->pdev, 599 irq_name[irq_idx]); 600 ab->irq_num[irq_idx] = irq; 601 irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY); 602 ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler, 603 IRQF_TRIGGER_RISING, 604 irq_name[irq_idx], irq_grp); 605 if (ret) { 606 ath11k_err(ab, "failed request_irq for %d\n", 607 irq); 608 } 609 } 610 } 611 612 return 0; 613 } 614 615 static int ath11k_ahb_config_irq(struct ath11k_base *ab) 616 { 617 int irq, irq_idx, i; 618 int ret; 619 620 if (ab->hw_params.hybrid_bus_type) 621 return ath11k_pcic_config_irq(ab); 622 623 /* Configure CE irqs */ 624 for (i = 0; i < ab->hw_params.ce_count; i++) { 625 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; 626 627 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) 628 continue; 629 630 irq_idx = ATH11K_IRQ_CE0_OFFSET + i; 631 632 tasklet_setup(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet); 633 irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]); 634 ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler, 635 IRQF_TRIGGER_RISING, irq_name[irq_idx], 636 ce_pipe); 637 if (ret) 638 return ret; 639 640 ab->irq_num[irq_idx] = irq; 641 } 642 643 /* Configure external interrupts */ 644 ret = ath11k_ahb_config_ext_irq(ab); 645 646 return ret; 647 } 648 649 static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, 650 u8 *ul_pipe, u8 *dl_pipe) 651 { 652 const struct service_to_pipe *entry; 653 bool ul_set = false, dl_set = false; 654 int i; 655 656 for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) { 657 entry = &ab->hw_params.svc_to_ce_map[i]; 658 659 if (__le32_to_cpu(entry->service_id) != service_id) 660 continue; 661 662 switch (__le32_to_cpu(entry->pipedir)) { 663 case PIPEDIR_NONE: 664 break; 665 case PIPEDIR_IN: 666 WARN_ON(dl_set); 667 *dl_pipe = __le32_to_cpu(entry->pipenum); 668 dl_set = true; 669 break; 670 case PIPEDIR_OUT: 671 WARN_ON(ul_set); 672 *ul_pipe = __le32_to_cpu(entry->pipenum); 673 ul_set = true; 674 break; 675 case PIPEDIR_INOUT: 676 WARN_ON(dl_set); 677 WARN_ON(ul_set); 678 *dl_pipe = __le32_to_cpu(entry->pipenum); 679 *ul_pipe = __le32_to_cpu(entry->pipenum); 680 dl_set = true; 681 ul_set = true; 682 break; 683 } 684 } 685 686 if (WARN_ON(!ul_set || !dl_set)) 687 return -ENOENT; 688 689 return 0; 690 } 691 692 static int ath11k_ahb_hif_suspend(struct ath11k_base *ab) 693 { 694 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 695 u32 wake_irq; 696 u32 value = 0; 697 int ret; 698 699 if (!device_may_wakeup(ab->dev)) 700 return -EPERM; 701 702 wake_irq = ab->irq_num[ATH11K_PCI_IRQ_CE0_OFFSET + ATH11K_PCI_CE_WAKE_IRQ]; 703 704 ret = enable_irq_wake(wake_irq); 705 if (ret) { 706 ath11k_err(ab, "failed to enable wakeup irq :%d\n", ret); 707 return ret; 708 } 709 710 value = u32_encode_bits(ab_ahb->smp2p_info.seq_no++, 711 ATH11K_AHB_SMP2P_SMEM_SEQ_NO); 712 value |= u32_encode_bits(ATH11K_AHB_POWER_SAVE_ENTER, 713 ATH11K_AHB_SMP2P_SMEM_MSG); 714 715 ret = qcom_smem_state_update_bits(ab_ahb->smp2p_info.smem_state, 716 ATH11K_AHB_SMP2P_SMEM_VALUE_MASK, value); 717 if (ret) { 718 ath11k_err(ab, "failed to send smp2p power save enter cmd :%d\n", ret); 719 return ret; 720 } 721 722 ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device suspended\n"); 723 724 return ret; 725 } 726 727 static int ath11k_ahb_hif_resume(struct ath11k_base *ab) 728 { 729 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 730 u32 wake_irq; 731 u32 value = 0; 732 int ret; 733 734 if (!device_may_wakeup(ab->dev)) 735 return -EPERM; 736 737 wake_irq = ab->irq_num[ATH11K_PCI_IRQ_CE0_OFFSET + ATH11K_PCI_CE_WAKE_IRQ]; 738 739 ret = disable_irq_wake(wake_irq); 740 if (ret) { 741 ath11k_err(ab, "failed to disable wakeup irq: %d\n", ret); 742 return ret; 743 } 744 745 reinit_completion(&ab->wow.wakeup_completed); 746 747 value = u32_encode_bits(ab_ahb->smp2p_info.seq_no++, 748 ATH11K_AHB_SMP2P_SMEM_SEQ_NO); 749 value |= u32_encode_bits(ATH11K_AHB_POWER_SAVE_EXIT, 750 ATH11K_AHB_SMP2P_SMEM_MSG); 751 752 ret = qcom_smem_state_update_bits(ab_ahb->smp2p_info.smem_state, 753 ATH11K_AHB_SMP2P_SMEM_VALUE_MASK, value); 754 if (ret) { 755 ath11k_err(ab, "failed to send smp2p power save enter cmd :%d\n", ret); 756 return ret; 757 } 758 759 ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ); 760 if (ret == 0) { 761 ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n"); 762 return -ETIMEDOUT; 763 } 764 765 ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device resumed\n"); 766 767 return 0; 768 } 769 770 static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = { 771 .start = ath11k_ahb_start, 772 .stop = ath11k_ahb_stop, 773 .read32 = ath11k_ahb_read32, 774 .write32 = ath11k_ahb_write32, 775 .read = NULL, 776 .irq_enable = ath11k_ahb_ext_irq_enable, 777 .irq_disable = ath11k_ahb_ext_irq_disable, 778 .map_service_to_pipe = ath11k_ahb_map_service_to_pipe, 779 .power_down = ath11k_ahb_power_down, 780 .power_up = ath11k_ahb_power_up, 781 }; 782 783 static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = { 784 .start = ath11k_pcic_start, 785 .stop = ath11k_pcic_stop, 786 .read32 = ath11k_pcic_read32, 787 .write32 = ath11k_pcic_write32, 788 .read = NULL, 789 .irq_enable = ath11k_pcic_ext_irq_enable, 790 .irq_disable = ath11k_pcic_ext_irq_disable, 791 .get_msi_address = ath11k_pcic_get_msi_address, 792 .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment, 793 .map_service_to_pipe = ath11k_pcic_map_service_to_pipe, 794 .power_down = ath11k_ahb_power_down, 795 .power_up = ath11k_ahb_power_up, 796 .suspend = ath11k_ahb_hif_suspend, 797 .resume = ath11k_ahb_hif_resume, 798 .ce_irq_enable = ath11k_pci_enable_ce_irqs_except_wake_irq, 799 .ce_irq_disable = ath11k_pci_disable_ce_irqs_except_wake_irq, 800 }; 801 802 static int ath11k_core_get_rproc(struct ath11k_base *ab) 803 { 804 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 805 struct device *dev = ab->dev; 806 struct rproc *prproc; 807 phandle rproc_phandle; 808 809 if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) { 810 ath11k_err(ab, "failed to get q6_rproc handle\n"); 811 return -ENOENT; 812 } 813 814 prproc = rproc_get_by_phandle(rproc_phandle); 815 if (!prproc) { 816 ath11k_err(ab, "failed to get rproc\n"); 817 return -EINVAL; 818 } 819 ab_ahb->tgt_rproc = prproc; 820 821 return 0; 822 } 823 824 static int ath11k_ahb_setup_msi_resources(struct ath11k_base *ab) 825 { 826 struct platform_device *pdev = ab->pdev; 827 phys_addr_t msi_addr_pa; 828 dma_addr_t msi_addr_iova; 829 struct resource *res; 830 int int_prop; 831 int ret; 832 int i; 833 834 ret = ath11k_pcic_init_msi_config(ab); 835 if (ret) { 836 ath11k_err(ab, "failed to init msi config: %d\n", ret); 837 return ret; 838 } 839 840 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 841 if (!res) { 842 ath11k_err(ab, "failed to fetch msi_addr\n"); 843 return -ENOENT; 844 } 845 846 msi_addr_pa = res->start; 847 msi_addr_iova = dma_map_resource(ab->dev, msi_addr_pa, PAGE_SIZE, 848 DMA_FROM_DEVICE, 0); 849 if (dma_mapping_error(ab->dev, msi_addr_iova)) 850 return -ENOMEM; 851 852 ab->pci.msi.addr_lo = lower_32_bits(msi_addr_iova); 853 ab->pci.msi.addr_hi = upper_32_bits(msi_addr_iova); 854 855 ret = of_property_read_u32_index(ab->dev->of_node, "interrupts", 1, &int_prop); 856 if (ret) 857 return ret; 858 859 ab->pci.msi.ep_base_data = int_prop + 32; 860 861 for (i = 0; i < ab->pci.msi.config->total_vectors; i++) { 862 res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 863 if (!res) 864 return -ENODEV; 865 866 ab->pci.msi.irqs[i] = res->start; 867 } 868 869 set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); 870 871 return 0; 872 } 873 874 static int ath11k_ahb_setup_smp2p_handle(struct ath11k_base *ab) 875 { 876 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 877 878 if (!ab->hw_params.smp2p_wow_exit) 879 return 0; 880 881 ab_ahb->smp2p_info.smem_state = qcom_smem_state_get(ab->dev, "wlan-smp2p-out", 882 &ab_ahb->smp2p_info.smem_bit); 883 if (IS_ERR(ab_ahb->smp2p_info.smem_state)) { 884 ath11k_err(ab, "failed to fetch smem state: %ld\n", 885 PTR_ERR(ab_ahb->smp2p_info.smem_state)); 886 return PTR_ERR(ab_ahb->smp2p_info.smem_state); 887 } 888 889 return 0; 890 } 891 892 static void ath11k_ahb_release_smp2p_handle(struct ath11k_base *ab) 893 { 894 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 895 896 if (!ab->hw_params.smp2p_wow_exit) 897 return; 898 899 qcom_smem_state_put(ab_ahb->smp2p_info.smem_state); 900 } 901 902 static int ath11k_ahb_setup_resources(struct ath11k_base *ab) 903 { 904 struct platform_device *pdev = ab->pdev; 905 struct resource *mem_res; 906 void __iomem *mem; 907 908 if (ab->hw_params.hybrid_bus_type) 909 return ath11k_ahb_setup_msi_resources(ab); 910 911 mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res); 912 if (IS_ERR(mem)) { 913 dev_err(&pdev->dev, "ioremap error\n"); 914 return PTR_ERR(mem); 915 } 916 917 ab->mem = mem; 918 ab->mem_len = resource_size(mem_res); 919 920 return 0; 921 } 922 923 static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab) 924 { 925 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 926 struct device *dev = ab->dev; 927 struct device_node *node; 928 struct resource r; 929 int ret; 930 931 node = of_parse_phandle(dev->of_node, "memory-region", 0); 932 if (!node) 933 return -ENOENT; 934 935 ret = of_address_to_resource(node, 0, &r); 936 of_node_put(node); 937 if (ret) { 938 dev_err(dev, "failed to resolve msa fixed region\n"); 939 return ret; 940 } 941 942 ab_ahb->fw.msa_paddr = r.start; 943 ab_ahb->fw.msa_size = resource_size(&r); 944 945 node = of_parse_phandle(dev->of_node, "memory-region", 1); 946 if (!node) 947 return -ENOENT; 948 949 ret = of_address_to_resource(node, 0, &r); 950 of_node_put(node); 951 if (ret) { 952 dev_err(dev, "failed to resolve ce fixed region\n"); 953 return ret; 954 } 955 956 ab_ahb->fw.ce_paddr = r.start; 957 ab_ahb->fw.ce_size = resource_size(&r); 958 959 return 0; 960 } 961 962 static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab) 963 { 964 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 965 struct device *host_dev = ab->dev; 966 struct platform_device_info info = {0}; 967 struct iommu_domain *iommu_dom; 968 struct platform_device *pdev; 969 struct device_node *node; 970 int ret; 971 972 /* Chipsets not requiring MSA need not initialize 973 * MSA resources, return success in such cases. 974 */ 975 if (!ab->hw_params.fixed_fw_mem) 976 return 0; 977 978 ret = ath11k_ahb_setup_msa_resources(ab); 979 if (ret) { 980 ath11k_err(ab, "failed to setup msa resources\n"); 981 return ret; 982 } 983 984 node = of_get_child_by_name(host_dev->of_node, "wifi-firmware"); 985 if (!node) { 986 ab_ahb->fw.use_tz = true; 987 return 0; 988 } 989 990 info.fwnode = &node->fwnode; 991 info.parent = host_dev; 992 info.name = node->name; 993 info.dma_mask = DMA_BIT_MASK(32); 994 995 pdev = platform_device_register_full(&info); 996 if (IS_ERR(pdev)) { 997 of_node_put(node); 998 return PTR_ERR(pdev); 999 } 1000 1001 ret = of_dma_configure(&pdev->dev, node, true); 1002 if (ret) { 1003 ath11k_err(ab, "dma configure fail: %d\n", ret); 1004 goto err_unregister; 1005 } 1006 1007 ab_ahb->fw.dev = &pdev->dev; 1008 1009 iommu_dom = iommu_domain_alloc(&platform_bus_type); 1010 if (!iommu_dom) { 1011 ath11k_err(ab, "failed to allocate iommu domain\n"); 1012 ret = -ENOMEM; 1013 goto err_unregister; 1014 } 1015 1016 ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev); 1017 if (ret) { 1018 ath11k_err(ab, "could not attach device: %d\n", ret); 1019 goto err_iommu_free; 1020 } 1021 1022 ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr, 1023 ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size, 1024 IOMMU_READ | IOMMU_WRITE); 1025 if (ret) { 1026 ath11k_err(ab, "failed to map firmware region: %d\n", ret); 1027 goto err_iommu_detach; 1028 } 1029 1030 ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr, 1031 ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size, 1032 IOMMU_READ | IOMMU_WRITE); 1033 if (ret) { 1034 ath11k_err(ab, "failed to map firmware CE region: %d\n", ret); 1035 goto err_iommu_unmap; 1036 } 1037 1038 ab_ahb->fw.use_tz = false; 1039 ab_ahb->fw.iommu_domain = iommu_dom; 1040 of_node_put(node); 1041 1042 return 0; 1043 1044 err_iommu_unmap: 1045 iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size); 1046 1047 err_iommu_detach: 1048 iommu_detach_device(iommu_dom, ab_ahb->fw.dev); 1049 1050 err_iommu_free: 1051 iommu_domain_free(iommu_dom); 1052 1053 err_unregister: 1054 platform_device_unregister(pdev); 1055 of_node_put(node); 1056 1057 return ret; 1058 } 1059 1060 static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab) 1061 { 1062 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); 1063 struct iommu_domain *iommu; 1064 size_t unmapped_size; 1065 1066 if (ab_ahb->fw.use_tz) 1067 return 0; 1068 1069 iommu = ab_ahb->fw.iommu_domain; 1070 1071 unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size); 1072 if (unmapped_size != ab_ahb->fw.msa_size) 1073 ath11k_err(ab, "failed to unmap firmware: %zu\n", 1074 unmapped_size); 1075 1076 unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size); 1077 if (unmapped_size != ab_ahb->fw.ce_size) 1078 ath11k_err(ab, "failed to unmap firmware CE memory: %zu\n", 1079 unmapped_size); 1080 1081 iommu_detach_device(iommu, ab_ahb->fw.dev); 1082 iommu_domain_free(iommu); 1083 1084 platform_device_unregister(to_platform_device(ab_ahb->fw.dev)); 1085 1086 return 0; 1087 } 1088 1089 static int ath11k_ahb_probe(struct platform_device *pdev) 1090 { 1091 struct ath11k_base *ab; 1092 const struct of_device_id *of_id; 1093 const struct ath11k_hif_ops *hif_ops; 1094 const struct ath11k_pci_ops *pci_ops; 1095 enum ath11k_hw_rev hw_rev; 1096 int ret; 1097 1098 of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev); 1099 if (!of_id) { 1100 dev_err(&pdev->dev, "failed to find matching device tree id\n"); 1101 return -EINVAL; 1102 } 1103 1104 hw_rev = (enum ath11k_hw_rev)of_id->data; 1105 1106 switch (hw_rev) { 1107 case ATH11K_HW_IPQ8074: 1108 case ATH11K_HW_IPQ6018_HW10: 1109 hif_ops = &ath11k_ahb_hif_ops_ipq8074; 1110 pci_ops = NULL; 1111 break; 1112 case ATH11K_HW_WCN6750_HW10: 1113 hif_ops = &ath11k_ahb_hif_ops_wcn6750; 1114 pci_ops = &ath11k_ahb_pci_ops_wcn6750; 1115 break; 1116 default: 1117 dev_err(&pdev->dev, "unsupported device type %d\n", hw_rev); 1118 return -EOPNOTSUPP; 1119 } 1120 1121 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 1122 if (ret) { 1123 dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n"); 1124 return ret; 1125 } 1126 1127 ab = ath11k_core_alloc(&pdev->dev, sizeof(struct ath11k_ahb), 1128 ATH11K_BUS_AHB); 1129 if (!ab) { 1130 dev_err(&pdev->dev, "failed to allocate ath11k base\n"); 1131 return -ENOMEM; 1132 } 1133 1134 ab->hif.ops = hif_ops; 1135 ab->pdev = pdev; 1136 ab->hw_rev = hw_rev; 1137 platform_set_drvdata(pdev, ab); 1138 1139 ret = ath11k_pcic_register_pci_ops(ab, pci_ops); 1140 if (ret) { 1141 ath11k_err(ab, "failed to register PCI ops: %d\n", ret); 1142 goto err_core_free; 1143 } 1144 1145 ret = ath11k_core_pre_init(ab); 1146 if (ret) 1147 goto err_core_free; 1148 1149 ret = ath11k_ahb_setup_resources(ab); 1150 if (ret) 1151 goto err_core_free; 1152 1153 ret = ath11k_ahb_fw_resources_init(ab); 1154 if (ret) 1155 goto err_core_free; 1156 1157 ret = ath11k_ahb_setup_smp2p_handle(ab); 1158 if (ret) 1159 goto err_fw_deinit; 1160 1161 ret = ath11k_hal_srng_init(ab); 1162 if (ret) 1163 goto err_release_smp2p_handle; 1164 1165 ret = ath11k_ce_alloc_pipes(ab); 1166 if (ret) { 1167 ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret); 1168 goto err_hal_srng_deinit; 1169 } 1170 1171 ath11k_ahb_init_qmi_ce_config(ab); 1172 1173 ret = ath11k_core_get_rproc(ab); 1174 if (ret) { 1175 ath11k_err(ab, "failed to get rproc: %d\n", ret); 1176 goto err_ce_free; 1177 } 1178 1179 ret = ath11k_core_init(ab); 1180 if (ret) { 1181 ath11k_err(ab, "failed to init core: %d\n", ret); 1182 goto err_ce_free; 1183 } 1184 1185 ret = ath11k_ahb_config_irq(ab); 1186 if (ret) { 1187 ath11k_err(ab, "failed to configure irq: %d\n", ret); 1188 goto err_ce_free; 1189 } 1190 1191 ath11k_ahb_fwreset_from_cold_boot(ab); 1192 1193 return 0; 1194 1195 err_ce_free: 1196 ath11k_ce_free_pipes(ab); 1197 1198 err_hal_srng_deinit: 1199 ath11k_hal_srng_deinit(ab); 1200 1201 err_release_smp2p_handle: 1202 ath11k_ahb_release_smp2p_handle(ab); 1203 1204 err_fw_deinit: 1205 ath11k_ahb_fw_resource_deinit(ab); 1206 1207 err_core_free: 1208 ath11k_core_free(ab); 1209 platform_set_drvdata(pdev, NULL); 1210 1211 return ret; 1212 } 1213 1214 static void ath11k_ahb_remove_prepare(struct ath11k_base *ab) 1215 { 1216 unsigned long left; 1217 1218 if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) { 1219 left = wait_for_completion_timeout(&ab->driver_recovery, 1220 ATH11K_AHB_RECOVERY_TIMEOUT); 1221 if (!left) 1222 ath11k_warn(ab, "failed to receive recovery response completion\n"); 1223 } 1224 1225 set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); 1226 cancel_work_sync(&ab->restart_work); 1227 cancel_work_sync(&ab->qmi.event_work); 1228 } 1229 1230 static void ath11k_ahb_free_resources(struct ath11k_base *ab) 1231 { 1232 struct platform_device *pdev = ab->pdev; 1233 1234 ath11k_ahb_free_irq(ab); 1235 ath11k_hal_srng_deinit(ab); 1236 ath11k_ahb_release_smp2p_handle(ab); 1237 ath11k_ahb_fw_resource_deinit(ab); 1238 ath11k_ce_free_pipes(ab); 1239 ath11k_core_free(ab); 1240 platform_set_drvdata(pdev, NULL); 1241 } 1242 1243 static int ath11k_ahb_remove(struct platform_device *pdev) 1244 { 1245 struct ath11k_base *ab = platform_get_drvdata(pdev); 1246 1247 if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { 1248 ath11k_ahb_power_down(ab); 1249 ath11k_debugfs_soc_destroy(ab); 1250 ath11k_qmi_deinit_service(ab); 1251 goto qmi_fail; 1252 } 1253 1254 ath11k_ahb_remove_prepare(ab); 1255 ath11k_core_deinit(ab); 1256 1257 qmi_fail: 1258 ath11k_ahb_free_resources(ab); 1259 1260 return 0; 1261 } 1262 1263 static void ath11k_ahb_shutdown(struct platform_device *pdev) 1264 { 1265 struct ath11k_base *ab = platform_get_drvdata(pdev); 1266 1267 /* platform shutdown() & remove() are mutually exclusive. 1268 * remove() is invoked during rmmod & shutdown() during 1269 * system reboot/shutdown. 1270 */ 1271 ath11k_ahb_remove_prepare(ab); 1272 1273 if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))) 1274 goto free_resources; 1275 1276 ath11k_core_deinit(ab); 1277 1278 free_resources: 1279 ath11k_ahb_free_resources(ab); 1280 } 1281 1282 static struct platform_driver ath11k_ahb_driver = { 1283 .driver = { 1284 .name = "ath11k", 1285 .of_match_table = ath11k_ahb_of_match, 1286 }, 1287 .probe = ath11k_ahb_probe, 1288 .remove = ath11k_ahb_remove, 1289 .shutdown = ath11k_ahb_shutdown, 1290 }; 1291 1292 static int ath11k_ahb_init(void) 1293 { 1294 return platform_driver_register(&ath11k_ahb_driver); 1295 } 1296 module_init(ath11k_ahb_init); 1297 1298 static void ath11k_ahb_exit(void) 1299 { 1300 platform_driver_unregister(&ath11k_ahb_driver); 1301 } 1302 module_exit(ath11k_ahb_exit); 1303 1304 MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices"); 1305 MODULE_LICENSE("Dual BSD/GPL"); 1306