16e0355afSGovind Singh // SPDX-License-Identifier: BSD-3-Clause-Clear 26e0355afSGovind Singh /* 36e0355afSGovind Singh * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 4b43310e4SGovindaraj Saminathan * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 56e0355afSGovind Singh */ 66e0355afSGovind Singh 76e0355afSGovind Singh #include <linux/module.h> 85697a564SGovind Singh #include <linux/msi.h> 96e0355afSGovind Singh #include <linux/pci.h> 106ac04bdcSAnilkumar Kolli #include <linux/of.h> 116e0355afSGovind Singh 125762613eSGovind Singh #include "pci.h" 136e0355afSGovind Singh #include "core.h" 141399fb87SGovind Singh #include "hif.h" 151399fb87SGovind Singh #include "mhi.h" 166e0355afSGovind Singh #include "debug.h" 17bbfdc5a7SManikanta Pubbisetty #include "pcic.h" 18bdfc967bSAnilkumar Kolli #include "qmi.h" 196e0355afSGovind Singh 205762613eSGovind Singh #define ATH11K_PCI_BAR_NUM 0 215762613eSGovind Singh #define ATH11K_PCI_DMA_MASK 32 225762613eSGovind Singh 2318ac1665SKalle Valo #define TCSR_SOC_HW_VERSION 0x0224 24d1147a31SBaochen Qiang #define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8) 2518ac1665SKalle Valo #define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 0) 2618ac1665SKalle Valo 276e0355afSGovind Singh #define QCA6390_DEVICE_ID 0x1101 284e809461SAnilkumar Kolli #define QCN9074_DEVICE_ID 0x1104 290fbf1957SBaochen Qiang #define WCN6855_DEVICE_ID 0x1103 306e0355afSGovind Singh 316e0355afSGovind Singh static const struct pci_device_id ath11k_pci_id_table[] = { 326e0355afSGovind Singh { PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) }, 330fbf1957SBaochen Qiang { PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) }, 3449f5b114SAnilkumar Kolli { PCI_VDEVICE(QCOM, QCN9074_DEVICE_ID) }, 356e0355afSGovind Singh {0} 366e0355afSGovind Singh }; 376e0355afSGovind Singh 386e0355afSGovind Singh MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table); 396e0355afSGovind Singh 405b32b6ddSManikanta Pubbisetty static int ath11k_pci_bus_wake_up(struct ath11k_base *ab) 415b32b6ddSManikanta Pubbisetty { 425b32b6ddSManikanta Pubbisetty struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 435b32b6ddSManikanta Pubbisetty 445b32b6ddSManikanta Pubbisetty return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); 455b32b6ddSManikanta Pubbisetty } 465b32b6ddSManikanta Pubbisetty 475b32b6ddSManikanta Pubbisetty static void ath11k_pci_bus_release(struct ath11k_base *ab) 485b32b6ddSManikanta Pubbisetty { 495b32b6ddSManikanta Pubbisetty struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 505b32b6ddSManikanta Pubbisetty 515b32b6ddSManikanta Pubbisetty mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); 525b32b6ddSManikanta Pubbisetty } 535b32b6ddSManikanta Pubbisetty 54867f4eeeSManikanta Pubbisetty static u32 ath11k_pci_get_window_start(struct ath11k_base *ab, u32 offset) 55867f4eeeSManikanta Pubbisetty { 56867f4eeeSManikanta Pubbisetty if (!ab->hw_params.static_window_map) 57867f4eeeSManikanta Pubbisetty return ATH11K_PCI_WINDOW_START; 58867f4eeeSManikanta Pubbisetty 59867f4eeeSManikanta Pubbisetty if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK) 60867f4eeeSManikanta Pubbisetty /* if offset lies within DP register range, use 3rd window */ 61867f4eeeSManikanta Pubbisetty return 3 * ATH11K_PCI_WINDOW_START; 62867f4eeeSManikanta Pubbisetty else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < 63867f4eeeSManikanta Pubbisetty ATH11K_PCI_WINDOW_RANGE_MASK) 64867f4eeeSManikanta Pubbisetty /* if offset lies within CE register range, use 2nd window */ 65867f4eeeSManikanta Pubbisetty return 2 * ATH11K_PCI_WINDOW_START; 66867f4eeeSManikanta Pubbisetty else 67867f4eeeSManikanta Pubbisetty return ATH11K_PCI_WINDOW_START; 68867f4eeeSManikanta Pubbisetty } 69867f4eeeSManikanta Pubbisetty 705b32b6ddSManikanta Pubbisetty static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset) 715b32b6ddSManikanta Pubbisetty { 725b32b6ddSManikanta Pubbisetty struct ath11k_base *ab = ab_pci->ab; 735b32b6ddSManikanta Pubbisetty 745b32b6ddSManikanta Pubbisetty u32 window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, offset); 755b32b6ddSManikanta Pubbisetty 765b32b6ddSManikanta Pubbisetty lockdep_assert_held(&ab_pci->window_lock); 775b32b6ddSManikanta Pubbisetty 785b32b6ddSManikanta Pubbisetty if (window != ab_pci->register_window) { 795b32b6ddSManikanta Pubbisetty iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window, 805b32b6ddSManikanta Pubbisetty ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS); 815b32b6ddSManikanta Pubbisetty ioread32(ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS); 825b32b6ddSManikanta Pubbisetty ab_pci->register_window = window; 835b32b6ddSManikanta Pubbisetty } 845b32b6ddSManikanta Pubbisetty } 855b32b6ddSManikanta Pubbisetty 865b32b6ddSManikanta Pubbisetty static void 875b32b6ddSManikanta Pubbisetty ath11k_pci_window_write32(struct ath11k_base *ab, u32 offset, u32 value) 885b32b6ddSManikanta Pubbisetty { 895b32b6ddSManikanta Pubbisetty struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 90867f4eeeSManikanta Pubbisetty u32 window_start; 915b32b6ddSManikanta Pubbisetty 92867f4eeeSManikanta Pubbisetty window_start = ath11k_pci_get_window_start(ab, offset); 93867f4eeeSManikanta Pubbisetty 94867f4eeeSManikanta Pubbisetty if (window_start == ATH11K_PCI_WINDOW_START) { 955b32b6ddSManikanta Pubbisetty spin_lock_bh(&ab_pci->window_lock); 965b32b6ddSManikanta Pubbisetty ath11k_pci_select_window(ab_pci, offset); 975b32b6ddSManikanta Pubbisetty iowrite32(value, ab->mem + window_start + 985b32b6ddSManikanta Pubbisetty (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); 995b32b6ddSManikanta Pubbisetty spin_unlock_bh(&ab_pci->window_lock); 100867f4eeeSManikanta Pubbisetty } else { 101867f4eeeSManikanta Pubbisetty iowrite32(value, ab->mem + window_start + 102867f4eeeSManikanta Pubbisetty (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); 103867f4eeeSManikanta Pubbisetty } 1045b32b6ddSManikanta Pubbisetty } 1055b32b6ddSManikanta Pubbisetty 1065b32b6ddSManikanta Pubbisetty static u32 ath11k_pci_window_read32(struct ath11k_base *ab, u32 offset) 1075b32b6ddSManikanta Pubbisetty { 1085b32b6ddSManikanta Pubbisetty struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 109867f4eeeSManikanta Pubbisetty u32 window_start, val; 1105b32b6ddSManikanta Pubbisetty 111867f4eeeSManikanta Pubbisetty window_start = ath11k_pci_get_window_start(ab, offset); 112867f4eeeSManikanta Pubbisetty 113867f4eeeSManikanta Pubbisetty if (window_start == ATH11K_PCI_WINDOW_START) { 1145b32b6ddSManikanta Pubbisetty spin_lock_bh(&ab_pci->window_lock); 1155b32b6ddSManikanta Pubbisetty ath11k_pci_select_window(ab_pci, offset); 1165b32b6ddSManikanta Pubbisetty val = ioread32(ab->mem + window_start + 1175b32b6ddSManikanta Pubbisetty (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); 1185b32b6ddSManikanta Pubbisetty spin_unlock_bh(&ab_pci->window_lock); 119867f4eeeSManikanta Pubbisetty } else { 120867f4eeeSManikanta Pubbisetty val = ioread32(ab->mem + window_start + 121867f4eeeSManikanta Pubbisetty (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); 122867f4eeeSManikanta Pubbisetty } 1235b32b6ddSManikanta Pubbisetty 1245b32b6ddSManikanta Pubbisetty return val; 1255b32b6ddSManikanta Pubbisetty } 1265b32b6ddSManikanta Pubbisetty 1275b32b6ddSManikanta Pubbisetty int ath11k_pci_get_msi_irq(struct ath11k_base *ab, unsigned int vector) 1285b32b6ddSManikanta Pubbisetty { 1295b32b6ddSManikanta Pubbisetty struct pci_dev *pci_dev = to_pci_dev(ab->dev); 1305b32b6ddSManikanta Pubbisetty 1315b32b6ddSManikanta Pubbisetty return pci_irq_vector(pci_dev, vector); 1325b32b6ddSManikanta Pubbisetty } 1335b32b6ddSManikanta Pubbisetty 1345b32b6ddSManikanta Pubbisetty static const struct ath11k_pci_ops ath11k_pci_ops_qca6390 = { 1355b32b6ddSManikanta Pubbisetty .wakeup = ath11k_pci_bus_wake_up, 1365b32b6ddSManikanta Pubbisetty .release = ath11k_pci_bus_release, 1375b32b6ddSManikanta Pubbisetty .get_msi_irq = ath11k_pci_get_msi_irq, 1385b32b6ddSManikanta Pubbisetty .window_write32 = ath11k_pci_window_write32, 1395b32b6ddSManikanta Pubbisetty .window_read32 = ath11k_pci_window_read32, 1405b32b6ddSManikanta Pubbisetty }; 1415b32b6ddSManikanta Pubbisetty 1425b32b6ddSManikanta Pubbisetty static const struct ath11k_pci_ops ath11k_pci_ops_qcn9074 = { 143867f4eeeSManikanta Pubbisetty .wakeup = NULL, 144867f4eeeSManikanta Pubbisetty .release = NULL, 1455b32b6ddSManikanta Pubbisetty .get_msi_irq = ath11k_pci_get_msi_irq, 1465b32b6ddSManikanta Pubbisetty .window_write32 = ath11k_pci_window_write32, 1475b32b6ddSManikanta Pubbisetty .window_read32 = ath11k_pci_window_read32, 1485b32b6ddSManikanta Pubbisetty }; 1495b32b6ddSManikanta Pubbisetty 150ac6e7348SCarl Huang static const struct ath11k_msi_config msi_config_one_msi = { 151ac6e7348SCarl Huang .total_vectors = 1, 152ac6e7348SCarl Huang .total_users = 4, 153ac6e7348SCarl Huang .users = (struct ath11k_msi_user[]) { 154ac6e7348SCarl Huang { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, 155ac6e7348SCarl Huang { .name = "CE", .num_vectors = 1, .base_vector = 0 }, 156ac6e7348SCarl Huang { .name = "WAKE", .num_vectors = 1, .base_vector = 0 }, 157ac6e7348SCarl Huang { .name = "DP", .num_vectors = 1, .base_vector = 0 }, 158ac6e7348SCarl Huang }, 159ac6e7348SCarl Huang }; 160ac6e7348SCarl Huang 161480a7361SKarthikeyan Periyasamy static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci) 162480a7361SKarthikeyan Periyasamy { 163948171b5SManikanta Pubbisetty u32 umac_window; 164948171b5SManikanta Pubbisetty u32 ce_window; 165480a7361SKarthikeyan Periyasamy u32 window; 166480a7361SKarthikeyan Periyasamy 167948171b5SManikanta Pubbisetty umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET); 168948171b5SManikanta Pubbisetty ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE); 169480a7361SKarthikeyan Periyasamy window = (umac_window << 12) | (ce_window << 6); 170480a7361SKarthikeyan Periyasamy 171948171b5SManikanta Pubbisetty iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window, 172948171b5SManikanta Pubbisetty ab_pci->ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS); 173480a7361SKarthikeyan Periyasamy } 174480a7361SKarthikeyan Periyasamy 175f3c603d4SCarl Huang static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) 176f3c603d4SCarl Huang { 177f3c603d4SCarl Huang u32 val, delay; 178f3c603d4SCarl Huang 179bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); 180f3c603d4SCarl Huang 181f3c603d4SCarl Huang val |= PCIE_SOC_GLOBAL_RESET_V; 182f3c603d4SCarl Huang 183bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); 184f3c603d4SCarl Huang 185f3c603d4SCarl Huang /* TODO: exact time to sleep is uncertain */ 186f3c603d4SCarl Huang delay = 10; 187f3c603d4SCarl Huang mdelay(delay); 188f3c603d4SCarl Huang 189f3c603d4SCarl Huang /* Need to toggle V bit back otherwise stuck in reset status */ 190f3c603d4SCarl Huang val &= ~PCIE_SOC_GLOBAL_RESET_V; 191f3c603d4SCarl Huang 192bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); 193f3c603d4SCarl Huang 194f3c603d4SCarl Huang mdelay(delay); 195f3c603d4SCarl Huang 196bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); 197f3c603d4SCarl Huang if (val == 0xffffffff) 198f3c603d4SCarl Huang ath11k_warn(ab, "link down error during global reset\n"); 199f3c603d4SCarl Huang } 200f3c603d4SCarl Huang 201f3c603d4SCarl Huang static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab) 202f3c603d4SCarl Huang { 203f3c603d4SCarl Huang u32 val; 204f3c603d4SCarl Huang 205f3c603d4SCarl Huang /* read cookie */ 206bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR); 207332c6562SKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_q6_cookie_addr 0x%x\n", val); 208f3c603d4SCarl Huang 209bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY); 210332c6562SKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val); 211f3c603d4SCarl Huang 212f3c603d4SCarl Huang /* TODO: exact time to sleep is uncertain */ 213f3c603d4SCarl Huang mdelay(10); 214f3c603d4SCarl Huang 215f3c603d4SCarl Huang /* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from 216f3c603d4SCarl Huang * continuing warm path and entering dead loop. 217f3c603d4SCarl Huang */ 218bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, WLAON_WARM_SW_ENTRY, 0); 219f3c603d4SCarl Huang mdelay(10); 220f3c603d4SCarl Huang 221bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY); 222332c6562SKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val); 223f3c603d4SCarl Huang 224f3c603d4SCarl Huang /* A read clear register. clear the register to prevent 225f3c603d4SCarl Huang * Q6 from entering wrong code path. 226f3c603d4SCarl Huang */ 227bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG); 228332c6562SKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause %d\n", val); 229f3c603d4SCarl Huang } 230f3c603d4SCarl Huang 23106999407SCarl Huang static int ath11k_pci_set_link_reg(struct ath11k_base *ab, 23206999407SCarl Huang u32 offset, u32 value, u32 mask) 23306999407SCarl Huang { 23406999407SCarl Huang u32 v; 23506999407SCarl Huang int i; 23606999407SCarl Huang 237bbfdc5a7SManikanta Pubbisetty v = ath11k_pcic_read32(ab, offset); 23806999407SCarl Huang if ((v & mask) == value) 23906999407SCarl Huang return 0; 24006999407SCarl Huang 24106999407SCarl Huang for (i = 0; i < 10; i++) { 242bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, offset, (v & ~mask) | value); 24306999407SCarl Huang 244bbfdc5a7SManikanta Pubbisetty v = ath11k_pcic_read32(ab, offset); 24506999407SCarl Huang if ((v & mask) == value) 24606999407SCarl Huang return 0; 24706999407SCarl Huang 24806999407SCarl Huang mdelay(2); 24906999407SCarl Huang } 25006999407SCarl Huang 25106999407SCarl Huang ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n", 25206999407SCarl Huang offset, v & mask, value); 25306999407SCarl Huang 25406999407SCarl Huang return -ETIMEDOUT; 25506999407SCarl Huang } 25606999407SCarl Huang 25706999407SCarl Huang static int ath11k_pci_fix_l1ss(struct ath11k_base *ab) 25806999407SCarl Huang { 25906999407SCarl Huang int ret; 26006999407SCarl Huang 26106999407SCarl Huang ret = ath11k_pci_set_link_reg(ab, 2626fe6f68fSKarthikeyan Periyasamy PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab), 26306999407SCarl Huang PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL, 26406999407SCarl Huang PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK); 26530d08503SDan Carpenter if (ret) { 26606999407SCarl Huang ath11k_warn(ab, "failed to set sysclk: %d\n", ret); 26706999407SCarl Huang return ret; 26806999407SCarl Huang } 26906999407SCarl Huang 27006999407SCarl Huang ret = ath11k_pci_set_link_reg(ab, 2716fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab), 2726fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG1_VAL, 2736fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG_MSK); 27430d08503SDan Carpenter if (ret) { 27506999407SCarl Huang ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret); 27606999407SCarl Huang return ret; 27706999407SCarl Huang } 27806999407SCarl Huang 27906999407SCarl Huang ret = ath11k_pci_set_link_reg(ab, 2806fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab), 2816fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG2_VAL, 2826fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG_MSK); 28330d08503SDan Carpenter if (ret) { 28406999407SCarl Huang ath11k_warn(ab, "failed to set dtct config2: %d\n", ret); 28506999407SCarl Huang return ret; 28606999407SCarl Huang } 28706999407SCarl Huang 28806999407SCarl Huang ret = ath11k_pci_set_link_reg(ab, 2896fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab), 2906fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG4_VAL, 2916fe6f68fSKarthikeyan Periyasamy PCIE_PCS_OSC_DTCT_CONFIG_MSK); 29230d08503SDan Carpenter if (ret) { 29306999407SCarl Huang ath11k_warn(ab, "failed to set dtct config4: %d\n", ret); 29406999407SCarl Huang return ret; 29506999407SCarl Huang } 29606999407SCarl Huang 29706999407SCarl Huang return 0; 29806999407SCarl Huang } 29906999407SCarl Huang 300babb0cedSCarl Huang static void ath11k_pci_enable_ltssm(struct ath11k_base *ab) 301babb0cedSCarl Huang { 302babb0cedSCarl Huang u32 val; 303babb0cedSCarl Huang int i; 304babb0cedSCarl Huang 305bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM); 306babb0cedSCarl Huang 307babb0cedSCarl Huang /* PCIE link seems very unstable after the Hot Reset*/ 308babb0cedSCarl Huang for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) { 309babb0cedSCarl Huang if (val == 0xffffffff) 310babb0cedSCarl Huang mdelay(5); 311babb0cedSCarl Huang 312bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE); 313bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM); 314babb0cedSCarl Huang } 315babb0cedSCarl Huang 316fc3b984aSKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "ltssm 0x%x\n", val); 317babb0cedSCarl Huang 318bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST); 319562934adSKalle Valo val |= GCC_GCC_PCIE_HOT_RST_VAL; 320bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val); 321bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST); 322babb0cedSCarl Huang 323fc3b984aSKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_hot_rst 0x%x\n", val); 324babb0cedSCarl Huang 325babb0cedSCarl Huang mdelay(5); 326babb0cedSCarl Huang } 327babb0cedSCarl Huang 328babb0cedSCarl Huang static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab) 329babb0cedSCarl Huang { 330babb0cedSCarl Huang /* This is a WAR for PCIE Hotreset. 331babb0cedSCarl Huang * When target receive Hotreset, but will set the interrupt. 332babb0cedSCarl Huang * So when download SBL again, SBL will open Interrupt and 333babb0cedSCarl Huang * receive it, and crash immediately. 334babb0cedSCarl Huang */ 335bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL); 336babb0cedSCarl Huang } 337babb0cedSCarl Huang 3380ccdf439SCarl Huang static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab) 3390ccdf439SCarl Huang { 3400ccdf439SCarl Huang u32 val; 3410ccdf439SCarl Huang 342bbfdc5a7SManikanta Pubbisetty val = ath11k_pcic_read32(ab, WLAON_QFPROM_PWR_CTRL_REG); 3430ccdf439SCarl Huang val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK; 344bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val); 3450ccdf439SCarl Huang } 3460ccdf439SCarl Huang 347f3c603d4SCarl Huang static void ath11k_pci_force_wake(struct ath11k_base *ab) 348f3c603d4SCarl Huang { 349bbfdc5a7SManikanta Pubbisetty ath11k_pcic_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1); 350f3c603d4SCarl Huang mdelay(5); 351f3c603d4SCarl Huang } 352f3c603d4SCarl Huang 353babb0cedSCarl Huang static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on) 354f3c603d4SCarl Huang { 3558a0b899fSBaochen Qiang mdelay(100); 3568a0b899fSBaochen Qiang 357babb0cedSCarl Huang if (power_on) { 358babb0cedSCarl Huang ath11k_pci_enable_ltssm(ab); 359babb0cedSCarl Huang ath11k_pci_clear_all_intrs(ab); 3600ccdf439SCarl Huang ath11k_pci_set_wlaon_pwr_ctrl(ab); 3615088df05SBaochen Qiang if (ab->hw_params.fix_l1ss) 36206999407SCarl Huang ath11k_pci_fix_l1ss(ab); 363babb0cedSCarl Huang } 364babb0cedSCarl Huang 365f3c603d4SCarl Huang ath11k_mhi_clear_vector(ab); 3668a0b899fSBaochen Qiang ath11k_pci_clear_dbg_registers(ab); 367f3c603d4SCarl Huang ath11k_pci_soc_global_reset(ab); 368f3c603d4SCarl Huang ath11k_mhi_set_mhictrl_reset(ab); 369f3c603d4SCarl Huang } 370f3c603d4SCarl Huang 3717f4beda2SGovind Singh static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab) 3727f4beda2SGovind Singh { 3737f4beda2SGovind Singh struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; 3747f4beda2SGovind Singh 375967c1d11SAnilkumar Kolli cfg->tgt_ce = ab->hw_params.target_ce_config; 376967c1d11SAnilkumar Kolli cfg->tgt_ce_len = ab->hw_params.target_ce_count; 3777f4beda2SGovind Singh 378967c1d11SAnilkumar Kolli cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map; 379967c1d11SAnilkumar Kolli cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len; 38016001e4bSAnilkumar Kolli ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; 381e838c14aSCarl Huang 382e838c14aSCarl Huang ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2, 383e838c14aSCarl Huang &cfg->shadow_reg_v2_len); 3847f4beda2SGovind Singh } 3857f4beda2SGovind Singh 38696527d52SBaochen Qiang static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable) 38796527d52SBaochen Qiang { 38896527d52SBaochen Qiang struct pci_dev *dev = ab_pci->pdev; 38996527d52SBaochen Qiang u16 control; 39096527d52SBaochen Qiang 39196527d52SBaochen Qiang pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); 39296527d52SBaochen Qiang 39396527d52SBaochen Qiang if (enable) 39496527d52SBaochen Qiang control |= PCI_MSI_FLAGS_ENABLE; 39596527d52SBaochen Qiang else 39696527d52SBaochen Qiang control &= ~PCI_MSI_FLAGS_ENABLE; 39796527d52SBaochen Qiang 39896527d52SBaochen Qiang pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); 39996527d52SBaochen Qiang } 40096527d52SBaochen Qiang 40196527d52SBaochen Qiang static void ath11k_pci_msi_enable(struct ath11k_pci *ab_pci) 40296527d52SBaochen Qiang { 40396527d52SBaochen Qiang ath11k_pci_msi_config(ab_pci, true); 40496527d52SBaochen Qiang } 40596527d52SBaochen Qiang 40696527d52SBaochen Qiang static void ath11k_pci_msi_disable(struct ath11k_pci *ab_pci) 40796527d52SBaochen Qiang { 40896527d52SBaochen Qiang ath11k_pci_msi_config(ab_pci, false); 40996527d52SBaochen Qiang } 41096527d52SBaochen Qiang 41196527d52SBaochen Qiang static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci) 4125697a564SGovind Singh { 4135697a564SGovind Singh struct ath11k_base *ab = ab_pci->ab; 4140cfaf224SManikanta Pubbisetty const struct ath11k_msi_config *msi_config = ab->pci.msi.config; 4150cfaf224SManikanta Pubbisetty struct pci_dev *pci_dev = ab_pci->pdev; 4165697a564SGovind Singh struct msi_desc *msi_desc; 4175697a564SGovind Singh int num_vectors; 4185697a564SGovind Singh int ret; 4195697a564SGovind Singh 4200cfaf224SManikanta Pubbisetty num_vectors = pci_alloc_irq_vectors(pci_dev, 4217a3aed0cSAnilkumar Kolli msi_config->total_vectors, 4227a3aed0cSAnilkumar Kolli msi_config->total_vectors, 4235697a564SGovind Singh PCI_IRQ_MSI); 424ac6e7348SCarl Huang if (num_vectors == msi_config->total_vectors) { 4255b32b6ddSManikanta Pubbisetty set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); 426ac6e7348SCarl Huang } else { 427ac6e7348SCarl Huang num_vectors = pci_alloc_irq_vectors(ab_pci->pdev, 428ac6e7348SCarl Huang 1, 429ac6e7348SCarl Huang 1, 430ac6e7348SCarl Huang PCI_IRQ_MSI); 431ac6e7348SCarl Huang if (num_vectors < 0) { 432ac6e7348SCarl Huang ret = -EINVAL; 433ac6e7348SCarl Huang goto reset_msi_config; 4345697a564SGovind Singh } 4355b32b6ddSManikanta Pubbisetty clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); 4360cfaf224SManikanta Pubbisetty ab->pci.msi.config = &msi_config_one_msi; 437332c6562SKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "request one msi vector\n"); 438ac6e7348SCarl Huang } 439ac6e7348SCarl Huang ath11k_info(ab, "MSI vectors: %d\n", num_vectors); 440ac6e7348SCarl Huang 44196527d52SBaochen Qiang ath11k_pci_msi_disable(ab_pci); 4425697a564SGovind Singh 4435697a564SGovind Singh msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); 4445697a564SGovind Singh if (!msi_desc) { 4455697a564SGovind Singh ath11k_err(ab, "msi_desc is NULL!\n"); 4465697a564SGovind Singh ret = -EINVAL; 4475697a564SGovind Singh goto free_msi_vector; 4485697a564SGovind Singh } 4495697a564SGovind Singh 4500cfaf224SManikanta Pubbisetty ab->pci.msi.ep_base_data = msi_desc->msg.data; 4515697a564SGovind Singh 4520cfaf224SManikanta Pubbisetty pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, 4530cfaf224SManikanta Pubbisetty &ab->pci.msi.addr_lo); 4540cfaf224SManikanta Pubbisetty 4550cfaf224SManikanta Pubbisetty if (msi_desc->pci.msi_attrib.is_64) { 4560cfaf224SManikanta Pubbisetty pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI, 4570cfaf224SManikanta Pubbisetty &ab->pci.msi.addr_hi); 4580cfaf224SManikanta Pubbisetty } else { 4590cfaf224SManikanta Pubbisetty ab->pci.msi.addr_hi = 0; 4600cfaf224SManikanta Pubbisetty } 4610cfaf224SManikanta Pubbisetty 4620cfaf224SManikanta Pubbisetty ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab->pci.msi.ep_base_data); 4635697a564SGovind Singh 4645697a564SGovind Singh return 0; 4655697a564SGovind Singh 4665697a564SGovind Singh free_msi_vector: 4675697a564SGovind Singh pci_free_irq_vectors(ab_pci->pdev); 4685697a564SGovind Singh 469ac6e7348SCarl Huang reset_msi_config: 4705697a564SGovind Singh return ret; 4715697a564SGovind Singh } 4725697a564SGovind Singh 47396527d52SBaochen Qiang static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci) 4745697a564SGovind Singh { 4755697a564SGovind Singh pci_free_irq_vectors(ab_pci->pdev); 4765697a564SGovind Singh } 4775697a564SGovind Singh 47887b4072dSCarl Huang static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci) 47987b4072dSCarl Huang { 48087b4072dSCarl Huang struct msi_desc *msi_desc; 48187b4072dSCarl Huang 48287b4072dSCarl Huang msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); 48387b4072dSCarl Huang if (!msi_desc) { 48487b4072dSCarl Huang ath11k_err(ab_pci->ab, "msi_desc is NULL!\n"); 48587b4072dSCarl Huang pci_free_irq_vectors(ab_pci->pdev); 48687b4072dSCarl Huang return -EINVAL; 48787b4072dSCarl Huang } 48887b4072dSCarl Huang 4890cfaf224SManikanta Pubbisetty ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data; 49087b4072dSCarl Huang 491fc3b984aSKalle Valo ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "after request_irq msi_ep_base_data %d\n", 4920cfaf224SManikanta Pubbisetty ab_pci->ab->pci.msi.ep_base_data); 49387b4072dSCarl Huang 49487b4072dSCarl Huang return 0; 49587b4072dSCarl Huang } 49687b4072dSCarl Huang 4975762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev) 4985762613eSGovind Singh { 4995762613eSGovind Singh struct ath11k_base *ab = ab_pci->ab; 5005762613eSGovind Singh u16 device_id; 5015762613eSGovind Singh int ret = 0; 5025762613eSGovind Singh 5035762613eSGovind Singh pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); 5045762613eSGovind Singh if (device_id != ab_pci->dev_id) { 5055762613eSGovind Singh ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n", 5065762613eSGovind Singh device_id, ab_pci->dev_id); 5075762613eSGovind Singh ret = -EIO; 5085762613eSGovind Singh goto out; 5095762613eSGovind Singh } 5105762613eSGovind Singh 5115762613eSGovind Singh ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM); 5125762613eSGovind Singh if (ret) { 5135762613eSGovind Singh ath11k_err(ab, "failed to assign pci resource: %d\n", ret); 5145762613eSGovind Singh goto out; 5155762613eSGovind Singh } 5165762613eSGovind Singh 5175762613eSGovind Singh ret = pci_enable_device(pdev); 5185762613eSGovind Singh if (ret) { 5195762613eSGovind Singh ath11k_err(ab, "failed to enable pci device: %d\n", ret); 5205762613eSGovind Singh goto out; 5215762613eSGovind Singh } 5225762613eSGovind Singh 5235762613eSGovind Singh ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci"); 5245762613eSGovind Singh if (ret) { 5255762613eSGovind Singh ath11k_err(ab, "failed to request pci region: %d\n", ret); 5265762613eSGovind Singh goto disable_device; 5275762613eSGovind Singh } 5285762613eSGovind Singh 529923a1346SChristophe JAILLET ret = dma_set_mask_and_coherent(&pdev->dev, 530923a1346SChristophe JAILLET DMA_BIT_MASK(ATH11K_PCI_DMA_MASK)); 5315762613eSGovind Singh if (ret) { 5325762613eSGovind Singh ath11k_err(ab, "failed to set pci dma mask to %d: %d\n", 5335762613eSGovind Singh ATH11K_PCI_DMA_MASK, ret); 5345762613eSGovind Singh goto release_region; 5355762613eSGovind Singh } 5365762613eSGovind Singh 5375762613eSGovind Singh pci_set_master(pdev); 5385762613eSGovind Singh 5395762613eSGovind Singh ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM); 5405762613eSGovind Singh ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0); 5415762613eSGovind Singh if (!ab->mem) { 5425762613eSGovind Singh ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM); 5435762613eSGovind Singh ret = -EIO; 544f812e2a9SCai Huoqing goto release_region; 5455762613eSGovind Singh } 5465762613eSGovind Singh 547b42b3678SSriram R ab->mem_ce = ab->mem; 548b42b3678SSriram R 549cf036c41SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem); 5505762613eSGovind Singh return 0; 5515762613eSGovind Singh 5525762613eSGovind Singh release_region: 5535762613eSGovind Singh pci_release_region(pdev, ATH11K_PCI_BAR_NUM); 5545762613eSGovind Singh disable_device: 5555762613eSGovind Singh pci_disable_device(pdev); 5565762613eSGovind Singh out: 5575762613eSGovind Singh return ret; 5585762613eSGovind Singh } 5595762613eSGovind Singh 5605762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci) 5615762613eSGovind Singh { 5625762613eSGovind Singh struct ath11k_base *ab = ab_pci->ab; 5635762613eSGovind Singh struct pci_dev *pci_dev = ab_pci->pdev; 5645762613eSGovind Singh 5655762613eSGovind Singh pci_iounmap(pci_dev, ab->mem); 5665762613eSGovind Singh ab->mem = NULL; 5675762613eSGovind Singh pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM); 5685762613eSGovind Singh if (pci_is_enabled(pci_dev)) 5695762613eSGovind Singh pci_disable_device(pci_dev); 5705762613eSGovind Singh } 5715762613eSGovind Singh 572e9603f4bSCarl Huang static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci) 573e9603f4bSCarl Huang { 574e9603f4bSCarl Huang struct ath11k_base *ab = ab_pci->ab; 575e9603f4bSCarl Huang 576e9603f4bSCarl Huang pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL, 577e9603f4bSCarl Huang &ab_pci->link_ctl); 578e9603f4bSCarl Huang 579fc3b984aSKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n", 580e9603f4bSCarl Huang ab_pci->link_ctl, 581e9603f4bSCarl Huang u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S), 582e9603f4bSCarl Huang u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1)); 583e9603f4bSCarl Huang 584e9603f4bSCarl Huang /* disable L0s and L1 */ 5856c1b6bdbSIlpo Järvinen pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL, 5866c1b6bdbSIlpo Järvinen PCI_EXP_LNKCTL_ASPMC); 587e9603f4bSCarl Huang 588e9603f4bSCarl Huang set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags); 589e9603f4bSCarl Huang } 590e9603f4bSCarl Huang 5915b32b6ddSManikanta Pubbisetty static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci) 5925b32b6ddSManikanta Pubbisetty { 5935b32b6ddSManikanta Pubbisetty if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags)) 5946c1b6bdbSIlpo Järvinen pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL, 5956c1b6bdbSIlpo Järvinen PCI_EXP_LNKCTL_ASPMC, 5966c1b6bdbSIlpo Järvinen ab_pci->link_ctl & 5976c1b6bdbSIlpo Järvinen PCI_EXP_LNKCTL_ASPMC); 5985b32b6ddSManikanta Pubbisetty } 5995b32b6ddSManikanta Pubbisetty 6001399fb87SGovind Singh static int ath11k_pci_power_up(struct ath11k_base *ab) 6011399fb87SGovind Singh { 6021399fb87SGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 6031399fb87SGovind Singh int ret; 6041399fb87SGovind Singh 605a05bd851SCarl Huang ab_pci->register_window = 0; 6065b32b6ddSManikanta Pubbisetty clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); 607babb0cedSCarl Huang ath11k_pci_sw_reset(ab_pci->ab, true); 608f3c603d4SCarl Huang 609e9603f4bSCarl Huang /* Disable ASPM during firmware download due to problems switching 610e9603f4bSCarl Huang * to AMSS state. 611e9603f4bSCarl Huang */ 612e9603f4bSCarl Huang ath11k_pci_aspm_disable(ab_pci); 613e9603f4bSCarl Huang 61496527d52SBaochen Qiang ath11k_pci_msi_enable(ab_pci); 61596527d52SBaochen Qiang 6161399fb87SGovind Singh ret = ath11k_mhi_start(ab_pci); 6171399fb87SGovind Singh if (ret) { 6181399fb87SGovind Singh ath11k_err(ab, "failed to start mhi: %d\n", ret); 6191399fb87SGovind Singh return ret; 6201399fb87SGovind Singh } 6211399fb87SGovind Singh 62292c1858eSManikanta Pubbisetty if (ab->hw_params.static_window_map) 623480a7361SKarthikeyan Periyasamy ath11k_pci_select_static_window(ab_pci); 624480a7361SKarthikeyan Periyasamy 6251399fb87SGovind Singh return 0; 6261399fb87SGovind Singh } 6271399fb87SGovind Singh 6281399fb87SGovind Singh static void ath11k_pci_power_down(struct ath11k_base *ab) 6291399fb87SGovind Singh { 6301399fb87SGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 6311399fb87SGovind Singh 632e9603f4bSCarl Huang /* restore aspm in case firmware bootup fails */ 6335b32b6ddSManikanta Pubbisetty ath11k_pci_aspm_restore(ab_pci); 634e9603f4bSCarl Huang 635babb0cedSCarl Huang ath11k_pci_force_wake(ab_pci->ab); 63696527d52SBaochen Qiang 63796527d52SBaochen Qiang ath11k_pci_msi_disable(ab_pci); 63896527d52SBaochen Qiang 6391399fb87SGovind Singh ath11k_mhi_stop(ab_pci); 6405b32b6ddSManikanta Pubbisetty clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); 641babb0cedSCarl Huang ath11k_pci_sw_reset(ab_pci->ab, false); 6421399fb87SGovind Singh } 6431399fb87SGovind Singh 644fa5917e4SCarl Huang static int ath11k_pci_hif_suspend(struct ath11k_base *ab) 645fa5917e4SCarl Huang { 646fa5917e4SCarl Huang struct ath11k_pci *ar_pci = ath11k_pci_priv(ab); 647fa5917e4SCarl Huang 6483e80fcbcSKalle Valo return ath11k_mhi_suspend(ar_pci); 649fa5917e4SCarl Huang } 650fa5917e4SCarl Huang 651fa5917e4SCarl Huang static int ath11k_pci_hif_resume(struct ath11k_base *ab) 652fa5917e4SCarl Huang { 653fa5917e4SCarl Huang struct ath11k_pci *ar_pci = ath11k_pci_priv(ab); 654fa5917e4SCarl Huang 6553e80fcbcSKalle Valo return ath11k_mhi_resume(ar_pci); 656fa5917e4SCarl Huang } 657fa5917e4SCarl Huang 658d578ec2aSCarl Huang static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab) 659d578ec2aSCarl Huang { 660bbfdc5a7SManikanta Pubbisetty ath11k_pcic_ce_irqs_enable(ab); 661d578ec2aSCarl Huang } 662d578ec2aSCarl Huang 663d578ec2aSCarl Huang static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab) 664d578ec2aSCarl Huang { 665bbfdc5a7SManikanta Pubbisetty ath11k_pcic_ce_irq_disable_sync(ab); 6667f4beda2SGovind Singh } 6677f4beda2SGovind Singh 6685b32b6ddSManikanta Pubbisetty static int ath11k_pci_start(struct ath11k_base *ab) 6695b32b6ddSManikanta Pubbisetty { 6705b32b6ddSManikanta Pubbisetty struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 6715b32b6ddSManikanta Pubbisetty 6725b32b6ddSManikanta Pubbisetty /* TODO: for now don't restore ASPM in case of single MSI 6735b32b6ddSManikanta Pubbisetty * vector as MHI register reading in M2 causes system hang. 6745b32b6ddSManikanta Pubbisetty */ 6755b32b6ddSManikanta Pubbisetty if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags)) 6765b32b6ddSManikanta Pubbisetty ath11k_pci_aspm_restore(ab_pci); 6775b32b6ddSManikanta Pubbisetty else 6785b32b6ddSManikanta Pubbisetty ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n"); 6795b32b6ddSManikanta Pubbisetty 6805b32b6ddSManikanta Pubbisetty ath11k_pcic_start(ab); 6815b32b6ddSManikanta Pubbisetty 6825b32b6ddSManikanta Pubbisetty return 0; 6835b32b6ddSManikanta Pubbisetty } 6845b32b6ddSManikanta Pubbisetty 6857f4beda2SGovind Singh static const struct ath11k_hif_ops ath11k_pci_hif_ops = { 6865b32b6ddSManikanta Pubbisetty .start = ath11k_pci_start, 687bbfdc5a7SManikanta Pubbisetty .stop = ath11k_pcic_stop, 688bbfdc5a7SManikanta Pubbisetty .read32 = ath11k_pcic_read32, 689bbfdc5a7SManikanta Pubbisetty .write32 = ath11k_pcic_write32, 690876eb848SBaochen Qiang .read = ath11k_pcic_read, 6911399fb87SGovind Singh .power_down = ath11k_pci_power_down, 6921399fb87SGovind Singh .power_up = ath11k_pci_power_up, 693fa5917e4SCarl Huang .suspend = ath11k_pci_hif_suspend, 694fa5917e4SCarl Huang .resume = ath11k_pci_hif_resume, 695bbfdc5a7SManikanta Pubbisetty .irq_enable = ath11k_pcic_ext_irq_enable, 696bbfdc5a7SManikanta Pubbisetty .irq_disable = ath11k_pcic_ext_irq_disable, 697bbfdc5a7SManikanta Pubbisetty .get_msi_address = ath11k_pcic_get_msi_address, 6980cfaf224SManikanta Pubbisetty .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment, 699bbfdc5a7SManikanta Pubbisetty .map_service_to_pipe = ath11k_pcic_map_service_to_pipe, 700d578ec2aSCarl Huang .ce_irq_enable = ath11k_pci_hif_ce_irq_enable, 701d578ec2aSCarl Huang .ce_irq_disable = ath11k_pci_hif_ce_irq_disable, 702bbfdc5a7SManikanta Pubbisetty .get_ce_msi_idx = ath11k_pcic_get_ce_msi_idx, 7031399fb87SGovind Singh }; 7041399fb87SGovind Singh 7050fbf1957SBaochen Qiang static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor) 7060fbf1957SBaochen Qiang { 7070fbf1957SBaochen Qiang u32 soc_hw_version; 7080fbf1957SBaochen Qiang 709bbfdc5a7SManikanta Pubbisetty soc_hw_version = ath11k_pcic_read32(ab, TCSR_SOC_HW_VERSION); 7100fbf1957SBaochen Qiang *major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK, 7110fbf1957SBaochen Qiang soc_hw_version); 7120fbf1957SBaochen Qiang *minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK, 7130fbf1957SBaochen Qiang soc_hw_version); 7140fbf1957SBaochen Qiang 715fc3b984aSKalle Valo ath11k_dbg(ab, ATH11K_DBG_PCI, "tcsr_soc_hw_version major %d minor %d\n", 7160fbf1957SBaochen Qiang *major, *minor); 7170fbf1957SBaochen Qiang } 7180fbf1957SBaochen Qiang 7195b32b6ddSManikanta Pubbisetty static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci, 7205b32b6ddSManikanta Pubbisetty const struct cpumask *m) 7215b32b6ddSManikanta Pubbisetty { 7225b32b6ddSManikanta Pubbisetty if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab_pci->ab->dev_flags)) 7235b32b6ddSManikanta Pubbisetty return 0; 7245b32b6ddSManikanta Pubbisetty 7255b32b6ddSManikanta Pubbisetty return irq_set_affinity_hint(ab_pci->pdev->irq, m); 7265b32b6ddSManikanta Pubbisetty } 7275b32b6ddSManikanta Pubbisetty 7286e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev, 7296e0355afSGovind Singh const struct pci_device_id *pci_dev) 7306e0355afSGovind Singh { 7316e0355afSGovind Singh struct ath11k_base *ab; 7325762613eSGovind Singh struct ath11k_pci *ab_pci; 7336ac04bdcSAnilkumar Kolli u32 soc_hw_version_major, soc_hw_version_minor, addr; 734867f4eeeSManikanta Pubbisetty const struct ath11k_pci_ops *pci_ops; 7355762613eSGovind Singh int ret; 7366e0355afSGovind Singh 73792c1858eSManikanta Pubbisetty ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI); 73892c1858eSManikanta Pubbisetty 7396e0355afSGovind Singh if (!ab) { 7406e0355afSGovind Singh dev_err(&pdev->dev, "failed to allocate ath11k base\n"); 7416e0355afSGovind Singh return -ENOMEM; 7426e0355afSGovind Singh } 7436e0355afSGovind Singh 7446e0355afSGovind Singh ab->dev = &pdev->dev; 7456e0355afSGovind Singh pci_set_drvdata(pdev, ab); 7465762613eSGovind Singh ab_pci = ath11k_pci_priv(ab); 7475762613eSGovind Singh ab_pci->dev_id = pci_dev->device; 7485762613eSGovind Singh ab_pci->ab = ab; 7495697a564SGovind Singh ab_pci->pdev = pdev; 7507f4beda2SGovind Singh ab->hif.ops = &ath11k_pci_hif_ops; 751b43310e4SGovindaraj Saminathan ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; 7525762613eSGovind Singh pci_set_drvdata(pdev, ab); 753654e959aSGovind Singh spin_lock_init(&ab_pci->window_lock); 7545762613eSGovind Singh 7556ac04bdcSAnilkumar Kolli /* Set fixed_mem_region to true for platforms support reserved memory 7566ac04bdcSAnilkumar Kolli * from DT. If memory is reserved from DT for FW, ath11k driver need not 7576ac04bdcSAnilkumar Kolli * allocate memory. 7586ac04bdcSAnilkumar Kolli */ 7596ac04bdcSAnilkumar Kolli ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr); 7606ac04bdcSAnilkumar Kolli if (!ret) 7616ac04bdcSAnilkumar Kolli set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags); 7626ac04bdcSAnilkumar Kolli 7635762613eSGovind Singh ret = ath11k_pci_claim(ab_pci, pdev); 7645762613eSGovind Singh if (ret) { 7655762613eSGovind Singh ath11k_err(ab, "failed to claim device: %d\n", ret); 7665762613eSGovind Singh goto err_free_core; 7675762613eSGovind Singh } 7686e0355afSGovind Singh 769fc95d10aSWen Gong ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n", 770fc95d10aSWen Gong pdev->vendor, pdev->device, 771fc95d10aSWen Gong pdev->subsystem_vendor, pdev->subsystem_device); 772fc95d10aSWen Gong 773fc95d10aSWen Gong ab->id.vendor = pdev->vendor; 774fc95d10aSWen Gong ab->id.device = pdev->device; 775fc95d10aSWen Gong ab->id.subsystem_vendor = pdev->subsystem_vendor; 776fc95d10aSWen Gong ab->id.subsystem_device = pdev->subsystem_device; 777fc95d10aSWen Gong 77818ac1665SKalle Valo switch (pci_dev->device) { 77918ac1665SKalle Valo case QCA6390_DEVICE_ID: 7800fbf1957SBaochen Qiang ath11k_pci_read_hw_version(ab, &soc_hw_version_major, 7810fbf1957SBaochen Qiang &soc_hw_version_minor); 78218ac1665SKalle Valo switch (soc_hw_version_major) { 78318ac1665SKalle Valo case 2: 78418ac1665SKalle Valo ab->hw_rev = ATH11K_HW_QCA6390_HW20; 78518ac1665SKalle Valo break; 78618ac1665SKalle Valo default: 78718ac1665SKalle Valo dev_err(&pdev->dev, "Unsupported QCA6390 SOC hardware version: %d %d\n", 78818ac1665SKalle Valo soc_hw_version_major, soc_hw_version_minor); 78918ac1665SKalle Valo ret = -EOPNOTSUPP; 79018ac1665SKalle Valo goto err_pci_free_region; 79118ac1665SKalle Valo } 7925b32b6ddSManikanta Pubbisetty 793867f4eeeSManikanta Pubbisetty pci_ops = &ath11k_pci_ops_qca6390; 7944e809461SAnilkumar Kolli break; 7954e809461SAnilkumar Kolli case QCN9074_DEVICE_ID: 796867f4eeeSManikanta Pubbisetty pci_ops = &ath11k_pci_ops_qcn9074; 7974e809461SAnilkumar Kolli ab->hw_rev = ATH11K_HW_QCN9074_HW10; 79818ac1665SKalle Valo break; 7990fbf1957SBaochen Qiang case WCN6855_DEVICE_ID: 800fc95d10aSWen Gong ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD; 8010fbf1957SBaochen Qiang ath11k_pci_read_hw_version(ab, &soc_hw_version_major, 8020fbf1957SBaochen Qiang &soc_hw_version_minor); 8030fbf1957SBaochen Qiang switch (soc_hw_version_major) { 8040fbf1957SBaochen Qiang case 2: 805d1147a31SBaochen Qiang switch (soc_hw_version_minor) { 806d1147a31SBaochen Qiang case 0x00: 807d1147a31SBaochen Qiang case 0x01: 8080fbf1957SBaochen Qiang ab->hw_rev = ATH11K_HW_WCN6855_HW20; 8090fbf1957SBaochen Qiang break; 810d1147a31SBaochen Qiang case 0x10: 811d1147a31SBaochen Qiang case 0x11: 812d1147a31SBaochen Qiang ab->hw_rev = ATH11K_HW_WCN6855_HW21; 813d1147a31SBaochen Qiang break; 8140fbf1957SBaochen Qiang default: 815d1147a31SBaochen Qiang goto unsupported_wcn6855_soc; 816d1147a31SBaochen Qiang } 817d1147a31SBaochen Qiang break; 818d1147a31SBaochen Qiang default: 819d1147a31SBaochen Qiang unsupported_wcn6855_soc: 8200fbf1957SBaochen Qiang dev_err(&pdev->dev, "Unsupported WCN6855 SOC hardware version: %d %d\n", 8210fbf1957SBaochen Qiang soc_hw_version_major, soc_hw_version_minor); 8220fbf1957SBaochen Qiang ret = -EOPNOTSUPP; 8230fbf1957SBaochen Qiang goto err_pci_free_region; 8240fbf1957SBaochen Qiang } 8255b32b6ddSManikanta Pubbisetty 826867f4eeeSManikanta Pubbisetty pci_ops = &ath11k_pci_ops_qca6390; 8270fbf1957SBaochen Qiang break; 82818ac1665SKalle Valo default: 82918ac1665SKalle Valo dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n", 83018ac1665SKalle Valo pci_dev->device); 83118ac1665SKalle Valo ret = -EOPNOTSUPP; 83218ac1665SKalle Valo goto err_pci_free_region; 83318ac1665SKalle Valo } 83418ac1665SKalle Valo 835867f4eeeSManikanta Pubbisetty ret = ath11k_pcic_register_pci_ops(ab, pci_ops); 836867f4eeeSManikanta Pubbisetty if (ret) { 837867f4eeeSManikanta Pubbisetty ath11k_err(ab, "failed to register PCI ops: %d\n", ret); 838867f4eeeSManikanta Pubbisetty goto err_pci_free_region; 839867f4eeeSManikanta Pubbisetty } 840867f4eeeSManikanta Pubbisetty 8418d06b802SManikanta Pubbisetty ret = ath11k_pcic_init_msi_config(ab); 8428d06b802SManikanta Pubbisetty if (ret) { 8438d06b802SManikanta Pubbisetty ath11k_err(ab, "failed to init msi config: %d\n", ret); 8448d06b802SManikanta Pubbisetty goto err_pci_free_region; 8458d06b802SManikanta Pubbisetty } 8468d06b802SManikanta Pubbisetty 84796527d52SBaochen Qiang ret = ath11k_pci_alloc_msi(ab_pci); 8485697a564SGovind Singh if (ret) { 8495697a564SGovind Singh ath11k_err(ab, "failed to enable msi: %d\n", ret); 8505697a564SGovind Singh goto err_pci_free_region; 8515697a564SGovind Singh } 8525697a564SGovind Singh 853b8246f88SKalle Valo ret = ath11k_core_pre_init(ab); 854b8246f88SKalle Valo if (ret) 855b8246f88SKalle Valo goto err_pci_disable_msi; 856b8246f88SKalle Valo 857*d412d0efSBaochen Qiang ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0)); 858*d412d0efSBaochen Qiang if (ret) { 859*d412d0efSBaochen Qiang ath11k_err(ab, "failed to set irq affinity %d\n", ret); 860*d412d0efSBaochen Qiang goto err_pci_disable_msi; 861*d412d0efSBaochen Qiang } 862*d412d0efSBaochen Qiang 8631399fb87SGovind Singh ret = ath11k_mhi_register(ab_pci); 8641399fb87SGovind Singh if (ret) { 8651399fb87SGovind Singh ath11k_err(ab, "failed to register mhi: %d\n", ret); 866*d412d0efSBaochen Qiang goto err_irq_affinity_cleanup; 8671399fb87SGovind Singh } 8681399fb87SGovind Singh 8697f4beda2SGovind Singh ret = ath11k_hal_srng_init(ab); 8707f4beda2SGovind Singh if (ret) 8717f4beda2SGovind Singh goto err_mhi_unregister; 8727f4beda2SGovind Singh 8737f4beda2SGovind Singh ret = ath11k_ce_alloc_pipes(ab); 8747f4beda2SGovind Singh if (ret) { 8757f4beda2SGovind Singh ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret); 8767f4beda2SGovind Singh goto err_hal_srng_deinit; 8777f4beda2SGovind Singh } 8787f4beda2SGovind Singh 8797f4beda2SGovind Singh ath11k_pci_init_qmi_ce_config(ab); 8807f4beda2SGovind Singh 881bbfdc5a7SManikanta Pubbisetty ret = ath11k_pcic_config_irq(ab); 8827f4beda2SGovind Singh if (ret) { 8837f4beda2SGovind Singh ath11k_err(ab, "failed to config irq: %d\n", ret); 8847f4beda2SGovind Singh goto err_ce_free; 8857f4beda2SGovind Singh } 8867f4beda2SGovind Singh 88787b4072dSCarl Huang /* kernel may allocate a dummy vector before request_irq and 88887b4072dSCarl Huang * then allocate a real vector when request_irq is called. 88987b4072dSCarl Huang * So get msi_data here again to avoid spurious interrupt 89087b4072dSCarl Huang * as msi_data will configured to srngs. 89187b4072dSCarl Huang */ 89287b4072dSCarl Huang ret = ath11k_pci_config_msi_data(ab_pci); 89387b4072dSCarl Huang if (ret) { 89487b4072dSCarl Huang ath11k_err(ab, "failed to config msi_data: %d\n", ret); 895*d412d0efSBaochen Qiang goto err_free_irq; 89687b4072dSCarl Huang } 89787b4072dSCarl Huang 8987f4beda2SGovind Singh ret = ath11k_core_init(ab); 8997f4beda2SGovind Singh if (ret) { 9007f4beda2SGovind Singh ath11k_err(ab, "failed to init core: %d\n", ret); 901*d412d0efSBaochen Qiang goto err_free_irq; 9027f4beda2SGovind Singh } 903bdfc967bSAnilkumar Kolli ath11k_qmi_fwreset_from_cold_boot(ab); 9046e0355afSGovind Singh return 0; 9055762613eSGovind Singh 9067f4beda2SGovind Singh err_free_irq: 907bbfdc5a7SManikanta Pubbisetty ath11k_pcic_free_irq(ab); 9087f4beda2SGovind Singh 9097f4beda2SGovind Singh err_ce_free: 9107f4beda2SGovind Singh ath11k_ce_free_pipes(ab); 9117f4beda2SGovind Singh 9127f4beda2SGovind Singh err_hal_srng_deinit: 9137f4beda2SGovind Singh ath11k_hal_srng_deinit(ab); 9147f4beda2SGovind Singh 9157f4beda2SGovind Singh err_mhi_unregister: 9167f4beda2SGovind Singh ath11k_mhi_unregister(ab_pci); 9177f4beda2SGovind Singh 918*d412d0efSBaochen Qiang err_irq_affinity_cleanup: 919*d412d0efSBaochen Qiang ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); 920*d412d0efSBaochen Qiang 921b8246f88SKalle Valo err_pci_disable_msi: 92296527d52SBaochen Qiang ath11k_pci_free_msi(ab_pci); 923b8246f88SKalle Valo 9245697a564SGovind Singh err_pci_free_region: 9255697a564SGovind Singh ath11k_pci_free_region(ab_pci); 9265697a564SGovind Singh 9275762613eSGovind Singh err_free_core: 9285762613eSGovind Singh ath11k_core_free(ab); 9295697a564SGovind Singh 9305762613eSGovind Singh return ret; 9316e0355afSGovind Singh } 9326e0355afSGovind Singh 9336e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev) 9346e0355afSGovind Singh { 9356e0355afSGovind Singh struct ath11k_base *ab = pci_get_drvdata(pdev); 9365762613eSGovind Singh struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 9376e0355afSGovind Singh 9385b32b6ddSManikanta Pubbisetty ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); 939e94b0749SBaochen Qiang 94061a57e51SAnilkumar Kolli if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { 94161a57e51SAnilkumar Kolli ath11k_pci_power_down(ab); 94261a57e51SAnilkumar Kolli ath11k_debugfs_soc_destroy(ab); 94361a57e51SAnilkumar Kolli ath11k_qmi_deinit_service(ab); 94461a57e51SAnilkumar Kolli goto qmi_fail; 94561a57e51SAnilkumar Kolli } 94661a57e51SAnilkumar Kolli 9476e0355afSGovind Singh set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); 9486fbd8898SCarl Huang 9496fbd8898SCarl Huang ath11k_core_deinit(ab); 9506fbd8898SCarl Huang 95161a57e51SAnilkumar Kolli qmi_fail: 9521399fb87SGovind Singh ath11k_mhi_unregister(ab_pci); 9536fbd8898SCarl Huang 954bbfdc5a7SManikanta Pubbisetty ath11k_pcic_free_irq(ab); 95596527d52SBaochen Qiang ath11k_pci_free_msi(ab_pci); 9565762613eSGovind Singh ath11k_pci_free_region(ab_pci); 9576fbd8898SCarl Huang 9586fbd8898SCarl Huang ath11k_hal_srng_deinit(ab); 9596fbd8898SCarl Huang ath11k_ce_free_pipes(ab); 9606e0355afSGovind Singh ath11k_core_free(ab); 9616e0355afSGovind Singh } 9626e0355afSGovind Singh 9631399fb87SGovind Singh static void ath11k_pci_shutdown(struct pci_dev *pdev) 9641399fb87SGovind Singh { 9651399fb87SGovind Singh struct ath11k_base *ab = pci_get_drvdata(pdev); 9663bd0c696SJohan Hovold struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); 9671399fb87SGovind Singh 9683bd0c696SJohan Hovold ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); 9691399fb87SGovind Singh ath11k_pci_power_down(ab); 9701399fb87SGovind Singh } 9711399fb87SGovind Singh 972d1b0c338SCarl Huang static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev) 973d1b0c338SCarl Huang { 974d1b0c338SCarl Huang struct ath11k_base *ab = dev_get_drvdata(dev); 975d1b0c338SCarl Huang int ret; 976d1b0c338SCarl Huang 977b4f4c564SKalle Valo if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { 978b4f4c564SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci suspend as qmi is not initialised\n"); 979b4f4c564SKalle Valo return 0; 980b4f4c564SKalle Valo } 981b4f4c564SKalle Valo 982d1b0c338SCarl Huang ret = ath11k_core_suspend(ab); 983d1b0c338SCarl Huang if (ret) 984d1b0c338SCarl Huang ath11k_warn(ab, "failed to suspend core: %d\n", ret); 985d1b0c338SCarl Huang 9867c154308SLen Brown return 0; 987d1b0c338SCarl Huang } 988d1b0c338SCarl Huang 989d1b0c338SCarl Huang static __maybe_unused int ath11k_pci_pm_resume(struct device *dev) 990d1b0c338SCarl Huang { 991d1b0c338SCarl Huang struct ath11k_base *ab = dev_get_drvdata(dev); 992d1b0c338SCarl Huang int ret; 993d1b0c338SCarl Huang 994b4f4c564SKalle Valo if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { 995b4f4c564SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci resume as qmi is not initialised\n"); 996b4f4c564SKalle Valo return 0; 997b4f4c564SKalle Valo } 998b4f4c564SKalle Valo 999d1b0c338SCarl Huang ret = ath11k_core_resume(ab); 1000d1b0c338SCarl Huang if (ret) 1001d1b0c338SCarl Huang ath11k_warn(ab, "failed to resume core: %d\n", ret); 1002d1b0c338SCarl Huang 1003d1b0c338SCarl Huang return ret; 1004d1b0c338SCarl Huang } 1005d1b0c338SCarl Huang 1006d1b0c338SCarl Huang static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops, 1007d1b0c338SCarl Huang ath11k_pci_pm_suspend, 1008d1b0c338SCarl Huang ath11k_pci_pm_resume); 1009d1b0c338SCarl Huang 10106e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = { 10116e0355afSGovind Singh .name = "ath11k_pci", 10126e0355afSGovind Singh .id_table = ath11k_pci_id_table, 10136e0355afSGovind Singh .probe = ath11k_pci_probe, 10146e0355afSGovind Singh .remove = ath11k_pci_remove, 10151399fb87SGovind Singh .shutdown = ath11k_pci_shutdown, 1016d1b0c338SCarl Huang #ifdef CONFIG_PM 1017d1b0c338SCarl Huang .driver.pm = &ath11k_pci_pm_ops, 1018d1b0c338SCarl Huang #endif 10196e0355afSGovind Singh }; 10206e0355afSGovind Singh 10216e0355afSGovind Singh static int ath11k_pci_init(void) 10226e0355afSGovind Singh { 10236e0355afSGovind Singh int ret; 10246e0355afSGovind Singh 10256e0355afSGovind Singh ret = pci_register_driver(&ath11k_pci_driver); 10266e0355afSGovind Singh if (ret) 10276e0355afSGovind Singh pr_err("failed to register ath11k pci driver: %d\n", 10286e0355afSGovind Singh ret); 10296e0355afSGovind Singh 10306e0355afSGovind Singh return ret; 10316e0355afSGovind Singh } 10326e0355afSGovind Singh module_init(ath11k_pci_init); 10336e0355afSGovind Singh 10346e0355afSGovind Singh static void ath11k_pci_exit(void) 10356e0355afSGovind Singh { 10366e0355afSGovind Singh pci_unregister_driver(&ath11k_pci_driver); 10376e0355afSGovind Singh } 10386e0355afSGovind Singh 10396e0355afSGovind Singh module_exit(ath11k_pci_exit); 10406e0355afSGovind Singh 10415d7cf67fSAlan Stern MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11ax WLAN devices"); 10426e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL"); 10433dbd7fe7SDevin Bayer 104406c58473STakashi Iwai /* firmware files */ 104506c58473STakashi Iwai MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*"); 104606c58473STakashi Iwai MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*"); 104706c58473STakashi Iwai MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*"); 104806c58473STakashi Iwai MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*"); 1049