216 lines
5.7 KiB
C
216 lines
5.7 KiB
C
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
/*
|
|
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
|
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
*/
|
|
|
|
#include <linux/pci.h>
|
|
|
|
#include "../pci.h"
|
|
#include "pci.h"
|
|
#include "../core.h"
|
|
#include "../hif.h"
|
|
#include "../mhi.h"
|
|
#include "hw.h"
|
|
#include "../hal.h"
|
|
#include "dp.h"
|
|
#include "core.h"
|
|
#include "hal.h"
|
|
|
|
#define QCN9274_DEVICE_ID 0x1109
|
|
#define WCN7850_DEVICE_ID 0x1107
|
|
#define QCC2072_DEVICE_ID 0x1112
|
|
|
|
#define ATH12K_PCI_W7_SOC_HW_VERSION_1 1
|
|
#define ATH12K_PCI_W7_SOC_HW_VERSION_2 2
|
|
|
|
#define TCSR_SOC_HW_VERSION 0x1B00000
|
|
#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
|
|
#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 4)
|
|
|
|
#define WINDOW_REG_ADDRESS 0x310c
|
|
#define WINDOW_REG_ADDRESS_QCC2072 0x3278
|
|
|
|
static const struct pci_device_id ath12k_wifi7_pci_id_table[] = {
|
|
{ PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) },
|
|
{ PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) },
|
|
{ PCI_VDEVICE(QCOM, QCC2072_DEVICE_ID) },
|
|
{}
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(pci, ath12k_wifi7_pci_id_table);
|
|
|
|
/* TODO: revisit IRQ mapping for new SRNG's */
|
|
static const struct ath12k_msi_config ath12k_wifi7_msi_config[] = {
|
|
{
|
|
.total_vectors = 16,
|
|
.total_users = 3,
|
|
.users = (struct ath12k_msi_user[]) {
|
|
{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
|
|
{ .name = "CE", .num_vectors = 5, .base_vector = 3 },
|
|
{ .name = "DP", .num_vectors = 8, .base_vector = 8 },
|
|
},
|
|
},
|
|
};
|
|
|
|
static const struct ath12k_pci_ops ath12k_wifi7_pci_ops_qcn9274 = {
|
|
.wakeup = NULL,
|
|
.release = NULL,
|
|
};
|
|
|
|
static int ath12k_wifi7_pci_bus_wake_up(struct ath12k_base *ab)
|
|
{
|
|
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
|
|
|
return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
|
}
|
|
|
|
static void ath12k_wifi7_pci_bus_release(struct ath12k_base *ab)
|
|
{
|
|
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
|
|
|
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
|
}
|
|
|
|
static const struct ath12k_pci_ops ath12k_wifi7_pci_ops_wcn7850 = {
|
|
.wakeup = ath12k_wifi7_pci_bus_wake_up,
|
|
.release = ath12k_wifi7_pci_bus_release,
|
|
};
|
|
|
|
static
|
|
void ath12k_wifi7_pci_read_hw_version(struct ath12k_base *ab,
|
|
u32 *major, u32 *minor)
|
|
{
|
|
u32 soc_hw_version;
|
|
|
|
soc_hw_version = ath12k_pci_read32(ab, TCSR_SOC_HW_VERSION);
|
|
*major = u32_get_bits(soc_hw_version, TCSR_SOC_HW_VERSION_MAJOR_MASK);
|
|
*minor = u32_get_bits(soc_hw_version, TCSR_SOC_HW_VERSION_MINOR_MASK);
|
|
}
|
|
|
|
static int ath12k_wifi7_pci_probe(struct pci_dev *pdev,
|
|
const struct pci_device_id *pci_dev)
|
|
{
|
|
u32 soc_hw_version_major, soc_hw_version_minor;
|
|
struct ath12k_pci *ab_pci;
|
|
struct ath12k_base *ab;
|
|
int ret;
|
|
|
|
ab = pci_get_drvdata(pdev);
|
|
if (!ab)
|
|
return -EINVAL;
|
|
|
|
ab_pci = ath12k_pci_priv(ab);
|
|
if (!ab_pci)
|
|
return -EINVAL;
|
|
|
|
switch (pci_dev->device) {
|
|
case QCN9274_DEVICE_ID:
|
|
ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
|
|
ab->static_window_map = true;
|
|
ab_pci->pci_ops = &ath12k_wifi7_pci_ops_qcn9274;
|
|
/*
|
|
* init window reg addr before reading hardware version
|
|
* as it will be used there
|
|
*/
|
|
ab_pci->window_reg_addr = WINDOW_REG_ADDRESS;
|
|
ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major,
|
|
&soc_hw_version_minor);
|
|
ab->target_mem_mode = ath12k_core_get_memory_mode(ab);
|
|
switch (soc_hw_version_major) {
|
|
case ATH12K_PCI_W7_SOC_HW_VERSION_2:
|
|
ab->hw_rev = ATH12K_HW_QCN9274_HW20;
|
|
break;
|
|
case ATH12K_PCI_W7_SOC_HW_VERSION_1:
|
|
ab->hw_rev = ATH12K_HW_QCN9274_HW10;
|
|
break;
|
|
default:
|
|
dev_err(&pdev->dev,
|
|
"Unknown hardware version found for QCN9274: 0x%x\n",
|
|
soc_hw_version_major);
|
|
return -EOPNOTSUPP;
|
|
}
|
|
break;
|
|
case WCN7850_DEVICE_ID:
|
|
ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
|
|
ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
|
|
ab->static_window_map = false;
|
|
ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850;
|
|
/*
|
|
* init window reg addr before reading hardware version
|
|
* as it will be used there
|
|
*/
|
|
ab_pci->window_reg_addr = WINDOW_REG_ADDRESS;
|
|
ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major,
|
|
&soc_hw_version_minor);
|
|
ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
|
|
switch (soc_hw_version_major) {
|
|
case ATH12K_PCI_W7_SOC_HW_VERSION_2:
|
|
ab->hw_rev = ATH12K_HW_WCN7850_HW20;
|
|
break;
|
|
default:
|
|
dev_err(&pdev->dev,
|
|
"Unknown hardware version found for WCN7850: 0x%x\n",
|
|
soc_hw_version_major);
|
|
return -EOPNOTSUPP;
|
|
}
|
|
break;
|
|
case QCC2072_DEVICE_ID:
|
|
ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
|
|
ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
|
|
ab->static_window_map = false;
|
|
ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850;
|
|
ab_pci->window_reg_addr = WINDOW_REG_ADDRESS_QCC2072;
|
|
ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
|
|
/* there is only one version till now */
|
|
ab->hw_rev = ATH12K_HW_QCC2072_HW10;
|
|
break;
|
|
default:
|
|
dev_err(&pdev->dev, "Unknown Wi-Fi 7 PCI device found: 0x%x\n",
|
|
pci_dev->device);
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
ret = ath12k_wifi7_hw_init(ab);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "WiFi-7 hw_init for PCI failed: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct ath12k_pci_reg_base ath12k_wifi7_reg_base = {
|
|
.umac_base = HAL_SEQ_WCSS_UMAC_OFFSET,
|
|
.ce_reg_base = HAL_CE_WFSS_CE_REG_BASE,
|
|
};
|
|
|
|
static struct ath12k_pci_driver ath12k_wifi7_pci_driver = {
|
|
.name = "ath12k_wifi7_pci",
|
|
.id_table = ath12k_wifi7_pci_id_table,
|
|
.ops.probe = ath12k_wifi7_pci_probe,
|
|
.reg_base = &ath12k_wifi7_reg_base,
|
|
.ops.arch_init = ath12k_wifi7_arch_init,
|
|
.ops.arch_deinit = ath12k_wifi7_arch_deinit,
|
|
};
|
|
|
|
int ath12k_wifi7_pci_init(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = ath12k_pci_register_driver(ATH12K_DEVICE_FAMILY_WIFI7,
|
|
&ath12k_wifi7_pci_driver);
|
|
if (ret) {
|
|
pr_err("Failed to register ath12k Wi-Fi 7 driver: %d\n",
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ath12k_wifi7_pci_exit(void)
|
|
{
|
|
ath12k_pci_unregister_driver(ATH12K_DEVICE_FAMILY_WIFI7);
|
|
}
|