xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/pci.c (revision 5762613ededb20f1893abf6aeda2d4091dd4178b)
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>
76e0355afSGovind Singh #include <linux/pci.h>
86e0355afSGovind Singh 
9*5762613eSGovind Singh #include "pci.h"
106e0355afSGovind Singh #include "core.h"
116e0355afSGovind Singh #include "debug.h"
126e0355afSGovind Singh 
13*5762613eSGovind Singh #define ATH11K_PCI_BAR_NUM		0
14*5762613eSGovind Singh #define ATH11K_PCI_DMA_MASK		32
15*5762613eSGovind Singh 
166e0355afSGovind Singh #define QCA6390_DEVICE_ID		0x1101
176e0355afSGovind Singh 
186e0355afSGovind Singh static const struct pci_device_id ath11k_pci_id_table[] = {
196e0355afSGovind Singh 	{ PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
206e0355afSGovind Singh 	{0}
216e0355afSGovind Singh };
226e0355afSGovind Singh 
236e0355afSGovind Singh MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
246e0355afSGovind Singh 
25*5762613eSGovind Singh static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
26*5762613eSGovind Singh {
27*5762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
28*5762613eSGovind Singh 	u16 device_id;
29*5762613eSGovind Singh 	int ret = 0;
30*5762613eSGovind Singh 
31*5762613eSGovind Singh 	pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
32*5762613eSGovind Singh 	if (device_id != ab_pci->dev_id)  {
33*5762613eSGovind Singh 		ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
34*5762613eSGovind Singh 			   device_id, ab_pci->dev_id);
35*5762613eSGovind Singh 		ret = -EIO;
36*5762613eSGovind Singh 		goto out;
37*5762613eSGovind Singh 	}
38*5762613eSGovind Singh 
39*5762613eSGovind Singh 	ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
40*5762613eSGovind Singh 	if (ret) {
41*5762613eSGovind Singh 		ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
42*5762613eSGovind Singh 		goto out;
43*5762613eSGovind Singh 	}
44*5762613eSGovind Singh 
45*5762613eSGovind Singh 	ret = pci_enable_device(pdev);
46*5762613eSGovind Singh 	if (ret) {
47*5762613eSGovind Singh 		ath11k_err(ab, "failed to enable pci device: %d\n", ret);
48*5762613eSGovind Singh 		goto out;
49*5762613eSGovind Singh 	}
50*5762613eSGovind Singh 
51*5762613eSGovind Singh 	ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
52*5762613eSGovind Singh 	if (ret) {
53*5762613eSGovind Singh 		ath11k_err(ab, "failed to request pci region: %d\n", ret);
54*5762613eSGovind Singh 		goto disable_device;
55*5762613eSGovind Singh 	}
56*5762613eSGovind Singh 
57*5762613eSGovind Singh 	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
58*5762613eSGovind Singh 	if (ret) {
59*5762613eSGovind Singh 		ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
60*5762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
61*5762613eSGovind Singh 		goto release_region;
62*5762613eSGovind Singh 	}
63*5762613eSGovind Singh 
64*5762613eSGovind Singh 	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
65*5762613eSGovind Singh 	if (ret) {
66*5762613eSGovind Singh 		ath11k_err(ab, "failed to set pci consistent dma mask to %d: %d\n",
67*5762613eSGovind Singh 			   ATH11K_PCI_DMA_MASK, ret);
68*5762613eSGovind Singh 		goto release_region;
69*5762613eSGovind Singh 	}
70*5762613eSGovind Singh 
71*5762613eSGovind Singh 	pci_set_master(pdev);
72*5762613eSGovind Singh 
73*5762613eSGovind Singh 	ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
74*5762613eSGovind Singh 	ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
75*5762613eSGovind Singh 	if (!ab->mem) {
76*5762613eSGovind Singh 		ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
77*5762613eSGovind Singh 		ret = -EIO;
78*5762613eSGovind Singh 		goto clear_master;
79*5762613eSGovind Singh 	}
80*5762613eSGovind Singh 
81*5762613eSGovind Singh 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
82*5762613eSGovind Singh 	return 0;
83*5762613eSGovind Singh 
84*5762613eSGovind Singh clear_master:
85*5762613eSGovind Singh 	pci_clear_master(pdev);
86*5762613eSGovind Singh release_region:
87*5762613eSGovind Singh 	pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
88*5762613eSGovind Singh disable_device:
89*5762613eSGovind Singh 	pci_disable_device(pdev);
90*5762613eSGovind Singh out:
91*5762613eSGovind Singh 	return ret;
92*5762613eSGovind Singh }
93*5762613eSGovind Singh 
94*5762613eSGovind Singh static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
95*5762613eSGovind Singh {
96*5762613eSGovind Singh 	struct ath11k_base *ab = ab_pci->ab;
97*5762613eSGovind Singh 	struct pci_dev *pci_dev = ab_pci->pdev;
98*5762613eSGovind Singh 
99*5762613eSGovind Singh 	pci_iounmap(pci_dev, ab->mem);
100*5762613eSGovind Singh 	ab->mem = NULL;
101*5762613eSGovind Singh 	pci_clear_master(pci_dev);
102*5762613eSGovind Singh 	pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
103*5762613eSGovind Singh 	if (pci_is_enabled(pci_dev))
104*5762613eSGovind Singh 		pci_disable_device(pci_dev);
105*5762613eSGovind Singh }
106*5762613eSGovind Singh 
1076e0355afSGovind Singh static int ath11k_pci_probe(struct pci_dev *pdev,
1086e0355afSGovind Singh 			    const struct pci_device_id *pci_dev)
1096e0355afSGovind Singh {
1106e0355afSGovind Singh 	struct ath11k_base *ab;
111*5762613eSGovind Singh 	struct ath11k_pci *ab_pci;
1126e0355afSGovind Singh 	enum ath11k_hw_rev hw_rev;
113*5762613eSGovind Singh 	int ret;
1146e0355afSGovind Singh 
1156e0355afSGovind Singh 	dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n");
1166e0355afSGovind Singh 
1176e0355afSGovind Singh 	switch (pci_dev->device) {
1186e0355afSGovind Singh 	case QCA6390_DEVICE_ID:
1196e0355afSGovind Singh 		hw_rev = ATH11K_HW_QCA6390_HW20;
1206e0355afSGovind Singh 		break;
1216e0355afSGovind Singh 	default:
1226e0355afSGovind Singh 		dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
1236e0355afSGovind Singh 			pci_dev->device);
1246e0355afSGovind Singh 		return -ENOTSUPP;
1256e0355afSGovind Singh 	}
1266e0355afSGovind Singh 
127*5762613eSGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI);
1286e0355afSGovind Singh 	if (!ab) {
1296e0355afSGovind Singh 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
1306e0355afSGovind Singh 		return -ENOMEM;
1316e0355afSGovind Singh 	}
1326e0355afSGovind Singh 
1336e0355afSGovind Singh 	ab->dev = &pdev->dev;
1346e0355afSGovind Singh 	ab->hw_rev = hw_rev;
1356e0355afSGovind Singh 	pci_set_drvdata(pdev, ab);
136*5762613eSGovind Singh 	ab_pci = ath11k_pci_priv(ab);
137*5762613eSGovind Singh 	ab_pci->dev_id = pci_dev->device;
138*5762613eSGovind Singh 	ab_pci->ab = ab;
139*5762613eSGovind Singh 	pci_set_drvdata(pdev, ab);
140*5762613eSGovind Singh 
141*5762613eSGovind Singh 	ret = ath11k_pci_claim(ab_pci, pdev);
142*5762613eSGovind Singh 	if (ret) {
143*5762613eSGovind Singh 		ath11k_err(ab, "failed to claim device: %d\n", ret);
144*5762613eSGovind Singh 		goto err_free_core;
145*5762613eSGovind Singh 	}
1466e0355afSGovind Singh 
1476e0355afSGovind Singh 	return 0;
148*5762613eSGovind Singh 
149*5762613eSGovind Singh err_free_core:
150*5762613eSGovind Singh 	ath11k_core_free(ab);
151*5762613eSGovind Singh 	return ret;
1526e0355afSGovind Singh }
1536e0355afSGovind Singh 
1546e0355afSGovind Singh static void ath11k_pci_remove(struct pci_dev *pdev)
1556e0355afSGovind Singh {
1566e0355afSGovind Singh 	struct ath11k_base *ab = pci_get_drvdata(pdev);
157*5762613eSGovind Singh 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
1586e0355afSGovind Singh 
1596e0355afSGovind Singh 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
160*5762613eSGovind Singh 	ath11k_pci_free_region(ab_pci);
1616e0355afSGovind Singh 	ath11k_core_free(ab);
1626e0355afSGovind Singh }
1636e0355afSGovind Singh 
1646e0355afSGovind Singh static struct pci_driver ath11k_pci_driver = {
1656e0355afSGovind Singh 	.name = "ath11k_pci",
1666e0355afSGovind Singh 	.id_table = ath11k_pci_id_table,
1676e0355afSGovind Singh 	.probe = ath11k_pci_probe,
1686e0355afSGovind Singh 	.remove = ath11k_pci_remove,
1696e0355afSGovind Singh };
1706e0355afSGovind Singh 
1716e0355afSGovind Singh static int ath11k_pci_init(void)
1726e0355afSGovind Singh {
1736e0355afSGovind Singh 	int ret;
1746e0355afSGovind Singh 
1756e0355afSGovind Singh 	ret = pci_register_driver(&ath11k_pci_driver);
1766e0355afSGovind Singh 	if (ret)
1776e0355afSGovind Singh 		pr_err("failed to register ath11k pci driver: %d\n",
1786e0355afSGovind Singh 		       ret);
1796e0355afSGovind Singh 
1806e0355afSGovind Singh 	return ret;
1816e0355afSGovind Singh }
1826e0355afSGovind Singh module_init(ath11k_pci_init);
1836e0355afSGovind Singh 
1846e0355afSGovind Singh static void ath11k_pci_exit(void)
1856e0355afSGovind Singh {
1866e0355afSGovind Singh 	pci_unregister_driver(&ath11k_pci_driver);
1876e0355afSGovind Singh }
1886e0355afSGovind Singh 
1896e0355afSGovind Singh module_exit(ath11k_pci_exit);
1906e0355afSGovind Singh 
1916e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
1926e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL");
193