xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/pci.c (revision 5b32b6dd966338005671780c1df02327582c4be4)
16e0355afSGovind Singh // SPDX-License-Identifier: BSD-3-Clause-Clear
26e0355afSGovind Singh /*
36e0355afSGovind Singh  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4948171b5SManikanta Pubbisetty  * Copyright (c) 2021-2022, 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"
186e0355afSGovind Singh 
195762613eSGovind Singh #define ATH11K_PCI_BAR_NUM		0
205762613eSGovind Singh #define ATH11K_PCI_DMA_MASK		32
215762613eSGovind Singh 
2218ac1665SKalle Valo #define TCSR_SOC_HW_VERSION		0x0224
23d1147a31SBaochen Qiang #define TCSR_SOC_HW_VERSION_MAJOR_MASK	GENMASK(11, 8)
2418ac1665SKalle Valo #define TCSR_SOC_HW_VERSION_MINOR_MASK	GENMASK(7, 0)
2518ac1665SKalle Valo 
266e0355afSGovind Singh #define QCA6390_DEVICE_ID		0x1101
274e809461SAnilkumar Kolli #define QCN9074_DEVICE_ID		0x1104
280fbf1957SBaochen Qiang #define WCN6855_DEVICE_ID		0x1103
296e0355afSGovind Singh 
306e0355afSGovind Singh static const struct pci_device_id ath11k_pci_id_table[] = {
316e0355afSGovind Singh 	{ PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
320fbf1957SBaochen Qiang 	{ PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) },
3349f5b114SAnilkumar Kolli 	{ PCI_VDEVICE(QCOM, QCN9074_DEVICE_ID) },
346e0355afSGovind Singh 	{0}
356e0355afSGovind Singh };
366e0355afSGovind Singh 
376e0355afSGovind Singh MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
386e0355afSGovind Singh 
39*5b32b6ddSManikanta Pubbisetty static int ath11k_pci_bus_wake_up(struct ath11k_base *ab)
40*5b32b6ddSManikanta Pubbisetty {
41*5b32b6ddSManikanta Pubbisetty 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
42*5b32b6ddSManikanta Pubbisetty 
43*5b32b6ddSManikanta Pubbisetty 	return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
44*5b32b6ddSManikanta Pubbisetty }
45*5b32b6ddSManikanta Pubbisetty 
46*5b32b6ddSManikanta Pubbisetty static void ath11k_pci_bus_release(struct ath11k_base *ab)
47*5b32b6ddSManikanta Pubbisetty {
48*5b32b6ddSManikanta Pubbisetty 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
49*5b32b6ddSManikanta Pubbisetty 
50*5b32b6ddSManikanta Pubbisetty 	mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
51*5b32b6ddSManikanta Pubbisetty }
52*5b32b6ddSManikanta Pubbisetty 
53*5b32b6ddSManikanta Pubbisetty static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset)
54*5b32b6ddSManikanta Pubbisetty {
55*5b32b6ddSManikanta Pubbisetty 	struct ath11k_base *ab = ab_pci->ab;
56*5b32b6ddSManikanta Pubbisetty 
57*5b32b6ddSManikanta Pubbisetty 	u32 window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, offset);
58*5b32b6ddSManikanta Pubbisetty 
59*5b32b6ddSManikanta Pubbisetty 	lockdep_assert_held(&ab_pci->window_lock);
60*5b32b6ddSManikanta Pubbisetty 
61*5b32b6ddSManikanta Pubbisetty 	if (window != ab_pci->register_window) {
62*5b32b6ddSManikanta Pubbisetty 		iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,
63*5b32b6ddSManikanta Pubbisetty 			  ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
64*5b32b6ddSManikanta Pubbisetty 		ioread32(ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
65*5b32b6ddSManikanta Pubbisetty 		ab_pci->register_window = window;
66*5b32b6ddSManikanta Pubbisetty 	}
67*5b32b6ddSManikanta Pubbisetty }
68*5b32b6ddSManikanta Pubbisetty 
69*5b32b6ddSManikanta Pubbisetty static void
70*5b32b6ddSManikanta Pubbisetty ath11k_pci_window_write32(struct ath11k_base *ab, u32 offset, u32 value)
71*5b32b6ddSManikanta Pubbisetty {
72*5b32b6ddSManikanta Pubbisetty 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
73*5b32b6ddSManikanta Pubbisetty 	u32 window_start = ATH11K_PCI_WINDOW_START;
74*5b32b6ddSManikanta Pubbisetty 
75*5b32b6ddSManikanta Pubbisetty 	spin_lock_bh(&ab_pci->window_lock);
76*5b32b6ddSManikanta Pubbisetty 	ath11k_pci_select_window(ab_pci, offset);
77*5b32b6ddSManikanta Pubbisetty 	iowrite32(value, ab->mem + window_start +
78*5b32b6ddSManikanta Pubbisetty 		  (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
79*5b32b6ddSManikanta Pubbisetty 	spin_unlock_bh(&ab_pci->window_lock);
80*5b32b6ddSManikanta Pubbisetty }
81*5b32b6ddSManikanta Pubbisetty 
82*5b32b6ddSManikanta Pubbisetty static u32 ath11k_pci_window_read32(struct ath11k_base *ab, u32 offset)
83*5b32b6ddSManikanta Pubbisetty {
84*5b32b6ddSManikanta Pubbisetty 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
85*5b32b6ddSManikanta Pubbisetty 	u32 window_start = ATH11K_PCI_WINDOW_START;
86*5b32b6ddSManikanta Pubbisetty 	u32 val;
87*5b32b6ddSManikanta Pubbisetty 
88*5b32b6ddSManikanta Pubbisetty 	spin_lock_bh(&ab_pci->window_lock);
89*5b32b6ddSManikanta Pubbisetty 	ath11k_pci_select_window(ab_pci, offset);
90*5b32b6ddSManikanta Pubbisetty 	val = ioread32(ab->mem + window_start +
91*5b32b6ddSManikanta Pubbisetty 		       (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
92*5b32b6ddSManikanta Pubbisetty 	spin_unlock_bh(&ab_pci->window_lock);
93*5b32b6ddSManikanta Pubbisetty 
94*5b32b6ddSManikanta Pubbisetty 	return val;
95*5b32b6ddSManikanta Pubbisetty }
96*5b32b6ddSManikanta Pubbisetty 
97*5b32b6ddSManikanta Pubbisetty int ath11k_pci_get_msi_irq(struct ath11k_base *ab, unsigned int vector)
98*5b32b6ddSManikanta Pubbisetty {
99*5b32b6ddSManikanta Pubbisetty 	struct pci_dev *pci_dev = to_pci_dev(ab->dev);
100*5b32b6ddSManikanta Pubbisetty 
101*5b32b6ddSManikanta Pubbisetty 	return pci_irq_vector(pci_dev, vector);
102*5b32b6ddSManikanta Pubbisetty }
103*5b32b6ddSManikanta Pubbisetty 
104*5b32b6ddSManikanta Pubbisetty static const struct ath11k_pci_ops ath11k_pci_ops_qca6390 = {
105*5b32b6ddSManikanta Pubbisetty 	.wakeup = ath11k_pci_bus_wake_up,
106*5b32b6ddSManikanta Pubbisetty 	.release = ath11k_pci_bus_release,
107*5b32b6ddSManikanta Pubbisetty 	.get_msi_irq = ath11k_pci_get_msi_irq,
108*5b32b6ddSManikanta Pubbisetty 	.window_write32 = ath11k_pci_window_write32,
109*5b32b6ddSManikanta Pubbisetty 	.window_read32 = ath11k_pci_window_read32,
110*5b32b6ddSManikanta Pubbisetty };
111*5b32b6ddSManikanta Pubbisetty 
112*5b32b6ddSManikanta Pubbisetty static const struct ath11k_pci_ops ath11k_pci_ops_qcn9074 = {
113*5b32b6ddSManikanta Pubbisetty 	.get_msi_irq = ath11k_pci_get_msi_irq,
114*5b32b6ddSManikanta Pubbisetty 	.window_write32 = ath11k_pci_window_write32,
115*5b32b6ddSManikanta Pubbisetty 	.window_read32 = ath11k_pci_window_read32,
116*5b32b6ddSManikanta Pubbisetty };
117*5b32b6ddSManikanta Pubbisetty 
1181ff8ed78SGovind Singh static const struct ath11k_bus_params ath11k_pci_bus_params = {
1191ff8ed78SGovind Singh 	.mhi_support = true,
12056970454SGovind Singh 	.m3_fw_support = true,
1216eb6ea51SGovind Singh 	.fixed_bdf_addr = false,
1226eb6ea51SGovind Singh 	.fixed_mem_region = false,
1231ff8ed78SGovind Singh };
1241ff8ed78SGovind Singh 
125ac6e7348SCarl Huang static const struct ath11k_msi_config msi_config_one_msi = {
126ac6e7348SCarl Huang 	.total_vectors = 1,
127ac6e7348SCarl Huang 	.total_users = 4,
128ac6e7348SCarl Huang 	.users = (struct ath11k_msi_user[]) {
129ac6e7348SCarl Huang 		{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
130ac6e7348SCarl Huang 		{ .name = "CE", .num_vectors = 1, .base_vector = 0 },
131ac6e7348SCarl Huang 		{ .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
132ac6e7348SCarl Huang 		{ .name = "DP", .num_vectors = 1, .base_vector = 0 },
133ac6e7348SCarl Huang 	},
134ac6e7348SCarl Huang };
135ac6e7348SCarl Huang 
136480a7361SKarthikeyan Periyasamy static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci)
137480a7361SKarthikeyan Periyasamy {
138948171b5SManikanta Pubbisetty 	u32 umac_window;
139948171b5SManikanta Pubbisetty 	u32 ce_window;
140480a7361SKarthikeyan Periyasamy 	u32 window;
141480a7361SKarthikeyan Periyasamy 
142948171b5SManikanta Pubbisetty 	umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET);
143948171b5SManikanta Pubbisetty 	ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE);
144480a7361SKarthikeyan Periyasamy 	window = (umac_window << 12) | (ce_window << 6);
145480a7361SKarthikeyan Periyasamy 
146948171b5SManikanta Pubbisetty 	iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,
147948171b5SManikanta Pubbisetty 		  ab_pci->ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
148480a7361SKarthikeyan Periyasamy }
149480a7361SKarthikeyan Periyasamy 
150f3c603d4SCarl Huang static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
151f3c603d4SCarl Huang {
152f3c603d4SCarl Huang 	u32 val, delay;
153f3c603d4SCarl Huang 
154bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
155f3c603d4SCarl Huang 
156f3c603d4SCarl Huang 	val |= PCIE_SOC_GLOBAL_RESET_V;
157f3c603d4SCarl Huang 
158bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
159f3c603d4SCarl Huang 
160f3c603d4SCarl Huang 	/* TODO: exact time to sleep is uncertain */
161f3c603d4SCarl Huang 	delay = 10;
162f3c603d4SCarl Huang 	mdelay(delay);
163f3c603d4SCarl Huang 
164f3c603d4SCarl Huang 	/* Need to toggle V bit back otherwise stuck in reset status */
165f3c603d4SCarl Huang 	val &= ~PCIE_SOC_GLOBAL_RESET_V;
166f3c603d4SCarl Huang 
167bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
168f3c603d4SCarl Huang 
169f3c603d4SCarl Huang 	mdelay(delay);
170f3c603d4SCarl Huang 
171bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
172f3c603d4SCarl Huang 	if (val == 0xffffffff)
173f3c603d4SCarl Huang 		ath11k_warn(ab, "link down error during global reset\n");
174f3c603d4SCarl Huang }
175f3c603d4SCarl Huang 
176f3c603d4SCarl Huang static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
177f3c603d4SCarl Huang {
178f3c603d4SCarl Huang 	u32 val;
179f3c603d4SCarl Huang 
180f3c603d4SCarl Huang 	/* read cookie */
181bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR);
182f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val);
183f3c603d4SCarl Huang 
184bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
185f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
186f3c603d4SCarl Huang 
187f3c603d4SCarl Huang 	/* TODO: exact time to sleep is uncertain */
188f3c603d4SCarl Huang 	mdelay(10);
189f3c603d4SCarl Huang 
190f3c603d4SCarl Huang 	/* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from
191f3c603d4SCarl Huang 	 * continuing warm path and entering dead loop.
192f3c603d4SCarl Huang 	 */
193bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, WLAON_WARM_SW_ENTRY, 0);
194f3c603d4SCarl Huang 	mdelay(10);
195f3c603d4SCarl Huang 
196bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
197f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
198f3c603d4SCarl Huang 
199f3c603d4SCarl Huang 	/* A read clear register. clear the register to prevent
200f3c603d4SCarl Huang 	 * Q6 from entering wrong code path.
201f3c603d4SCarl Huang 	 */
202bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
203f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
204f3c603d4SCarl Huang }
205f3c603d4SCarl Huang 
20606999407SCarl Huang static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
20706999407SCarl Huang 				   u32 offset, u32 value, u32 mask)
20806999407SCarl Huang {
20906999407SCarl Huang 	u32 v;
21006999407SCarl Huang 	int i;
21106999407SCarl Huang 
212bbfdc5a7SManikanta Pubbisetty 	v = ath11k_pcic_read32(ab, offset);
21306999407SCarl Huang 	if ((v & mask) == value)
21406999407SCarl Huang 		return 0;
21506999407SCarl Huang 
21606999407SCarl Huang 	for (i = 0; i < 10; i++) {
217bbfdc5a7SManikanta Pubbisetty 		ath11k_pcic_write32(ab, offset, (v & ~mask) | value);
21806999407SCarl Huang 
219bbfdc5a7SManikanta Pubbisetty 		v = ath11k_pcic_read32(ab, offset);
22006999407SCarl Huang 		if ((v & mask) == value)
22106999407SCarl Huang 			return 0;
22206999407SCarl Huang 
22306999407SCarl Huang 		mdelay(2);
22406999407SCarl Huang 	}
22506999407SCarl Huang 
22606999407SCarl Huang 	ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n",
22706999407SCarl Huang 		    offset, v & mask, value);
22806999407SCarl Huang 
22906999407SCarl Huang 	return -ETIMEDOUT;
23006999407SCarl Huang }
23106999407SCarl Huang 
23206999407SCarl Huang static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
23306999407SCarl Huang {
23406999407SCarl Huang 	int ret;
23506999407SCarl Huang 
23606999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
2376fe6f68fSKarthikeyan Periyasamy 				      PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab),
23806999407SCarl Huang 				      PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
23906999407SCarl Huang 				      PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
24030d08503SDan Carpenter 	if (ret) {
24106999407SCarl Huang 		ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
24206999407SCarl Huang 		return ret;
24306999407SCarl Huang 	}
24406999407SCarl Huang 
24506999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
2466fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab),
2476fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG1_VAL,
2486fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG_MSK);
24930d08503SDan Carpenter 	if (ret) {
25006999407SCarl Huang 		ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
25106999407SCarl Huang 		return ret;
25206999407SCarl Huang 	}
25306999407SCarl Huang 
25406999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
2556fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab),
2566fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG2_VAL,
2576fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG_MSK);
25830d08503SDan Carpenter 	if (ret) {
25906999407SCarl Huang 		ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
26006999407SCarl Huang 		return ret;
26106999407SCarl Huang 	}
26206999407SCarl Huang 
26306999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
2646fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab),
2656fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG4_VAL,
2666fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG_MSK);
26730d08503SDan Carpenter 	if (ret) {
26806999407SCarl Huang 		ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
26906999407SCarl Huang 		return ret;
27006999407SCarl Huang 	}
27106999407SCarl Huang 
27206999407SCarl Huang 	return 0;
27306999407SCarl Huang }
27406999407SCarl Huang 
275babb0cedSCarl Huang static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
276babb0cedSCarl Huang {
277babb0cedSCarl Huang 	u32 val;
278babb0cedSCarl Huang 	int i;
279babb0cedSCarl Huang 
280bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);
281babb0cedSCarl Huang 
282babb0cedSCarl Huang 	/* PCIE link seems very unstable after the Hot Reset*/
283babb0cedSCarl Huang 	for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {
284babb0cedSCarl Huang 		if (val == 0xffffffff)
285babb0cedSCarl Huang 			mdelay(5);
286babb0cedSCarl Huang 
287bbfdc5a7SManikanta Pubbisetty 		ath11k_pcic_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);
288bbfdc5a7SManikanta Pubbisetty 		val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);
289babb0cedSCarl Huang 	}
290babb0cedSCarl Huang 
291babb0cedSCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
292babb0cedSCarl Huang 
293bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
294562934adSKalle Valo 	val |= GCC_GCC_PCIE_HOT_RST_VAL;
295bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
296bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
297babb0cedSCarl Huang 
298babb0cedSCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
299babb0cedSCarl Huang 
300babb0cedSCarl Huang 	mdelay(5);
301babb0cedSCarl Huang }
302babb0cedSCarl Huang 
303babb0cedSCarl Huang static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)
304babb0cedSCarl Huang {
305babb0cedSCarl Huang 	/* This is a WAR for PCIE Hotreset.
306babb0cedSCarl Huang 	 * When target receive Hotreset, but will set the interrupt.
307babb0cedSCarl Huang 	 * So when download SBL again, SBL will open Interrupt and
308babb0cedSCarl Huang 	 * receive it, and crash immediately.
309babb0cedSCarl Huang 	 */
310bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);
311babb0cedSCarl Huang }
312babb0cedSCarl Huang 
3130ccdf439SCarl Huang static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab)
3140ccdf439SCarl Huang {
3150ccdf439SCarl Huang 	u32 val;
3160ccdf439SCarl Huang 
317bbfdc5a7SManikanta Pubbisetty 	val = ath11k_pcic_read32(ab, WLAON_QFPROM_PWR_CTRL_REG);
3180ccdf439SCarl Huang 	val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK;
319bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val);
3200ccdf439SCarl Huang }
3210ccdf439SCarl Huang 
322f3c603d4SCarl Huang static void ath11k_pci_force_wake(struct ath11k_base *ab)
323f3c603d4SCarl Huang {
324bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
325f3c603d4SCarl Huang 	mdelay(5);
326f3c603d4SCarl Huang }
327f3c603d4SCarl Huang 
328babb0cedSCarl Huang static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
329f3c603d4SCarl Huang {
3308a0b899fSBaochen Qiang 	mdelay(100);
3318a0b899fSBaochen Qiang 
332babb0cedSCarl Huang 	if (power_on) {
333babb0cedSCarl Huang 		ath11k_pci_enable_ltssm(ab);
334babb0cedSCarl Huang 		ath11k_pci_clear_all_intrs(ab);
3350ccdf439SCarl Huang 		ath11k_pci_set_wlaon_pwr_ctrl(ab);
3365088df05SBaochen Qiang 		if (ab->hw_params.fix_l1ss)
33706999407SCarl Huang 			ath11k_pci_fix_l1ss(ab);
338babb0cedSCarl Huang 	}
339babb0cedSCarl Huang 
340f3c603d4SCarl Huang 	ath11k_mhi_clear_vector(ab);
3418a0b899fSBaochen Qiang 	ath11k_pci_clear_dbg_registers(ab);
342f3c603d4SCarl Huang 	ath11k_pci_soc_global_reset(ab);
343f3c603d4SCarl Huang 	ath11k_mhi_set_mhictrl_reset(ab);
344f3c603d4SCarl Huang }
345f3c603d4SCarl Huang 
3467f4beda2SGovind Singh static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
3477f4beda2SGovind Singh {
3487f4beda2SGovind Singh 	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
3497f4beda2SGovind Singh 
350967c1d11SAnilkumar Kolli 	cfg->tgt_ce = ab->hw_params.target_ce_config;
351967c1d11SAnilkumar Kolli 	cfg->tgt_ce_len = ab->hw_params.target_ce_count;
3527f4beda2SGovind Singh 
353967c1d11SAnilkumar Kolli 	cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
354967c1d11SAnilkumar Kolli 	cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
35516001e4bSAnilkumar Kolli 	ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
356e838c14aSCarl Huang 
357e838c14aSCarl Huang 	ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2,
358e838c14aSCarl Huang 				    &cfg->shadow_reg_v2_len);
3597f4beda2SGovind Singh }
3607f4beda2SGovind Singh 
36196527d52SBaochen Qiang static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable)
36296527d52SBaochen Qiang {
36396527d52SBaochen Qiang 	struct pci_dev *dev = ab_pci->pdev;
36496527d52SBaochen Qiang 	u16 control;
36596527d52SBaochen Qiang 
36696527d52SBaochen Qiang 	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
36796527d52SBaochen Qiang 
36896527d52SBaochen Qiang 	if (enable)
36996527d52SBaochen Qiang 		control |= PCI_MSI_FLAGS_ENABLE;
37096527d52SBaochen Qiang 	else
37196527d52SBaochen Qiang 		control &= ~PCI_MSI_FLAGS_ENABLE;
37296527d52SBaochen Qiang 
37396527d52SBaochen Qiang 	pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
37496527d52SBaochen Qiang }
37596527d52SBaochen Qiang 
37696527d52SBaochen Qiang static void ath11k_pci_msi_enable(struct ath11k_pci *ab_pci)
37796527d52SBaochen Qiang {
37896527d52SBaochen Qiang 	ath11k_pci_msi_config(ab_pci, true);
37996527d52SBaochen Qiang }
38096527d52SBaochen Qiang 
38196527d52SBaochen Qiang static void ath11k_pci_msi_disable(struct ath11k_pci *ab_pci)
38296527d52SBaochen Qiang {
38396527d52SBaochen Qiang 	ath11k_pci_msi_config(ab_pci, false);
38496527d52SBaochen Qiang }
38596527d52SBaochen Qiang 
38696527d52SBaochen Qiang static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
3875697a564SGovind Singh {
3885697a564SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
3890cfaf224SManikanta Pubbisetty 	const struct ath11k_msi_config *msi_config = ab->pci.msi.config;
3900cfaf224SManikanta Pubbisetty 	struct pci_dev *pci_dev = ab_pci->pdev;
3915697a564SGovind Singh 	struct msi_desc *msi_desc;
3925697a564SGovind Singh 	int num_vectors;
3935697a564SGovind Singh 	int ret;
3945697a564SGovind Singh 
3950cfaf224SManikanta Pubbisetty 	num_vectors = pci_alloc_irq_vectors(pci_dev,
3967a3aed0cSAnilkumar Kolli 					    msi_config->total_vectors,
3977a3aed0cSAnilkumar Kolli 					    msi_config->total_vectors,
3985697a564SGovind Singh 					    PCI_IRQ_MSI);
399ac6e7348SCarl Huang 	if (num_vectors == msi_config->total_vectors) {
400*5b32b6ddSManikanta Pubbisetty 		set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
401ac6e7348SCarl Huang 	} else {
402ac6e7348SCarl Huang 		num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
403ac6e7348SCarl Huang 						    1,
404ac6e7348SCarl Huang 						    1,
405ac6e7348SCarl Huang 						    PCI_IRQ_MSI);
406ac6e7348SCarl Huang 		if (num_vectors < 0) {
407ac6e7348SCarl Huang 			ret = -EINVAL;
408ac6e7348SCarl Huang 			goto reset_msi_config;
4095697a564SGovind Singh 		}
410*5b32b6ddSManikanta Pubbisetty 		clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
4110cfaf224SManikanta Pubbisetty 		ab->pci.msi.config = &msi_config_one_msi;
412ac6e7348SCarl Huang 		ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n");
413ac6e7348SCarl Huang 	}
414ac6e7348SCarl Huang 	ath11k_info(ab, "MSI vectors: %d\n", num_vectors);
415ac6e7348SCarl Huang 
41696527d52SBaochen Qiang 	ath11k_pci_msi_disable(ab_pci);
4175697a564SGovind Singh 
4185697a564SGovind Singh 	msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
4195697a564SGovind Singh 	if (!msi_desc) {
4205697a564SGovind Singh 		ath11k_err(ab, "msi_desc is NULL!\n");
4215697a564SGovind Singh 		ret = -EINVAL;
4225697a564SGovind Singh 		goto free_msi_vector;
4235697a564SGovind Singh 	}
4245697a564SGovind Singh 
4250cfaf224SManikanta Pubbisetty 	ab->pci.msi.ep_base_data = msi_desc->msg.data;
4265697a564SGovind Singh 
4270cfaf224SManikanta Pubbisetty 	pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
4280cfaf224SManikanta Pubbisetty 			      &ab->pci.msi.addr_lo);
4290cfaf224SManikanta Pubbisetty 
4300cfaf224SManikanta Pubbisetty 	if (msi_desc->pci.msi_attrib.is_64) {
4310cfaf224SManikanta Pubbisetty 		pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
4320cfaf224SManikanta Pubbisetty 				      &ab->pci.msi.addr_hi);
4330cfaf224SManikanta Pubbisetty 	} else {
4340cfaf224SManikanta Pubbisetty 		ab->pci.msi.addr_hi = 0;
4350cfaf224SManikanta Pubbisetty 	}
4360cfaf224SManikanta Pubbisetty 
4370cfaf224SManikanta Pubbisetty 	ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab->pci.msi.ep_base_data);
4385697a564SGovind Singh 
4395697a564SGovind Singh 	return 0;
4405697a564SGovind Singh 
4415697a564SGovind Singh free_msi_vector:
4425697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
4435697a564SGovind Singh 
444ac6e7348SCarl Huang reset_msi_config:
4455697a564SGovind Singh 	return ret;
4465697a564SGovind Singh }
4475697a564SGovind Singh 
44896527d52SBaochen Qiang static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci)
4495697a564SGovind Singh {
4505697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
4515697a564SGovind Singh }
4525697a564SGovind Singh 
45387b4072dSCarl Huang static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
45487b4072dSCarl Huang {
45587b4072dSCarl Huang 	struct msi_desc *msi_desc;
45687b4072dSCarl Huang 
45787b4072dSCarl Huang 	msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
45887b4072dSCarl Huang 	if (!msi_desc) {
45987b4072dSCarl Huang 		ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");
46087b4072dSCarl Huang 		pci_free_irq_vectors(ab_pci->pdev);
46187b4072dSCarl Huang 		return -EINVAL;
46287b4072dSCarl Huang 	}
46387b4072dSCarl Huang 
4640cfaf224SManikanta Pubbisetty 	ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data;
46587b4072dSCarl Huang 
46687b4072dSCarl Huang 	ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n",
4670cfaf224SManikanta Pubbisetty 		   ab_pci->ab->pci.msi.ep_base_data);
46887b4072dSCarl Huang 
46987b4072dSCarl Huang 	return 0;
47087b4072dSCarl Huang }
47187b4072dSCarl Huang 
4725762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
4735762613eSGovind Singh {
4745762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
4755762613eSGovind Singh 	u16 device_id;
4765762613eSGovind Singh 	int ret = 0;
4775762613eSGovind Singh 
4785762613eSGovind Singh 	pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
4795762613eSGovind Singh 	if (device_id != ab_pci->dev_id)  {
4805762613eSGovind Singh 		ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
4815762613eSGovind Singh 			   device_id, ab_pci->dev_id);
4825762613eSGovind Singh 		ret = -EIO;
4835762613eSGovind Singh 		goto out;
4845762613eSGovind Singh 	}
4855762613eSGovind Singh 
4865762613eSGovind Singh 	ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
4875762613eSGovind Singh 	if (ret) {
4885762613eSGovind Singh 		ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
4895762613eSGovind Singh 		goto out;
4905762613eSGovind Singh 	}
4915762613eSGovind Singh 
4925762613eSGovind Singh 	ret = pci_enable_device(pdev);
4935762613eSGovind Singh 	if (ret) {
4945762613eSGovind Singh 		ath11k_err(ab, "failed to enable pci device: %d\n", ret);
4955762613eSGovind Singh 		goto out;
4965762613eSGovind Singh 	}
4975762613eSGovind Singh 
4985762613eSGovind Singh 	ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
4995762613eSGovind Singh 	if (ret) {
5005762613eSGovind Singh 		ath11k_err(ab, "failed to request pci region: %d\n", ret);
5015762613eSGovind Singh 		goto disable_device;
5025762613eSGovind Singh 	}
5035762613eSGovind Singh 
504923a1346SChristophe JAILLET 	ret = dma_set_mask_and_coherent(&pdev->dev,
505923a1346SChristophe JAILLET 					DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
5065762613eSGovind Singh 	if (ret) {
5075762613eSGovind Singh 		ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
5085762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
5095762613eSGovind Singh 		goto release_region;
5105762613eSGovind Singh 	}
5115762613eSGovind Singh 
5125762613eSGovind Singh 	pci_set_master(pdev);
5135762613eSGovind Singh 
5145762613eSGovind Singh 	ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
5155762613eSGovind Singh 	ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
5165762613eSGovind Singh 	if (!ab->mem) {
5175762613eSGovind Singh 		ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
5185762613eSGovind Singh 		ret = -EIO;
5195762613eSGovind Singh 		goto clear_master;
5205762613eSGovind Singh 	}
5215762613eSGovind Singh 
5225762613eSGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
5235762613eSGovind Singh 	return 0;
5245762613eSGovind Singh 
5255762613eSGovind Singh clear_master:
5265762613eSGovind Singh 	pci_clear_master(pdev);
5275762613eSGovind Singh release_region:
5285762613eSGovind Singh 	pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
5295762613eSGovind Singh disable_device:
5305762613eSGovind Singh 	pci_disable_device(pdev);
5315762613eSGovind Singh out:
5325762613eSGovind Singh 	return ret;
5335762613eSGovind Singh }
5345762613eSGovind Singh 
5355762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
5365762613eSGovind Singh {
5375762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
5385762613eSGovind Singh 	struct pci_dev *pci_dev = ab_pci->pdev;
5395762613eSGovind Singh 
5405762613eSGovind Singh 	pci_iounmap(pci_dev, ab->mem);
5415762613eSGovind Singh 	ab->mem = NULL;
5425762613eSGovind Singh 	pci_clear_master(pci_dev);
5435762613eSGovind Singh 	pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
5445762613eSGovind Singh 	if (pci_is_enabled(pci_dev))
5455762613eSGovind Singh 		pci_disable_device(pci_dev);
5465762613eSGovind Singh }
5475762613eSGovind Singh 
548e9603f4bSCarl Huang static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
549e9603f4bSCarl Huang {
550e9603f4bSCarl Huang 	struct ath11k_base *ab = ab_pci->ab;
551e9603f4bSCarl Huang 
552e9603f4bSCarl Huang 	pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
553e9603f4bSCarl Huang 				  &ab_pci->link_ctl);
554e9603f4bSCarl Huang 
555e9603f4bSCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
556e9603f4bSCarl Huang 		   ab_pci->link_ctl,
557e9603f4bSCarl Huang 		   u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
558e9603f4bSCarl Huang 		   u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
559e9603f4bSCarl Huang 
560e9603f4bSCarl Huang 	/* disable L0s and L1 */
561e9603f4bSCarl Huang 	pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
562e9603f4bSCarl Huang 				   ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
563e9603f4bSCarl Huang 
564e9603f4bSCarl Huang 	set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
565e9603f4bSCarl Huang }
566e9603f4bSCarl Huang 
567*5b32b6ddSManikanta Pubbisetty static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
568*5b32b6ddSManikanta Pubbisetty {
569*5b32b6ddSManikanta Pubbisetty 	if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
570*5b32b6ddSManikanta Pubbisetty 		pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
571*5b32b6ddSManikanta Pubbisetty 					   ab_pci->link_ctl);
572*5b32b6ddSManikanta Pubbisetty }
573*5b32b6ddSManikanta Pubbisetty 
5741399fb87SGovind Singh static int ath11k_pci_power_up(struct ath11k_base *ab)
5751399fb87SGovind Singh {
5761399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
5771399fb87SGovind Singh 	int ret;
5781399fb87SGovind Singh 
579a05bd851SCarl Huang 	ab_pci->register_window = 0;
580*5b32b6ddSManikanta Pubbisetty 	clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
581babb0cedSCarl Huang 	ath11k_pci_sw_reset(ab_pci->ab, true);
582f3c603d4SCarl Huang 
583e9603f4bSCarl Huang 	/* Disable ASPM during firmware download due to problems switching
584e9603f4bSCarl Huang 	 * to AMSS state.
585e9603f4bSCarl Huang 	 */
586e9603f4bSCarl Huang 	ath11k_pci_aspm_disable(ab_pci);
587e9603f4bSCarl Huang 
58896527d52SBaochen Qiang 	ath11k_pci_msi_enable(ab_pci);
58996527d52SBaochen Qiang 
5901399fb87SGovind Singh 	ret = ath11k_mhi_start(ab_pci);
5911399fb87SGovind Singh 	if (ret) {
5921399fb87SGovind Singh 		ath11k_err(ab, "failed to start mhi: %d\n", ret);
5931399fb87SGovind Singh 		return ret;
5941399fb87SGovind Singh 	}
5951399fb87SGovind Singh 
596480a7361SKarthikeyan Periyasamy 	if (ab->bus_params.static_window_map)
597480a7361SKarthikeyan Periyasamy 		ath11k_pci_select_static_window(ab_pci);
598480a7361SKarthikeyan Periyasamy 
5991399fb87SGovind Singh 	return 0;
6001399fb87SGovind Singh }
6011399fb87SGovind Singh 
6021399fb87SGovind Singh static void ath11k_pci_power_down(struct ath11k_base *ab)
6031399fb87SGovind Singh {
6041399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
6051399fb87SGovind Singh 
606e9603f4bSCarl Huang 	/* restore aspm in case firmware bootup fails */
607*5b32b6ddSManikanta Pubbisetty 	ath11k_pci_aspm_restore(ab_pci);
608e9603f4bSCarl Huang 
609babb0cedSCarl Huang 	ath11k_pci_force_wake(ab_pci->ab);
61096527d52SBaochen Qiang 
61196527d52SBaochen Qiang 	ath11k_pci_msi_disable(ab_pci);
61296527d52SBaochen Qiang 
6131399fb87SGovind Singh 	ath11k_mhi_stop(ab_pci);
614*5b32b6ddSManikanta Pubbisetty 	clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
615babb0cedSCarl Huang 	ath11k_pci_sw_reset(ab_pci->ab, false);
6161399fb87SGovind Singh }
6171399fb87SGovind Singh 
618fa5917e4SCarl Huang static int ath11k_pci_hif_suspend(struct ath11k_base *ab)
619fa5917e4SCarl Huang {
620fa5917e4SCarl Huang 	struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
621fa5917e4SCarl Huang 
622fa5917e4SCarl Huang 	ath11k_mhi_suspend(ar_pci);
623fa5917e4SCarl Huang 
624fa5917e4SCarl Huang 	return 0;
625fa5917e4SCarl Huang }
626fa5917e4SCarl Huang 
627fa5917e4SCarl Huang static int ath11k_pci_hif_resume(struct ath11k_base *ab)
628fa5917e4SCarl Huang {
629fa5917e4SCarl Huang 	struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
630fa5917e4SCarl Huang 
631fa5917e4SCarl Huang 	ath11k_mhi_resume(ar_pci);
632fa5917e4SCarl Huang 
633fa5917e4SCarl Huang 	return 0;
634fa5917e4SCarl Huang }
635fa5917e4SCarl Huang 
636d578ec2aSCarl Huang static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab)
637d578ec2aSCarl Huang {
638bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_ce_irqs_enable(ab);
639d578ec2aSCarl Huang }
640d578ec2aSCarl Huang 
641d578ec2aSCarl Huang static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab)
642d578ec2aSCarl Huang {
643bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_ce_irq_disable_sync(ab);
6447f4beda2SGovind Singh }
6457f4beda2SGovind Singh 
646*5b32b6ddSManikanta Pubbisetty static int ath11k_pci_start(struct ath11k_base *ab)
647*5b32b6ddSManikanta Pubbisetty {
648*5b32b6ddSManikanta Pubbisetty 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
649*5b32b6ddSManikanta Pubbisetty 
650*5b32b6ddSManikanta Pubbisetty 	/* TODO: for now don't restore ASPM in case of single MSI
651*5b32b6ddSManikanta Pubbisetty 	 * vector as MHI register reading in M2 causes system hang.
652*5b32b6ddSManikanta Pubbisetty 	 */
653*5b32b6ddSManikanta Pubbisetty 	if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
654*5b32b6ddSManikanta Pubbisetty 		ath11k_pci_aspm_restore(ab_pci);
655*5b32b6ddSManikanta Pubbisetty 	else
656*5b32b6ddSManikanta Pubbisetty 		ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n");
657*5b32b6ddSManikanta Pubbisetty 
658*5b32b6ddSManikanta Pubbisetty 	ath11k_pcic_start(ab);
659*5b32b6ddSManikanta Pubbisetty 
660*5b32b6ddSManikanta Pubbisetty 	return 0;
661*5b32b6ddSManikanta Pubbisetty }
662*5b32b6ddSManikanta Pubbisetty 
6637f4beda2SGovind Singh static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
664*5b32b6ddSManikanta Pubbisetty 	.start = ath11k_pci_start,
665bbfdc5a7SManikanta Pubbisetty 	.stop = ath11k_pcic_stop,
666bbfdc5a7SManikanta Pubbisetty 	.read32 = ath11k_pcic_read32,
667bbfdc5a7SManikanta Pubbisetty 	.write32 = ath11k_pcic_write32,
6681399fb87SGovind Singh 	.power_down = ath11k_pci_power_down,
6691399fb87SGovind Singh 	.power_up = ath11k_pci_power_up,
670fa5917e4SCarl Huang 	.suspend = ath11k_pci_hif_suspend,
671fa5917e4SCarl Huang 	.resume = ath11k_pci_hif_resume,
672bbfdc5a7SManikanta Pubbisetty 	.irq_enable = ath11k_pcic_ext_irq_enable,
673bbfdc5a7SManikanta Pubbisetty 	.irq_disable = ath11k_pcic_ext_irq_disable,
674bbfdc5a7SManikanta Pubbisetty 	.get_msi_address =  ath11k_pcic_get_msi_address,
6750cfaf224SManikanta Pubbisetty 	.get_user_msi_vector = ath11k_pcic_get_user_msi_assignment,
676bbfdc5a7SManikanta Pubbisetty 	.map_service_to_pipe = ath11k_pcic_map_service_to_pipe,
677d578ec2aSCarl Huang 	.ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
678d578ec2aSCarl Huang 	.ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
679bbfdc5a7SManikanta Pubbisetty 	.get_ce_msi_idx = ath11k_pcic_get_ce_msi_idx,
6801399fb87SGovind Singh };
6811399fb87SGovind Singh 
6820fbf1957SBaochen Qiang static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)
6830fbf1957SBaochen Qiang {
6840fbf1957SBaochen Qiang 	u32 soc_hw_version;
6850fbf1957SBaochen Qiang 
686bbfdc5a7SManikanta Pubbisetty 	soc_hw_version = ath11k_pcic_read32(ab, TCSR_SOC_HW_VERSION);
6870fbf1957SBaochen Qiang 	*major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
6880fbf1957SBaochen Qiang 			   soc_hw_version);
6890fbf1957SBaochen Qiang 	*minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
6900fbf1957SBaochen Qiang 			   soc_hw_version);
6910fbf1957SBaochen Qiang 
6920fbf1957SBaochen Qiang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci tcsr_soc_hw_version major %d minor %d\n",
6930fbf1957SBaochen Qiang 		   *major, *minor);
6940fbf1957SBaochen Qiang }
6950fbf1957SBaochen Qiang 
696*5b32b6ddSManikanta Pubbisetty static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci,
697*5b32b6ddSManikanta Pubbisetty 					    const struct cpumask *m)
698*5b32b6ddSManikanta Pubbisetty {
699*5b32b6ddSManikanta Pubbisetty 	if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab_pci->ab->dev_flags))
700*5b32b6ddSManikanta Pubbisetty 		return 0;
701*5b32b6ddSManikanta Pubbisetty 
702*5b32b6ddSManikanta Pubbisetty 	return irq_set_affinity_hint(ab_pci->pdev->irq, m);
703*5b32b6ddSManikanta Pubbisetty }
704*5b32b6ddSManikanta Pubbisetty 
7056e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev,
7066e0355afSGovind Singh 			    const struct pci_device_id *pci_dev)
7076e0355afSGovind Singh {
7086e0355afSGovind Singh 	struct ath11k_base *ab;
7095762613eSGovind Singh 	struct ath11k_pci *ab_pci;
7106ac04bdcSAnilkumar Kolli 	u32 soc_hw_version_major, soc_hw_version_minor, addr;
7115762613eSGovind Singh 	int ret;
7126e0355afSGovind Singh 
7131ff8ed78SGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI,
7141ff8ed78SGovind Singh 			       &ath11k_pci_bus_params);
7156e0355afSGovind Singh 	if (!ab) {
7166e0355afSGovind Singh 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
7176e0355afSGovind Singh 		return -ENOMEM;
7186e0355afSGovind Singh 	}
7196e0355afSGovind Singh 
7206e0355afSGovind Singh 	ab->dev = &pdev->dev;
7216e0355afSGovind Singh 	pci_set_drvdata(pdev, ab);
7225762613eSGovind Singh 	ab_pci = ath11k_pci_priv(ab);
7235762613eSGovind Singh 	ab_pci->dev_id = pci_dev->device;
7245762613eSGovind Singh 	ab_pci->ab = ab;
7255697a564SGovind Singh 	ab_pci->pdev = pdev;
7267f4beda2SGovind Singh 	ab->hif.ops = &ath11k_pci_hif_ops;
7275762613eSGovind Singh 	pci_set_drvdata(pdev, ab);
728654e959aSGovind Singh 	spin_lock_init(&ab_pci->window_lock);
7295762613eSGovind Singh 
7306ac04bdcSAnilkumar Kolli 	/* Set fixed_mem_region to true for platforms support reserved memory
7316ac04bdcSAnilkumar Kolli 	 * from DT. If memory is reserved from DT for FW, ath11k driver need not
7326ac04bdcSAnilkumar Kolli 	 * allocate memory.
7336ac04bdcSAnilkumar Kolli 	 */
7346ac04bdcSAnilkumar Kolli 	ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr);
7356ac04bdcSAnilkumar Kolli 	if (!ret)
7366ac04bdcSAnilkumar Kolli 		set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags);
7376ac04bdcSAnilkumar Kolli 
7385762613eSGovind Singh 	ret = ath11k_pci_claim(ab_pci, pdev);
7395762613eSGovind Singh 	if (ret) {
7405762613eSGovind Singh 		ath11k_err(ab, "failed to claim device: %d\n", ret);
7415762613eSGovind Singh 		goto err_free_core;
7425762613eSGovind Singh 	}
7436e0355afSGovind Singh 
744fc95d10aSWen Gong 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n",
745fc95d10aSWen Gong 		   pdev->vendor, pdev->device,
746fc95d10aSWen Gong 		   pdev->subsystem_vendor, pdev->subsystem_device);
747fc95d10aSWen Gong 
748fc95d10aSWen Gong 	ab->id.vendor = pdev->vendor;
749fc95d10aSWen Gong 	ab->id.device = pdev->device;
750fc95d10aSWen Gong 	ab->id.subsystem_vendor = pdev->subsystem_vendor;
751fc95d10aSWen Gong 	ab->id.subsystem_device = pdev->subsystem_device;
752fc95d10aSWen Gong 
75318ac1665SKalle Valo 	switch (pci_dev->device) {
75418ac1665SKalle Valo 	case QCA6390_DEVICE_ID:
7550fbf1957SBaochen Qiang 		ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
7560fbf1957SBaochen Qiang 					   &soc_hw_version_minor);
75718ac1665SKalle Valo 		switch (soc_hw_version_major) {
75818ac1665SKalle Valo 		case 2:
75918ac1665SKalle Valo 			ab->hw_rev = ATH11K_HW_QCA6390_HW20;
76018ac1665SKalle Valo 			break;
76118ac1665SKalle Valo 		default:
76218ac1665SKalle Valo 			dev_err(&pdev->dev, "Unsupported QCA6390 SOC hardware version: %d %d\n",
76318ac1665SKalle Valo 				soc_hw_version_major, soc_hw_version_minor);
76418ac1665SKalle Valo 			ret = -EOPNOTSUPP;
76518ac1665SKalle Valo 			goto err_pci_free_region;
76618ac1665SKalle Valo 		}
767*5b32b6ddSManikanta Pubbisetty 
768*5b32b6ddSManikanta Pubbisetty 		ab->pci.ops = &ath11k_pci_ops_qca6390;
7694e809461SAnilkumar Kolli 		break;
7704e809461SAnilkumar Kolli 	case QCN9074_DEVICE_ID:
7714e809461SAnilkumar Kolli 		ab->bus_params.static_window_map = true;
772*5b32b6ddSManikanta Pubbisetty 		ab->pci.ops = &ath11k_pci_ops_qcn9074;
7734e809461SAnilkumar Kolli 		ab->hw_rev = ATH11K_HW_QCN9074_HW10;
77418ac1665SKalle Valo 		break;
7750fbf1957SBaochen Qiang 	case WCN6855_DEVICE_ID:
776fc95d10aSWen Gong 		ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD;
7770fbf1957SBaochen Qiang 		ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
7780fbf1957SBaochen Qiang 					   &soc_hw_version_minor);
7790fbf1957SBaochen Qiang 		switch (soc_hw_version_major) {
7800fbf1957SBaochen Qiang 		case 2:
781d1147a31SBaochen Qiang 			switch (soc_hw_version_minor) {
782d1147a31SBaochen Qiang 			case 0x00:
783d1147a31SBaochen Qiang 			case 0x01:
7840fbf1957SBaochen Qiang 				ab->hw_rev = ATH11K_HW_WCN6855_HW20;
7850fbf1957SBaochen Qiang 				break;
786d1147a31SBaochen Qiang 			case 0x10:
787d1147a31SBaochen Qiang 			case 0x11:
788d1147a31SBaochen Qiang 				ab->hw_rev = ATH11K_HW_WCN6855_HW21;
789d1147a31SBaochen Qiang 				break;
7900fbf1957SBaochen Qiang 			default:
791d1147a31SBaochen Qiang 				goto unsupported_wcn6855_soc;
792d1147a31SBaochen Qiang 			}
793d1147a31SBaochen Qiang 			break;
794d1147a31SBaochen Qiang 		default:
795d1147a31SBaochen Qiang unsupported_wcn6855_soc:
7960fbf1957SBaochen Qiang 			dev_err(&pdev->dev, "Unsupported WCN6855 SOC hardware version: %d %d\n",
7970fbf1957SBaochen Qiang 				soc_hw_version_major, soc_hw_version_minor);
7980fbf1957SBaochen Qiang 			ret = -EOPNOTSUPP;
7990fbf1957SBaochen Qiang 			goto err_pci_free_region;
8000fbf1957SBaochen Qiang 		}
801*5b32b6ddSManikanta Pubbisetty 
802*5b32b6ddSManikanta Pubbisetty 		ab->pci.ops = &ath11k_pci_ops_qca6390;
8030fbf1957SBaochen Qiang 		break;
80418ac1665SKalle Valo 	default:
80518ac1665SKalle Valo 		dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
80618ac1665SKalle Valo 			pci_dev->device);
80718ac1665SKalle Valo 		ret = -EOPNOTSUPP;
80818ac1665SKalle Valo 		goto err_pci_free_region;
80918ac1665SKalle Valo 	}
81018ac1665SKalle Valo 
8118d06b802SManikanta Pubbisetty 	ret = ath11k_pcic_init_msi_config(ab);
8128d06b802SManikanta Pubbisetty 	if (ret) {
8138d06b802SManikanta Pubbisetty 		ath11k_err(ab, "failed to init msi config: %d\n", ret);
8148d06b802SManikanta Pubbisetty 		goto err_pci_free_region;
8158d06b802SManikanta Pubbisetty 	}
8168d06b802SManikanta Pubbisetty 
81796527d52SBaochen Qiang 	ret = ath11k_pci_alloc_msi(ab_pci);
8185697a564SGovind Singh 	if (ret) {
8195697a564SGovind Singh 		ath11k_err(ab, "failed to enable msi: %d\n", ret);
8205697a564SGovind Singh 		goto err_pci_free_region;
8215697a564SGovind Singh 	}
8225697a564SGovind Singh 
823b8246f88SKalle Valo 	ret = ath11k_core_pre_init(ab);
824b8246f88SKalle Valo 	if (ret)
825b8246f88SKalle Valo 		goto err_pci_disable_msi;
826b8246f88SKalle Valo 
8271399fb87SGovind Singh 	ret = ath11k_mhi_register(ab_pci);
8281399fb87SGovind Singh 	if (ret) {
8291399fb87SGovind Singh 		ath11k_err(ab, "failed to register mhi: %d\n", ret);
8301399fb87SGovind Singh 		goto err_pci_disable_msi;
8311399fb87SGovind Singh 	}
8321399fb87SGovind Singh 
8337f4beda2SGovind Singh 	ret = ath11k_hal_srng_init(ab);
8347f4beda2SGovind Singh 	if (ret)
8357f4beda2SGovind Singh 		goto err_mhi_unregister;
8367f4beda2SGovind Singh 
8377f4beda2SGovind Singh 	ret = ath11k_ce_alloc_pipes(ab);
8387f4beda2SGovind Singh 	if (ret) {
8397f4beda2SGovind Singh 		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
8407f4beda2SGovind Singh 		goto err_hal_srng_deinit;
8417f4beda2SGovind Singh 	}
8427f4beda2SGovind Singh 
8437f4beda2SGovind Singh 	ath11k_pci_init_qmi_ce_config(ab);
8447f4beda2SGovind Singh 
845bbfdc5a7SManikanta Pubbisetty 	ret = ath11k_pcic_config_irq(ab);
8467f4beda2SGovind Singh 	if (ret) {
8477f4beda2SGovind Singh 		ath11k_err(ab, "failed to config irq: %d\n", ret);
8487f4beda2SGovind Singh 		goto err_ce_free;
8497f4beda2SGovind Singh 	}
8507f4beda2SGovind Singh 
851*5b32b6ddSManikanta Pubbisetty 	ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));
852*5b32b6ddSManikanta Pubbisetty 	if (ret) {
853*5b32b6ddSManikanta Pubbisetty 		ath11k_err(ab, "failed to set irq affinity %d\n", ret);
854*5b32b6ddSManikanta Pubbisetty 		goto err_free_irq;
855*5b32b6ddSManikanta Pubbisetty 	}
856*5b32b6ddSManikanta Pubbisetty 
85787b4072dSCarl Huang 	/* kernel may allocate a dummy vector before request_irq and
85887b4072dSCarl Huang 	 * then allocate a real vector when request_irq is called.
85987b4072dSCarl Huang 	 * So get msi_data here again to avoid spurious interrupt
86087b4072dSCarl Huang 	 * as msi_data will configured to srngs.
86187b4072dSCarl Huang 	 */
86287b4072dSCarl Huang 	ret = ath11k_pci_config_msi_data(ab_pci);
86387b4072dSCarl Huang 	if (ret) {
86487b4072dSCarl Huang 		ath11k_err(ab, "failed to config msi_data: %d\n", ret);
865*5b32b6ddSManikanta Pubbisetty 		goto err_irq_affinity_cleanup;
86687b4072dSCarl Huang 	}
86787b4072dSCarl Huang 
8687f4beda2SGovind Singh 	ret = ath11k_core_init(ab);
8697f4beda2SGovind Singh 	if (ret) {
8707f4beda2SGovind Singh 		ath11k_err(ab, "failed to init core: %d\n", ret);
871*5b32b6ddSManikanta Pubbisetty 		goto err_irq_affinity_cleanup;
8727f4beda2SGovind Singh 	}
8736e0355afSGovind Singh 	return 0;
8745762613eSGovind Singh 
875*5b32b6ddSManikanta Pubbisetty err_irq_affinity_cleanup:
876*5b32b6ddSManikanta Pubbisetty 	ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
877*5b32b6ddSManikanta Pubbisetty 
8787f4beda2SGovind Singh err_free_irq:
879bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_free_irq(ab);
8807f4beda2SGovind Singh 
8817f4beda2SGovind Singh err_ce_free:
8827f4beda2SGovind Singh 	ath11k_ce_free_pipes(ab);
8837f4beda2SGovind Singh 
8847f4beda2SGovind Singh err_hal_srng_deinit:
8857f4beda2SGovind Singh 	ath11k_hal_srng_deinit(ab);
8867f4beda2SGovind Singh 
8877f4beda2SGovind Singh err_mhi_unregister:
8887f4beda2SGovind Singh 	ath11k_mhi_unregister(ab_pci);
8897f4beda2SGovind Singh 
890b8246f88SKalle Valo err_pci_disable_msi:
89196527d52SBaochen Qiang 	ath11k_pci_free_msi(ab_pci);
892b8246f88SKalle Valo 
8935697a564SGovind Singh err_pci_free_region:
8945697a564SGovind Singh 	ath11k_pci_free_region(ab_pci);
8955697a564SGovind Singh 
8965762613eSGovind Singh err_free_core:
8975762613eSGovind Singh 	ath11k_core_free(ab);
8985697a564SGovind Singh 
8995762613eSGovind Singh 	return ret;
9006e0355afSGovind Singh }
9016e0355afSGovind Singh 
9026e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev)
9036e0355afSGovind Singh {
9046e0355afSGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
9055762613eSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
9066e0355afSGovind Singh 
907*5b32b6ddSManikanta Pubbisetty 	ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
908e94b0749SBaochen Qiang 
90961a57e51SAnilkumar Kolli 	if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
91061a57e51SAnilkumar Kolli 		ath11k_pci_power_down(ab);
91161a57e51SAnilkumar Kolli 		ath11k_debugfs_soc_destroy(ab);
91261a57e51SAnilkumar Kolli 		ath11k_qmi_deinit_service(ab);
91361a57e51SAnilkumar Kolli 		goto qmi_fail;
91461a57e51SAnilkumar Kolli 	}
91561a57e51SAnilkumar Kolli 
9166e0355afSGovind Singh 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
9176fbd8898SCarl Huang 
9186fbd8898SCarl Huang 	ath11k_core_deinit(ab);
9196fbd8898SCarl Huang 
92061a57e51SAnilkumar Kolli qmi_fail:
9211399fb87SGovind Singh 	ath11k_mhi_unregister(ab_pci);
9226fbd8898SCarl Huang 
923bbfdc5a7SManikanta Pubbisetty 	ath11k_pcic_free_irq(ab);
92496527d52SBaochen Qiang 	ath11k_pci_free_msi(ab_pci);
9255762613eSGovind Singh 	ath11k_pci_free_region(ab_pci);
9266fbd8898SCarl Huang 
9276fbd8898SCarl Huang 	ath11k_hal_srng_deinit(ab);
9286fbd8898SCarl Huang 	ath11k_ce_free_pipes(ab);
9296e0355afSGovind Singh 	ath11k_core_free(ab);
9306e0355afSGovind Singh }
9316e0355afSGovind Singh 
9321399fb87SGovind Singh static void ath11k_pci_shutdown(struct pci_dev *pdev)
9331399fb87SGovind Singh {
9341399fb87SGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
9351399fb87SGovind Singh 
9361399fb87SGovind Singh 	ath11k_pci_power_down(ab);
9371399fb87SGovind Singh }
9381399fb87SGovind Singh 
939d1b0c338SCarl Huang static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
940d1b0c338SCarl Huang {
941d1b0c338SCarl Huang 	struct ath11k_base *ab = dev_get_drvdata(dev);
942d1b0c338SCarl Huang 	int ret;
943d1b0c338SCarl Huang 
944b4f4c564SKalle Valo 	if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
945b4f4c564SKalle Valo 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci suspend as qmi is not initialised\n");
946b4f4c564SKalle Valo 		return 0;
947b4f4c564SKalle Valo 	}
948b4f4c564SKalle Valo 
949d1b0c338SCarl Huang 	ret = ath11k_core_suspend(ab);
950d1b0c338SCarl Huang 	if (ret)
951d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to suspend core: %d\n", ret);
952d1b0c338SCarl Huang 
953d1b0c338SCarl Huang 	return ret;
954d1b0c338SCarl Huang }
955d1b0c338SCarl Huang 
956d1b0c338SCarl Huang static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
957d1b0c338SCarl Huang {
958d1b0c338SCarl Huang 	struct ath11k_base *ab = dev_get_drvdata(dev);
959d1b0c338SCarl Huang 	int ret;
960d1b0c338SCarl Huang 
961b4f4c564SKalle Valo 	if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
962b4f4c564SKalle Valo 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci resume as qmi is not initialised\n");
963b4f4c564SKalle Valo 		return 0;
964b4f4c564SKalle Valo 	}
965b4f4c564SKalle Valo 
966d1b0c338SCarl Huang 	ret = ath11k_core_resume(ab);
967d1b0c338SCarl Huang 	if (ret)
968d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to resume core: %d\n", ret);
969d1b0c338SCarl Huang 
970d1b0c338SCarl Huang 	return ret;
971d1b0c338SCarl Huang }
972d1b0c338SCarl Huang 
973d1b0c338SCarl Huang static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
974d1b0c338SCarl Huang 			 ath11k_pci_pm_suspend,
975d1b0c338SCarl Huang 			 ath11k_pci_pm_resume);
976d1b0c338SCarl Huang 
9776e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = {
9786e0355afSGovind Singh 	.name = "ath11k_pci",
9796e0355afSGovind Singh 	.id_table = ath11k_pci_id_table,
9806e0355afSGovind Singh 	.probe = ath11k_pci_probe,
9816e0355afSGovind Singh 	.remove = ath11k_pci_remove,
9821399fb87SGovind Singh 	.shutdown = ath11k_pci_shutdown,
983d1b0c338SCarl Huang #ifdef CONFIG_PM
984d1b0c338SCarl Huang 	.driver.pm = &ath11k_pci_pm_ops,
985d1b0c338SCarl Huang #endif
9866e0355afSGovind Singh };
9876e0355afSGovind Singh 
9886e0355afSGovind Singh static int ath11k_pci_init(void)
9896e0355afSGovind Singh {
9906e0355afSGovind Singh 	int ret;
9916e0355afSGovind Singh 
9926e0355afSGovind Singh 	ret = pci_register_driver(&ath11k_pci_driver);
9936e0355afSGovind Singh 	if (ret)
9946e0355afSGovind Singh 		pr_err("failed to register ath11k pci driver: %d\n",
9956e0355afSGovind Singh 		       ret);
9966e0355afSGovind Singh 
9976e0355afSGovind Singh 	return ret;
9986e0355afSGovind Singh }
9996e0355afSGovind Singh module_init(ath11k_pci_init);
10006e0355afSGovind Singh 
10016e0355afSGovind Singh static void ath11k_pci_exit(void)
10026e0355afSGovind Singh {
10036e0355afSGovind Singh 	pci_unregister_driver(&ath11k_pci_driver);
10046e0355afSGovind Singh }
10056e0355afSGovind Singh 
10066e0355afSGovind Singh module_exit(ath11k_pci_exit);
10076e0355afSGovind Singh 
10086e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
10096e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL");
10103dbd7fe7SDevin Bayer 
10113dbd7fe7SDevin Bayer /* QCA639x 2.0 firmware files */
10123dbd7fe7SDevin Bayer MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE);
10133dbd7fe7SDevin Bayer MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE);
10143dbd7fe7SDevin Bayer MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE);
1015