xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/pci.c (revision eb8de0490e1f819c50c1b5b0a5558a9897dd75f0)
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 
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 
301ff8ed78SGovind Singh static const struct ath11k_bus_params ath11k_pci_bus_params = {
311ff8ed78SGovind Singh 	.mhi_support = true,
3256970454SGovind Singh 	.m3_fw_support = true,
336eb6ea51SGovind Singh 	.fixed_bdf_addr = false,
346eb6ea51SGovind Singh 	.fixed_mem_region = false,
351ff8ed78SGovind Singh };
361ff8ed78SGovind Singh 
375697a564SGovind Singh static const struct ath11k_msi_config msi_config = {
385697a564SGovind Singh 	.total_vectors = 32,
395697a564SGovind Singh 	.total_users = 4,
405697a564SGovind Singh 	.users = (struct ath11k_msi_user[]) {
415697a564SGovind Singh 		{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
425697a564SGovind Singh 		{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
435697a564SGovind Singh 		{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
445697a564SGovind Singh 		{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
455697a564SGovind Singh 	},
465697a564SGovind Singh };
475697a564SGovind Singh 
487f4beda2SGovind Singh /* Target firmware's Copy Engine configuration. */
497f4beda2SGovind Singh static const struct ce_pipe_config target_ce_config_wlan[] = {
507f4beda2SGovind Singh 	/* CE0: host->target HTC control and raw streams */
517f4beda2SGovind Singh 	{
527f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(0),
537f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
547f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
557f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
567f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
577f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
587f4beda2SGovind Singh 	},
597f4beda2SGovind Singh 
607f4beda2SGovind Singh 	/* CE1: target->host HTT + HTC control */
617f4beda2SGovind Singh 	{
627f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(1),
637f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
647f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
657f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
667f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
677f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
687f4beda2SGovind Singh 	},
697f4beda2SGovind Singh 
707f4beda2SGovind Singh 	/* CE2: target->host WMI */
717f4beda2SGovind Singh 	{
727f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(2),
737f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
747f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
757f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
767f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
777f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
787f4beda2SGovind Singh 	},
797f4beda2SGovind Singh 
807f4beda2SGovind Singh 	/* CE3: host->target WMI */
817f4beda2SGovind Singh 	{
827f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(3),
837f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
847f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
857f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
867f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
877f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
887f4beda2SGovind Singh 	},
897f4beda2SGovind Singh 
907f4beda2SGovind Singh 	/* CE4: host->target HTT */
917f4beda2SGovind Singh 	{
927f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(4),
937f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
947f4beda2SGovind Singh 		.nentries = __cpu_to_le32(256),
957f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(256),
967f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
977f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
987f4beda2SGovind Singh 	},
997f4beda2SGovind Singh 
1007f4beda2SGovind Singh 	/* CE5: target->host Pktlog */
1017f4beda2SGovind Singh 	{
1027f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(5),
1037f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
1047f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
1057f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(2048),
1067f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
1077f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
1087f4beda2SGovind Singh 	},
1097f4beda2SGovind Singh 
1107f4beda2SGovind Singh 	/* CE6: Reserved for target autonomous hif_memcpy */
1117f4beda2SGovind Singh 	{
1127f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(6),
1137f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
1147f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
1157f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(16384),
1167f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
1177f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
1187f4beda2SGovind Singh 	},
1197f4beda2SGovind Singh 
1207f4beda2SGovind Singh 	/* CE7 used only by Host */
1217f4beda2SGovind Singh 	{
1227f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(7),
1237f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
1247f4beda2SGovind Singh 		.nentries = __cpu_to_le32(0),
1257f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(0),
1267f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
1277f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
1287f4beda2SGovind Singh 	},
1297f4beda2SGovind Singh 
1307f4beda2SGovind Singh 	/* CE8 target->host used only by IPA */
1317f4beda2SGovind Singh 	{
1327f4beda2SGovind Singh 		.pipenum = __cpu_to_le32(8),
1337f4beda2SGovind Singh 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
1347f4beda2SGovind Singh 		.nentries = __cpu_to_le32(32),
1357f4beda2SGovind Singh 		.nbytes_max = __cpu_to_le32(16384),
1367f4beda2SGovind Singh 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
1377f4beda2SGovind Singh 		.reserved = __cpu_to_le32(0),
1387f4beda2SGovind Singh 	},
1397f4beda2SGovind Singh 	/* CE 9, 10, 11 are used by MHI driver */
1407f4beda2SGovind Singh };
1417f4beda2SGovind Singh 
1427f4beda2SGovind Singh /* Map from service/endpoint to Copy Engine.
1437f4beda2SGovind Singh  * This table is derived from the CE_PCI TABLE, above.
1447f4beda2SGovind Singh  * It is passed to the Target at startup for use by firmware.
1457f4beda2SGovind Singh  */
1467f4beda2SGovind Singh static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
1477f4beda2SGovind Singh 	{
1487f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
1497f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
1507f4beda2SGovind Singh 		__cpu_to_le32(3),
1517f4beda2SGovind Singh 	},
1527f4beda2SGovind Singh 	{
1537f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
1547f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
1557f4beda2SGovind Singh 		__cpu_to_le32(2),
1567f4beda2SGovind Singh 	},
1577f4beda2SGovind Singh 	{
1587f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
1597f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
1607f4beda2SGovind Singh 		__cpu_to_le32(3),
1617f4beda2SGovind Singh 	},
1627f4beda2SGovind Singh 	{
1637f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
1647f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
1657f4beda2SGovind Singh 		__cpu_to_le32(2),
1667f4beda2SGovind Singh 	},
1677f4beda2SGovind Singh 	{
1687f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
1697f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
1707f4beda2SGovind Singh 		__cpu_to_le32(3),
1717f4beda2SGovind Singh 	},
1727f4beda2SGovind Singh 	{
1737f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
1747f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
1757f4beda2SGovind Singh 		__cpu_to_le32(2),
1767f4beda2SGovind Singh 	},
1777f4beda2SGovind Singh 	{
1787f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
1797f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
1807f4beda2SGovind Singh 		__cpu_to_le32(3),
1817f4beda2SGovind Singh 	},
1827f4beda2SGovind Singh 	{
1837f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
1847f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
1857f4beda2SGovind Singh 		__cpu_to_le32(2),
1867f4beda2SGovind Singh 	},
1877f4beda2SGovind Singh 	{
1887f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
1897f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
1907f4beda2SGovind Singh 		__cpu_to_le32(3),
1917f4beda2SGovind Singh 	},
1927f4beda2SGovind Singh 	{
1937f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
1947f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
1957f4beda2SGovind Singh 		__cpu_to_le32(2),
1967f4beda2SGovind Singh 	},
1977f4beda2SGovind Singh 
1987f4beda2SGovind Singh 	{
1997f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
2007f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
2017f4beda2SGovind Singh 		__cpu_to_le32(0),
2027f4beda2SGovind Singh 	},
2037f4beda2SGovind Singh 	{
2047f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
2057f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
2067f4beda2SGovind Singh 		__cpu_to_le32(2),
2077f4beda2SGovind Singh 	},
2087f4beda2SGovind Singh 
2097f4beda2SGovind Singh 	{
2107f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
2117f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
2127f4beda2SGovind Singh 		__cpu_to_le32(4),
2137f4beda2SGovind Singh 	},
2147f4beda2SGovind Singh 	{
2157f4beda2SGovind Singh 		__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
2167f4beda2SGovind Singh 		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
2177f4beda2SGovind Singh 		__cpu_to_le32(1),
2187f4beda2SGovind Singh 	},
2197f4beda2SGovind Singh 
2207f4beda2SGovind Singh 	/* (Additions here) */
2217f4beda2SGovind Singh 
2227f4beda2SGovind Singh 	{ /* must be last */
2237f4beda2SGovind Singh 		__cpu_to_le32(0),
2247f4beda2SGovind Singh 		__cpu_to_le32(0),
2257f4beda2SGovind Singh 		__cpu_to_le32(0),
2267f4beda2SGovind Singh 	},
2277f4beda2SGovind Singh };
2287f4beda2SGovind Singh 
2297f4beda2SGovind Singh static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
2307f4beda2SGovind Singh 	"bhi",
2317f4beda2SGovind Singh 	"mhi-er0",
2327f4beda2SGovind Singh 	"mhi-er1",
2337f4beda2SGovind Singh 	"ce0",
2347f4beda2SGovind Singh 	"ce1",
2357f4beda2SGovind Singh 	"ce2",
2367f4beda2SGovind Singh 	"ce3",
2377f4beda2SGovind Singh 	"ce4",
2387f4beda2SGovind Singh 	"ce5",
2397f4beda2SGovind Singh 	"ce6",
2407f4beda2SGovind Singh 	"ce7",
2417f4beda2SGovind Singh 	"ce8",
2427f4beda2SGovind Singh 	"ce9",
2437f4beda2SGovind Singh 	"ce10",
2447f4beda2SGovind Singh 	"ce11",
2457f4beda2SGovind Singh 	"host2wbm-desc-feed",
2467f4beda2SGovind Singh 	"host2reo-re-injection",
2477f4beda2SGovind Singh 	"host2reo-command",
2487f4beda2SGovind Singh 	"host2rxdma-monitor-ring3",
2497f4beda2SGovind Singh 	"host2rxdma-monitor-ring2",
2507f4beda2SGovind Singh 	"host2rxdma-monitor-ring1",
2517f4beda2SGovind Singh 	"reo2ost-exception",
2527f4beda2SGovind Singh 	"wbm2host-rx-release",
2537f4beda2SGovind Singh 	"reo2host-status",
2547f4beda2SGovind Singh 	"reo2host-destination-ring4",
2557f4beda2SGovind Singh 	"reo2host-destination-ring3",
2567f4beda2SGovind Singh 	"reo2host-destination-ring2",
2577f4beda2SGovind Singh 	"reo2host-destination-ring1",
2587f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac3",
2597f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac2",
2607f4beda2SGovind Singh 	"rxdma2host-monitor-destination-mac1",
2617f4beda2SGovind Singh 	"ppdu-end-interrupts-mac3",
2627f4beda2SGovind Singh 	"ppdu-end-interrupts-mac2",
2637f4beda2SGovind Singh 	"ppdu-end-interrupts-mac1",
2647f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac3",
2657f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac2",
2667f4beda2SGovind Singh 	"rxdma2host-monitor-status-ring-mac1",
2677f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac3",
2687f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac2",
2697f4beda2SGovind Singh 	"host2rxdma-host-buf-ring-mac1",
2707f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac3",
2717f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac2",
2727f4beda2SGovind Singh 	"rxdma2host-destination-ring-mac1",
2737f4beda2SGovind Singh 	"host2tcl-input-ring4",
2747f4beda2SGovind Singh 	"host2tcl-input-ring3",
2757f4beda2SGovind Singh 	"host2tcl-input-ring2",
2767f4beda2SGovind Singh 	"host2tcl-input-ring1",
2777f4beda2SGovind Singh 	"wbm2host-tx-completions-ring3",
2787f4beda2SGovind Singh 	"wbm2host-tx-completions-ring2",
2797f4beda2SGovind Singh 	"wbm2host-tx-completions-ring1",
2807f4beda2SGovind Singh 	"tcl2host-status-ring",
2817f4beda2SGovind Singh };
2827f4beda2SGovind Singh 
2831399fb87SGovind Singh int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
2841399fb87SGovind Singh {
2851399fb87SGovind Singh 	struct pci_dev *pci_dev = to_pci_dev(dev);
2861399fb87SGovind Singh 
2871399fb87SGovind Singh 	return pci_irq_vector(pci_dev, vector);
2881399fb87SGovind Singh }
2891399fb87SGovind Singh 
2901399fb87SGovind Singh int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
2911399fb87SGovind Singh 				       int *num_vectors, u32 *user_base_data,
2921399fb87SGovind Singh 				       u32 *base_vector)
2931399fb87SGovind Singh {
2941399fb87SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
2951399fb87SGovind Singh 	int idx;
2961399fb87SGovind Singh 
2971399fb87SGovind Singh 	for (idx = 0; idx < msi_config.total_users; idx++) {
2981399fb87SGovind Singh 		if (strcmp(user_name, msi_config.users[idx].name) == 0) {
2991399fb87SGovind Singh 			*num_vectors = msi_config.users[idx].num_vectors;
3001399fb87SGovind Singh 			*user_base_data = msi_config.users[idx].base_vector
3011399fb87SGovind Singh 				+ ab_pci->msi_ep_base_data;
3021399fb87SGovind Singh 			*base_vector = msi_config.users[idx].base_vector;
3031399fb87SGovind Singh 
3041399fb87SGovind Singh 			ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
3051399fb87SGovind Singh 				   user_name, *num_vectors, *user_base_data,
3061399fb87SGovind Singh 				   *base_vector);
3071399fb87SGovind Singh 
3081399fb87SGovind Singh 			return 0;
3091399fb87SGovind Singh 		}
3101399fb87SGovind Singh 	}
3111399fb87SGovind Singh 
3121399fb87SGovind Singh 	ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
3131399fb87SGovind Singh 
3141399fb87SGovind Singh 	return -EINVAL;
3151399fb87SGovind Singh }
3161399fb87SGovind Singh 
3177f4beda2SGovind Singh static void ath11k_pci_free_irq(struct ath11k_base *ab)
3187f4beda2SGovind Singh {
3197f4beda2SGovind Singh 	int i, irq_idx;
3207f4beda2SGovind Singh 
3217f4beda2SGovind Singh 	for (i = 0; i < CE_COUNT; i++) {
3227f4beda2SGovind Singh 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
3237f4beda2SGovind Singh 			continue;
3247f4beda2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
3257f4beda2SGovind Singh 		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
3267f4beda2SGovind Singh 	}
3277f4beda2SGovind Singh }
3287f4beda2SGovind Singh 
3297f4beda2SGovind Singh static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
3307f4beda2SGovind Singh {
3317f4beda2SGovind Singh 	u32 irq_idx;
3327f4beda2SGovind Singh 
3337f4beda2SGovind Singh 	irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
3347f4beda2SGovind Singh 	disable_irq_nosync(ab->irq_num[irq_idx]);
3357f4beda2SGovind Singh }
3367f4beda2SGovind Singh 
3377f4beda2SGovind Singh static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
3387f4beda2SGovind Singh {
3397f4beda2SGovind Singh 	struct ath11k_ce_pipe *ce_pipe = arg;
3407f4beda2SGovind Singh 
3417f4beda2SGovind Singh 	ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
3427f4beda2SGovind Singh 
3437f4beda2SGovind Singh 	return IRQ_HANDLED;
3447f4beda2SGovind Singh }
3457f4beda2SGovind Singh 
3467f4beda2SGovind Singh static int ath11k_pci_config_irq(struct ath11k_base *ab)
3477f4beda2SGovind Singh {
3487f4beda2SGovind Singh 	struct ath11k_ce_pipe *ce_pipe;
3497f4beda2SGovind Singh 	u32 msi_data_start;
3507f4beda2SGovind Singh 	u32 msi_data_count;
3517f4beda2SGovind Singh 	u32 msi_irq_start;
3527f4beda2SGovind Singh 	unsigned int msi_data;
3537f4beda2SGovind Singh 	int irq, i, ret, irq_idx;
3547f4beda2SGovind Singh 
3557f4beda2SGovind Singh 	ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab),
3567f4beda2SGovind Singh 						 "CE", &msi_data_count,
3577f4beda2SGovind Singh 						 &msi_data_start, &msi_irq_start);
3587f4beda2SGovind Singh 	if (ret)
3597f4beda2SGovind Singh 		return ret;
3607f4beda2SGovind Singh 
3617f4beda2SGovind Singh 	/* Configure CE irqs */
3627f4beda2SGovind Singh 	for (i = 0; i < CE_COUNT; i++) {
3637f4beda2SGovind Singh 		msi_data = (i % msi_data_count) + msi_irq_start;
3647f4beda2SGovind Singh 		irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
3657f4beda2SGovind Singh 		ce_pipe = &ab->ce.ce_pipe[i];
3667f4beda2SGovind Singh 
3677f4beda2SGovind Singh 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
3687f4beda2SGovind Singh 			continue;
3697f4beda2SGovind Singh 
3707f4beda2SGovind Singh 		irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
3717f4beda2SGovind Singh 
3727f4beda2SGovind Singh 		ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
3737f4beda2SGovind Singh 				  IRQF_SHARED, irq_name[irq_idx],
3747f4beda2SGovind Singh 				  ce_pipe);
3757f4beda2SGovind Singh 		if (ret) {
3767f4beda2SGovind Singh 			ath11k_err(ab, "failed to request irq %d: %d\n",
3777f4beda2SGovind Singh 				   irq_idx, ret);
3787f4beda2SGovind Singh 			return ret;
3797f4beda2SGovind Singh 		}
3807f4beda2SGovind Singh 
3817f4beda2SGovind Singh 		ab->irq_num[irq_idx] = irq;
3827f4beda2SGovind Singh 	}
3837f4beda2SGovind Singh 
3847f4beda2SGovind Singh 	return 0;
3857f4beda2SGovind Singh }
3867f4beda2SGovind Singh 
3877f4beda2SGovind Singh static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
3887f4beda2SGovind Singh {
3897f4beda2SGovind Singh 	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
3907f4beda2SGovind Singh 
3917f4beda2SGovind Singh 	cfg->tgt_ce = target_ce_config_wlan;
3927f4beda2SGovind Singh 	cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan);
3937f4beda2SGovind Singh 
3947f4beda2SGovind Singh 	cfg->svc_to_ce_map = target_service_to_ce_map_wlan;
3957f4beda2SGovind Singh 	cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan);
396*eb8de049SGovind Singh 	ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390;
3977f4beda2SGovind Singh }
3987f4beda2SGovind Singh 
3997f4beda2SGovind Singh static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
4007f4beda2SGovind Singh {
4017f4beda2SGovind Singh 	u32 irq_idx;
4027f4beda2SGovind Singh 
4037f4beda2SGovind Singh 	irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
4047f4beda2SGovind Singh 	enable_irq(ab->irq_num[irq_idx]);
4057f4beda2SGovind Singh }
4067f4beda2SGovind Singh 
4077f4beda2SGovind Singh static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
4087f4beda2SGovind Singh {
4097f4beda2SGovind Singh 	int i;
4107f4beda2SGovind Singh 
4117f4beda2SGovind Singh 	for (i = 0; i < CE_COUNT; i++) {
4127f4beda2SGovind Singh 		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
4137f4beda2SGovind Singh 			continue;
4147f4beda2SGovind Singh 		ath11k_pci_ce_irq_enable(ab, i);
4157f4beda2SGovind Singh 	}
4167f4beda2SGovind Singh }
4177f4beda2SGovind Singh 
4185697a564SGovind Singh static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
4195697a564SGovind Singh {
4205697a564SGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
4215697a564SGovind Singh 	struct msi_desc *msi_desc;
4225697a564SGovind Singh 	int num_vectors;
4235697a564SGovind Singh 	int ret;
4245697a564SGovind Singh 
4255697a564SGovind Singh 	num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
4265697a564SGovind Singh 					    msi_config.total_vectors,
4275697a564SGovind Singh 					    msi_config.total_vectors,
4285697a564SGovind Singh 					    PCI_IRQ_MSI);
4295697a564SGovind Singh 	if (num_vectors != msi_config.total_vectors) {
4305697a564SGovind Singh 		ath11k_err(ab, "failed to get %d MSI vectors, only %d available",
4315697a564SGovind Singh 			   msi_config.total_vectors, num_vectors);
4325697a564SGovind Singh 
4335697a564SGovind Singh 		if (num_vectors >= 0)
4345697a564SGovind Singh 			return -EINVAL;
4355697a564SGovind Singh 		else
4365697a564SGovind Singh 			return num_vectors;
4375697a564SGovind Singh 	}
4385697a564SGovind Singh 
4395697a564SGovind Singh 	msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
4405697a564SGovind Singh 	if (!msi_desc) {
4415697a564SGovind Singh 		ath11k_err(ab, "msi_desc is NULL!\n");
4425697a564SGovind Singh 		ret = -EINVAL;
4435697a564SGovind Singh 		goto free_msi_vector;
4445697a564SGovind Singh 	}
4455697a564SGovind Singh 
4465697a564SGovind Singh 	ab_pci->msi_ep_base_data = msi_desc->msg.data;
4475697a564SGovind Singh 
4485697a564SGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
4495697a564SGovind Singh 
4505697a564SGovind Singh 	return 0;
4515697a564SGovind Singh 
4525697a564SGovind Singh free_msi_vector:
4535697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
4545697a564SGovind Singh 
4555697a564SGovind Singh 	return ret;
4565697a564SGovind Singh }
4575697a564SGovind Singh 
4585697a564SGovind Singh static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
4595697a564SGovind Singh {
4605697a564SGovind Singh 	pci_free_irq_vectors(ab_pci->pdev);
4615697a564SGovind Singh }
4625697a564SGovind Singh 
4635762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
4645762613eSGovind Singh {
4655762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
4665762613eSGovind Singh 	u16 device_id;
4675762613eSGovind Singh 	int ret = 0;
4685762613eSGovind Singh 
4695762613eSGovind Singh 	pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
4705762613eSGovind Singh 	if (device_id != ab_pci->dev_id)  {
4715762613eSGovind Singh 		ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
4725762613eSGovind Singh 			   device_id, ab_pci->dev_id);
4735762613eSGovind Singh 		ret = -EIO;
4745762613eSGovind Singh 		goto out;
4755762613eSGovind Singh 	}
4765762613eSGovind Singh 
4775762613eSGovind Singh 	ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
4785762613eSGovind Singh 	if (ret) {
4795762613eSGovind Singh 		ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
4805762613eSGovind Singh 		goto out;
4815762613eSGovind Singh 	}
4825762613eSGovind Singh 
4835762613eSGovind Singh 	ret = pci_enable_device(pdev);
4845762613eSGovind Singh 	if (ret) {
4855762613eSGovind Singh 		ath11k_err(ab, "failed to enable pci device: %d\n", ret);
4865762613eSGovind Singh 		goto out;
4875762613eSGovind Singh 	}
4885762613eSGovind Singh 
4895762613eSGovind Singh 	ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
4905762613eSGovind Singh 	if (ret) {
4915762613eSGovind Singh 		ath11k_err(ab, "failed to request pci region: %d\n", ret);
4925762613eSGovind Singh 		goto disable_device;
4935762613eSGovind Singh 	}
4945762613eSGovind Singh 
4955762613eSGovind Singh 	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
4965762613eSGovind Singh 	if (ret) {
4975762613eSGovind Singh 		ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
4985762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
4995762613eSGovind Singh 		goto release_region;
5005762613eSGovind Singh 	}
5015762613eSGovind Singh 
5025762613eSGovind Singh 	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
5035762613eSGovind Singh 	if (ret) {
5045762613eSGovind Singh 		ath11k_err(ab, "failed to set pci consistent dma mask to %d: %d\n",
5055762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
5065762613eSGovind Singh 		goto release_region;
5075762613eSGovind Singh 	}
5085762613eSGovind Singh 
5095762613eSGovind Singh 	pci_set_master(pdev);
5105762613eSGovind Singh 
5115762613eSGovind Singh 	ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
5125762613eSGovind Singh 	ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
5135762613eSGovind Singh 	if (!ab->mem) {
5145762613eSGovind Singh 		ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
5155762613eSGovind Singh 		ret = -EIO;
5165762613eSGovind Singh 		goto clear_master;
5175762613eSGovind Singh 	}
5185762613eSGovind Singh 
5195762613eSGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
5205762613eSGovind Singh 	return 0;
5215762613eSGovind Singh 
5225762613eSGovind Singh clear_master:
5235762613eSGovind Singh 	pci_clear_master(pdev);
5245762613eSGovind Singh release_region:
5255762613eSGovind Singh 	pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
5265762613eSGovind Singh disable_device:
5275762613eSGovind Singh 	pci_disable_device(pdev);
5285762613eSGovind Singh out:
5295762613eSGovind Singh 	return ret;
5305762613eSGovind Singh }
5315762613eSGovind Singh 
5325762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
5335762613eSGovind Singh {
5345762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
5355762613eSGovind Singh 	struct pci_dev *pci_dev = ab_pci->pdev;
5365762613eSGovind Singh 
5375762613eSGovind Singh 	pci_iounmap(pci_dev, ab->mem);
5385762613eSGovind Singh 	ab->mem = NULL;
5395762613eSGovind Singh 	pci_clear_master(pci_dev);
5405762613eSGovind Singh 	pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
5415762613eSGovind Singh 	if (pci_is_enabled(pci_dev))
5425762613eSGovind Singh 		pci_disable_device(pci_dev);
5435762613eSGovind Singh }
5445762613eSGovind Singh 
5451399fb87SGovind Singh static int ath11k_pci_power_up(struct ath11k_base *ab)
5461399fb87SGovind Singh {
5471399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
5481399fb87SGovind Singh 	int ret;
5491399fb87SGovind Singh 
5501399fb87SGovind Singh 	ret = ath11k_mhi_start(ab_pci);
5511399fb87SGovind Singh 	if (ret) {
5521399fb87SGovind Singh 		ath11k_err(ab, "failed to start mhi: %d\n", ret);
5531399fb87SGovind Singh 		return ret;
5541399fb87SGovind Singh 	}
5551399fb87SGovind Singh 
5561399fb87SGovind Singh 	return 0;
5571399fb87SGovind Singh }
5581399fb87SGovind Singh 
5591399fb87SGovind Singh static void ath11k_pci_power_down(struct ath11k_base *ab)
5601399fb87SGovind Singh {
5611399fb87SGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
5621399fb87SGovind Singh 
5631399fb87SGovind Singh 	ath11k_mhi_stop(ab_pci);
5641399fb87SGovind Singh }
5651399fb87SGovind Singh 
5667f4beda2SGovind Singh static void ath11k_pci_stop(struct ath11k_base *ab)
5677f4beda2SGovind Singh {
5687f4beda2SGovind Singh 	ath11k_ce_cleanup_pipes(ab);
5697f4beda2SGovind Singh }
5707f4beda2SGovind Singh 
5717f4beda2SGovind Singh static int ath11k_pci_start(struct ath11k_base *ab)
5727f4beda2SGovind Singh {
5737f4beda2SGovind Singh 	ath11k_pci_ce_irqs_enable(ab);
5747f4beda2SGovind Singh 
5757f4beda2SGovind Singh 	return 0;
5767f4beda2SGovind Singh }
5777f4beda2SGovind Singh 
5787f4beda2SGovind Singh static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
5797f4beda2SGovind Singh 	.start = ath11k_pci_start,
5807f4beda2SGovind Singh 	.stop = ath11k_pci_stop,
5811399fb87SGovind Singh 	.power_down = ath11k_pci_power_down,
5821399fb87SGovind Singh 	.power_up = ath11k_pci_power_up,
5831399fb87SGovind Singh };
5841399fb87SGovind Singh 
5856e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev,
5866e0355afSGovind Singh 			    const struct pci_device_id *pci_dev)
5876e0355afSGovind Singh {
5886e0355afSGovind Singh 	struct ath11k_base *ab;
5895762613eSGovind Singh 	struct ath11k_pci *ab_pci;
5906e0355afSGovind Singh 	enum ath11k_hw_rev hw_rev;
5915762613eSGovind Singh 	int ret;
5926e0355afSGovind Singh 
5936e0355afSGovind Singh 	dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n");
5946e0355afSGovind Singh 
5956e0355afSGovind Singh 	switch (pci_dev->device) {
5966e0355afSGovind Singh 	case QCA6390_DEVICE_ID:
5976e0355afSGovind Singh 		hw_rev = ATH11K_HW_QCA6390_HW20;
5986e0355afSGovind Singh 		break;
5996e0355afSGovind Singh 	default:
6006e0355afSGovind Singh 		dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
6016e0355afSGovind Singh 			pci_dev->device);
6026e0355afSGovind Singh 		return -ENOTSUPP;
6036e0355afSGovind Singh 	}
6046e0355afSGovind Singh 
6051ff8ed78SGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI,
6061ff8ed78SGovind Singh 			       &ath11k_pci_bus_params);
6076e0355afSGovind Singh 	if (!ab) {
6086e0355afSGovind Singh 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
6096e0355afSGovind Singh 		return -ENOMEM;
6106e0355afSGovind Singh 	}
6116e0355afSGovind Singh 
6126e0355afSGovind Singh 	ab->dev = &pdev->dev;
6136e0355afSGovind Singh 	ab->hw_rev = hw_rev;
6146e0355afSGovind Singh 	pci_set_drvdata(pdev, ab);
6155762613eSGovind Singh 	ab_pci = ath11k_pci_priv(ab);
6165762613eSGovind Singh 	ab_pci->dev_id = pci_dev->device;
6175762613eSGovind Singh 	ab_pci->ab = ab;
6185697a564SGovind Singh 	ab_pci->pdev = pdev;
6197f4beda2SGovind Singh 	ab->hif.ops = &ath11k_pci_hif_ops;
6205762613eSGovind Singh 	pci_set_drvdata(pdev, ab);
6215762613eSGovind Singh 
6225762613eSGovind Singh 	ret = ath11k_pci_claim(ab_pci, pdev);
6235762613eSGovind Singh 	if (ret) {
6245762613eSGovind Singh 		ath11k_err(ab, "failed to claim device: %d\n", ret);
6255762613eSGovind Singh 		goto err_free_core;
6265762613eSGovind Singh 	}
6276e0355afSGovind Singh 
6285697a564SGovind Singh 	ret = ath11k_pci_enable_msi(ab_pci);
6295697a564SGovind Singh 	if (ret) {
6305697a564SGovind Singh 		ath11k_err(ab, "failed to enable msi: %d\n", ret);
6315697a564SGovind Singh 		goto err_pci_free_region;
6325697a564SGovind Singh 	}
6335697a564SGovind Singh 
634b8246f88SKalle Valo 	ret = ath11k_core_pre_init(ab);
635b8246f88SKalle Valo 	if (ret)
636b8246f88SKalle Valo 		goto err_pci_disable_msi;
637b8246f88SKalle Valo 
6381399fb87SGovind Singh 	ret = ath11k_mhi_register(ab_pci);
6391399fb87SGovind Singh 	if (ret) {
6401399fb87SGovind Singh 		ath11k_err(ab, "failed to register mhi: %d\n", ret);
6411399fb87SGovind Singh 		goto err_pci_disable_msi;
6421399fb87SGovind Singh 	}
6431399fb87SGovind Singh 
6447f4beda2SGovind Singh 	ret = ath11k_hal_srng_init(ab);
6457f4beda2SGovind Singh 	if (ret)
6467f4beda2SGovind Singh 		goto err_mhi_unregister;
6477f4beda2SGovind Singh 
6487f4beda2SGovind Singh 	ret = ath11k_ce_alloc_pipes(ab);
6497f4beda2SGovind Singh 	if (ret) {
6507f4beda2SGovind Singh 		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
6517f4beda2SGovind Singh 		goto err_hal_srng_deinit;
6527f4beda2SGovind Singh 	}
6537f4beda2SGovind Singh 
6547f4beda2SGovind Singh 	ath11k_pci_init_qmi_ce_config(ab);
6557f4beda2SGovind Singh 
6567f4beda2SGovind Singh 	ret = ath11k_pci_config_irq(ab);
6577f4beda2SGovind Singh 	if (ret) {
6587f4beda2SGovind Singh 		ath11k_err(ab, "failed to config irq: %d\n", ret);
6597f4beda2SGovind Singh 		goto err_ce_free;
6607f4beda2SGovind Singh 	}
6617f4beda2SGovind Singh 
6627f4beda2SGovind Singh 	ret = ath11k_core_init(ab);
6637f4beda2SGovind Singh 	if (ret) {
6647f4beda2SGovind Singh 		ath11k_err(ab, "failed to init core: %d\n", ret);
6657f4beda2SGovind Singh 		goto err_free_irq;
6667f4beda2SGovind Singh 	}
6676e0355afSGovind Singh 	return 0;
6685762613eSGovind Singh 
6697f4beda2SGovind Singh err_free_irq:
6707f4beda2SGovind Singh 	ath11k_pci_free_irq(ab);
6717f4beda2SGovind Singh 
6727f4beda2SGovind Singh err_ce_free:
6737f4beda2SGovind Singh 	ath11k_ce_free_pipes(ab);
6747f4beda2SGovind Singh 
6757f4beda2SGovind Singh err_hal_srng_deinit:
6767f4beda2SGovind Singh 	ath11k_hal_srng_deinit(ab);
6777f4beda2SGovind Singh 
6787f4beda2SGovind Singh err_mhi_unregister:
6797f4beda2SGovind Singh 	ath11k_mhi_unregister(ab_pci);
6807f4beda2SGovind Singh 
681b8246f88SKalle Valo err_pci_disable_msi:
682b8246f88SKalle Valo 	ath11k_pci_disable_msi(ab_pci);
683b8246f88SKalle Valo 
6845697a564SGovind Singh err_pci_free_region:
6855697a564SGovind Singh 	ath11k_pci_free_region(ab_pci);
6865697a564SGovind Singh 
6875762613eSGovind Singh err_free_core:
6885762613eSGovind Singh 	ath11k_core_free(ab);
6895697a564SGovind Singh 
6905762613eSGovind Singh 	return ret;
6916e0355afSGovind Singh }
6926e0355afSGovind Singh 
6936e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev)
6946e0355afSGovind Singh {
6956e0355afSGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
6965762613eSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
6976e0355afSGovind Singh 
6986e0355afSGovind Singh 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
6991399fb87SGovind Singh 	ath11k_mhi_unregister(ab_pci);
7005697a564SGovind Singh 	ath11k_pci_disable_msi(ab_pci);
7015762613eSGovind Singh 	ath11k_pci_free_region(ab_pci);
7027f4beda2SGovind Singh 	ath11k_pci_free_irq(ab);
7036e0355afSGovind Singh 	ath11k_core_free(ab);
7046e0355afSGovind Singh }
7056e0355afSGovind Singh 
7061399fb87SGovind Singh static void ath11k_pci_shutdown(struct pci_dev *pdev)
7071399fb87SGovind Singh {
7081399fb87SGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
7091399fb87SGovind Singh 
7101399fb87SGovind Singh 	ath11k_pci_power_down(ab);
7111399fb87SGovind Singh }
7121399fb87SGovind Singh 
7136e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = {
7146e0355afSGovind Singh 	.name = "ath11k_pci",
7156e0355afSGovind Singh 	.id_table = ath11k_pci_id_table,
7166e0355afSGovind Singh 	.probe = ath11k_pci_probe,
7176e0355afSGovind Singh 	.remove = ath11k_pci_remove,
7181399fb87SGovind Singh 	.shutdown = ath11k_pci_shutdown,
7196e0355afSGovind Singh };
7206e0355afSGovind Singh 
7216e0355afSGovind Singh static int ath11k_pci_init(void)
7226e0355afSGovind Singh {
7236e0355afSGovind Singh 	int ret;
7246e0355afSGovind Singh 
7256e0355afSGovind Singh 	ret = pci_register_driver(&ath11k_pci_driver);
7266e0355afSGovind Singh 	if (ret)
7276e0355afSGovind Singh 		pr_err("failed to register ath11k pci driver: %d\n",
7286e0355afSGovind Singh 		       ret);
7296e0355afSGovind Singh 
7306e0355afSGovind Singh 	return ret;
7316e0355afSGovind Singh }
7326e0355afSGovind Singh module_init(ath11k_pci_init);
7336e0355afSGovind Singh 
7346e0355afSGovind Singh static void ath11k_pci_exit(void)
7356e0355afSGovind Singh {
7366e0355afSGovind Singh 	pci_unregister_driver(&ath11k_pci_driver);
7376e0355afSGovind Singh }
7386e0355afSGovind Singh 
7396e0355afSGovind Singh module_exit(ath11k_pci_exit);
7406e0355afSGovind Singh 
7416e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
7426e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL");
743