16e0355afSGovind Singh // SPDX-License-Identifier: BSD-3-Clause-Clear 26e0355afSGovind Singh /* 36e0355afSGovind Singh * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 46e0355afSGovind Singh */ 56e0355afSGovind Singh 66e0355afSGovind Singh #include <linux/module.h> 75697a564SGovind Singh #include <linux/msi.h> 86e0355afSGovind Singh #include <linux/pci.h> 96e0355afSGovind Singh 105762613eSGovind Singh #include "pci.h" 116e0355afSGovind Singh #include "core.h" 121399fb87SGovind Singh #include "hif.h" 131399fb87SGovind Singh #include "mhi.h" 146e0355afSGovind Singh #include "debug.h" 156e0355afSGovind Singh 165762613eSGovind Singh #define ATH11K_PCI_BAR_NUM 0 175762613eSGovind Singh #define ATH11K_PCI_DMA_MASK 32 185762613eSGovind Singh 197f4beda2SGovind Singh #define ATH11K_PCI_IRQ_CE0_OFFSET 3 207f4beda2SGovind Singh 21*654e959aSGovind Singh #define WINDOW_ENABLE_BIT 0x40000000 22*654e959aSGovind Singh #define WINDOW_REG_ADDRESS 0x310c 23*654e959aSGovind Singh #define WINDOW_VALUE_MASK GENMASK(24, 19) 24*654e959aSGovind Singh #define WINDOW_START 0x80000 25*654e959aSGovind Singh #define WINDOW_RANGE_MASK GENMASK(18, 0) 26*654e959aSGovind Singh 276e0355afSGovind Singh #define QCA6390_DEVICE_ID 0x1101 286e0355afSGovind Singh 296e0355afSGovind Singh static const struct pci_device_id ath11k_pci_id_table[] = { 306e0355afSGovind Singh { PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) }, 316e0355afSGovind Singh {0} 326e0355afSGovind Singh }; 336e0355afSGovind Singh 346e0355afSGovind Singh MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table); 356e0355afSGovind Singh 361ff8ed78SGovind Singh static const struct ath11k_bus_params ath11k_pci_bus_params = { 371ff8ed78SGovind Singh .mhi_support = true, 3856970454SGovind Singh .m3_fw_support = true, 396eb6ea51SGovind Singh .fixed_bdf_addr = false, 406eb6ea51SGovind Singh .fixed_mem_region = false, 411ff8ed78SGovind Singh }; 421ff8ed78SGovind Singh 435697a564SGovind Singh static const struct ath11k_msi_config msi_config = { 445697a564SGovind Singh .total_vectors = 32, 455697a564SGovind Singh .total_users = 4, 465697a564SGovind Singh .users = (struct ath11k_msi_user[]) { 475697a564SGovind Singh { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, 485697a564SGovind Singh { .name = "CE", .num_vectors = 10, .base_vector = 3 }, 495697a564SGovind Singh { .name = "WAKE", .num_vectors = 1, .base_vector = 13 }, 505697a564SGovind Singh { .name = "DP", .num_vectors = 18, .base_vector = 14 }, 515697a564SGovind Singh }, 525697a564SGovind Singh }; 535697a564SGovind Singh 547f4beda2SGovind Singh /* Target firmware's Copy Engine configuration. */ 557f4beda2SGovind Singh static const struct ce_pipe_config target_ce_config_wlan[] = { 567f4beda2SGovind Singh /* CE0: host->target HTC control and raw streams */ 577f4beda2SGovind Singh { 587f4beda2SGovind Singh .pipenum = __cpu_to_le32(0), 597f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_OUT), 607f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 617f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(2048), 627f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 637f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 647f4beda2SGovind Singh }, 657f4beda2SGovind Singh 667f4beda2SGovind Singh /* CE1: target->host HTT + HTC control */ 677f4beda2SGovind Singh { 687f4beda2SGovind Singh .pipenum = __cpu_to_le32(1), 697f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_IN), 707f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 717f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(2048), 727f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 737f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 747f4beda2SGovind Singh }, 757f4beda2SGovind Singh 767f4beda2SGovind Singh /* CE2: target->host WMI */ 777f4beda2SGovind Singh { 787f4beda2SGovind Singh .pipenum = __cpu_to_le32(2), 797f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_IN), 807f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 817f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(2048), 827f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 837f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 847f4beda2SGovind Singh }, 857f4beda2SGovind Singh 867f4beda2SGovind Singh /* CE3: host->target WMI */ 877f4beda2SGovind Singh { 887f4beda2SGovind Singh .pipenum = __cpu_to_le32(3), 897f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_OUT), 907f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 917f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(2048), 927f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 937f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 947f4beda2SGovind Singh }, 957f4beda2SGovind Singh 967f4beda2SGovind Singh /* CE4: host->target HTT */ 977f4beda2SGovind Singh { 987f4beda2SGovind Singh .pipenum = __cpu_to_le32(4), 997f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_OUT), 1007f4beda2SGovind Singh .nentries = __cpu_to_le32(256), 1017f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(256), 1027f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), 1037f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 1047f4beda2SGovind Singh }, 1057f4beda2SGovind Singh 1067f4beda2SGovind Singh /* CE5: target->host Pktlog */ 1077f4beda2SGovind Singh { 1087f4beda2SGovind Singh .pipenum = __cpu_to_le32(5), 1097f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_IN), 1107f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 1117f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(2048), 1127f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 1137f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 1147f4beda2SGovind Singh }, 1157f4beda2SGovind Singh 1167f4beda2SGovind Singh /* CE6: Reserved for target autonomous hif_memcpy */ 1177f4beda2SGovind Singh { 1187f4beda2SGovind Singh .pipenum = __cpu_to_le32(6), 1197f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_INOUT), 1207f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 1217f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(16384), 1227f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 1237f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 1247f4beda2SGovind Singh }, 1257f4beda2SGovind Singh 1267f4beda2SGovind Singh /* CE7 used only by Host */ 1277f4beda2SGovind Singh { 1287f4beda2SGovind Singh .pipenum = __cpu_to_le32(7), 1297f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H), 1307f4beda2SGovind Singh .nentries = __cpu_to_le32(0), 1317f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(0), 1327f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), 1337f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 1347f4beda2SGovind Singh }, 1357f4beda2SGovind Singh 1367f4beda2SGovind Singh /* CE8 target->host used only by IPA */ 1377f4beda2SGovind Singh { 1387f4beda2SGovind Singh .pipenum = __cpu_to_le32(8), 1397f4beda2SGovind Singh .pipedir = __cpu_to_le32(PIPEDIR_INOUT), 1407f4beda2SGovind Singh .nentries = __cpu_to_le32(32), 1417f4beda2SGovind Singh .nbytes_max = __cpu_to_le32(16384), 1427f4beda2SGovind Singh .flags = __cpu_to_le32(CE_ATTR_FLAGS), 1437f4beda2SGovind Singh .reserved = __cpu_to_le32(0), 1447f4beda2SGovind Singh }, 1457f4beda2SGovind Singh /* CE 9, 10, 11 are used by MHI driver */ 1467f4beda2SGovind Singh }; 1477f4beda2SGovind Singh 1487f4beda2SGovind Singh /* Map from service/endpoint to Copy Engine. 1497f4beda2SGovind Singh * This table is derived from the CE_PCI TABLE, above. 1507f4beda2SGovind Singh * It is passed to the Target at startup for use by firmware. 1517f4beda2SGovind Singh */ 1527f4beda2SGovind Singh static const struct service_to_pipe target_service_to_ce_map_wlan[] = { 1537f4beda2SGovind Singh { 1547f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO), 1557f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 1567f4beda2SGovind Singh __cpu_to_le32(3), 1577f4beda2SGovind Singh }, 1587f4beda2SGovind Singh { 1597f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO), 1607f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 1617f4beda2SGovind Singh __cpu_to_le32(2), 1627f4beda2SGovind Singh }, 1637f4beda2SGovind Singh { 1647f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK), 1657f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 1667f4beda2SGovind Singh __cpu_to_le32(3), 1677f4beda2SGovind Singh }, 1687f4beda2SGovind Singh { 1697f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK), 1707f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 1717f4beda2SGovind Singh __cpu_to_le32(2), 1727f4beda2SGovind Singh }, 1737f4beda2SGovind Singh { 1747f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE), 1757f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 1767f4beda2SGovind Singh __cpu_to_le32(3), 1777f4beda2SGovind Singh }, 1787f4beda2SGovind Singh { 1797f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE), 1807f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 1817f4beda2SGovind Singh __cpu_to_le32(2), 1827f4beda2SGovind Singh }, 1837f4beda2SGovind Singh { 1847f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI), 1857f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 1867f4beda2SGovind Singh __cpu_to_le32(3), 1877f4beda2SGovind Singh }, 1887f4beda2SGovind Singh { 1897f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI), 1907f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 1917f4beda2SGovind Singh __cpu_to_le32(2), 1927f4beda2SGovind Singh }, 1937f4beda2SGovind Singh { 1947f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL), 1957f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 1967f4beda2SGovind Singh __cpu_to_le32(3), 1977f4beda2SGovind Singh }, 1987f4beda2SGovind Singh { 1997f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL), 2007f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 2017f4beda2SGovind Singh __cpu_to_le32(2), 2027f4beda2SGovind Singh }, 2037f4beda2SGovind Singh 2047f4beda2SGovind Singh { 2057f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL), 2067f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 2077f4beda2SGovind Singh __cpu_to_le32(0), 2087f4beda2SGovind Singh }, 2097f4beda2SGovind Singh { 2107f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL), 2117f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 2127f4beda2SGovind Singh __cpu_to_le32(2), 2137f4beda2SGovind Singh }, 2147f4beda2SGovind Singh 2157f4beda2SGovind Singh { 2167f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG), 2177f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 2187f4beda2SGovind Singh __cpu_to_le32(4), 2197f4beda2SGovind Singh }, 2207f4beda2SGovind Singh { 2217f4beda2SGovind Singh __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG), 2227f4beda2SGovind Singh __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 2237f4beda2SGovind Singh __cpu_to_le32(1), 2247f4beda2SGovind Singh }, 2257f4beda2SGovind Singh 2267f4beda2SGovind Singh /* (Additions here) */ 2277f4beda2SGovind Singh 2287f4beda2SGovind Singh { /* must be last */ 2297f4beda2SGovind Singh __cpu_to_le32(0), 2307f4beda2SGovind Singh __cpu_to_le32(0), 2317f4beda2SGovind Singh __cpu_to_le32(0), 2327f4beda2SGovind Singh }, 2337f4beda2SGovind Singh }; 2347f4beda2SGovind Singh 2357f4beda2SGovind Singh static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { 2367f4beda2SGovind Singh "bhi", 2377f4beda2SGovind Singh "mhi-er0", 2387f4beda2SGovind Singh "mhi-er1", 2397f4beda2SGovind Singh "ce0", 2407f4beda2SGovind Singh "ce1", 2417f4beda2SGovind Singh "ce2", 2427f4beda2SGovind Singh "ce3", 2437f4beda2SGovind Singh "ce4", 2447f4beda2SGovind Singh "ce5", 2457f4beda2SGovind Singh "ce6", 2467f4beda2SGovind Singh "ce7", 2477f4beda2SGovind Singh "ce8", 2487f4beda2SGovind Singh "ce9", 2497f4beda2SGovind Singh "ce10", 2507f4beda2SGovind Singh "ce11", 2517f4beda2SGovind Singh "host2wbm-desc-feed", 2527f4beda2SGovind Singh "host2reo-re-injection", 2537f4beda2SGovind Singh "host2reo-command", 2547f4beda2SGovind Singh "host2rxdma-monitor-ring3", 2557f4beda2SGovind Singh "host2rxdma-monitor-ring2", 2567f4beda2SGovind Singh "host2rxdma-monitor-ring1", 2577f4beda2SGovind Singh "reo2ost-exception", 2587f4beda2SGovind Singh "wbm2host-rx-release", 2597f4beda2SGovind Singh "reo2host-status", 2607f4beda2SGovind Singh "reo2host-destination-ring4", 2617f4beda2SGovind Singh "reo2host-destination-ring3", 2627f4beda2SGovind Singh "reo2host-destination-ring2", 2637f4beda2SGovind Singh "reo2host-destination-ring1", 2647f4beda2SGovind Singh "rxdma2host-monitor-destination-mac3", 2657f4beda2SGovind Singh "rxdma2host-monitor-destination-mac2", 2667f4beda2SGovind Singh "rxdma2host-monitor-destination-mac1", 2677f4beda2SGovind Singh "ppdu-end-interrupts-mac3", 2687f4beda2SGovind Singh "ppdu-end-interrupts-mac2", 2697f4beda2SGovind Singh "ppdu-end-interrupts-mac1", 2707f4beda2SGovind Singh "rxdma2host-monitor-status-ring-mac3", 2717f4beda2SGovind Singh "rxdma2host-monitor-status-ring-mac2", 2727f4beda2SGovind Singh "rxdma2host-monitor-status-ring-mac1", 2737f4beda2SGovind Singh "host2rxdma-host-buf-ring-mac3", 2747f4beda2SGovind Singh "host2rxdma-host-buf-ring-mac2", 2757f4beda2SGovind Singh "host2rxdma-host-buf-ring-mac1", 2767f4beda2SGovind Singh "rxdma2host-destination-ring-mac3", 2777f4beda2SGovind Singh "rxdma2host-destination-ring-mac2", 2787f4beda2SGovind Singh "rxdma2host-destination-ring-mac1", 2797f4beda2SGovind Singh "host2tcl-input-ring4", 2807f4beda2SGovind Singh "host2tcl-input-ring3", 2817f4beda2SGovind Singh "host2tcl-input-ring2", 2827f4beda2SGovind Singh "host2tcl-input-ring1", 2837f4beda2SGovind Singh "wbm2host-tx-completions-ring3", 2847f4beda2SGovind Singh "wbm2host-tx-completions-ring2", 2857f4beda2SGovind Singh "wbm2host-tx-completions-ring1", 2867f4beda2SGovind Singh "tcl2host-status-ring", 2877f4beda2SGovind Singh }; 2887f4beda2SGovind Singh 289*654e959aSGovind Singh static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset) 290*654e959aSGovind Singh { 291*654e959aSGovind Singh struct ath11k_base *ab = ab_pci->ab; 292*654e959aSGovind Singh 293*654e959aSGovind Singh u32 window = FIELD_GET(WINDOW_VALUE_MASK, offset); 294*654e959aSGovind Singh 295*654e959aSGovind Singh lockdep_assert_held(&ab_pci->window_lock); 296*654e959aSGovind Singh 297*654e959aSGovind Singh if (window != ab_pci->register_window) { 298*654e959aSGovind Singh iowrite32(WINDOW_ENABLE_BIT | window, 299*654e959aSGovind Singh ab->mem + WINDOW_REG_ADDRESS); 300*654e959aSGovind Singh ab_pci->register_window = window; 301*654e959aSGovind Singh } 302*654e959aSGovind Singh } 303*654e959aSGovind Singh 304*654e959aSGovind Singh static void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) 305*654e959aSGovind Singh { 306*654e959aSGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 307*654e959aSGovind Singh 308*654e959aSGovind Singh if (offset < WINDOW_START) { 309*654e959aSGovind Singh iowrite32(value, ab->mem + offset); 310*654e959aSGovind Singh } else { 311*654e959aSGovind Singh spin_lock_bh(&ab_pci->window_lock); 312*654e959aSGovind Singh ath11k_pci_select_window(ab_pci, offset); 313*654e959aSGovind Singh iowrite32(value, ab->mem + WINDOW_START + (offset & WINDOW_RANGE_MASK)); 314*654e959aSGovind Singh spin_unlock_bh(&ab_pci->window_lock); 315*654e959aSGovind Singh } 316*654e959aSGovind Singh } 317*654e959aSGovind Singh 318*654e959aSGovind Singh static u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset) 319*654e959aSGovind Singh { 320*654e959aSGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 321*654e959aSGovind Singh u32 val; 322*654e959aSGovind Singh 323*654e959aSGovind Singh if (offset < WINDOW_START) { 324*654e959aSGovind Singh val = ioread32(ab->mem + offset); 325*654e959aSGovind Singh } else { 326*654e959aSGovind Singh spin_lock_bh(&ab_pci->window_lock); 327*654e959aSGovind Singh ath11k_pci_select_window(ab_pci, offset); 328*654e959aSGovind Singh val = ioread32(ab->mem + WINDOW_START + (offset & WINDOW_RANGE_MASK)); 329*654e959aSGovind Singh spin_unlock_bh(&ab_pci->window_lock); 330*654e959aSGovind Singh } 331*654e959aSGovind Singh 332*654e959aSGovind Singh return val; 333*654e959aSGovind Singh } 334*654e959aSGovind Singh 3351399fb87SGovind Singh int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector) 3361399fb87SGovind Singh { 3371399fb87SGovind Singh struct pci_dev *pci_dev = to_pci_dev(dev); 3381399fb87SGovind Singh 3391399fb87SGovind Singh return pci_irq_vector(pci_dev, vector); 3401399fb87SGovind Singh } 3411399fb87SGovind Singh 3421399fb87SGovind Singh int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name, 3431399fb87SGovind Singh int *num_vectors, u32 *user_base_data, 3441399fb87SGovind Singh u32 *base_vector) 3451399fb87SGovind Singh { 3461399fb87SGovind Singh struct ath11k_base *ab = ab_pci->ab; 3471399fb87SGovind Singh int idx; 3481399fb87SGovind Singh 3491399fb87SGovind Singh for (idx = 0; idx < msi_config.total_users; idx++) { 3501399fb87SGovind Singh if (strcmp(user_name, msi_config.users[idx].name) == 0) { 3511399fb87SGovind Singh *num_vectors = msi_config.users[idx].num_vectors; 3521399fb87SGovind Singh *user_base_data = msi_config.users[idx].base_vector 3531399fb87SGovind Singh + ab_pci->msi_ep_base_data; 3541399fb87SGovind Singh *base_vector = msi_config.users[idx].base_vector; 3551399fb87SGovind Singh 3561399fb87SGovind Singh ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n", 3571399fb87SGovind Singh user_name, *num_vectors, *user_base_data, 3581399fb87SGovind Singh *base_vector); 3591399fb87SGovind Singh 3601399fb87SGovind Singh return 0; 3611399fb87SGovind Singh } 3621399fb87SGovind Singh } 3631399fb87SGovind Singh 3641399fb87SGovind Singh ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name); 3651399fb87SGovind Singh 3661399fb87SGovind Singh return -EINVAL; 3671399fb87SGovind Singh } 3681399fb87SGovind Singh 3697f4beda2SGovind Singh static void ath11k_pci_free_irq(struct ath11k_base *ab) 3707f4beda2SGovind Singh { 3717f4beda2SGovind Singh int i, irq_idx; 3727f4beda2SGovind Singh 3737f4beda2SGovind Singh for (i = 0; i < CE_COUNT; i++) { 3747f4beda2SGovind Singh if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 3757f4beda2SGovind Singh continue; 3767f4beda2SGovind Singh irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; 3777f4beda2SGovind Singh free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); 3787f4beda2SGovind Singh } 3797f4beda2SGovind Singh } 3807f4beda2SGovind Singh 3817f4beda2SGovind Singh static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) 3827f4beda2SGovind Singh { 3837f4beda2SGovind Singh u32 irq_idx; 3847f4beda2SGovind Singh 3857f4beda2SGovind Singh irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id; 3867f4beda2SGovind Singh disable_irq_nosync(ab->irq_num[irq_idx]); 3877f4beda2SGovind Singh } 3887f4beda2SGovind Singh 3897f4beda2SGovind Singh static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg) 3907f4beda2SGovind Singh { 3917f4beda2SGovind Singh struct ath11k_ce_pipe *ce_pipe = arg; 3927f4beda2SGovind Singh 3937f4beda2SGovind Singh ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num); 3947f4beda2SGovind Singh 3957f4beda2SGovind Singh return IRQ_HANDLED; 3967f4beda2SGovind Singh } 3977f4beda2SGovind Singh 3987f4beda2SGovind Singh static int ath11k_pci_config_irq(struct ath11k_base *ab) 3997f4beda2SGovind Singh { 4007f4beda2SGovind Singh struct ath11k_ce_pipe *ce_pipe; 4017f4beda2SGovind Singh u32 msi_data_start; 4027f4beda2SGovind Singh u32 msi_data_count; 4037f4beda2SGovind Singh u32 msi_irq_start; 4047f4beda2SGovind Singh unsigned int msi_data; 4057f4beda2SGovind Singh int irq, i, ret, irq_idx; 4067f4beda2SGovind Singh 4077f4beda2SGovind Singh ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), 4087f4beda2SGovind Singh "CE", &msi_data_count, 4097f4beda2SGovind Singh &msi_data_start, &msi_irq_start); 4107f4beda2SGovind Singh if (ret) 4117f4beda2SGovind Singh return ret; 4127f4beda2SGovind Singh 4137f4beda2SGovind Singh /* Configure CE irqs */ 4147f4beda2SGovind Singh for (i = 0; i < CE_COUNT; i++) { 4157f4beda2SGovind Singh msi_data = (i % msi_data_count) + msi_irq_start; 4167f4beda2SGovind Singh irq = ath11k_pci_get_msi_irq(ab->dev, msi_data); 4177f4beda2SGovind Singh ce_pipe = &ab->ce.ce_pipe[i]; 4187f4beda2SGovind Singh 4197f4beda2SGovind Singh if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 4207f4beda2SGovind Singh continue; 4217f4beda2SGovind Singh 4227f4beda2SGovind Singh irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; 4237f4beda2SGovind Singh 4247f4beda2SGovind Singh ret = request_irq(irq, ath11k_pci_ce_interrupt_handler, 4257f4beda2SGovind Singh IRQF_SHARED, irq_name[irq_idx], 4267f4beda2SGovind Singh ce_pipe); 4277f4beda2SGovind Singh if (ret) { 4287f4beda2SGovind Singh ath11k_err(ab, "failed to request irq %d: %d\n", 4297f4beda2SGovind Singh irq_idx, ret); 4307f4beda2SGovind Singh return ret; 4317f4beda2SGovind Singh } 4327f4beda2SGovind Singh 4337f4beda2SGovind Singh ab->irq_num[irq_idx] = irq; 4347f4beda2SGovind Singh } 4357f4beda2SGovind Singh 4367f4beda2SGovind Singh return 0; 4377f4beda2SGovind Singh } 4387f4beda2SGovind Singh 4397f4beda2SGovind Singh static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab) 4407f4beda2SGovind Singh { 4417f4beda2SGovind Singh struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; 4427f4beda2SGovind Singh 4437f4beda2SGovind Singh cfg->tgt_ce = target_ce_config_wlan; 4447f4beda2SGovind Singh cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan); 4457f4beda2SGovind Singh 4467f4beda2SGovind Singh cfg->svc_to_ce_map = target_service_to_ce_map_wlan; 4477f4beda2SGovind Singh cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan); 448eb8de049SGovind Singh ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390; 4497f4beda2SGovind Singh } 4507f4beda2SGovind Singh 4517f4beda2SGovind Singh static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) 4527f4beda2SGovind Singh { 4537f4beda2SGovind Singh u32 irq_idx; 4547f4beda2SGovind Singh 4557f4beda2SGovind Singh irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id; 4567f4beda2SGovind Singh enable_irq(ab->irq_num[irq_idx]); 4577f4beda2SGovind Singh } 4587f4beda2SGovind Singh 4597f4beda2SGovind Singh static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab) 4607f4beda2SGovind Singh { 4617f4beda2SGovind Singh int i; 4627f4beda2SGovind Singh 4637f4beda2SGovind Singh for (i = 0; i < CE_COUNT; i++) { 4647f4beda2SGovind Singh if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 4657f4beda2SGovind Singh continue; 4667f4beda2SGovind Singh ath11k_pci_ce_irq_enable(ab, i); 4677f4beda2SGovind Singh } 4687f4beda2SGovind Singh } 4697f4beda2SGovind Singh 4705697a564SGovind Singh static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci) 4715697a564SGovind Singh { 4725697a564SGovind Singh struct ath11k_base *ab = ab_pci->ab; 4735697a564SGovind Singh struct msi_desc *msi_desc; 4745697a564SGovind Singh int num_vectors; 4755697a564SGovind Singh int ret; 4765697a564SGovind Singh 4775697a564SGovind Singh num_vectors = pci_alloc_irq_vectors(ab_pci->pdev, 4785697a564SGovind Singh msi_config.total_vectors, 4795697a564SGovind Singh msi_config.total_vectors, 4805697a564SGovind Singh PCI_IRQ_MSI); 4815697a564SGovind Singh if (num_vectors != msi_config.total_vectors) { 4825697a564SGovind Singh ath11k_err(ab, "failed to get %d MSI vectors, only %d available", 4835697a564SGovind Singh msi_config.total_vectors, num_vectors); 4845697a564SGovind Singh 4855697a564SGovind Singh if (num_vectors >= 0) 4865697a564SGovind Singh return -EINVAL; 4875697a564SGovind Singh else 4885697a564SGovind Singh return num_vectors; 4895697a564SGovind Singh } 4905697a564SGovind Singh 4915697a564SGovind Singh msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); 4925697a564SGovind Singh if (!msi_desc) { 4935697a564SGovind Singh ath11k_err(ab, "msi_desc is NULL!\n"); 4945697a564SGovind Singh ret = -EINVAL; 4955697a564SGovind Singh goto free_msi_vector; 4965697a564SGovind Singh } 4975697a564SGovind Singh 4985697a564SGovind Singh ab_pci->msi_ep_base_data = msi_desc->msg.data; 4995697a564SGovind Singh 5005697a564SGovind Singh ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data); 5015697a564SGovind Singh 5025697a564SGovind Singh return 0; 5035697a564SGovind Singh 5045697a564SGovind Singh free_msi_vector: 5055697a564SGovind Singh pci_free_irq_vectors(ab_pci->pdev); 5065697a564SGovind Singh 5075697a564SGovind Singh return ret; 5085697a564SGovind Singh } 5095697a564SGovind Singh 5105697a564SGovind Singh static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci) 5115697a564SGovind Singh { 5125697a564SGovind Singh pci_free_irq_vectors(ab_pci->pdev); 5135697a564SGovind Singh } 5145697a564SGovind Singh 5155762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev) 5165762613eSGovind Singh { 5175762613eSGovind Singh struct ath11k_base *ab = ab_pci->ab; 5185762613eSGovind Singh u16 device_id; 5195762613eSGovind Singh int ret = 0; 5205762613eSGovind Singh 5215762613eSGovind Singh pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); 5225762613eSGovind Singh if (device_id != ab_pci->dev_id) { 5235762613eSGovind Singh ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n", 5245762613eSGovind Singh device_id, ab_pci->dev_id); 5255762613eSGovind Singh ret = -EIO; 5265762613eSGovind Singh goto out; 5275762613eSGovind Singh } 5285762613eSGovind Singh 5295762613eSGovind Singh ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM); 5305762613eSGovind Singh if (ret) { 5315762613eSGovind Singh ath11k_err(ab, "failed to assign pci resource: %d\n", ret); 5325762613eSGovind Singh goto out; 5335762613eSGovind Singh } 5345762613eSGovind Singh 5355762613eSGovind Singh ret = pci_enable_device(pdev); 5365762613eSGovind Singh if (ret) { 5375762613eSGovind Singh ath11k_err(ab, "failed to enable pci device: %d\n", ret); 5385762613eSGovind Singh goto out; 5395762613eSGovind Singh } 5405762613eSGovind Singh 5415762613eSGovind Singh ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci"); 5425762613eSGovind Singh if (ret) { 5435762613eSGovind Singh ath11k_err(ab, "failed to request pci region: %d\n", ret); 5445762613eSGovind Singh goto disable_device; 5455762613eSGovind Singh } 5465762613eSGovind Singh 5475762613eSGovind Singh ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK)); 5485762613eSGovind Singh if (ret) { 5495762613eSGovind Singh ath11k_err(ab, "failed to set pci dma mask to %d: %d\n", 5505762613eSGovind Singh ATH11K_PCI_DMA_MASK, ret); 5515762613eSGovind Singh goto release_region; 5525762613eSGovind Singh } 5535762613eSGovind Singh 5545762613eSGovind Singh ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK)); 5555762613eSGovind Singh if (ret) { 5565762613eSGovind Singh ath11k_err(ab, "failed to set pci consistent dma mask to %d: %d\n", 5575762613eSGovind Singh ATH11K_PCI_DMA_MASK, ret); 5585762613eSGovind Singh goto release_region; 5595762613eSGovind Singh } 5605762613eSGovind Singh 5615762613eSGovind Singh pci_set_master(pdev); 5625762613eSGovind Singh 5635762613eSGovind Singh ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM); 5645762613eSGovind Singh ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0); 5655762613eSGovind Singh if (!ab->mem) { 5665762613eSGovind Singh ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM); 5675762613eSGovind Singh ret = -EIO; 5685762613eSGovind Singh goto clear_master; 5695762613eSGovind Singh } 5705762613eSGovind Singh 5715762613eSGovind Singh ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); 5725762613eSGovind Singh return 0; 5735762613eSGovind Singh 5745762613eSGovind Singh clear_master: 5755762613eSGovind Singh pci_clear_master(pdev); 5765762613eSGovind Singh release_region: 5775762613eSGovind Singh pci_release_region(pdev, ATH11K_PCI_BAR_NUM); 5785762613eSGovind Singh disable_device: 5795762613eSGovind Singh pci_disable_device(pdev); 5805762613eSGovind Singh out: 5815762613eSGovind Singh return ret; 5825762613eSGovind Singh } 5835762613eSGovind Singh 5845762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci) 5855762613eSGovind Singh { 5865762613eSGovind Singh struct ath11k_base *ab = ab_pci->ab; 5875762613eSGovind Singh struct pci_dev *pci_dev = ab_pci->pdev; 5885762613eSGovind Singh 5895762613eSGovind Singh pci_iounmap(pci_dev, ab->mem); 5905762613eSGovind Singh ab->mem = NULL; 5915762613eSGovind Singh pci_clear_master(pci_dev); 5925762613eSGovind Singh pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM); 5935762613eSGovind Singh if (pci_is_enabled(pci_dev)) 5945762613eSGovind Singh pci_disable_device(pci_dev); 5955762613eSGovind Singh } 5965762613eSGovind Singh 5971399fb87SGovind Singh static int ath11k_pci_power_up(struct ath11k_base *ab) 5981399fb87SGovind Singh { 5991399fb87SGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 6001399fb87SGovind Singh int ret; 6011399fb87SGovind Singh 6021399fb87SGovind Singh ret = ath11k_mhi_start(ab_pci); 6031399fb87SGovind Singh if (ret) { 6041399fb87SGovind Singh ath11k_err(ab, "failed to start mhi: %d\n", ret); 6051399fb87SGovind Singh return ret; 6061399fb87SGovind Singh } 6071399fb87SGovind Singh 6081399fb87SGovind Singh return 0; 6091399fb87SGovind Singh } 6101399fb87SGovind Singh 6111399fb87SGovind Singh static void ath11k_pci_power_down(struct ath11k_base *ab) 6121399fb87SGovind Singh { 6131399fb87SGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 6141399fb87SGovind Singh 6151399fb87SGovind Singh ath11k_mhi_stop(ab_pci); 6161399fb87SGovind Singh } 6171399fb87SGovind Singh 6187f4beda2SGovind Singh static void ath11k_pci_stop(struct ath11k_base *ab) 6197f4beda2SGovind Singh { 6207f4beda2SGovind Singh ath11k_ce_cleanup_pipes(ab); 6217f4beda2SGovind Singh } 6227f4beda2SGovind Singh 6237f4beda2SGovind Singh static int ath11k_pci_start(struct ath11k_base *ab) 6247f4beda2SGovind Singh { 6257f4beda2SGovind Singh ath11k_pci_ce_irqs_enable(ab); 6267f4beda2SGovind Singh 6277f4beda2SGovind Singh return 0; 6287f4beda2SGovind Singh } 6297f4beda2SGovind Singh 6307f4beda2SGovind Singh static const struct ath11k_hif_ops ath11k_pci_hif_ops = { 6317f4beda2SGovind Singh .start = ath11k_pci_start, 6327f4beda2SGovind Singh .stop = ath11k_pci_stop, 633*654e959aSGovind Singh .read32 = ath11k_pci_read32, 634*654e959aSGovind Singh .write32 = ath11k_pci_write32, 6351399fb87SGovind Singh .power_down = ath11k_pci_power_down, 6361399fb87SGovind Singh .power_up = ath11k_pci_power_up, 6371399fb87SGovind Singh }; 6381399fb87SGovind Singh 6396e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev, 6406e0355afSGovind Singh const struct pci_device_id *pci_dev) 6416e0355afSGovind Singh { 6426e0355afSGovind Singh struct ath11k_base *ab; 6435762613eSGovind Singh struct ath11k_pci *ab_pci; 6446e0355afSGovind Singh enum ath11k_hw_rev hw_rev; 6455762613eSGovind Singh int ret; 6466e0355afSGovind Singh 6476e0355afSGovind Singh dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n"); 6486e0355afSGovind Singh 6496e0355afSGovind Singh switch (pci_dev->device) { 6506e0355afSGovind Singh case QCA6390_DEVICE_ID: 6516e0355afSGovind Singh hw_rev = ATH11K_HW_QCA6390_HW20; 6526e0355afSGovind Singh break; 6536e0355afSGovind Singh default: 6546e0355afSGovind Singh dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n", 6556e0355afSGovind Singh pci_dev->device); 6566e0355afSGovind Singh return -ENOTSUPP; 6576e0355afSGovind Singh } 6586e0355afSGovind Singh 6591ff8ed78SGovind Singh ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI, 6601ff8ed78SGovind Singh &ath11k_pci_bus_params); 6616e0355afSGovind Singh if (!ab) { 6626e0355afSGovind Singh dev_err(&pdev->dev, "failed to allocate ath11k base\n"); 6636e0355afSGovind Singh return -ENOMEM; 6646e0355afSGovind Singh } 6656e0355afSGovind Singh 6666e0355afSGovind Singh ab->dev = &pdev->dev; 6676e0355afSGovind Singh ab->hw_rev = hw_rev; 6686e0355afSGovind Singh pci_set_drvdata(pdev, ab); 6695762613eSGovind Singh ab_pci = ath11k_pci_priv(ab); 6705762613eSGovind Singh ab_pci->dev_id = pci_dev->device; 6715762613eSGovind Singh ab_pci->ab = ab; 6725697a564SGovind Singh ab_pci->pdev = pdev; 6737f4beda2SGovind Singh ab->hif.ops = &ath11k_pci_hif_ops; 6745762613eSGovind Singh pci_set_drvdata(pdev, ab); 675*654e959aSGovind Singh spin_lock_init(&ab_pci->window_lock); 6765762613eSGovind Singh 6775762613eSGovind Singh ret = ath11k_pci_claim(ab_pci, pdev); 6785762613eSGovind Singh if (ret) { 6795762613eSGovind Singh ath11k_err(ab, "failed to claim device: %d\n", ret); 6805762613eSGovind Singh goto err_free_core; 6815762613eSGovind Singh } 6826e0355afSGovind Singh 6835697a564SGovind Singh ret = ath11k_pci_enable_msi(ab_pci); 6845697a564SGovind Singh if (ret) { 6855697a564SGovind Singh ath11k_err(ab, "failed to enable msi: %d\n", ret); 6865697a564SGovind Singh goto err_pci_free_region; 6875697a564SGovind Singh } 6885697a564SGovind Singh 689b8246f88SKalle Valo ret = ath11k_core_pre_init(ab); 690b8246f88SKalle Valo if (ret) 691b8246f88SKalle Valo goto err_pci_disable_msi; 692b8246f88SKalle Valo 6931399fb87SGovind Singh ret = ath11k_mhi_register(ab_pci); 6941399fb87SGovind Singh if (ret) { 6951399fb87SGovind Singh ath11k_err(ab, "failed to register mhi: %d\n", ret); 6961399fb87SGovind Singh goto err_pci_disable_msi; 6971399fb87SGovind Singh } 6981399fb87SGovind Singh 6997f4beda2SGovind Singh ret = ath11k_hal_srng_init(ab); 7007f4beda2SGovind Singh if (ret) 7017f4beda2SGovind Singh goto err_mhi_unregister; 7027f4beda2SGovind Singh 7037f4beda2SGovind Singh ret = ath11k_ce_alloc_pipes(ab); 7047f4beda2SGovind Singh if (ret) { 7057f4beda2SGovind Singh ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret); 7067f4beda2SGovind Singh goto err_hal_srng_deinit; 7077f4beda2SGovind Singh } 7087f4beda2SGovind Singh 7097f4beda2SGovind Singh ath11k_pci_init_qmi_ce_config(ab); 7107f4beda2SGovind Singh 7117f4beda2SGovind Singh ret = ath11k_pci_config_irq(ab); 7127f4beda2SGovind Singh if (ret) { 7137f4beda2SGovind Singh ath11k_err(ab, "failed to config irq: %d\n", ret); 7147f4beda2SGovind Singh goto err_ce_free; 7157f4beda2SGovind Singh } 7167f4beda2SGovind Singh 7177f4beda2SGovind Singh ret = ath11k_core_init(ab); 7187f4beda2SGovind Singh if (ret) { 7197f4beda2SGovind Singh ath11k_err(ab, "failed to init core: %d\n", ret); 7207f4beda2SGovind Singh goto err_free_irq; 7217f4beda2SGovind Singh } 7226e0355afSGovind Singh return 0; 7235762613eSGovind Singh 7247f4beda2SGovind Singh err_free_irq: 7257f4beda2SGovind Singh ath11k_pci_free_irq(ab); 7267f4beda2SGovind Singh 7277f4beda2SGovind Singh err_ce_free: 7287f4beda2SGovind Singh ath11k_ce_free_pipes(ab); 7297f4beda2SGovind Singh 7307f4beda2SGovind Singh err_hal_srng_deinit: 7317f4beda2SGovind Singh ath11k_hal_srng_deinit(ab); 7327f4beda2SGovind Singh 7337f4beda2SGovind Singh err_mhi_unregister: 7347f4beda2SGovind Singh ath11k_mhi_unregister(ab_pci); 7357f4beda2SGovind Singh 736b8246f88SKalle Valo err_pci_disable_msi: 737b8246f88SKalle Valo ath11k_pci_disable_msi(ab_pci); 738b8246f88SKalle Valo 7395697a564SGovind Singh err_pci_free_region: 7405697a564SGovind Singh ath11k_pci_free_region(ab_pci); 7415697a564SGovind Singh 7425762613eSGovind Singh err_free_core: 7435762613eSGovind Singh ath11k_core_free(ab); 7445697a564SGovind Singh 7455762613eSGovind Singh return ret; 7466e0355afSGovind Singh } 7476e0355afSGovind Singh 7486e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev) 7496e0355afSGovind Singh { 7506e0355afSGovind Singh struct ath11k_base *ab = pci_get_drvdata(pdev); 7515762613eSGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 7526e0355afSGovind Singh 7536e0355afSGovind Singh set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); 7541399fb87SGovind Singh ath11k_mhi_unregister(ab_pci); 7555697a564SGovind Singh ath11k_pci_disable_msi(ab_pci); 7565762613eSGovind Singh ath11k_pci_free_region(ab_pci); 7577f4beda2SGovind Singh ath11k_pci_free_irq(ab); 7586e0355afSGovind Singh ath11k_core_free(ab); 7596e0355afSGovind Singh } 7606e0355afSGovind Singh 7611399fb87SGovind Singh static void ath11k_pci_shutdown(struct pci_dev *pdev) 7621399fb87SGovind Singh { 7631399fb87SGovind Singh struct ath11k_base *ab = pci_get_drvdata(pdev); 7641399fb87SGovind Singh 7651399fb87SGovind Singh ath11k_pci_power_down(ab); 7661399fb87SGovind Singh } 7671399fb87SGovind Singh 7686e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = { 7696e0355afSGovind Singh .name = "ath11k_pci", 7706e0355afSGovind Singh .id_table = ath11k_pci_id_table, 7716e0355afSGovind Singh .probe = ath11k_pci_probe, 7726e0355afSGovind Singh .remove = ath11k_pci_remove, 7731399fb87SGovind Singh .shutdown = ath11k_pci_shutdown, 7746e0355afSGovind Singh }; 7756e0355afSGovind Singh 7766e0355afSGovind Singh static int ath11k_pci_init(void) 7776e0355afSGovind Singh { 7786e0355afSGovind Singh int ret; 7796e0355afSGovind Singh 7806e0355afSGovind Singh ret = pci_register_driver(&ath11k_pci_driver); 7816e0355afSGovind Singh if (ret) 7826e0355afSGovind Singh pr_err("failed to register ath11k pci driver: %d\n", 7836e0355afSGovind Singh ret); 7846e0355afSGovind Singh 7856e0355afSGovind Singh return ret; 7866e0355afSGovind Singh } 7876e0355afSGovind Singh module_init(ath11k_pci_init); 7886e0355afSGovind Singh 7896e0355afSGovind Singh static void ath11k_pci_exit(void) 7906e0355afSGovind Singh { 7916e0355afSGovind Singh pci_unregister_driver(&ath11k_pci_driver); 7926e0355afSGovind Singh } 7936e0355afSGovind Singh 7946e0355afSGovind Singh module_exit(ath11k_pci_exit); 7956e0355afSGovind Singh 7966e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices"); 7976e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL"); 798