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