xref: /linux/drivers/net/wireless/ath/ath12k/wifi7/pci.c (revision 37a93dd5c49b5fda807fd204edf2547c3493319c)
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