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
ath11k_pci_bus_wake_up(struct ath11k_base * ab)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
ath11k_pci_bus_release(struct ath11k_base * ab)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
ath11k_pci_get_window_start(struct ath11k_base * ab,u32 offset)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
ath11k_pci_select_window(struct ath11k_pci * ab_pci,u32 offset)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
ath11k_pci_window_write32(struct ath11k_base * ab,u32 offset,u32 value)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
ath11k_pci_window_read32(struct ath11k_base * ab,u32 offset)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
ath11k_pci_get_msi_irq(struct ath11k_base * ab,unsigned int vector)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
ath11k_pci_select_static_window(struct ath11k_pci * ab_pci)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
ath11k_pci_soc_global_reset(struct ath11k_base * ab)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
ath11k_pci_clear_dbg_registers(struct ath11k_base * ab)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
ath11k_pci_set_link_reg(struct ath11k_base * ab,u32 offset,u32 value,u32 mask)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
ath11k_pci_fix_l1ss(struct ath11k_base * ab)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
ath11k_pci_enable_ltssm(struct ath11k_base * ab)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
ath11k_pci_clear_all_intrs(struct ath11k_base * ab)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
ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base * ab)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
ath11k_pci_force_wake(struct ath11k_base * ab)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
ath11k_pci_sw_reset(struct ath11k_base * ab,bool power_on)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
ath11k_pci_init_qmi_ce_config(struct ath11k_base * ab)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
ath11k_pci_msi_config(struct ath11k_pci * ab_pci,bool enable)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
ath11k_pci_msi_enable(struct ath11k_pci * ab_pci)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
ath11k_pci_msi_disable(struct ath11k_pci * ab_pci)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
ath11k_pci_alloc_msi(struct ath11k_pci * ab_pci)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
ath11k_pci_free_msi(struct ath11k_pci * ab_pci)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
ath11k_pci_config_msi_data(struct ath11k_pci * ab_pci)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
ath11k_pci_claim(struct ath11k_pci * ab_pci,struct pci_dev * pdev)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
ath11k_pci_free_region(struct ath11k_pci * ab_pci)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
ath11k_pci_aspm_disable(struct ath11k_pci * ab_pci)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
ath11k_pci_aspm_restore(struct ath11k_pci * ab_pci)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
ath11k_pci_power_up(struct ath11k_base * ab)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
ath11k_pci_power_down(struct ath11k_base * ab)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
ath11k_pci_hif_suspend(struct ath11k_base * ab)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
ath11k_pci_hif_resume(struct ath11k_base * ab)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
ath11k_pci_hif_ce_irq_enable(struct ath11k_base * ab)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
ath11k_pci_hif_ce_irq_disable(struct ath11k_base * ab)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
ath11k_pci_start(struct ath11k_base * ab)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
ath11k_pci_read_hw_version(struct ath11k_base * ab,u32 * major,u32 * minor)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
ath11k_pci_set_irq_affinity_hint(struct ath11k_pci * ab_pci,const struct cpumask * m)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
ath11k_pci_probe(struct pci_dev * pdev,const struct pci_device_id * pci_dev)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
ath11k_pci_remove(struct pci_dev * pdev)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
ath11k_pci_shutdown(struct pci_dev * pdev)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
ath11k_pci_pm_suspend(struct device * dev)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
ath11k_pci_pm_resume(struct device * dev)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
ath11k_pci_init(void)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
ath11k_pci_exit(void)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