xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/pci.c (revision 7dc67af063e3f0237c864504bb2188ada753b804)
16e0355afSGovind Singh // SPDX-License-Identifier: BSD-3-Clause-Clear
26e0355afSGovind Singh /*
36e0355afSGovind Singh  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
46e0355afSGovind Singh  */
56e0355afSGovind Singh 
66e0355afSGovind Singh #include <linux/module.h>
75697a564SGovind Singh #include <linux/msi.h>
86e0355afSGovind Singh #include <linux/pci.h>
96e0355afSGovind Singh 
105762613eSGovind Singh #include "pci.h"
116e0355afSGovind Singh #include "core.h"
121399fb87SGovind Singh #include "hif.h"
131399fb87SGovind Singh #include "mhi.h"
146e0355afSGovind Singh #include "debug.h"
156e0355afSGovind Singh 
165762613eSGovind Singh #define ATH11K_PCI_BAR_NUM		0
175762613eSGovind Singh #define ATH11K_PCI_DMA_MASK		32
185762613eSGovind Singh 
197f4beda2SGovind Singh #define ATH11K_PCI_IRQ_CE0_OFFSET		3
207f4beda2SGovind Singh 
21654e959aSGovind Singh #define WINDOW_ENABLE_BIT		0x40000000
22654e959aSGovind Singh #define WINDOW_REG_ADDRESS		0x310c
23654e959aSGovind Singh #define WINDOW_VALUE_MASK		GENMASK(24, 19)
24654e959aSGovind Singh #define WINDOW_START			0x80000
25654e959aSGovind Singh #define WINDOW_RANGE_MASK		GENMASK(18, 0)
26654e959aSGovind Singh 
2718ac1665SKalle Valo #define TCSR_SOC_HW_VERSION		0x0224
2818ac1665SKalle Valo #define TCSR_SOC_HW_VERSION_MAJOR_MASK	GENMASK(16, 8)
2918ac1665SKalle Valo #define TCSR_SOC_HW_VERSION_MINOR_MASK	GENMASK(7, 0)
3018ac1665SKalle Valo 
31a05bd851SCarl Huang /* BAR0 + 4k is always accessible, and no
32a05bd851SCarl Huang  * need to force wakeup.
33a05bd851SCarl Huang  * 4K - 32 = 0xFE0
34a05bd851SCarl Huang  */
35a05bd851SCarl Huang #define ACCESS_ALWAYS_OFF 0xFE0
36a05bd851SCarl Huang 
376e0355afSGovind Singh #define QCA6390_DEVICE_ID		0x1101
386e0355afSGovind Singh 
396e0355afSGovind Singh static const struct pci_device_id ath11k_pci_id_table[] = {
406e0355afSGovind Singh 	{ PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
416e0355afSGovind Singh 	{0}
426e0355afSGovind Singh };
436e0355afSGovind Singh 
446e0355afSGovind Singh MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
456e0355afSGovind Singh 
461ff8ed78SGovind Singh static const struct ath11k_bus_params ath11k_pci_bus_params = {
471ff8ed78SGovind Singh 	.mhi_support = true,
4856970454SGovind Singh 	.m3_fw_support = true,
496eb6ea51SGovind Singh 	.fixed_bdf_addr = false,
506eb6ea51SGovind Singh 	.fixed_mem_region = false,
511ff8ed78SGovind Singh };
521ff8ed78SGovind Singh 
537a3aed0cSAnilkumar Kolli static const struct ath11k_msi_config ath11k_msi_config[] = {
547a3aed0cSAnilkumar Kolli 	{
555697a564SGovind Singh 		.total_vectors = 32,
565697a564SGovind Singh 		.total_users = 4,
575697a564SGovind Singh 		.users = (struct ath11k_msi_user[]) {
585697a564SGovind Singh 			{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
595697a564SGovind Singh 			{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
605697a564SGovind Singh 			{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
615697a564SGovind Singh 			{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
625697a564SGovind Singh 		},
637a3aed0cSAnilkumar Kolli 	},
645697a564SGovind Singh };
655697a564SGovind Singh 
667f4beda2SGovind Singh static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
677f4beda2SGovind Singh 	"bhi",
687f4beda2SGovind Singh 	"mhi-er0",
697f4beda2SGovind Singh 	"mhi-er1",
707f4beda2SGovind Singh 	"ce0",
717f4beda2SGovind Singh 	"ce1",
727f4beda2SGovind Singh 	"ce2",
737f4beda2SGovind Singh 	"ce3",
747f4beda2SGovind Singh 	"ce4",
757f4beda2SGovind Singh 	"ce5",
767f4beda2SGovind Singh 	"ce6",
777f4beda2SGovind Singh 	"ce7",
787f4beda2SGovind Singh 	"ce8",
797f4beda2SGovind Singh 	"ce9",
807f4beda2SGovind Singh 	"ce10",
817f4beda2SGovind Singh 	"ce11",
827f4beda2SGovind Singh 	"host2wbm-desc-feed",
837f4beda2SGovind Singh 	"host2reo-re-injection",
847f4beda2SGovind Singh 	"host2reo-command",
857f4beda2SGovind Singh 	"host2rxdma-monitor-ring3",
867f4beda2SGovind Singh 	"host2rxdma-monitor-ring2",
877f4beda2SGovind Singh 	"host2rxdma-monitor-ring1",
887f4beda2SGovind Singh 	"reo2ost-exception",
897f4beda2SGovind Singh 	"wbm2host-rx-release",
907f4beda2SGovind Singh 	"reo2host-status",
917f4beda2SGovind Singh 	"reo2host-destination-ring4",
927f4beda2SGovind Singh 	"reo2host-destination-ring3",
937f4beda2SGovind Singh 	"reo2host-destination-ring2",
947f4beda2SGovind Singh 	"reo2host-destination-ring1",
957f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac3",
967f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac2",
977f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac1",
987f4beda2SGovind Singh 	"ppdu-end-interrupts-mac3",
997f4beda2SGovind Singh 	"ppdu-end-interrupts-mac2",
1007f4beda2SGovind Singh 	"ppdu-end-interrupts-mac1",
1017f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac3",
1027f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac2",
1037f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac1",
1047f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac3",
1057f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac2",
1067f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac1",
1077f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac3",
1087f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac2",
1097f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac1",
1107f4beda2SGovind Singh 	"host2tcl-input-ring4",
1117f4beda2SGovind Singh 	"host2tcl-input-ring3",
1127f4beda2SGovind Singh 	"host2tcl-input-ring2",
1137f4beda2SGovind Singh 	"host2tcl-input-ring1",
1147f4beda2SGovind Singh 	"wbm2host-tx-completions-ring3",
1157f4beda2SGovind Singh 	"wbm2host-tx-completions-ring2",
1167f4beda2SGovind Singh 	"wbm2host-tx-completions-ring1",
1177f4beda2SGovind Singh 	"tcl2host-status-ring",
1187f4beda2SGovind Singh };
1197f4beda2SGovind Singh 
120654e959aSGovind Singh static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset)
121654e959aSGovind Singh {
122654e959aSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
123654e959aSGovind Singh 
124654e959aSGovind Singh 	u32 window = FIELD_GET(WINDOW_VALUE_MASK, offset);
125654e959aSGovind Singh 
126654e959aSGovind Singh 	lockdep_assert_held(&ab_pci->window_lock);
127654e959aSGovind Singh 
128654e959aSGovind Singh 	if (window != ab_pci->register_window) {
129654e959aSGovind Singh 		iowrite32(WINDOW_ENABLE_BIT | window,
130654e959aSGovind Singh 			  ab->mem + WINDOW_REG_ADDRESS);
131f6fa37a4SCarl Huang 		ioread32(ab->mem + WINDOW_REG_ADDRESS);
132654e959aSGovind Singh 		ab_pci->register_window = window;
133654e959aSGovind Singh 	}
134654e959aSGovind Singh }
135654e959aSGovind Singh 
136480a7361SKarthikeyan Periyasamy static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci)
137480a7361SKarthikeyan Periyasamy {
138480a7361SKarthikeyan Periyasamy 	u32 umac_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET);
139480a7361SKarthikeyan Periyasamy 	u32 ce_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE);
140480a7361SKarthikeyan Periyasamy 	u32 window;
141480a7361SKarthikeyan Periyasamy 
142480a7361SKarthikeyan Periyasamy 	window = (umac_window << 12) | (ce_window << 6);
143480a7361SKarthikeyan Periyasamy 
144480a7361SKarthikeyan Periyasamy 	iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + WINDOW_REG_ADDRESS);
145480a7361SKarthikeyan Periyasamy }
146480a7361SKarthikeyan Periyasamy 
147480a7361SKarthikeyan Periyasamy static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab,
148480a7361SKarthikeyan Periyasamy 					      u32 offset)
149480a7361SKarthikeyan Periyasamy {
150480a7361SKarthikeyan Periyasamy 	u32 window_start;
151480a7361SKarthikeyan Periyasamy 
152480a7361SKarthikeyan Periyasamy 	/* If offset lies within DP register range, use 3rd window */
153480a7361SKarthikeyan Periyasamy 	if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK)
154480a7361SKarthikeyan Periyasamy 		window_start = 3 * WINDOW_START;
155480a7361SKarthikeyan Periyasamy 	/* If offset lies within CE register range, use 2nd window */
156480a7361SKarthikeyan Periyasamy 	else if ((offset ^ HAL_CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK)
157480a7361SKarthikeyan Periyasamy 		window_start = 2 * WINDOW_START;
158480a7361SKarthikeyan Periyasamy 	else
159480a7361SKarthikeyan Periyasamy 		window_start = WINDOW_START;
160480a7361SKarthikeyan Periyasamy 
161480a7361SKarthikeyan Periyasamy 	return window_start;
162480a7361SKarthikeyan Periyasamy }
163480a7361SKarthikeyan Periyasamy 
164f3c603d4SCarl Huang void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
165654e959aSGovind Singh {
166654e959aSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
167480a7361SKarthikeyan Periyasamy 	u32 window_start;
168654e959aSGovind Singh 
169a05bd851SCarl Huang 	/* for offset beyond BAR + 4K - 32, may
170a05bd851SCarl Huang 	 * need to wakeup MHI to access.
171a05bd851SCarl Huang 	 */
172a05bd851SCarl Huang 	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
173a05bd851SCarl Huang 	    offset >= ACCESS_ALWAYS_OFF)
174a05bd851SCarl Huang 		mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
175a05bd851SCarl Huang 
176654e959aSGovind Singh 	if (offset < WINDOW_START) {
177654e959aSGovind Singh 		iowrite32(value, ab->mem  + offset);
178654e959aSGovind Singh 	} else {
179480a7361SKarthikeyan Periyasamy 		if (ab->bus_params.static_window_map)
180480a7361SKarthikeyan Periyasamy 			window_start = ath11k_pci_get_window_start(ab, offset);
181480a7361SKarthikeyan Periyasamy 		else
182480a7361SKarthikeyan Periyasamy 			window_start = WINDOW_START;
183480a7361SKarthikeyan Periyasamy 
184480a7361SKarthikeyan Periyasamy 		if (window_start == WINDOW_START) {
185654e959aSGovind Singh 			spin_lock_bh(&ab_pci->window_lock);
186654e959aSGovind Singh 			ath11k_pci_select_window(ab_pci, offset);
187480a7361SKarthikeyan Periyasamy 			iowrite32(value, ab->mem + window_start +
188480a7361SKarthikeyan Periyasamy 				  (offset & WINDOW_RANGE_MASK));
189654e959aSGovind Singh 			spin_unlock_bh(&ab_pci->window_lock);
190480a7361SKarthikeyan Periyasamy 		} else {
191480a7361SKarthikeyan Periyasamy 			iowrite32(value, ab->mem + window_start +
192480a7361SKarthikeyan Periyasamy 				  (offset & WINDOW_RANGE_MASK));
193480a7361SKarthikeyan Periyasamy 		}
194654e959aSGovind Singh 	}
195a05bd851SCarl Huang 
196a05bd851SCarl Huang 	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
197a05bd851SCarl Huang 	    offset >= ACCESS_ALWAYS_OFF)
198a05bd851SCarl Huang 		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
199654e959aSGovind Singh }
200654e959aSGovind Singh 
201f3c603d4SCarl Huang u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
202654e959aSGovind Singh {
203654e959aSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
204480a7361SKarthikeyan Periyasamy 	u32 val, window_start;
205654e959aSGovind Singh 
206a05bd851SCarl Huang 	/* for offset beyond BAR + 4K - 32, may
207a05bd851SCarl Huang 	 * need to wakeup MHI to access.
208a05bd851SCarl Huang 	 */
209a05bd851SCarl Huang 	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
210a05bd851SCarl Huang 	    offset >= ACCESS_ALWAYS_OFF)
211a05bd851SCarl Huang 		mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
212a05bd851SCarl Huang 
213654e959aSGovind Singh 	if (offset < WINDOW_START) {
214654e959aSGovind Singh 		val = ioread32(ab->mem + offset);
215654e959aSGovind Singh 	} else {
216480a7361SKarthikeyan Periyasamy 		if (ab->bus_params.static_window_map)
217480a7361SKarthikeyan Periyasamy 			window_start = ath11k_pci_get_window_start(ab, offset);
218480a7361SKarthikeyan Periyasamy 		else
219480a7361SKarthikeyan Periyasamy 			window_start = WINDOW_START;
220480a7361SKarthikeyan Periyasamy 
221480a7361SKarthikeyan Periyasamy 		if (window_start == WINDOW_START) {
222654e959aSGovind Singh 			spin_lock_bh(&ab_pci->window_lock);
223654e959aSGovind Singh 			ath11k_pci_select_window(ab_pci, offset);
224480a7361SKarthikeyan Periyasamy 			val = ioread32(ab->mem + window_start +
225480a7361SKarthikeyan Periyasamy 				       (offset & WINDOW_RANGE_MASK));
226654e959aSGovind Singh 			spin_unlock_bh(&ab_pci->window_lock);
227480a7361SKarthikeyan Periyasamy 		} else {
228480a7361SKarthikeyan Periyasamy 			val = ioread32(ab->mem + window_start +
229480a7361SKarthikeyan Periyasamy 				       (offset & WINDOW_RANGE_MASK));
230480a7361SKarthikeyan Periyasamy 		}
231654e959aSGovind Singh 	}
232654e959aSGovind Singh 
233a05bd851SCarl Huang 	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
234a05bd851SCarl Huang 	    offset >= ACCESS_ALWAYS_OFF)
235a05bd851SCarl Huang 		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
236a05bd851SCarl Huang 
237654e959aSGovind Singh 	return val;
238654e959aSGovind Singh }
239654e959aSGovind Singh 
240f3c603d4SCarl Huang static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
241f3c603d4SCarl Huang {
242f3c603d4SCarl Huang 	u32 val, delay;
243f3c603d4SCarl Huang 
244f3c603d4SCarl Huang 	val = ath11k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
245f3c603d4SCarl Huang 
246f3c603d4SCarl Huang 	val |= PCIE_SOC_GLOBAL_RESET_V;
247f3c603d4SCarl Huang 
248f3c603d4SCarl Huang 	ath11k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
249f3c603d4SCarl Huang 
250f3c603d4SCarl Huang 	/* TODO: exact time to sleep is uncertain */
251f3c603d4SCarl Huang 	delay = 10;
252f3c603d4SCarl Huang 	mdelay(delay);
253f3c603d4SCarl Huang 
254f3c603d4SCarl Huang 	/* Need to toggle V bit back otherwise stuck in reset status */
255f3c603d4SCarl Huang 	val &= ~PCIE_SOC_GLOBAL_RESET_V;
256f3c603d4SCarl Huang 
257f3c603d4SCarl Huang 	ath11k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
258f3c603d4SCarl Huang 
259f3c603d4SCarl Huang 	mdelay(delay);
260f3c603d4SCarl Huang 
261f3c603d4SCarl Huang 	val = ath11k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
262f3c603d4SCarl Huang 	if (val == 0xffffffff)
263f3c603d4SCarl Huang 		ath11k_warn(ab, "link down error during global reset\n");
264f3c603d4SCarl Huang }
265f3c603d4SCarl Huang 
266f3c603d4SCarl Huang static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
267f3c603d4SCarl Huang {
268f3c603d4SCarl Huang 	u32 val;
269f3c603d4SCarl Huang 
270f3c603d4SCarl Huang 	/* read cookie */
271f3c603d4SCarl Huang 	val = ath11k_pci_read32(ab, PCIE_Q6_COOKIE_ADDR);
272f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val);
273f3c603d4SCarl Huang 
274f3c603d4SCarl Huang 	val = ath11k_pci_read32(ab, WLAON_WARM_SW_ENTRY);
275f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
276f3c603d4SCarl Huang 
277f3c603d4SCarl Huang 	/* TODO: exact time to sleep is uncertain */
278f3c603d4SCarl Huang 	mdelay(10);
279f3c603d4SCarl Huang 
280f3c603d4SCarl Huang 	/* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from
281f3c603d4SCarl Huang 	 * continuing warm path and entering dead loop.
282f3c603d4SCarl Huang 	 */
283f3c603d4SCarl Huang 	ath11k_pci_write32(ab, WLAON_WARM_SW_ENTRY, 0);
284f3c603d4SCarl Huang 	mdelay(10);
285f3c603d4SCarl Huang 
286f3c603d4SCarl Huang 	val = ath11k_pci_read32(ab, WLAON_WARM_SW_ENTRY);
287f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
288f3c603d4SCarl Huang 
289f3c603d4SCarl Huang 	/* A read clear register. clear the register to prevent
290f3c603d4SCarl Huang 	 * Q6 from entering wrong code path.
291f3c603d4SCarl Huang 	 */
292f3c603d4SCarl Huang 	val = ath11k_pci_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
293f3c603d4SCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
294f3c603d4SCarl Huang }
295f3c603d4SCarl Huang 
29606999407SCarl Huang static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
29706999407SCarl Huang 				   u32 offset, u32 value, u32 mask)
29806999407SCarl Huang {
29906999407SCarl Huang 	u32 v;
30006999407SCarl Huang 	int i;
30106999407SCarl Huang 
30206999407SCarl Huang 	v = ath11k_pci_read32(ab, offset);
30306999407SCarl Huang 	if ((v & mask) == value)
30406999407SCarl Huang 		return 0;
30506999407SCarl Huang 
30606999407SCarl Huang 	for (i = 0; i < 10; i++) {
30706999407SCarl Huang 		ath11k_pci_write32(ab, offset, (v & ~mask) | value);
30806999407SCarl Huang 
30906999407SCarl Huang 		v = ath11k_pci_read32(ab, offset);
31006999407SCarl Huang 		if ((v & mask) == value)
31106999407SCarl Huang 			return 0;
31206999407SCarl Huang 
31306999407SCarl Huang 		mdelay(2);
31406999407SCarl Huang 	}
31506999407SCarl Huang 
31606999407SCarl Huang 	ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n",
31706999407SCarl Huang 		    offset, v & mask, value);
31806999407SCarl Huang 
31906999407SCarl Huang 	return -ETIMEDOUT;
32006999407SCarl Huang }
32106999407SCarl Huang 
32206999407SCarl Huang static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
32306999407SCarl Huang {
32406999407SCarl Huang 	int ret;
32506999407SCarl Huang 
32606999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
3276fe6f68fSKarthikeyan Periyasamy 				      PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab),
32806999407SCarl Huang 				      PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
32906999407SCarl Huang 				      PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
33030d08503SDan Carpenter 	if (ret) {
33106999407SCarl Huang 		ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
33206999407SCarl Huang 		return ret;
33306999407SCarl Huang 	}
33406999407SCarl Huang 
33506999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
3366fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab),
3376fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG1_VAL,
3386fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG_MSK);
33930d08503SDan Carpenter 	if (ret) {
34006999407SCarl Huang 		ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
34106999407SCarl Huang 		return ret;
34206999407SCarl Huang 	}
34306999407SCarl Huang 
34406999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
3456fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab),
3466fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG2_VAL,
3476fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG_MSK);
34830d08503SDan Carpenter 	if (ret) {
34906999407SCarl Huang 		ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
35006999407SCarl Huang 		return ret;
35106999407SCarl Huang 	}
35206999407SCarl Huang 
35306999407SCarl Huang 	ret = ath11k_pci_set_link_reg(ab,
3546fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab),
3556fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG4_VAL,
3566fe6f68fSKarthikeyan Periyasamy 				      PCIE_PCS_OSC_DTCT_CONFIG_MSK);
35730d08503SDan Carpenter 	if (ret) {
35806999407SCarl Huang 		ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
35906999407SCarl Huang 		return ret;
36006999407SCarl Huang 	}
36106999407SCarl Huang 
36206999407SCarl Huang 	return 0;
36306999407SCarl Huang }
36406999407SCarl Huang 
365babb0cedSCarl Huang static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
366babb0cedSCarl Huang {
367babb0cedSCarl Huang 	u32 val;
368babb0cedSCarl Huang 	int i;
369babb0cedSCarl Huang 
370babb0cedSCarl Huang 	val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
371babb0cedSCarl Huang 
372babb0cedSCarl Huang 	/* PCIE link seems very unstable after the Hot Reset*/
373babb0cedSCarl Huang 	for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {
374babb0cedSCarl Huang 		if (val == 0xffffffff)
375babb0cedSCarl Huang 			mdelay(5);
376babb0cedSCarl Huang 
377babb0cedSCarl Huang 		ath11k_pci_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);
378babb0cedSCarl Huang 		val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
379babb0cedSCarl Huang 	}
380babb0cedSCarl Huang 
381babb0cedSCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
382babb0cedSCarl Huang 
383babb0cedSCarl Huang 	val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
384562934adSKalle Valo 	val |= GCC_GCC_PCIE_HOT_RST_VAL;
385babb0cedSCarl Huang 	ath11k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
386babb0cedSCarl Huang 	val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
387babb0cedSCarl Huang 
388babb0cedSCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
389babb0cedSCarl Huang 
390babb0cedSCarl Huang 	mdelay(5);
391babb0cedSCarl Huang }
392babb0cedSCarl Huang 
393babb0cedSCarl Huang static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)
394babb0cedSCarl Huang {
395babb0cedSCarl Huang 	/* This is a WAR for PCIE Hotreset.
396babb0cedSCarl Huang 	 * When target receive Hotreset, but will set the interrupt.
397babb0cedSCarl Huang 	 * So when download SBL again, SBL will open Interrupt and
398babb0cedSCarl Huang 	 * receive it, and crash immediately.
399babb0cedSCarl Huang 	 */
400babb0cedSCarl Huang 	ath11k_pci_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);
401babb0cedSCarl Huang }
402babb0cedSCarl Huang 
4030ccdf439SCarl Huang static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab)
4040ccdf439SCarl Huang {
4050ccdf439SCarl Huang 	u32 val;
4060ccdf439SCarl Huang 
4070ccdf439SCarl Huang 	val = ath11k_pci_read32(ab, WLAON_QFPROM_PWR_CTRL_REG);
4080ccdf439SCarl Huang 	val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK;
4090ccdf439SCarl Huang 	ath11k_pci_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val);
4100ccdf439SCarl Huang }
4110ccdf439SCarl Huang 
412f3c603d4SCarl Huang static void ath11k_pci_force_wake(struct ath11k_base *ab)
413f3c603d4SCarl Huang {
414f3c603d4SCarl Huang 	ath11k_pci_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
415f3c603d4SCarl Huang 	mdelay(5);
416f3c603d4SCarl Huang }
417f3c603d4SCarl Huang 
418babb0cedSCarl Huang static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
419f3c603d4SCarl Huang {
420babb0cedSCarl Huang 	if (power_on) {
421babb0cedSCarl Huang 		ath11k_pci_enable_ltssm(ab);
422babb0cedSCarl Huang 		ath11k_pci_clear_all_intrs(ab);
4230ccdf439SCarl Huang 		ath11k_pci_set_wlaon_pwr_ctrl(ab);
42406999407SCarl Huang 		ath11k_pci_fix_l1ss(ab);
425babb0cedSCarl Huang 	}
426babb0cedSCarl Huang 
427f3c603d4SCarl Huang 	ath11k_mhi_clear_vector(ab);
428f3c603d4SCarl Huang 	ath11k_pci_soc_global_reset(ab);
429f3c603d4SCarl Huang 	ath11k_mhi_set_mhictrl_reset(ab);
430f3c603d4SCarl Huang 	ath11k_pci_clear_dbg_registers(ab);
431f3c603d4SCarl Huang }
432f3c603d4SCarl Huang 
4331399fb87SGovind Singh int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
4341399fb87SGovind Singh {
4351399fb87SGovind Singh 	struct pci_dev *pci_dev = to_pci_dev(dev);
4361399fb87SGovind Singh 
4371399fb87SGovind Singh 	return pci_irq_vector(pci_dev, vector);
4381399fb87SGovind Singh }
4391399fb87SGovind Singh 
440c4eacabeSGovind Singh static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
441c4eacabeSGovind Singh 				       u32 *msi_addr_hi)
442c4eacabeSGovind Singh {
443e8e55d89SAnilkumar Kolli 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
444c4eacabeSGovind Singh 	struct pci_dev *pci_dev = to_pci_dev(ab->dev);
445c4eacabeSGovind Singh 
446c4eacabeSGovind Singh 	pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
447c4eacabeSGovind Singh 			      msi_addr_lo);
448c4eacabeSGovind Singh 
449e8e55d89SAnilkumar Kolli 	if (test_bit(ATH11K_PCI_FLAG_IS_MSI_64, &ab_pci->flags)) {
450c4eacabeSGovind Singh 		pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
451c4eacabeSGovind Singh 				      msi_addr_hi);
452e8e55d89SAnilkumar Kolli 	} else {
453e8e55d89SAnilkumar Kolli 		*msi_addr_hi = 0;
454e8e55d89SAnilkumar Kolli 	}
455c4eacabeSGovind Singh }
456c4eacabeSGovind Singh 
4571399fb87SGovind Singh int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
4581399fb87SGovind Singh 				       int *num_vectors, u32 *user_base_data,
4591399fb87SGovind Singh 				       u32 *base_vector)
4601399fb87SGovind Singh {
4611399fb87SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
4627a3aed0cSAnilkumar Kolli 	const struct ath11k_msi_config *msi_config = ab_pci->msi_config;
4631399fb87SGovind Singh 	int idx;
4641399fb87SGovind Singh 
4657a3aed0cSAnilkumar Kolli 	for (idx = 0; idx < msi_config->total_users; idx++) {
4667a3aed0cSAnilkumar Kolli 		if (strcmp(user_name, msi_config->users[idx].name) == 0) {
4677a3aed0cSAnilkumar Kolli 			*num_vectors = msi_config->users[idx].num_vectors;
4687a3aed0cSAnilkumar Kolli 			*user_base_data = msi_config->users[idx].base_vector
4691399fb87SGovind Singh 				+ ab_pci->msi_ep_base_data;
4707a3aed0cSAnilkumar Kolli 			*base_vector = msi_config->users[idx].base_vector;
4711399fb87SGovind Singh 
4721399fb87SGovind Singh 			ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
4731399fb87SGovind Singh 				   user_name, *num_vectors, *user_base_data,
4741399fb87SGovind Singh 				   *base_vector);
4751399fb87SGovind Singh 
4761399fb87SGovind Singh 			return 0;
4771399fb87SGovind Singh 		}
4781399fb87SGovind Singh 	}
4791399fb87SGovind Singh 
4801399fb87SGovind Singh 	ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
4811399fb87SGovind Singh 
4821399fb87SGovind Singh 	return -EINVAL;
4831399fb87SGovind Singh }
4841399fb87SGovind Singh 
4856289ac2bSKarthikeyan Periyasamy static void ath11k_pci_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
4866289ac2bSKarthikeyan Periyasamy 				      u32 *msi_idx)
4876289ac2bSKarthikeyan Periyasamy {
4886289ac2bSKarthikeyan Periyasamy 	u32 i, msi_data_idx;
4896289ac2bSKarthikeyan Periyasamy 
4906289ac2bSKarthikeyan Periyasamy 	for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
4916289ac2bSKarthikeyan Periyasamy 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
4926289ac2bSKarthikeyan Periyasamy 			continue;
4936289ac2bSKarthikeyan Periyasamy 
4946289ac2bSKarthikeyan Periyasamy 		if (ce_id == i)
4956289ac2bSKarthikeyan Periyasamy 			break;
4966289ac2bSKarthikeyan Periyasamy 
4976289ac2bSKarthikeyan Periyasamy 		msi_data_idx++;
4986289ac2bSKarthikeyan Periyasamy 	}
4996289ac2bSKarthikeyan Periyasamy 	*msi_idx = msi_data_idx;
5006289ac2bSKarthikeyan Periyasamy }
5016289ac2bSKarthikeyan Periyasamy 
502c4eacabeSGovind Singh static int ath11k_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
503c4eacabeSGovind Singh 					  int *num_vectors, u32 *user_base_data,
504c4eacabeSGovind Singh 					  u32 *base_vector)
505c4eacabeSGovind Singh {
506c4eacabeSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
507c4eacabeSGovind Singh 
508c4eacabeSGovind Singh 	return ath11k_pci_get_user_msi_assignment(ab_pci, user_name,
509c4eacabeSGovind Singh 						  num_vectors, user_base_data,
510c4eacabeSGovind Singh 						  base_vector);
511c4eacabeSGovind Singh }
512c4eacabeSGovind Singh 
513d4ecb90bSCarl Huang static void ath11k_pci_free_ext_irq(struct ath11k_base *ab)
514d4ecb90bSCarl Huang {
515d4ecb90bSCarl Huang 	int i, j;
516d4ecb90bSCarl Huang 
517d4ecb90bSCarl Huang 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
518d4ecb90bSCarl Huang 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
519d4ecb90bSCarl Huang 
520d4ecb90bSCarl Huang 		for (j = 0; j < irq_grp->num_irq; j++)
521d4ecb90bSCarl Huang 			free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
522d4ecb90bSCarl Huang 
523d4ecb90bSCarl Huang 		netif_napi_del(&irq_grp->napi);
524d4ecb90bSCarl Huang 	}
525d4ecb90bSCarl Huang }
526d4ecb90bSCarl Huang 
5277f4beda2SGovind Singh static void ath11k_pci_free_irq(struct ath11k_base *ab)
5287f4beda2SGovind Singh {
5297f4beda2SGovind Singh 	int i, irq_idx;
5307f4beda2SGovind Singh 
531d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
532e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
5337f4beda2SGovind Singh 			continue;
5347f4beda2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
5357f4beda2SGovind Singh 		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
5367f4beda2SGovind Singh 	}
537d4ecb90bSCarl Huang 
538d4ecb90bSCarl Huang 	ath11k_pci_free_ext_irq(ab);
5397f4beda2SGovind Singh }
5407f4beda2SGovind Singh 
5412c3960c2SGovind Singh static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
5422c3960c2SGovind Singh {
5432c3960c2SGovind Singh 	u32 irq_idx;
5442c3960c2SGovind Singh 
5452c3960c2SGovind Singh 	irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
5462c3960c2SGovind Singh 	enable_irq(ab->irq_num[irq_idx]);
5472c3960c2SGovind Singh }
5482c3960c2SGovind Singh 
5497f4beda2SGovind Singh static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
5507f4beda2SGovind Singh {
5517f4beda2SGovind Singh 	u32 irq_idx;
5527f4beda2SGovind Singh 
5537f4beda2SGovind Singh 	irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
5547f4beda2SGovind Singh 	disable_irq_nosync(ab->irq_num[irq_idx]);
5557f4beda2SGovind Singh }
5567f4beda2SGovind Singh 
5572c3960c2SGovind Singh static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
5582c3960c2SGovind Singh {
5592c3960c2SGovind Singh 	int i;
5602c3960c2SGovind Singh 
561d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
562e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
5632c3960c2SGovind Singh 			continue;
5642c3960c2SGovind Singh 		ath11k_pci_ce_irq_disable(ab, i);
5652c3960c2SGovind Singh 	}
5662c3960c2SGovind Singh }
5672c3960c2SGovind Singh 
5682c3960c2SGovind Singh static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
5692c3960c2SGovind Singh {
5702c3960c2SGovind Singh 	int i;
5712c3960c2SGovind Singh 	int irq_idx;
5722c3960c2SGovind Singh 
573d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
574e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
5752c3960c2SGovind Singh 			continue;
5762c3960c2SGovind Singh 
5772c3960c2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
5782c3960c2SGovind Singh 		synchronize_irq(ab->irq_num[irq_idx]);
5792c3960c2SGovind Singh 	}
5802c3960c2SGovind Singh }
5812c3960c2SGovind Singh 
5820f01dcb8SAllen Pais static void ath11k_pci_ce_tasklet(struct tasklet_struct *t)
5832c3960c2SGovind Singh {
5840f01dcb8SAllen Pais 	struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
5852c3960c2SGovind Singh 
5862c3960c2SGovind Singh 	ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
5872c3960c2SGovind Singh 
5882c3960c2SGovind Singh 	ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
5892c3960c2SGovind Singh }
5902c3960c2SGovind Singh 
5917f4beda2SGovind Singh static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
5927f4beda2SGovind Singh {
5937f4beda2SGovind Singh 	struct ath11k_ce_pipe *ce_pipe = arg;
5947f4beda2SGovind Singh 
595*7dc67af0SKarthikeyan Periyasamy 	/* last interrupt received for this CE */
596*7dc67af0SKarthikeyan Periyasamy 	ce_pipe->timestamp = jiffies;
597*7dc67af0SKarthikeyan Periyasamy 
5987f4beda2SGovind Singh 	ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
5992c3960c2SGovind Singh 	tasklet_schedule(&ce_pipe->intr_tq);
6007f4beda2SGovind Singh 
6017f4beda2SGovind Singh 	return IRQ_HANDLED;
6027f4beda2SGovind Singh }
6037f4beda2SGovind Singh 
604d4ecb90bSCarl Huang static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
605d4ecb90bSCarl Huang {
606d4ecb90bSCarl Huang 	int i;
607d4ecb90bSCarl Huang 
608d4ecb90bSCarl Huang 	for (i = 0; i < irq_grp->num_irq; i++)
609d4ecb90bSCarl Huang 		disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
610d4ecb90bSCarl Huang }
611d4ecb90bSCarl Huang 
612d4ecb90bSCarl Huang static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
613d4ecb90bSCarl Huang {
614d4ecb90bSCarl Huang 	int i;
615d4ecb90bSCarl Huang 
616d4ecb90bSCarl Huang 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
617d4ecb90bSCarl Huang 		struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
618d4ecb90bSCarl Huang 
619d4ecb90bSCarl Huang 		ath11k_pci_ext_grp_disable(irq_grp);
620d4ecb90bSCarl Huang 
621d4ecb90bSCarl Huang 		napi_synchronize(&irq_grp->napi);
622d4ecb90bSCarl Huang 		napi_disable(&irq_grp->napi);
623d4ecb90bSCarl Huang 	}
624d4ecb90bSCarl Huang }
625d4ecb90bSCarl Huang 
626d4ecb90bSCarl Huang static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
627d4ecb90bSCarl Huang {
628d4ecb90bSCarl Huang 	int i;
629d4ecb90bSCarl Huang 
630d4ecb90bSCarl Huang 	for (i = 0; i < irq_grp->num_irq; i++)
631d4ecb90bSCarl Huang 		enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
632d4ecb90bSCarl Huang }
633d4ecb90bSCarl Huang 
634d4ecb90bSCarl Huang static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
635d4ecb90bSCarl Huang {
636d4ecb90bSCarl Huang 	int i;
637d4ecb90bSCarl Huang 
638d4ecb90bSCarl Huang 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
639d4ecb90bSCarl Huang 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
640d4ecb90bSCarl Huang 
641d4ecb90bSCarl Huang 		napi_enable(&irq_grp->napi);
642d4ecb90bSCarl Huang 		ath11k_pci_ext_grp_enable(irq_grp);
643d4ecb90bSCarl Huang 	}
644d4ecb90bSCarl Huang }
645d4ecb90bSCarl Huang 
646d4ecb90bSCarl Huang static void ath11k_pci_sync_ext_irqs(struct ath11k_base *ab)
647d4ecb90bSCarl Huang {
648d4ecb90bSCarl Huang 	int i, j, irq_idx;
649d4ecb90bSCarl Huang 
650d4ecb90bSCarl Huang 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
651d4ecb90bSCarl Huang 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
652d4ecb90bSCarl Huang 
653d4ecb90bSCarl Huang 		for (j = 0; j < irq_grp->num_irq; j++) {
654d4ecb90bSCarl Huang 			irq_idx = irq_grp->irqs[j];
655d4ecb90bSCarl Huang 			synchronize_irq(ab->irq_num[irq_idx]);
656d4ecb90bSCarl Huang 		}
657d4ecb90bSCarl Huang 	}
658d4ecb90bSCarl Huang }
659d4ecb90bSCarl Huang 
660d4ecb90bSCarl Huang static void ath11k_pci_ext_irq_disable(struct ath11k_base *ab)
661d4ecb90bSCarl Huang {
662d4ecb90bSCarl Huang 	__ath11k_pci_ext_irq_disable(ab);
663d4ecb90bSCarl Huang 	ath11k_pci_sync_ext_irqs(ab);
664d4ecb90bSCarl Huang }
665d4ecb90bSCarl Huang 
666d4ecb90bSCarl Huang static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
667d4ecb90bSCarl Huang {
668d4ecb90bSCarl Huang 	struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
669d4ecb90bSCarl Huang 						struct ath11k_ext_irq_grp,
670d4ecb90bSCarl Huang 						napi);
671d4ecb90bSCarl Huang 	struct ath11k_base *ab = irq_grp->ab;
672d4ecb90bSCarl Huang 	int work_done;
673d4ecb90bSCarl Huang 
674d4ecb90bSCarl Huang 	work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
675d4ecb90bSCarl Huang 	if (work_done < budget) {
676d4ecb90bSCarl Huang 		napi_complete_done(napi, work_done);
677d4ecb90bSCarl Huang 		ath11k_pci_ext_grp_enable(irq_grp);
678d4ecb90bSCarl Huang 	}
679d4ecb90bSCarl Huang 
680d4ecb90bSCarl Huang 	if (work_done > budget)
681d4ecb90bSCarl Huang 		work_done = budget;
682d4ecb90bSCarl Huang 
683d4ecb90bSCarl Huang 	return work_done;
684d4ecb90bSCarl Huang }
685d4ecb90bSCarl Huang 
686d4ecb90bSCarl Huang static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
687d4ecb90bSCarl Huang {
688d4ecb90bSCarl Huang 	struct ath11k_ext_irq_grp *irq_grp = arg;
689d4ecb90bSCarl Huang 
690d4ecb90bSCarl Huang 	ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
691d4ecb90bSCarl Huang 
692*7dc67af0SKarthikeyan Periyasamy 	/* last interrupt received for this group */
693*7dc67af0SKarthikeyan Periyasamy 	irq_grp->timestamp = jiffies;
694*7dc67af0SKarthikeyan Periyasamy 
695d4ecb90bSCarl Huang 	ath11k_pci_ext_grp_disable(irq_grp);
696d4ecb90bSCarl Huang 
697d4ecb90bSCarl Huang 	napi_schedule(&irq_grp->napi);
698d4ecb90bSCarl Huang 
699d4ecb90bSCarl Huang 	return IRQ_HANDLED;
700d4ecb90bSCarl Huang }
701d4ecb90bSCarl Huang 
702d4ecb90bSCarl Huang static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
703d4ecb90bSCarl Huang {
704d4ecb90bSCarl Huang 	int i, j, ret, num_vectors = 0;
705*7dc67af0SKarthikeyan Periyasamy 	u32 user_base_data = 0, base_vector = 0, base_idx;
706d4ecb90bSCarl Huang 
707*7dc67af0SKarthikeyan Periyasamy 	base_idx = ATH11K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX;
708b2c09458SColin Ian King 	ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
709b2c09458SColin Ian King 						 &num_vectors,
710b2c09458SColin Ian King 						 &user_base_data,
711d4ecb90bSCarl Huang 						 &base_vector);
712b2c09458SColin Ian King 	if (ret < 0)
713b2c09458SColin Ian King 		return ret;
714d4ecb90bSCarl Huang 
715d4ecb90bSCarl Huang 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
716d4ecb90bSCarl Huang 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
717d4ecb90bSCarl Huang 		u32 num_irq = 0;
718d4ecb90bSCarl Huang 
719d4ecb90bSCarl Huang 		irq_grp->ab = ab;
720d4ecb90bSCarl Huang 		irq_grp->grp_id = i;
721d4ecb90bSCarl Huang 		init_dummy_netdev(&irq_grp->napi_ndev);
722d4ecb90bSCarl Huang 		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
723d4ecb90bSCarl Huang 			       ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
724d4ecb90bSCarl Huang 
725d4ecb90bSCarl Huang 		if (ab->hw_params.ring_mask->tx[i] ||
726d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->rx[i] ||
727d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->rx_err[i] ||
728d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->rx_wbm_rel[i] ||
729d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->reo_status[i] ||
730d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->rxdma2host[i] ||
731d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->host2rxdma[i] ||
732d4ecb90bSCarl Huang 		    ab->hw_params.ring_mask->rx_mon_status[i]) {
733d4ecb90bSCarl Huang 			num_irq = 1;
734d4ecb90bSCarl Huang 		}
735d4ecb90bSCarl Huang 
736d4ecb90bSCarl Huang 		irq_grp->num_irq = num_irq;
737*7dc67af0SKarthikeyan Periyasamy 		irq_grp->irqs[0] = base_idx + i;
738d4ecb90bSCarl Huang 
739d4ecb90bSCarl Huang 		for (j = 0; j < irq_grp->num_irq; j++) {
740d4ecb90bSCarl Huang 			int irq_idx = irq_grp->irqs[j];
741d4ecb90bSCarl Huang 			int vector = (i % num_vectors) + base_vector;
742d4ecb90bSCarl Huang 			int irq = ath11k_pci_get_msi_irq(ab->dev, vector);
743d4ecb90bSCarl Huang 
744d4ecb90bSCarl Huang 			ab->irq_num[irq_idx] = irq;
745d4ecb90bSCarl Huang 
746d4ecb90bSCarl Huang 			ath11k_dbg(ab, ATH11K_DBG_PCI,
747d4ecb90bSCarl Huang 				   "irq:%d group:%d\n", irq, i);
748*7dc67af0SKarthikeyan Periyasamy 
749*7dc67af0SKarthikeyan Periyasamy 			irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
750d4ecb90bSCarl Huang 			ret = request_irq(irq, ath11k_pci_ext_interrupt_handler,
751d4ecb90bSCarl Huang 					  IRQF_SHARED,
752d4ecb90bSCarl Huang 					  "DP_EXT_IRQ", irq_grp);
753d4ecb90bSCarl Huang 			if (ret) {
754d4ecb90bSCarl Huang 				ath11k_err(ab, "failed request irq %d: %d\n",
755d4ecb90bSCarl Huang 					   vector, ret);
756d4ecb90bSCarl Huang 				return ret;
757d4ecb90bSCarl Huang 			}
758d4ecb90bSCarl Huang 
759d4ecb90bSCarl Huang 			disable_irq_nosync(ab->irq_num[irq_idx]);
760d4ecb90bSCarl Huang 		}
761d4ecb90bSCarl Huang 	}
762d4ecb90bSCarl Huang 
763d4ecb90bSCarl Huang 	return 0;
764d4ecb90bSCarl Huang }
765d4ecb90bSCarl Huang 
7667f4beda2SGovind Singh static int ath11k_pci_config_irq(struct ath11k_base *ab)
7677f4beda2SGovind Singh {
7687f4beda2SGovind Singh 	struct ath11k_ce_pipe *ce_pipe;
7697f4beda2SGovind Singh 	u32 msi_data_start;
7706289ac2bSKarthikeyan Periyasamy 	u32 msi_data_count, msi_data_idx;
7717f4beda2SGovind Singh 	u32 msi_irq_start;
7727f4beda2SGovind Singh 	unsigned int msi_data;
7737f4beda2SGovind Singh 	int irq, i, ret, irq_idx;
7747f4beda2SGovind Singh 
7757f4beda2SGovind Singh 	ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab),
7767f4beda2SGovind Singh 						 "CE", &msi_data_count,
7777f4beda2SGovind Singh 						 &msi_data_start, &msi_irq_start);
7787f4beda2SGovind Singh 	if (ret)
7797f4beda2SGovind Singh 		return ret;
7807f4beda2SGovind Singh 
7817f4beda2SGovind Singh 	/* Configure CE irqs */
7826289ac2bSKarthikeyan Periyasamy 	for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
783e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
7847f4beda2SGovind Singh 			continue;
7857f4beda2SGovind Singh 
7866289ac2bSKarthikeyan Periyasamy 		msi_data = (msi_data_idx % msi_data_count) + msi_irq_start;
7876289ac2bSKarthikeyan Periyasamy 		irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
7886289ac2bSKarthikeyan Periyasamy 		ce_pipe = &ab->ce.ce_pipe[i];
7896289ac2bSKarthikeyan Periyasamy 
7907f4beda2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
7917f4beda2SGovind Singh 
7920f01dcb8SAllen Pais 		tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);
7932c3960c2SGovind Singh 
7947f4beda2SGovind Singh 		ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
7957f4beda2SGovind Singh 				  IRQF_SHARED, irq_name[irq_idx],
7967f4beda2SGovind Singh 				  ce_pipe);
7977f4beda2SGovind Singh 		if (ret) {
7987f4beda2SGovind Singh 			ath11k_err(ab, "failed to request irq %d: %d\n",
7997f4beda2SGovind Singh 				   irq_idx, ret);
8007f4beda2SGovind Singh 			return ret;
8017f4beda2SGovind Singh 		}
8027f4beda2SGovind Singh 
8037f4beda2SGovind Singh 		ab->irq_num[irq_idx] = irq;
8046289ac2bSKarthikeyan Periyasamy 		msi_data_idx++;
805e678fbd4SKarthikeyan Periyasamy 
806e5c860e1SCarl Huang 		ath11k_pci_ce_irq_disable(ab, i);
8077f4beda2SGovind Singh 	}
8087f4beda2SGovind Singh 
809d4ecb90bSCarl Huang 	ret = ath11k_pci_ext_irq_config(ab);
810d4ecb90bSCarl Huang 	if (ret)
811d4ecb90bSCarl Huang 		return ret;
812d4ecb90bSCarl Huang 
8137f4beda2SGovind Singh 	return 0;
8147f4beda2SGovind Singh }
8157f4beda2SGovind Singh 
8167f4beda2SGovind Singh static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
8177f4beda2SGovind Singh {
8187f4beda2SGovind Singh 	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
8197f4beda2SGovind Singh 
820967c1d11SAnilkumar Kolli 	cfg->tgt_ce = ab->hw_params.target_ce_config;
821967c1d11SAnilkumar Kolli 	cfg->tgt_ce_len = ab->hw_params.target_ce_count;
8227f4beda2SGovind Singh 
823967c1d11SAnilkumar Kolli 	cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
824967c1d11SAnilkumar Kolli 	cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
82516001e4bSAnilkumar Kolli 	ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
826e838c14aSCarl Huang 
827e838c14aSCarl Huang 	ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2,
828e838c14aSCarl Huang 				    &cfg->shadow_reg_v2_len);
8297f4beda2SGovind Singh }
8307f4beda2SGovind Singh 
8317f4beda2SGovind Singh static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
8327f4beda2SGovind Singh {
8337f4beda2SGovind Singh 	int i;
8347f4beda2SGovind Singh 
835d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
836e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
8377f4beda2SGovind Singh 			continue;
8387f4beda2SGovind Singh 		ath11k_pci_ce_irq_enable(ab, i);
8397f4beda2SGovind Singh 	}
8407f4beda2SGovind Singh }
8417f4beda2SGovind Singh 
8425697a564SGovind Singh static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
8435697a564SGovind Singh {
8445697a564SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
8457a3aed0cSAnilkumar Kolli 	const struct ath11k_msi_config *msi_config = ab_pci->msi_config;
8465697a564SGovind Singh 	struct msi_desc *msi_desc;
8475697a564SGovind Singh 	int num_vectors;
8485697a564SGovind Singh 	int ret;
8495697a564SGovind Singh 
8505697a564SGovind Singh 	num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
8517a3aed0cSAnilkumar Kolli 					    msi_config->total_vectors,
8527a3aed0cSAnilkumar Kolli 					    msi_config->total_vectors,
8535697a564SGovind Singh 					    PCI_IRQ_MSI);
8547a3aed0cSAnilkumar Kolli 	if (num_vectors != msi_config->total_vectors) {
8555697a564SGovind Singh 		ath11k_err(ab, "failed to get %d MSI vectors, only %d available",
8567a3aed0cSAnilkumar Kolli 			   msi_config->total_vectors, num_vectors);
8575697a564SGovind Singh 
8585697a564SGovind Singh 		if (num_vectors >= 0)
8595697a564SGovind Singh 			return -EINVAL;
8605697a564SGovind Singh 		else
8615697a564SGovind Singh 			return num_vectors;
8625697a564SGovind Singh 	}
8635697a564SGovind Singh 
8645697a564SGovind Singh 	msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
8655697a564SGovind Singh 	if (!msi_desc) {
8665697a564SGovind Singh 		ath11k_err(ab, "msi_desc is NULL!\n");
8675697a564SGovind Singh 		ret = -EINVAL;
8685697a564SGovind Singh 		goto free_msi_vector;
8695697a564SGovind Singh 	}
8705697a564SGovind Singh 
8715697a564SGovind Singh 	ab_pci->msi_ep_base_data = msi_desc->msg.data;
872e8e55d89SAnilkumar Kolli 	if (msi_desc->msi_attrib.is_64)
873e8e55d89SAnilkumar Kolli 		set_bit(ATH11K_PCI_FLAG_IS_MSI_64, &ab_pci->flags);
8745697a564SGovind Singh 
8755697a564SGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
8765697a564SGovind Singh 
8775697a564SGovind Singh 	return 0;
8785697a564SGovind Singh 
8795697a564SGovind Singh free_msi_vector:
8805697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
8815697a564SGovind Singh 
8825697a564SGovind Singh 	return ret;
8835697a564SGovind Singh }
8845697a564SGovind Singh 
8855697a564SGovind Singh static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
8865697a564SGovind Singh {
8875697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
8885697a564SGovind Singh }
8895697a564SGovind Singh 
8905762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
8915762613eSGovind Singh {
8925762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
8935762613eSGovind Singh 	u16 device_id;
8945762613eSGovind Singh 	int ret = 0;
8955762613eSGovind Singh 
8965762613eSGovind Singh 	pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
8975762613eSGovind Singh 	if (device_id != ab_pci->dev_id)  {
8985762613eSGovind Singh 		ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
8995762613eSGovind Singh 			   device_id, ab_pci->dev_id);
9005762613eSGovind Singh 		ret = -EIO;
9015762613eSGovind Singh 		goto out;
9025762613eSGovind Singh 	}
9035762613eSGovind Singh 
9045762613eSGovind Singh 	ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
9055762613eSGovind Singh 	if (ret) {
9065762613eSGovind Singh 		ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
9075762613eSGovind Singh 		goto out;
9085762613eSGovind Singh 	}
9095762613eSGovind Singh 
9105762613eSGovind Singh 	ret = pci_enable_device(pdev);
9115762613eSGovind Singh 	if (ret) {
9125762613eSGovind Singh 		ath11k_err(ab, "failed to enable pci device: %d\n", ret);
9135762613eSGovind Singh 		goto out;
9145762613eSGovind Singh 	}
9155762613eSGovind Singh 
9165762613eSGovind Singh 	ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
9175762613eSGovind Singh 	if (ret) {
9185762613eSGovind Singh 		ath11k_err(ab, "failed to request pci region: %d\n", ret);
9195762613eSGovind Singh 		goto disable_device;
9205762613eSGovind Singh 	}
9215762613eSGovind Singh 
9225762613eSGovind Singh 	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
9235762613eSGovind Singh 	if (ret) {
9245762613eSGovind Singh 		ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
9255762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
9265762613eSGovind Singh 		goto release_region;
9275762613eSGovind Singh 	}
9285762613eSGovind Singh 
9295762613eSGovind Singh 	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
9305762613eSGovind Singh 	if (ret) {
9315762613eSGovind Singh 		ath11k_err(ab, "failed to set pci consistent dma mask to %d: %d\n",
9325762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
9335762613eSGovind Singh 		goto release_region;
9345762613eSGovind Singh 	}
9355762613eSGovind Singh 
9365762613eSGovind Singh 	pci_set_master(pdev);
9375762613eSGovind Singh 
9385762613eSGovind Singh 	ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
9395762613eSGovind Singh 	ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
9405762613eSGovind Singh 	if (!ab->mem) {
9415762613eSGovind Singh 		ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
9425762613eSGovind Singh 		ret = -EIO;
9435762613eSGovind Singh 		goto clear_master;
9445762613eSGovind Singh 	}
9455762613eSGovind Singh 
9465762613eSGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
9475762613eSGovind Singh 	return 0;
9485762613eSGovind Singh 
9495762613eSGovind Singh clear_master:
9505762613eSGovind Singh 	pci_clear_master(pdev);
9515762613eSGovind Singh release_region:
9525762613eSGovind Singh 	pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
9535762613eSGovind Singh disable_device:
9545762613eSGovind Singh 	pci_disable_device(pdev);
9555762613eSGovind Singh out:
9565762613eSGovind Singh 	return ret;
9575762613eSGovind Singh }
9585762613eSGovind Singh 
9595762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
9605762613eSGovind Singh {
9615762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
9625762613eSGovind Singh 	struct pci_dev *pci_dev = ab_pci->pdev;
9635762613eSGovind Singh 
9645762613eSGovind Singh 	pci_iounmap(pci_dev, ab->mem);
9655762613eSGovind Singh 	ab->mem = NULL;
9665762613eSGovind Singh 	pci_clear_master(pci_dev);
9675762613eSGovind Singh 	pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
9685762613eSGovind Singh 	if (pci_is_enabled(pci_dev))
9695762613eSGovind Singh 		pci_disable_device(pci_dev);
9705762613eSGovind Singh }
9715762613eSGovind Singh 
972e9603f4bSCarl Huang static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
973e9603f4bSCarl Huang {
974e9603f4bSCarl Huang 	struct ath11k_base *ab = ab_pci->ab;
975e9603f4bSCarl Huang 
976e9603f4bSCarl Huang 	pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
977e9603f4bSCarl Huang 				  &ab_pci->link_ctl);
978e9603f4bSCarl Huang 
979e9603f4bSCarl Huang 	ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
980e9603f4bSCarl Huang 		   ab_pci->link_ctl,
981e9603f4bSCarl Huang 		   u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
982e9603f4bSCarl Huang 		   u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
983e9603f4bSCarl Huang 
984e9603f4bSCarl Huang 	/* disable L0s and L1 */
985e9603f4bSCarl Huang 	pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
986e9603f4bSCarl Huang 				   ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
987e9603f4bSCarl Huang 
988e9603f4bSCarl Huang 	set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
989e9603f4bSCarl Huang }
990e9603f4bSCarl Huang 
991e9603f4bSCarl Huang static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
992e9603f4bSCarl Huang {
993e9603f4bSCarl Huang 	if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
994e9603f4bSCarl Huang 		pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
995e9603f4bSCarl Huang 					   ab_pci->link_ctl);
996e9603f4bSCarl Huang }
997e9603f4bSCarl Huang 
9981399fb87SGovind Singh static int ath11k_pci_power_up(struct ath11k_base *ab)
9991399fb87SGovind Singh {
10001399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
10011399fb87SGovind Singh 	int ret;
10021399fb87SGovind Singh 
1003a05bd851SCarl Huang 	ab_pci->register_window = 0;
1004a05bd851SCarl Huang 	clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
1005babb0cedSCarl Huang 	ath11k_pci_sw_reset(ab_pci->ab, true);
1006f3c603d4SCarl Huang 
1007e9603f4bSCarl Huang 	/* Disable ASPM during firmware download due to problems switching
1008e9603f4bSCarl Huang 	 * to AMSS state.
1009e9603f4bSCarl Huang 	 */
1010e9603f4bSCarl Huang 	ath11k_pci_aspm_disable(ab_pci);
1011e9603f4bSCarl Huang 
10121399fb87SGovind Singh 	ret = ath11k_mhi_start(ab_pci);
10131399fb87SGovind Singh 	if (ret) {
10141399fb87SGovind Singh 		ath11k_err(ab, "failed to start mhi: %d\n", ret);
10151399fb87SGovind Singh 		return ret;
10161399fb87SGovind Singh 	}
10171399fb87SGovind Singh 
1018480a7361SKarthikeyan Periyasamy 	if (ab->bus_params.static_window_map)
1019480a7361SKarthikeyan Periyasamy 		ath11k_pci_select_static_window(ab_pci);
1020480a7361SKarthikeyan Periyasamy 
10211399fb87SGovind Singh 	return 0;
10221399fb87SGovind Singh }
10231399fb87SGovind Singh 
10241399fb87SGovind Singh static void ath11k_pci_power_down(struct ath11k_base *ab)
10251399fb87SGovind Singh {
10261399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
10271399fb87SGovind Singh 
1028e9603f4bSCarl Huang 	/* restore aspm in case firmware bootup fails */
1029e9603f4bSCarl Huang 	ath11k_pci_aspm_restore(ab_pci);
1030e9603f4bSCarl Huang 
1031babb0cedSCarl Huang 	ath11k_pci_force_wake(ab_pci->ab);
10321399fb87SGovind Singh 	ath11k_mhi_stop(ab_pci);
1033a05bd851SCarl Huang 	clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
1034babb0cedSCarl Huang 	ath11k_pci_sw_reset(ab_pci->ab, false);
10351399fb87SGovind Singh }
10361399fb87SGovind Singh 
1037fa5917e4SCarl Huang static int ath11k_pci_hif_suspend(struct ath11k_base *ab)
1038fa5917e4SCarl Huang {
1039fa5917e4SCarl Huang 	struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
1040fa5917e4SCarl Huang 
1041fa5917e4SCarl Huang 	ath11k_mhi_suspend(ar_pci);
1042fa5917e4SCarl Huang 
1043fa5917e4SCarl Huang 	return 0;
1044fa5917e4SCarl Huang }
1045fa5917e4SCarl Huang 
1046fa5917e4SCarl Huang static int ath11k_pci_hif_resume(struct ath11k_base *ab)
1047fa5917e4SCarl Huang {
1048fa5917e4SCarl Huang 	struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
1049fa5917e4SCarl Huang 
1050fa5917e4SCarl Huang 	ath11k_mhi_resume(ar_pci);
1051fa5917e4SCarl Huang 
1052fa5917e4SCarl Huang 	return 0;
1053fa5917e4SCarl Huang }
1054fa5917e4SCarl Huang 
10552c3960c2SGovind Singh static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
10562c3960c2SGovind Singh {
10572c3960c2SGovind Singh 	int i;
10582c3960c2SGovind Singh 
1059d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
10602c3960c2SGovind Singh 		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
10612c3960c2SGovind Singh 
1062e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
10632c3960c2SGovind Singh 			continue;
10642c3960c2SGovind Singh 
10652c3960c2SGovind Singh 		tasklet_kill(&ce_pipe->intr_tq);
10662c3960c2SGovind Singh 	}
10672c3960c2SGovind Singh }
10682c3960c2SGovind Singh 
1069d578ec2aSCarl Huang static void ath11k_pci_ce_irq_disable_sync(struct ath11k_base *ab)
10707f4beda2SGovind Singh {
10712c3960c2SGovind Singh 	ath11k_pci_ce_irqs_disable(ab);
10722c3960c2SGovind Singh 	ath11k_pci_sync_ce_irqs(ab);
10732c3960c2SGovind Singh 	ath11k_pci_kill_tasklets(ab);
1074d578ec2aSCarl Huang }
1075d578ec2aSCarl Huang 
1076d578ec2aSCarl Huang static void ath11k_pci_stop(struct ath11k_base *ab)
1077d578ec2aSCarl Huang {
1078d578ec2aSCarl Huang 	ath11k_pci_ce_irq_disable_sync(ab);
10797f4beda2SGovind Singh 	ath11k_ce_cleanup_pipes(ab);
10807f4beda2SGovind Singh }
10817f4beda2SGovind Singh 
10827f4beda2SGovind Singh static int ath11k_pci_start(struct ath11k_base *ab)
10837f4beda2SGovind Singh {
1084a05bd851SCarl Huang 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
1085a05bd851SCarl Huang 
1086a05bd851SCarl Huang 	set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
1087a05bd851SCarl Huang 
1088e9603f4bSCarl Huang 	ath11k_pci_aspm_restore(ab_pci);
1089e9603f4bSCarl Huang 
10907f4beda2SGovind Singh 	ath11k_pci_ce_irqs_enable(ab);
10912c3960c2SGovind Singh 	ath11k_ce_rx_post_buf(ab);
10922c3960c2SGovind Singh 
10932c3960c2SGovind Singh 	return 0;
10942c3960c2SGovind Singh }
10952c3960c2SGovind Singh 
1096d578ec2aSCarl Huang static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab)
1097d578ec2aSCarl Huang {
1098d578ec2aSCarl Huang 	ath11k_pci_ce_irqs_enable(ab);
1099d578ec2aSCarl Huang }
1100d578ec2aSCarl Huang 
1101d578ec2aSCarl Huang static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab)
1102d578ec2aSCarl Huang {
1103d578ec2aSCarl Huang 	ath11k_pci_ce_irq_disable_sync(ab);
1104d578ec2aSCarl Huang }
1105d578ec2aSCarl Huang 
11062c3960c2SGovind Singh static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
11072c3960c2SGovind Singh 					  u8 *ul_pipe, u8 *dl_pipe)
11082c3960c2SGovind Singh {
11092c3960c2SGovind Singh 	const struct service_to_pipe *entry;
11102c3960c2SGovind Singh 	bool ul_set = false, dl_set = false;
11112c3960c2SGovind Singh 	int i;
11122c3960c2SGovind Singh 
1113967c1d11SAnilkumar Kolli 	for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
1114967c1d11SAnilkumar Kolli 		entry = &ab->hw_params.svc_to_ce_map[i];
11152c3960c2SGovind Singh 
11162c3960c2SGovind Singh 		if (__le32_to_cpu(entry->service_id) != service_id)
11172c3960c2SGovind Singh 			continue;
11182c3960c2SGovind Singh 
11192c3960c2SGovind Singh 		switch (__le32_to_cpu(entry->pipedir)) {
11202c3960c2SGovind Singh 		case PIPEDIR_NONE:
11212c3960c2SGovind Singh 			break;
11222c3960c2SGovind Singh 		case PIPEDIR_IN:
11232c3960c2SGovind Singh 			WARN_ON(dl_set);
11242c3960c2SGovind Singh 			*dl_pipe = __le32_to_cpu(entry->pipenum);
11252c3960c2SGovind Singh 			dl_set = true;
11262c3960c2SGovind Singh 			break;
11272c3960c2SGovind Singh 		case PIPEDIR_OUT:
11282c3960c2SGovind Singh 			WARN_ON(ul_set);
11292c3960c2SGovind Singh 			*ul_pipe = __le32_to_cpu(entry->pipenum);
11302c3960c2SGovind Singh 			ul_set = true;
11312c3960c2SGovind Singh 			break;
11322c3960c2SGovind Singh 		case PIPEDIR_INOUT:
11332c3960c2SGovind Singh 			WARN_ON(dl_set);
11342c3960c2SGovind Singh 			WARN_ON(ul_set);
11352c3960c2SGovind Singh 			*dl_pipe = __le32_to_cpu(entry->pipenum);
11362c3960c2SGovind Singh 			*ul_pipe = __le32_to_cpu(entry->pipenum);
11372c3960c2SGovind Singh 			dl_set = true;
11382c3960c2SGovind Singh 			ul_set = true;
11392c3960c2SGovind Singh 			break;
11402c3960c2SGovind Singh 		}
11412c3960c2SGovind Singh 	}
11422c3960c2SGovind Singh 
11432c3960c2SGovind Singh 	if (WARN_ON(!ul_set || !dl_set))
11442c3960c2SGovind Singh 		return -ENOENT;
11457f4beda2SGovind Singh 
11467f4beda2SGovind Singh 	return 0;
11477f4beda2SGovind Singh }
11487f4beda2SGovind Singh 
11497f4beda2SGovind Singh static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
11507f4beda2SGovind Singh 	.start = ath11k_pci_start,
11517f4beda2SGovind Singh 	.stop = ath11k_pci_stop,
1152654e959aSGovind Singh 	.read32 = ath11k_pci_read32,
1153654e959aSGovind Singh 	.write32 = ath11k_pci_write32,
11541399fb87SGovind Singh 	.power_down = ath11k_pci_power_down,
11551399fb87SGovind Singh 	.power_up = ath11k_pci_power_up,
1156fa5917e4SCarl Huang 	.suspend = ath11k_pci_hif_suspend,
1157fa5917e4SCarl Huang 	.resume = ath11k_pci_hif_resume,
1158d4ecb90bSCarl Huang 	.irq_enable = ath11k_pci_ext_irq_enable,
1159d4ecb90bSCarl Huang 	.irq_disable = ath11k_pci_ext_irq_disable,
1160c4eacabeSGovind Singh 	.get_msi_address =  ath11k_pci_get_msi_address,
1161c4eacabeSGovind Singh 	.get_user_msi_vector = ath11k_get_user_msi_assignment,
11622c3960c2SGovind Singh 	.map_service_to_pipe = ath11k_pci_map_service_to_pipe,
1163d578ec2aSCarl Huang 	.ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
1164d578ec2aSCarl Huang 	.ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
11656289ac2bSKarthikeyan Periyasamy 	.get_ce_msi_idx = ath11k_pci_get_ce_msi_idx,
11661399fb87SGovind Singh };
11671399fb87SGovind Singh 
11686e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev,
11696e0355afSGovind Singh 			    const struct pci_device_id *pci_dev)
11706e0355afSGovind Singh {
11716e0355afSGovind Singh 	struct ath11k_base *ab;
11725762613eSGovind Singh 	struct ath11k_pci *ab_pci;
117318ac1665SKalle Valo 	u32 soc_hw_version, soc_hw_version_major, soc_hw_version_minor;
11745762613eSGovind Singh 	int ret;
11756e0355afSGovind Singh 
11761ff8ed78SGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI,
11771ff8ed78SGovind Singh 			       &ath11k_pci_bus_params);
11786e0355afSGovind Singh 	if (!ab) {
11796e0355afSGovind Singh 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
11806e0355afSGovind Singh 		return -ENOMEM;
11816e0355afSGovind Singh 	}
11826e0355afSGovind Singh 
11836e0355afSGovind Singh 	ab->dev = &pdev->dev;
11846e0355afSGovind Singh 	pci_set_drvdata(pdev, ab);
11855762613eSGovind Singh 	ab_pci = ath11k_pci_priv(ab);
11865762613eSGovind Singh 	ab_pci->dev_id = pci_dev->device;
11875762613eSGovind Singh 	ab_pci->ab = ab;
11885697a564SGovind Singh 	ab_pci->pdev = pdev;
11897f4beda2SGovind Singh 	ab->hif.ops = &ath11k_pci_hif_ops;
11905762613eSGovind Singh 	pci_set_drvdata(pdev, ab);
1191654e959aSGovind Singh 	spin_lock_init(&ab_pci->window_lock);
11925762613eSGovind Singh 
11935762613eSGovind Singh 	ret = ath11k_pci_claim(ab_pci, pdev);
11945762613eSGovind Singh 	if (ret) {
11955762613eSGovind Singh 		ath11k_err(ab, "failed to claim device: %d\n", ret);
11965762613eSGovind Singh 		goto err_free_core;
11975762613eSGovind Singh 	}
11986e0355afSGovind Singh 
119918ac1665SKalle Valo 	switch (pci_dev->device) {
120018ac1665SKalle Valo 	case QCA6390_DEVICE_ID:
120118ac1665SKalle Valo 		soc_hw_version = ath11k_pci_read32(ab, TCSR_SOC_HW_VERSION);
120218ac1665SKalle Valo 		soc_hw_version_major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
120318ac1665SKalle Valo 						 soc_hw_version);
120418ac1665SKalle Valo 		soc_hw_version_minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
120518ac1665SKalle Valo 						 soc_hw_version);
120618ac1665SKalle Valo 
120718ac1665SKalle Valo 		ath11k_dbg(ab, ATH11K_DBG_PCI, "pci tcsr_soc_hw_version major %d minor %d\n",
120818ac1665SKalle Valo 			   soc_hw_version_major, soc_hw_version_minor);
120918ac1665SKalle Valo 
121018ac1665SKalle Valo 		switch (soc_hw_version_major) {
121118ac1665SKalle Valo 		case 2:
121218ac1665SKalle Valo 			ab->hw_rev = ATH11K_HW_QCA6390_HW20;
121318ac1665SKalle Valo 			break;
121418ac1665SKalle Valo 		default:
121518ac1665SKalle Valo 			dev_err(&pdev->dev, "Unsupported QCA6390 SOC hardware version: %d %d\n",
121618ac1665SKalle Valo 				soc_hw_version_major, soc_hw_version_minor);
121718ac1665SKalle Valo 			ret = -EOPNOTSUPP;
121818ac1665SKalle Valo 			goto err_pci_free_region;
121918ac1665SKalle Valo 		}
122018ac1665SKalle Valo 		break;
122118ac1665SKalle Valo 	default:
122218ac1665SKalle Valo 		dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
122318ac1665SKalle Valo 			pci_dev->device);
122418ac1665SKalle Valo 		ret = -EOPNOTSUPP;
122518ac1665SKalle Valo 		goto err_pci_free_region;
122618ac1665SKalle Valo 	}
122718ac1665SKalle Valo 
12287a3aed0cSAnilkumar Kolli 	ab_pci->msi_config = &ath11k_msi_config[0];
12295697a564SGovind Singh 	ret = ath11k_pci_enable_msi(ab_pci);
12305697a564SGovind Singh 	if (ret) {
12315697a564SGovind Singh 		ath11k_err(ab, "failed to enable msi: %d\n", ret);
12325697a564SGovind Singh 		goto err_pci_free_region;
12335697a564SGovind Singh 	}
12345697a564SGovind Singh 
1235b8246f88SKalle Valo 	ret = ath11k_core_pre_init(ab);
1236b8246f88SKalle Valo 	if (ret)
1237b8246f88SKalle Valo 		goto err_pci_disable_msi;
1238b8246f88SKalle Valo 
12391399fb87SGovind Singh 	ret = ath11k_mhi_register(ab_pci);
12401399fb87SGovind Singh 	if (ret) {
12411399fb87SGovind Singh 		ath11k_err(ab, "failed to register mhi: %d\n", ret);
12421399fb87SGovind Singh 		goto err_pci_disable_msi;
12431399fb87SGovind Singh 	}
12441399fb87SGovind Singh 
12457f4beda2SGovind Singh 	ret = ath11k_hal_srng_init(ab);
12467f4beda2SGovind Singh 	if (ret)
12477f4beda2SGovind Singh 		goto err_mhi_unregister;
12487f4beda2SGovind Singh 
12497f4beda2SGovind Singh 	ret = ath11k_ce_alloc_pipes(ab);
12507f4beda2SGovind Singh 	if (ret) {
12517f4beda2SGovind Singh 		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
12527f4beda2SGovind Singh 		goto err_hal_srng_deinit;
12537f4beda2SGovind Singh 	}
12547f4beda2SGovind Singh 
12557f4beda2SGovind Singh 	ath11k_pci_init_qmi_ce_config(ab);
12567f4beda2SGovind Singh 
12577f4beda2SGovind Singh 	ret = ath11k_pci_config_irq(ab);
12587f4beda2SGovind Singh 	if (ret) {
12597f4beda2SGovind Singh 		ath11k_err(ab, "failed to config irq: %d\n", ret);
12607f4beda2SGovind Singh 		goto err_ce_free;
12617f4beda2SGovind Singh 	}
12627f4beda2SGovind Singh 
12637f4beda2SGovind Singh 	ret = ath11k_core_init(ab);
12647f4beda2SGovind Singh 	if (ret) {
12657f4beda2SGovind Singh 		ath11k_err(ab, "failed to init core: %d\n", ret);
12667f4beda2SGovind Singh 		goto err_free_irq;
12677f4beda2SGovind Singh 	}
12686e0355afSGovind Singh 	return 0;
12695762613eSGovind Singh 
12707f4beda2SGovind Singh err_free_irq:
12717f4beda2SGovind Singh 	ath11k_pci_free_irq(ab);
12727f4beda2SGovind Singh 
12737f4beda2SGovind Singh err_ce_free:
12747f4beda2SGovind Singh 	ath11k_ce_free_pipes(ab);
12757f4beda2SGovind Singh 
12767f4beda2SGovind Singh err_hal_srng_deinit:
12777f4beda2SGovind Singh 	ath11k_hal_srng_deinit(ab);
12787f4beda2SGovind Singh 
12797f4beda2SGovind Singh err_mhi_unregister:
12807f4beda2SGovind Singh 	ath11k_mhi_unregister(ab_pci);
12817f4beda2SGovind Singh 
1282b8246f88SKalle Valo err_pci_disable_msi:
1283b8246f88SKalle Valo 	ath11k_pci_disable_msi(ab_pci);
1284b8246f88SKalle Valo 
12855697a564SGovind Singh err_pci_free_region:
12865697a564SGovind Singh 	ath11k_pci_free_region(ab_pci);
12875697a564SGovind Singh 
12885762613eSGovind Singh err_free_core:
12895762613eSGovind Singh 	ath11k_core_free(ab);
12905697a564SGovind Singh 
12915762613eSGovind Singh 	return ret;
12926e0355afSGovind Singh }
12936e0355afSGovind Singh 
12946e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev)
12956e0355afSGovind Singh {
12966e0355afSGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
12975762613eSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
12986e0355afSGovind Singh 
129961a57e51SAnilkumar Kolli 	if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
130061a57e51SAnilkumar Kolli 		ath11k_pci_power_down(ab);
130161a57e51SAnilkumar Kolli 		ath11k_debugfs_soc_destroy(ab);
130261a57e51SAnilkumar Kolli 		ath11k_qmi_deinit_service(ab);
130361a57e51SAnilkumar Kolli 		goto qmi_fail;
130461a57e51SAnilkumar Kolli 	}
130561a57e51SAnilkumar Kolli 
13066e0355afSGovind Singh 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
13076fbd8898SCarl Huang 
13086fbd8898SCarl Huang 	ath11k_core_deinit(ab);
13096fbd8898SCarl Huang 
131061a57e51SAnilkumar Kolli qmi_fail:
13111399fb87SGovind Singh 	ath11k_mhi_unregister(ab_pci);
13126fbd8898SCarl Huang 
13136fbd8898SCarl Huang 	ath11k_pci_free_irq(ab);
13145697a564SGovind Singh 	ath11k_pci_disable_msi(ab_pci);
13155762613eSGovind Singh 	ath11k_pci_free_region(ab_pci);
13166fbd8898SCarl Huang 
13176fbd8898SCarl Huang 	ath11k_hal_srng_deinit(ab);
13186fbd8898SCarl Huang 	ath11k_ce_free_pipes(ab);
13196e0355afSGovind Singh 	ath11k_core_free(ab);
13206e0355afSGovind Singh }
13216e0355afSGovind Singh 
13221399fb87SGovind Singh static void ath11k_pci_shutdown(struct pci_dev *pdev)
13231399fb87SGovind Singh {
13241399fb87SGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
13251399fb87SGovind Singh 
13261399fb87SGovind Singh 	ath11k_pci_power_down(ab);
13271399fb87SGovind Singh }
13281399fb87SGovind Singh 
1329d1b0c338SCarl Huang static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
1330d1b0c338SCarl Huang {
1331d1b0c338SCarl Huang 	struct ath11k_base *ab = dev_get_drvdata(dev);
1332d1b0c338SCarl Huang 	int ret;
1333d1b0c338SCarl Huang 
1334d1b0c338SCarl Huang 	ret = ath11k_core_suspend(ab);
1335d1b0c338SCarl Huang 	if (ret)
1336d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to suspend core: %d\n", ret);
1337d1b0c338SCarl Huang 
1338d1b0c338SCarl Huang 	return ret;
1339d1b0c338SCarl Huang }
1340d1b0c338SCarl Huang 
1341d1b0c338SCarl Huang static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
1342d1b0c338SCarl Huang {
1343d1b0c338SCarl Huang 	struct ath11k_base *ab = dev_get_drvdata(dev);
1344d1b0c338SCarl Huang 	int ret;
1345d1b0c338SCarl Huang 
1346d1b0c338SCarl Huang 	ret = ath11k_core_resume(ab);
1347d1b0c338SCarl Huang 	if (ret)
1348d1b0c338SCarl Huang 		ath11k_warn(ab, "failed to resume core: %d\n", ret);
1349d1b0c338SCarl Huang 
1350d1b0c338SCarl Huang 	return ret;
1351d1b0c338SCarl Huang }
1352d1b0c338SCarl Huang 
1353d1b0c338SCarl Huang static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
1354d1b0c338SCarl Huang 			 ath11k_pci_pm_suspend,
1355d1b0c338SCarl Huang 			 ath11k_pci_pm_resume);
1356d1b0c338SCarl Huang 
13576e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = {
13586e0355afSGovind Singh 	.name = "ath11k_pci",
13596e0355afSGovind Singh 	.id_table = ath11k_pci_id_table,
13606e0355afSGovind Singh 	.probe = ath11k_pci_probe,
13616e0355afSGovind Singh 	.remove = ath11k_pci_remove,
13621399fb87SGovind Singh 	.shutdown = ath11k_pci_shutdown,
1363d1b0c338SCarl Huang #ifdef CONFIG_PM
1364d1b0c338SCarl Huang 	.driver.pm = &ath11k_pci_pm_ops,
1365d1b0c338SCarl Huang #endif
13666e0355afSGovind Singh };
13676e0355afSGovind Singh 
13686e0355afSGovind Singh static int ath11k_pci_init(void)
13696e0355afSGovind Singh {
13706e0355afSGovind Singh 	int ret;
13716e0355afSGovind Singh 
13726e0355afSGovind Singh 	ret = pci_register_driver(&ath11k_pci_driver);
13736e0355afSGovind Singh 	if (ret)
13746e0355afSGovind Singh 		pr_err("failed to register ath11k pci driver: %d\n",
13756e0355afSGovind Singh 		       ret);
13766e0355afSGovind Singh 
13776e0355afSGovind Singh 	return ret;
13786e0355afSGovind Singh }
13796e0355afSGovind Singh module_init(ath11k_pci_init);
13806e0355afSGovind Singh 
13816e0355afSGovind Singh static void ath11k_pci_exit(void)
13826e0355afSGovind Singh {
13836e0355afSGovind Singh 	pci_unregister_driver(&ath11k_pci_driver);
13846e0355afSGovind Singh }
13856e0355afSGovind Singh 
13866e0355afSGovind Singh module_exit(ath11k_pci_exit);
13876e0355afSGovind Singh 
13886e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
13896e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL");
13903dbd7fe7SDevin Bayer 
13913dbd7fe7SDevin Bayer /* QCA639x 2.0 firmware files */
13923dbd7fe7SDevin Bayer MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE);
13933dbd7fe7SDevin Bayer MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE);
13943dbd7fe7SDevin Bayer MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE);
1395