1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. 4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 5 */ 6 7 #include <linux/pci.h> 8 9 #include "../pci.h" 10 #include "pci.h" 11 #include "../core.h" 12 #include "../hif.h" 13 #include "../mhi.h" 14 #include "hw.h" 15 #include "../hal.h" 16 #include "dp.h" 17 #include "core.h" 18 #include "hal.h" 19 20 #define QCN9274_DEVICE_ID 0x1109 21 #define WCN7850_DEVICE_ID 0x1107 22 #define QCC2072_DEVICE_ID 0x1112 23 24 #define ATH12K_PCI_W7_SOC_HW_VERSION_1 1 25 #define ATH12K_PCI_W7_SOC_HW_VERSION_2 2 26 27 #define TCSR_SOC_HW_VERSION 0x1B00000 28 #define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8) 29 #define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 4) 30 31 #define WINDOW_REG_ADDRESS 0x310c 32 #define WINDOW_REG_ADDRESS_QCC2072 0x3278 33 34 static const struct pci_device_id ath12k_wifi7_pci_id_table[] = { 35 { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) }, 36 { PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) }, 37 { PCI_VDEVICE(QCOM, QCC2072_DEVICE_ID) }, 38 {} 39 }; 40 41 MODULE_DEVICE_TABLE(pci, ath12k_wifi7_pci_id_table); 42 43 /* TODO: revisit IRQ mapping for new SRNG's */ 44 static const struct ath12k_msi_config ath12k_wifi7_msi_config[] = { 45 { 46 .total_vectors = 16, 47 .total_users = 3, 48 .users = (struct ath12k_msi_user[]) { 49 { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, 50 { .name = "CE", .num_vectors = 5, .base_vector = 3 }, 51 { .name = "DP", .num_vectors = 8, .base_vector = 8 }, 52 }, 53 }, 54 }; 55 56 static const struct ath12k_pci_ops ath12k_wifi7_pci_ops_qcn9274 = { 57 .wakeup = NULL, 58 .release = NULL, 59 }; 60 61 static int ath12k_wifi7_pci_bus_wake_up(struct ath12k_base *ab) 62 { 63 struct ath12k_pci *ab_pci = ath12k_pci_priv(ab); 64 65 return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); 66 } 67 68 static void ath12k_wifi7_pci_bus_release(struct ath12k_base *ab) 69 { 70 struct ath12k_pci *ab_pci = ath12k_pci_priv(ab); 71 72 mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); 73 } 74 75 static const struct ath12k_pci_ops ath12k_wifi7_pci_ops_wcn7850 = { 76 .wakeup = ath12k_wifi7_pci_bus_wake_up, 77 .release = ath12k_wifi7_pci_bus_release, 78 }; 79 80 static 81 void ath12k_wifi7_pci_read_hw_version(struct ath12k_base *ab, 82 u32 *major, u32 *minor) 83 { 84 u32 soc_hw_version; 85 86 soc_hw_version = ath12k_pci_read32(ab, TCSR_SOC_HW_VERSION); 87 *major = u32_get_bits(soc_hw_version, TCSR_SOC_HW_VERSION_MAJOR_MASK); 88 *minor = u32_get_bits(soc_hw_version, TCSR_SOC_HW_VERSION_MINOR_MASK); 89 } 90 91 static int ath12k_wifi7_pci_probe(struct pci_dev *pdev, 92 const struct pci_device_id *pci_dev) 93 { 94 u32 soc_hw_version_major, soc_hw_version_minor; 95 struct ath12k_pci *ab_pci; 96 struct ath12k_base *ab; 97 int ret; 98 99 ab = pci_get_drvdata(pdev); 100 if (!ab) 101 return -EINVAL; 102 103 ab_pci = ath12k_pci_priv(ab); 104 if (!ab_pci) 105 return -EINVAL; 106 107 switch (pci_dev->device) { 108 case QCN9274_DEVICE_ID: 109 ab_pci->msi_config = &ath12k_wifi7_msi_config[0]; 110 ab->static_window_map = true; 111 ab_pci->pci_ops = &ath12k_wifi7_pci_ops_qcn9274; 112 /* 113 * init window reg addr before reading hardware version 114 * as it will be used there 115 */ 116 ab_pci->window_reg_addr = WINDOW_REG_ADDRESS; 117 ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major, 118 &soc_hw_version_minor); 119 ab->target_mem_mode = ath12k_core_get_memory_mode(ab); 120 switch (soc_hw_version_major) { 121 case ATH12K_PCI_W7_SOC_HW_VERSION_2: 122 ab->hw_rev = ATH12K_HW_QCN9274_HW20; 123 break; 124 case ATH12K_PCI_W7_SOC_HW_VERSION_1: 125 ab->hw_rev = ATH12K_HW_QCN9274_HW10; 126 break; 127 default: 128 dev_err(&pdev->dev, 129 "Unknown hardware version found for QCN9274: 0x%x\n", 130 soc_hw_version_major); 131 return -EOPNOTSUPP; 132 } 133 break; 134 case WCN7850_DEVICE_ID: 135 ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD; 136 ab_pci->msi_config = &ath12k_wifi7_msi_config[0]; 137 ab->static_window_map = false; 138 ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850; 139 /* 140 * init window reg addr before reading hardware version 141 * as it will be used there 142 */ 143 ab_pci->window_reg_addr = WINDOW_REG_ADDRESS; 144 ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major, 145 &soc_hw_version_minor); 146 ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT; 147 switch (soc_hw_version_major) { 148 case ATH12K_PCI_W7_SOC_HW_VERSION_2: 149 ab->hw_rev = ATH12K_HW_WCN7850_HW20; 150 break; 151 default: 152 dev_err(&pdev->dev, 153 "Unknown hardware version found for WCN7850: 0x%x\n", 154 soc_hw_version_major); 155 return -EOPNOTSUPP; 156 } 157 break; 158 case QCC2072_DEVICE_ID: 159 ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD; 160 ab_pci->msi_config = &ath12k_wifi7_msi_config[0]; 161 ab->static_window_map = false; 162 ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850; 163 ab_pci->window_reg_addr = WINDOW_REG_ADDRESS_QCC2072; 164 ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT; 165 /* there is only one version till now */ 166 ab->hw_rev = ATH12K_HW_QCC2072_HW10; 167 break; 168 default: 169 dev_err(&pdev->dev, "Unknown Wi-Fi 7 PCI device found: 0x%x\n", 170 pci_dev->device); 171 return -EOPNOTSUPP; 172 } 173 174 ret = ath12k_wifi7_hw_init(ab); 175 if (ret) { 176 dev_err(&pdev->dev, "WiFi-7 hw_init for PCI failed: %d\n", ret); 177 return ret; 178 } 179 180 return 0; 181 } 182 183 static const struct ath12k_pci_reg_base ath12k_wifi7_reg_base = { 184 .umac_base = HAL_SEQ_WCSS_UMAC_OFFSET, 185 .ce_reg_base = HAL_CE_WFSS_CE_REG_BASE, 186 }; 187 188 static struct ath12k_pci_driver ath12k_wifi7_pci_driver = { 189 .name = "ath12k_wifi7_pci", 190 .id_table = ath12k_wifi7_pci_id_table, 191 .ops.probe = ath12k_wifi7_pci_probe, 192 .reg_base = &ath12k_wifi7_reg_base, 193 .ops.arch_init = ath12k_wifi7_arch_init, 194 .ops.arch_deinit = ath12k_wifi7_arch_deinit, 195 }; 196 197 int ath12k_wifi7_pci_init(void) 198 { 199 int ret; 200 201 ret = ath12k_pci_register_driver(ATH12K_DEVICE_FAMILY_WIFI7, 202 &ath12k_wifi7_pci_driver); 203 if (ret) { 204 pr_err("Failed to register ath12k Wi-Fi 7 driver: %d\n", 205 ret); 206 return ret; 207 } 208 209 return 0; 210 } 211 212 void ath12k_wifi7_pci_exit(void) 213 { 214 ath12k_pci_unregister_driver(ATH12K_DEVICE_FAMILY_WIFI7); 215 } 216