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