xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/pci.c (revision 7f4beda2ba0393ecb04b4ae3017f819041236c43)
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 
19*7f4beda2SGovind Singh #define ATH11K_PCI_IRQ_CE0_OFFSET		3
20*7f4beda2SGovind Singh 
216e0355afSGovind Singh #define QCA6390_DEVICE_ID		0x1101
226e0355afSGovind Singh 
236e0355afSGovind Singh static const struct pci_device_id ath11k_pci_id_table[] = {
246e0355afSGovind Singh 	{ PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
256e0355afSGovind Singh 	{0}
266e0355afSGovind Singh };
276e0355afSGovind Singh 
286e0355afSGovind Singh MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
296e0355afSGovind Singh 
305697a564SGovind Singh static const struct ath11k_msi_config msi_config = {
315697a564SGovind Singh 	.total_vectors = 32,
325697a564SGovind Singh 	.total_users = 4,
335697a564SGovind Singh 	.users = (struct ath11k_msi_user[]) {
345697a564SGovind Singh 		{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
355697a564SGovind Singh 		{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
365697a564SGovind Singh 		{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
375697a564SGovind Singh 		{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
385697a564SGovind Singh 	},
395697a564SGovind Singh };
405697a564SGovind Singh 
41*7f4beda2SGovind Singh /* Target firmware's Copy Engine configuration. */
42*7f4beda2SGovind Singh static const struct ce_pipe_config target_ce_config_wlan[] = {
43*7f4beda2SGovind Singh 	/* CE0: host->target HTC control and raw streams */
44*7f4beda2SGovind Singh 	{
45*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(0),
46*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
47*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
48*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
49*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
50*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
51*7f4beda2SGovind Singh 	},
52*7f4beda2SGovind Singh 
53*7f4beda2SGovind Singh 	/* CE1: target->host HTT + HTC control */
54*7f4beda2SGovind Singh 	{
55*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(1),
56*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
57*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
58*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
59*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
60*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
61*7f4beda2SGovind Singh 	},
62*7f4beda2SGovind Singh 
63*7f4beda2SGovind Singh 	/* CE2: target->host WMI */
64*7f4beda2SGovind Singh 	{
65*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(2),
66*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
67*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
68*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
69*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
70*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
71*7f4beda2SGovind Singh 	},
72*7f4beda2SGovind Singh 
73*7f4beda2SGovind Singh 	/* CE3: host->target WMI */
74*7f4beda2SGovind Singh 	{
75*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(3),
76*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
77*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
78*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
79*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
80*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
81*7f4beda2SGovind Singh 	},
82*7f4beda2SGovind Singh 
83*7f4beda2SGovind Singh 	/* CE4: host->target HTT */
84*7f4beda2SGovind Singh 	{
85*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(4),
86*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
87*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(256),
88*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(256),
89*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
90*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
91*7f4beda2SGovind Singh 	},
92*7f4beda2SGovind Singh 
93*7f4beda2SGovind Singh 	/* CE5: target->host Pktlog */
94*7f4beda2SGovind Singh 	{
95*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(5),
96*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
97*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
98*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
99*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
100*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
101*7f4beda2SGovind Singh 	},
102*7f4beda2SGovind Singh 
103*7f4beda2SGovind Singh 	/* CE6: Reserved for target autonomous hif_memcpy */
104*7f4beda2SGovind Singh 	{
105*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(6),
106*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
107*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
108*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(16384),
109*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
110*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
111*7f4beda2SGovind Singh 	},
112*7f4beda2SGovind Singh 
113*7f4beda2SGovind Singh 	/* CE7 used only by Host */
114*7f4beda2SGovind Singh 	{
115*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(7),
116*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
117*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(0),
118*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(0),
119*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
120*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
121*7f4beda2SGovind Singh 	},
122*7f4beda2SGovind Singh 
123*7f4beda2SGovind Singh 	/* CE8 target->host used only by IPA */
124*7f4beda2SGovind Singh 	{
125*7f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(8),
126*7f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
127*7f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
128*7f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(16384),
129*7f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
130*7f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
131*7f4beda2SGovind Singh 	},
132*7f4beda2SGovind Singh 	/* CE 9, 10, 11 are used by MHI driver */
133*7f4beda2SGovind Singh };
134*7f4beda2SGovind Singh 
135*7f4beda2SGovind Singh /* Map from service/endpoint to Copy Engine.
136*7f4beda2SGovind Singh  * This table is derived from the CE_PCI TABLE, above.
137*7f4beda2SGovind Singh  * It is passed to the Target at startup for use by firmware.
138*7f4beda2SGovind Singh  */
139*7f4beda2SGovind Singh static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
140*7f4beda2SGovind Singh 	{
141*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
142*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
143*7f4beda2SGovind Singh 		__cpu_to_le32(3),
144*7f4beda2SGovind Singh 	},
145*7f4beda2SGovind Singh 	{
146*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
147*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
148*7f4beda2SGovind Singh 		__cpu_to_le32(2),
149*7f4beda2SGovind Singh 	},
150*7f4beda2SGovind Singh 	{
151*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
152*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
153*7f4beda2SGovind Singh 		__cpu_to_le32(3),
154*7f4beda2SGovind Singh 	},
155*7f4beda2SGovind Singh 	{
156*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
157*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
158*7f4beda2SGovind Singh 		__cpu_to_le32(2),
159*7f4beda2SGovind Singh 	},
160*7f4beda2SGovind Singh 	{
161*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
162*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
163*7f4beda2SGovind Singh 		__cpu_to_le32(3),
164*7f4beda2SGovind Singh 	},
165*7f4beda2SGovind Singh 	{
166*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
167*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
168*7f4beda2SGovind Singh 		__cpu_to_le32(2),
169*7f4beda2SGovind Singh 	},
170*7f4beda2SGovind Singh 	{
171*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
172*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
173*7f4beda2SGovind Singh 		__cpu_to_le32(3),
174*7f4beda2SGovind Singh 	},
175*7f4beda2SGovind Singh 	{
176*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
177*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
178*7f4beda2SGovind Singh 		__cpu_to_le32(2),
179*7f4beda2SGovind Singh 	},
180*7f4beda2SGovind Singh 	{
181*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
182*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
183*7f4beda2SGovind Singh 		__cpu_to_le32(3),
184*7f4beda2SGovind Singh 	},
185*7f4beda2SGovind Singh 	{
186*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
187*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
188*7f4beda2SGovind Singh 		__cpu_to_le32(2),
189*7f4beda2SGovind Singh 	},
190*7f4beda2SGovind Singh 
191*7f4beda2SGovind Singh 	{
192*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
193*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
194*7f4beda2SGovind Singh 		__cpu_to_le32(0),
195*7f4beda2SGovind Singh 	},
196*7f4beda2SGovind Singh 	{
197*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
198*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
199*7f4beda2SGovind Singh 		__cpu_to_le32(2),
200*7f4beda2SGovind Singh 	},
201*7f4beda2SGovind Singh 
202*7f4beda2SGovind Singh 	{
203*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
204*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
205*7f4beda2SGovind Singh 		__cpu_to_le32(4),
206*7f4beda2SGovind Singh 	},
207*7f4beda2SGovind Singh 	{
208*7f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
209*7f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
210*7f4beda2SGovind Singh 		__cpu_to_le32(1),
211*7f4beda2SGovind Singh 	},
212*7f4beda2SGovind Singh 
213*7f4beda2SGovind Singh 	/* (Additions here) */
214*7f4beda2SGovind Singh 
215*7f4beda2SGovind Singh 	{ /* must be last */
216*7f4beda2SGovind Singh 		__cpu_to_le32(0),
217*7f4beda2SGovind Singh 		__cpu_to_le32(0),
218*7f4beda2SGovind Singh 		__cpu_to_le32(0),
219*7f4beda2SGovind Singh 	},
220*7f4beda2SGovind Singh };
221*7f4beda2SGovind Singh 
222*7f4beda2SGovind Singh static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
223*7f4beda2SGovind Singh 	"bhi",
224*7f4beda2SGovind Singh 	"mhi-er0",
225*7f4beda2SGovind Singh 	"mhi-er1",
226*7f4beda2SGovind Singh 	"ce0",
227*7f4beda2SGovind Singh 	"ce1",
228*7f4beda2SGovind Singh 	"ce2",
229*7f4beda2SGovind Singh 	"ce3",
230*7f4beda2SGovind Singh 	"ce4",
231*7f4beda2SGovind Singh 	"ce5",
232*7f4beda2SGovind Singh 	"ce6",
233*7f4beda2SGovind Singh 	"ce7",
234*7f4beda2SGovind Singh 	"ce8",
235*7f4beda2SGovind Singh 	"ce9",
236*7f4beda2SGovind Singh 	"ce10",
237*7f4beda2SGovind Singh 	"ce11",
238*7f4beda2SGovind Singh 	"host2wbm-desc-feed",
239*7f4beda2SGovind Singh 	"host2reo-re-injection",
240*7f4beda2SGovind Singh 	"host2reo-command",
241*7f4beda2SGovind Singh 	"host2rxdma-monitor-ring3",
242*7f4beda2SGovind Singh 	"host2rxdma-monitor-ring2",
243*7f4beda2SGovind Singh 	"host2rxdma-monitor-ring1",
244*7f4beda2SGovind Singh 	"reo2ost-exception",
245*7f4beda2SGovind Singh 	"wbm2host-rx-release",
246*7f4beda2SGovind Singh 	"reo2host-status",
247*7f4beda2SGovind Singh 	"reo2host-destination-ring4",
248*7f4beda2SGovind Singh 	"reo2host-destination-ring3",
249*7f4beda2SGovind Singh 	"reo2host-destination-ring2",
250*7f4beda2SGovind Singh 	"reo2host-destination-ring1",
251*7f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac3",
252*7f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac2",
253*7f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac1",
254*7f4beda2SGovind Singh 	"ppdu-end-interrupts-mac3",
255*7f4beda2SGovind Singh 	"ppdu-end-interrupts-mac2",
256*7f4beda2SGovind Singh 	"ppdu-end-interrupts-mac1",
257*7f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac3",
258*7f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac2",
259*7f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac1",
260*7f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac3",
261*7f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac2",
262*7f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac1",
263*7f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac3",
264*7f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac2",
265*7f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac1",
266*7f4beda2SGovind Singh 	"host2tcl-input-ring4",
267*7f4beda2SGovind Singh 	"host2tcl-input-ring3",
268*7f4beda2SGovind Singh 	"host2tcl-input-ring2",
269*7f4beda2SGovind Singh 	"host2tcl-input-ring1",
270*7f4beda2SGovind Singh 	"wbm2host-tx-completions-ring3",
271*7f4beda2SGovind Singh 	"wbm2host-tx-completions-ring2",
272*7f4beda2SGovind Singh 	"wbm2host-tx-completions-ring1",
273*7f4beda2SGovind Singh 	"tcl2host-status-ring",
274*7f4beda2SGovind Singh };
275*7f4beda2SGovind Singh 
2761399fb87SGovind Singh int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
2771399fb87SGovind Singh {
2781399fb87SGovind Singh 	struct pci_dev *pci_dev = to_pci_dev(dev);
2791399fb87SGovind Singh 
2801399fb87SGovind Singh 	return pci_irq_vector(pci_dev, vector);
2811399fb87SGovind Singh }
2821399fb87SGovind Singh 
2831399fb87SGovind Singh int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
2841399fb87SGovind Singh 				       int *num_vectors, u32 *user_base_data,
2851399fb87SGovind Singh 				       u32 *base_vector)
2861399fb87SGovind Singh {
2871399fb87SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
2881399fb87SGovind Singh 	int idx;
2891399fb87SGovind Singh 
2901399fb87SGovind Singh 	for (idx = 0; idx < msi_config.total_users; idx++) {
2911399fb87SGovind Singh 		if (strcmp(user_name, msi_config.users[idx].name) == 0) {
2921399fb87SGovind Singh 			*num_vectors = msi_config.users[idx].num_vectors;
2931399fb87SGovind Singh 			*user_base_data = msi_config.users[idx].base_vector
2941399fb87SGovind Singh 				+ ab_pci->msi_ep_base_data;
2951399fb87SGovind Singh 			*base_vector = msi_config.users[idx].base_vector;
2961399fb87SGovind Singh 
2971399fb87SGovind Singh 			ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
2981399fb87SGovind Singh 				   user_name, *num_vectors, *user_base_data,
2991399fb87SGovind Singh 				   *base_vector);
3001399fb87SGovind Singh 
3011399fb87SGovind Singh 			return 0;
3021399fb87SGovind Singh 		}
3031399fb87SGovind Singh 	}
3041399fb87SGovind Singh 
3051399fb87SGovind Singh 	ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
3061399fb87SGovind Singh 
3071399fb87SGovind Singh 	return -EINVAL;
3081399fb87SGovind Singh }
3091399fb87SGovind Singh 
310*7f4beda2SGovind Singh static void ath11k_pci_free_irq(struct ath11k_base *ab)
311*7f4beda2SGovind Singh {
312*7f4beda2SGovind Singh 	int i, irq_idx;
313*7f4beda2SGovind Singh 
314*7f4beda2SGovind Singh 	for (i = 0; i < CE_COUNT; i++) {
315*7f4beda2SGovind Singh 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
316*7f4beda2SGovind Singh 			continue;
317*7f4beda2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
318*7f4beda2SGovind Singh 		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
319*7f4beda2SGovind Singh 	}
320*7f4beda2SGovind Singh }
321*7f4beda2SGovind Singh 
322*7f4beda2SGovind Singh static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
323*7f4beda2SGovind Singh {
324*7f4beda2SGovind Singh 	u32 irq_idx;
325*7f4beda2SGovind Singh 
326*7f4beda2SGovind Singh 	irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
327*7f4beda2SGovind Singh 	disable_irq_nosync(ab->irq_num[irq_idx]);
328*7f4beda2SGovind Singh }
329*7f4beda2SGovind Singh 
330*7f4beda2SGovind Singh static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
331*7f4beda2SGovind Singh {
332*7f4beda2SGovind Singh 	struct ath11k_ce_pipe *ce_pipe = arg;
333*7f4beda2SGovind Singh 
334*7f4beda2SGovind Singh 	ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
335*7f4beda2SGovind Singh 
336*7f4beda2SGovind Singh 	return IRQ_HANDLED;
337*7f4beda2SGovind Singh }
338*7f4beda2SGovind Singh 
339*7f4beda2SGovind Singh static int ath11k_pci_config_irq(struct ath11k_base *ab)
340*7f4beda2SGovind Singh {
341*7f4beda2SGovind Singh 	struct ath11k_ce_pipe *ce_pipe;
342*7f4beda2SGovind Singh 	u32 msi_data_start;
343*7f4beda2SGovind Singh 	u32 msi_data_count;
344*7f4beda2SGovind Singh 	u32 msi_irq_start;
345*7f4beda2SGovind Singh 	unsigned int msi_data;
346*7f4beda2SGovind Singh 	int irq, i, ret, irq_idx;
347*7f4beda2SGovind Singh 
348*7f4beda2SGovind Singh 	ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab),
349*7f4beda2SGovind Singh 						 "CE", &msi_data_count,
350*7f4beda2SGovind Singh 						 &msi_data_start, &msi_irq_start);
351*7f4beda2SGovind Singh 	if (ret)
352*7f4beda2SGovind Singh 		return ret;
353*7f4beda2SGovind Singh 
354*7f4beda2SGovind Singh 	/* Configure CE irqs */
355*7f4beda2SGovind Singh 	for (i = 0; i < CE_COUNT; i++) {
356*7f4beda2SGovind Singh 		msi_data = (i % msi_data_count) + msi_irq_start;
357*7f4beda2SGovind Singh 		irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
358*7f4beda2SGovind Singh 		ce_pipe = &ab->ce.ce_pipe[i];
359*7f4beda2SGovind Singh 
360*7f4beda2SGovind Singh 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
361*7f4beda2SGovind Singh 			continue;
362*7f4beda2SGovind Singh 
363*7f4beda2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
364*7f4beda2SGovind Singh 
365*7f4beda2SGovind Singh 		ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
366*7f4beda2SGovind Singh 				  IRQF_SHARED, irq_name[irq_idx],
367*7f4beda2SGovind Singh 				  ce_pipe);
368*7f4beda2SGovind Singh 		if (ret) {
369*7f4beda2SGovind Singh 			ath11k_err(ab, "failed to request irq %d: %d\n",
370*7f4beda2SGovind Singh 				   irq_idx, ret);
371*7f4beda2SGovind Singh 			return ret;
372*7f4beda2SGovind Singh 		}
373*7f4beda2SGovind Singh 
374*7f4beda2SGovind Singh 		ab->irq_num[irq_idx] = irq;
375*7f4beda2SGovind Singh 	}
376*7f4beda2SGovind Singh 
377*7f4beda2SGovind Singh 	return 0;
378*7f4beda2SGovind Singh }
379*7f4beda2SGovind Singh 
380*7f4beda2SGovind Singh static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
381*7f4beda2SGovind Singh {
382*7f4beda2SGovind Singh 	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
383*7f4beda2SGovind Singh 
384*7f4beda2SGovind Singh 	cfg->tgt_ce = target_ce_config_wlan;
385*7f4beda2SGovind Singh 	cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan);
386*7f4beda2SGovind Singh 
387*7f4beda2SGovind Singh 	cfg->svc_to_ce_map = target_service_to_ce_map_wlan;
388*7f4beda2SGovind Singh 	cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan);
389*7f4beda2SGovind Singh }
390*7f4beda2SGovind Singh 
391*7f4beda2SGovind Singh static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
392*7f4beda2SGovind Singh {
393*7f4beda2SGovind Singh 	u32 irq_idx;
394*7f4beda2SGovind Singh 
395*7f4beda2SGovind Singh 	irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
396*7f4beda2SGovind Singh 	enable_irq(ab->irq_num[irq_idx]);
397*7f4beda2SGovind Singh }
398*7f4beda2SGovind Singh 
399*7f4beda2SGovind Singh static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
400*7f4beda2SGovind Singh {
401*7f4beda2SGovind Singh 	int i;
402*7f4beda2SGovind Singh 
403*7f4beda2SGovind Singh 	for (i = 0; i < CE_COUNT; i++) {
404*7f4beda2SGovind Singh 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
405*7f4beda2SGovind Singh 			continue;
406*7f4beda2SGovind Singh 		ath11k_pci_ce_irq_enable(ab, i);
407*7f4beda2SGovind Singh 	}
408*7f4beda2SGovind Singh }
409*7f4beda2SGovind Singh 
4105697a564SGovind Singh static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
4115697a564SGovind Singh {
4125697a564SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
4135697a564SGovind Singh 	struct msi_desc *msi_desc;
4145697a564SGovind Singh 	int num_vectors;
4155697a564SGovind Singh 	int ret;
4165697a564SGovind Singh 
4175697a564SGovind Singh 	num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
4185697a564SGovind Singh 					    msi_config.total_vectors,
4195697a564SGovind Singh 					    msi_config.total_vectors,
4205697a564SGovind Singh 					    PCI_IRQ_MSI);
4215697a564SGovind Singh 	if (num_vectors != msi_config.total_vectors) {
4225697a564SGovind Singh 		ath11k_err(ab, "failed to get %d MSI vectors, only %d available",
4235697a564SGovind Singh 			   msi_config.total_vectors, num_vectors);
4245697a564SGovind Singh 
4255697a564SGovind Singh 		if (num_vectors >= 0)
4265697a564SGovind Singh 			return -EINVAL;
4275697a564SGovind Singh 		else
4285697a564SGovind Singh 			return num_vectors;
4295697a564SGovind Singh 	}
4305697a564SGovind Singh 
4315697a564SGovind Singh 	msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
4325697a564SGovind Singh 	if (!msi_desc) {
4335697a564SGovind Singh 		ath11k_err(ab, "msi_desc is NULL!\n");
4345697a564SGovind Singh 		ret = -EINVAL;
4355697a564SGovind Singh 		goto free_msi_vector;
4365697a564SGovind Singh 	}
4375697a564SGovind Singh 
4385697a564SGovind Singh 	ab_pci->msi_ep_base_data = msi_desc->msg.data;
4395697a564SGovind Singh 
4405697a564SGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
4415697a564SGovind Singh 
4425697a564SGovind Singh 	return 0;
4435697a564SGovind Singh 
4445697a564SGovind Singh free_msi_vector:
4455697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
4465697a564SGovind Singh 
4475697a564SGovind Singh 	return ret;
4485697a564SGovind Singh }
4495697a564SGovind Singh 
4505697a564SGovind Singh static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
4515697a564SGovind Singh {
4525697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
4535697a564SGovind Singh }
4545697a564SGovind Singh 
4555762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
4565762613eSGovind Singh {
4575762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
4585762613eSGovind Singh 	u16 device_id;
4595762613eSGovind Singh 	int ret = 0;
4605762613eSGovind Singh 
4615762613eSGovind Singh 	pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
4625762613eSGovind Singh 	if (device_id != ab_pci->dev_id)  {
4635762613eSGovind Singh 		ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
4645762613eSGovind Singh 			   device_id, ab_pci->dev_id);
4655762613eSGovind Singh 		ret = -EIO;
4665762613eSGovind Singh 		goto out;
4675762613eSGovind Singh 	}
4685762613eSGovind Singh 
4695762613eSGovind Singh 	ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
4705762613eSGovind Singh 	if (ret) {
4715762613eSGovind Singh 		ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
4725762613eSGovind Singh 		goto out;
4735762613eSGovind Singh 	}
4745762613eSGovind Singh 
4755762613eSGovind Singh 	ret = pci_enable_device(pdev);
4765762613eSGovind Singh 	if (ret) {
4775762613eSGovind Singh 		ath11k_err(ab, "failed to enable pci device: %d\n", ret);
4785762613eSGovind Singh 		goto out;
4795762613eSGovind Singh 	}
4805762613eSGovind Singh 
4815762613eSGovind Singh 	ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
4825762613eSGovind Singh 	if (ret) {
4835762613eSGovind Singh 		ath11k_err(ab, "failed to request pci region: %d\n", ret);
4845762613eSGovind Singh 		goto disable_device;
4855762613eSGovind Singh 	}
4865762613eSGovind Singh 
4875762613eSGovind Singh 	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
4885762613eSGovind Singh 	if (ret) {
4895762613eSGovind Singh 		ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
4905762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
4915762613eSGovind Singh 		goto release_region;
4925762613eSGovind Singh 	}
4935762613eSGovind Singh 
4945762613eSGovind Singh 	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
4955762613eSGovind Singh 	if (ret) {
4965762613eSGovind Singh 		ath11k_err(ab, "failed to set pci consistent dma mask to %d: %d\n",
4975762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
4985762613eSGovind Singh 		goto release_region;
4995762613eSGovind Singh 	}
5005762613eSGovind Singh 
5015762613eSGovind Singh 	pci_set_master(pdev);
5025762613eSGovind Singh 
5035762613eSGovind Singh 	ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
5045762613eSGovind Singh 	ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
5055762613eSGovind Singh 	if (!ab->mem) {
5065762613eSGovind Singh 		ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
5075762613eSGovind Singh 		ret = -EIO;
5085762613eSGovind Singh 		goto clear_master;
5095762613eSGovind Singh 	}
5105762613eSGovind Singh 
5115762613eSGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
5125762613eSGovind Singh 	return 0;
5135762613eSGovind Singh 
5145762613eSGovind Singh clear_master:
5155762613eSGovind Singh 	pci_clear_master(pdev);
5165762613eSGovind Singh release_region:
5175762613eSGovind Singh 	pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
5185762613eSGovind Singh disable_device:
5195762613eSGovind Singh 	pci_disable_device(pdev);
5205762613eSGovind Singh out:
5215762613eSGovind Singh 	return ret;
5225762613eSGovind Singh }
5235762613eSGovind Singh 
5245762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
5255762613eSGovind Singh {
5265762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
5275762613eSGovind Singh 	struct pci_dev *pci_dev = ab_pci->pdev;
5285762613eSGovind Singh 
5295762613eSGovind Singh 	pci_iounmap(pci_dev, ab->mem);
5305762613eSGovind Singh 	ab->mem = NULL;
5315762613eSGovind Singh 	pci_clear_master(pci_dev);
5325762613eSGovind Singh 	pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
5335762613eSGovind Singh 	if (pci_is_enabled(pci_dev))
5345762613eSGovind Singh 		pci_disable_device(pci_dev);
5355762613eSGovind Singh }
5365762613eSGovind Singh 
5371399fb87SGovind Singh static int ath11k_pci_power_up(struct ath11k_base *ab)
5381399fb87SGovind Singh {
5391399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
5401399fb87SGovind Singh 	int ret;
5411399fb87SGovind Singh 
5421399fb87SGovind Singh 	ret = ath11k_mhi_start(ab_pci);
5431399fb87SGovind Singh 	if (ret) {
5441399fb87SGovind Singh 		ath11k_err(ab, "failed to start mhi: %d\n", ret);
5451399fb87SGovind Singh 		return ret;
5461399fb87SGovind Singh 	}
5471399fb87SGovind Singh 
5481399fb87SGovind Singh 	return 0;
5491399fb87SGovind Singh }
5501399fb87SGovind Singh 
5511399fb87SGovind Singh static void ath11k_pci_power_down(struct ath11k_base *ab)
5521399fb87SGovind Singh {
5531399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
5541399fb87SGovind Singh 
5551399fb87SGovind Singh 	ath11k_mhi_stop(ab_pci);
5561399fb87SGovind Singh }
5571399fb87SGovind Singh 
558*7f4beda2SGovind Singh static void ath11k_pci_stop(struct ath11k_base *ab)
559*7f4beda2SGovind Singh {
560*7f4beda2SGovind Singh 	ath11k_ce_cleanup_pipes(ab);
561*7f4beda2SGovind Singh }
562*7f4beda2SGovind Singh 
563*7f4beda2SGovind Singh static int ath11k_pci_start(struct ath11k_base *ab)
564*7f4beda2SGovind Singh {
565*7f4beda2SGovind Singh 	ath11k_pci_ce_irqs_enable(ab);
566*7f4beda2SGovind Singh 
567*7f4beda2SGovind Singh 	return 0;
568*7f4beda2SGovind Singh }
569*7f4beda2SGovind Singh 
570*7f4beda2SGovind Singh static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
571*7f4beda2SGovind Singh 	.start = ath11k_pci_start,
572*7f4beda2SGovind Singh 	.stop = ath11k_pci_stop,
5731399fb87SGovind Singh 	.power_down = ath11k_pci_power_down,
5741399fb87SGovind Singh 	.power_up = ath11k_pci_power_up,
5751399fb87SGovind Singh };
5761399fb87SGovind Singh 
5776e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev,
5786e0355afSGovind Singh 			    const struct pci_device_id *pci_dev)
5796e0355afSGovind Singh {
5806e0355afSGovind Singh 	struct ath11k_base *ab;
5815762613eSGovind Singh 	struct ath11k_pci *ab_pci;
5826e0355afSGovind Singh 	enum ath11k_hw_rev hw_rev;
5835762613eSGovind Singh 	int ret;
5846e0355afSGovind Singh 
5856e0355afSGovind Singh 	dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n");
5866e0355afSGovind Singh 
5876e0355afSGovind Singh 	switch (pci_dev->device) {
5886e0355afSGovind Singh 	case QCA6390_DEVICE_ID:
5896e0355afSGovind Singh 		hw_rev = ATH11K_HW_QCA6390_HW20;
5906e0355afSGovind Singh 		break;
5916e0355afSGovind Singh 	default:
5926e0355afSGovind Singh 		dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
5936e0355afSGovind Singh 			pci_dev->device);
5946e0355afSGovind Singh 		return -ENOTSUPP;
5956e0355afSGovind Singh 	}
5966e0355afSGovind Singh 
5975762613eSGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI);
5986e0355afSGovind Singh 	if (!ab) {
5996e0355afSGovind Singh 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
6006e0355afSGovind Singh 		return -ENOMEM;
6016e0355afSGovind Singh 	}
6026e0355afSGovind Singh 
6036e0355afSGovind Singh 	ab->dev = &pdev->dev;
6046e0355afSGovind Singh 	ab->hw_rev = hw_rev;
6056e0355afSGovind Singh 	pci_set_drvdata(pdev, ab);
6065762613eSGovind Singh 	ab_pci = ath11k_pci_priv(ab);
6075762613eSGovind Singh 	ab_pci->dev_id = pci_dev->device;
6085762613eSGovind Singh 	ab_pci->ab = ab;
6095697a564SGovind Singh 	ab_pci->pdev = pdev;
610*7f4beda2SGovind Singh 	ab->hif.ops = &ath11k_pci_hif_ops;
6115762613eSGovind Singh 	pci_set_drvdata(pdev, ab);
6125762613eSGovind Singh 
6135762613eSGovind Singh 	ret = ath11k_pci_claim(ab_pci, pdev);
6145762613eSGovind Singh 	if (ret) {
6155762613eSGovind Singh 		ath11k_err(ab, "failed to claim device: %d\n", ret);
6165762613eSGovind Singh 		goto err_free_core;
6175762613eSGovind Singh 	}
6186e0355afSGovind Singh 
6195697a564SGovind Singh 	ret = ath11k_pci_enable_msi(ab_pci);
6205697a564SGovind Singh 	if (ret) {
6215697a564SGovind Singh 		ath11k_err(ab, "failed to enable msi: %d\n", ret);
6225697a564SGovind Singh 		goto err_pci_free_region;
6235697a564SGovind Singh 	}
6245697a564SGovind Singh 
625b8246f88SKalle Valo 	ret = ath11k_core_pre_init(ab);
626b8246f88SKalle Valo 	if (ret)
627b8246f88SKalle Valo 		goto err_pci_disable_msi;
628b8246f88SKalle Valo 
6291399fb87SGovind Singh 	ret = ath11k_mhi_register(ab_pci);
6301399fb87SGovind Singh 	if (ret) {
6311399fb87SGovind Singh 		ath11k_err(ab, "failed to register mhi: %d\n", ret);
6321399fb87SGovind Singh 		goto err_pci_disable_msi;
6331399fb87SGovind Singh 	}
6341399fb87SGovind Singh 
635*7f4beda2SGovind Singh 	ret = ath11k_hal_srng_init(ab);
636*7f4beda2SGovind Singh 	if (ret)
637*7f4beda2SGovind Singh 		goto err_mhi_unregister;
638*7f4beda2SGovind Singh 
639*7f4beda2SGovind Singh 	ret = ath11k_ce_alloc_pipes(ab);
640*7f4beda2SGovind Singh 	if (ret) {
641*7f4beda2SGovind Singh 		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
642*7f4beda2SGovind Singh 		goto err_hal_srng_deinit;
643*7f4beda2SGovind Singh 	}
644*7f4beda2SGovind Singh 
645*7f4beda2SGovind Singh 	ath11k_pci_init_qmi_ce_config(ab);
646*7f4beda2SGovind Singh 
647*7f4beda2SGovind Singh 	ret = ath11k_pci_config_irq(ab);
648*7f4beda2SGovind Singh 	if (ret) {
649*7f4beda2SGovind Singh 		ath11k_err(ab, "failed to config irq: %d\n", ret);
650*7f4beda2SGovind Singh 		goto err_ce_free;
651*7f4beda2SGovind Singh 	}
652*7f4beda2SGovind Singh 
653*7f4beda2SGovind Singh 	ret = ath11k_core_init(ab);
654*7f4beda2SGovind Singh 	if (ret) {
655*7f4beda2SGovind Singh 		ath11k_err(ab, "failed to init core: %d\n", ret);
656*7f4beda2SGovind Singh 		goto err_free_irq;
657*7f4beda2SGovind Singh 	}
6586e0355afSGovind Singh 	return 0;
6595762613eSGovind Singh 
660*7f4beda2SGovind Singh err_free_irq:
661*7f4beda2SGovind Singh 	ath11k_pci_free_irq(ab);
662*7f4beda2SGovind Singh 
663*7f4beda2SGovind Singh err_ce_free:
664*7f4beda2SGovind Singh 	ath11k_ce_free_pipes(ab);
665*7f4beda2SGovind Singh 
666*7f4beda2SGovind Singh err_hal_srng_deinit:
667*7f4beda2SGovind Singh 	ath11k_hal_srng_deinit(ab);
668*7f4beda2SGovind Singh 
669*7f4beda2SGovind Singh err_mhi_unregister:
670*7f4beda2SGovind Singh 	ath11k_mhi_unregister(ab_pci);
671*7f4beda2SGovind Singh 
672b8246f88SKalle Valo err_pci_disable_msi:
673b8246f88SKalle Valo 	ath11k_pci_disable_msi(ab_pci);
674b8246f88SKalle Valo 
6755697a564SGovind Singh err_pci_free_region:
6765697a564SGovind Singh 	ath11k_pci_free_region(ab_pci);
6775697a564SGovind Singh 
6785762613eSGovind Singh err_free_core:
6795762613eSGovind Singh 	ath11k_core_free(ab);
6805697a564SGovind Singh 
6815762613eSGovind Singh 	return ret;
6826e0355afSGovind Singh }
6836e0355afSGovind Singh 
6846e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev)
6856e0355afSGovind Singh {
6866e0355afSGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
6875762613eSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
6886e0355afSGovind Singh 
6896e0355afSGovind Singh 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
6901399fb87SGovind Singh 	ath11k_mhi_unregister(ab_pci);
6915697a564SGovind Singh 	ath11k_pci_disable_msi(ab_pci);
6925762613eSGovind Singh 	ath11k_pci_free_region(ab_pci);
693*7f4beda2SGovind Singh 	ath11k_pci_free_irq(ab);
6946e0355afSGovind Singh 	ath11k_core_free(ab);
6956e0355afSGovind Singh }
6966e0355afSGovind Singh 
6971399fb87SGovind Singh static void ath11k_pci_shutdown(struct pci_dev *pdev)
6981399fb87SGovind Singh {
6991399fb87SGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
7001399fb87SGovind Singh 
7011399fb87SGovind Singh 	ath11k_pci_power_down(ab);
7021399fb87SGovind Singh }
7031399fb87SGovind Singh 
7046e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = {
7056e0355afSGovind Singh 	.name = "ath11k_pci",
7066e0355afSGovind Singh 	.id_table = ath11k_pci_id_table,
7076e0355afSGovind Singh 	.probe = ath11k_pci_probe,
7086e0355afSGovind Singh 	.remove = ath11k_pci_remove,
7091399fb87SGovind Singh 	.shutdown = ath11k_pci_shutdown,
7106e0355afSGovind Singh };
7116e0355afSGovind Singh 
7126e0355afSGovind Singh static int ath11k_pci_init(void)
7136e0355afSGovind Singh {
7146e0355afSGovind Singh 	int ret;
7156e0355afSGovind Singh 
7166e0355afSGovind Singh 	ret = pci_register_driver(&ath11k_pci_driver);
7176e0355afSGovind Singh 	if (ret)
7186e0355afSGovind Singh 		pr_err("failed to register ath11k pci driver: %d\n",
7196e0355afSGovind Singh 		       ret);
7206e0355afSGovind Singh 
7216e0355afSGovind Singh 	return ret;
7226e0355afSGovind Singh }
7236e0355afSGovind Singh module_init(ath11k_pci_init);
7246e0355afSGovind Singh 
7256e0355afSGovind Singh static void ath11k_pci_exit(void)
7266e0355afSGovind Singh {
7276e0355afSGovind Singh 	pci_unregister_driver(&ath11k_pci_driver);
7286e0355afSGovind Singh }
7296e0355afSGovind Singh 
7306e0355afSGovind Singh module_exit(ath11k_pci_exit);
7316e0355afSGovind Singh 
7326e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
7336e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL");
734