blob: de71ad594f347267bca585a72d2b717c5461fcd0 [file] [log] [blame]
Govind Singh6e0355a2020-08-13 12:04:20 +03001// SPDX-License-Identifier: BSD-3-Clause-Clear
2/*
3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/module.h>
Govind Singh5697a562020-08-13 12:04:22 +03007#include <linux/msi.h>
Govind Singh6e0355a2020-08-13 12:04:20 +03008#include <linux/pci.h>
Anilkumar Kolli6ac04bd2021-12-14 17:39:43 +02009#include <linux/of.h>
Govind Singh6e0355a2020-08-13 12:04:20 +030010
Govind Singh57626132020-08-13 12:04:21 +030011#include "pci.h"
Govind Singh6e0355a2020-08-13 12:04:20 +030012#include "core.h"
Govind Singh1399fb82020-08-13 12:04:24 +030013#include "hif.h"
14#include "mhi.h"
Govind Singh6e0355a2020-08-13 12:04:20 +030015#include "debug.h"
16
Govind Singh57626132020-08-13 12:04:21 +030017#define ATH11K_PCI_BAR_NUM 0
18#define ATH11K_PCI_DMA_MASK 32
19
Carl Huang4ab46932021-11-19 15:36:26 +020020#define ATH11K_PCI_IRQ_CE0_OFFSET 3
21#define ATH11K_PCI_IRQ_DP_OFFSET 14
Govind Singh7f4beda2020-08-13 12:04:25 +030022
Govind Singh654e9592020-08-14 10:10:23 +030023#define WINDOW_ENABLE_BIT 0x40000000
24#define WINDOW_REG_ADDRESS 0x310c
25#define WINDOW_VALUE_MASK GENMASK(24, 19)
26#define WINDOW_START 0x80000
27#define WINDOW_RANGE_MASK GENMASK(18, 0)
28
Kalle Valo18ac1662020-09-29 20:15:32 +030029#define TCSR_SOC_HW_VERSION 0x0224
Baochen Qiangd1147a32021-11-29 10:56:12 +080030#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
Kalle Valo18ac1662020-09-29 20:15:32 +030031#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 0)
32
Carl Huanga05bd852020-10-01 12:34:43 +030033/* BAR0 + 4k is always accessible, and no
34 * need to force wakeup.
35 * 4K - 32 = 0xFE0
36 */
37#define ACCESS_ALWAYS_OFF 0xFE0
38
Govind Singh6e0355a2020-08-13 12:04:20 +030039#define QCA6390_DEVICE_ID 0x1101
Anilkumar Kolli4e809462021-02-16 09:16:25 +020040#define QCN9074_DEVICE_ID 0x1104
Baochen Qiang0fbf1952021-05-31 17:41:28 +030041#define WCN6855_DEVICE_ID 0x1103
Govind Singh6e0355a2020-08-13 12:04:20 +030042
43static const struct pci_device_id ath11k_pci_id_table[] = {
44 { PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
Baochen Qiang0fbf1952021-05-31 17:41:28 +030045 { PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) },
Anilkumar Kolli49f5b112021-06-17 11:29:40 +030046 { PCI_VDEVICE(QCOM, QCN9074_DEVICE_ID) },
Govind Singh6e0355a2020-08-13 12:04:20 +030047 {0}
48};
49
50MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
51
Govind Singh1ff8ed72020-08-13 12:04:26 +030052static const struct ath11k_bus_params ath11k_pci_bus_params = {
53 .mhi_support = true,
Govind Singh56970452020-08-14 10:10:20 +030054 .m3_fw_support = true,
Govind Singh6eb6ea52020-08-14 10:10:21 +030055 .fixed_bdf_addr = false,
56 .fixed_mem_region = false,
Govind Singh1ff8ed72020-08-13 12:04:26 +030057};
58
Anilkumar Kolli7a3aed02021-02-16 09:15:35 +020059static const struct ath11k_msi_config ath11k_msi_config[] = {
60 {
61 .total_vectors = 32,
62 .total_users = 4,
63 .users = (struct ath11k_msi_user[]) {
64 { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
65 { .name = "CE", .num_vectors = 10, .base_vector = 3 },
66 { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
67 { .name = "DP", .num_vectors = 18, .base_vector = 14 },
68 },
Govind Singh5697a562020-08-13 12:04:22 +030069 },
Anilkumar Kolli4e809462021-02-16 09:16:25 +020070 {
71 .total_vectors = 16,
72 .total_users = 3,
73 .users = (struct ath11k_msi_user[]) {
74 { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
75 { .name = "CE", .num_vectors = 5, .base_vector = 3 },
76 { .name = "DP", .num_vectors = 8, .base_vector = 8 },
77 },
78 },
Govind Singh5697a562020-08-13 12:04:22 +030079};
80
Carl Huangac6e7342021-11-19 15:36:26 +020081static const struct ath11k_msi_config msi_config_one_msi = {
82 .total_vectors = 1,
83 .total_users = 4,
84 .users = (struct ath11k_msi_user[]) {
85 { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
86 { .name = "CE", .num_vectors = 1, .base_vector = 0 },
87 { .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
88 { .name = "DP", .num_vectors = 1, .base_vector = 0 },
89 },
90};
91
Govind Singh7f4beda2020-08-13 12:04:25 +030092static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
93 "bhi",
94 "mhi-er0",
95 "mhi-er1",
96 "ce0",
97 "ce1",
98 "ce2",
99 "ce3",
100 "ce4",
101 "ce5",
102 "ce6",
103 "ce7",
104 "ce8",
105 "ce9",
106 "ce10",
107 "ce11",
108 "host2wbm-desc-feed",
109 "host2reo-re-injection",
110 "host2reo-command",
111 "host2rxdma-monitor-ring3",
112 "host2rxdma-monitor-ring2",
113 "host2rxdma-monitor-ring1",
114 "reo2ost-exception",
115 "wbm2host-rx-release",
116 "reo2host-status",
117 "reo2host-destination-ring4",
118 "reo2host-destination-ring3",
119 "reo2host-destination-ring2",
120 "reo2host-destination-ring1",
121 "rxdma2host-monitor-destination-mac3",
122 "rxdma2host-monitor-destination-mac2",
123 "rxdma2host-monitor-destination-mac1",
124 "ppdu-end-interrupts-mac3",
125 "ppdu-end-interrupts-mac2",
126 "ppdu-end-interrupts-mac1",
127 "rxdma2host-monitor-status-ring-mac3",
128 "rxdma2host-monitor-status-ring-mac2",
129 "rxdma2host-monitor-status-ring-mac1",
130 "host2rxdma-host-buf-ring-mac3",
131 "host2rxdma-host-buf-ring-mac2",
132 "host2rxdma-host-buf-ring-mac1",
133 "rxdma2host-destination-ring-mac3",
134 "rxdma2host-destination-ring-mac2",
135 "rxdma2host-destination-ring-mac1",
136 "host2tcl-input-ring4",
137 "host2tcl-input-ring3",
138 "host2tcl-input-ring2",
139 "host2tcl-input-ring1",
140 "wbm2host-tx-completions-ring3",
141 "wbm2host-tx-completions-ring2",
142 "wbm2host-tx-completions-ring1",
143 "tcl2host-status-ring",
144};
145
Govind Singh654e9592020-08-14 10:10:23 +0300146static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset)
147{
148 struct ath11k_base *ab = ab_pci->ab;
149
150 u32 window = FIELD_GET(WINDOW_VALUE_MASK, offset);
151
152 lockdep_assert_held(&ab_pci->window_lock);
153
154 if (window != ab_pci->register_window) {
155 iowrite32(WINDOW_ENABLE_BIT | window,
156 ab->mem + WINDOW_REG_ADDRESS);
Carl Huangf6fa37a2020-12-11 19:35:43 +0200157 ioread32(ab->mem + WINDOW_REG_ADDRESS);
Govind Singh654e9592020-08-14 10:10:23 +0300158 ab_pci->register_window = window;
159 }
160}
161
Karthikeyan Periyasamy480a7362021-02-16 09:16:17 +0200162static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci)
163{
164 u32 umac_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET);
165 u32 ce_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE);
166 u32 window;
167
168 window = (umac_window << 12) | (ce_window << 6);
169
170 iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + WINDOW_REG_ADDRESS);
171}
172
173static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab,
174 u32 offset)
175{
176 u32 window_start;
177
178 /* If offset lies within DP register range, use 3rd window */
179 if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK)
180 window_start = 3 * WINDOW_START;
181 /* If offset lies within CE register range, use 2nd window */
182 else if ((offset ^ HAL_CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK)
183 window_start = 2 * WINDOW_START;
184 else
185 window_start = WINDOW_START;
186
187 return window_start;
188}
189
Carl Huangf3c603d2020-08-17 13:31:55 +0300190void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
Govind Singh654e9592020-08-14 10:10:23 +0300191{
192 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Karthikeyan Periyasamy480a7362021-02-16 09:16:17 +0200193 u32 window_start;
Govind Singh654e9592020-08-14 10:10:23 +0300194
Carl Huanga05bd852020-10-01 12:34:43 +0300195 /* for offset beyond BAR + 4K - 32, may
196 * need to wakeup MHI to access.
197 */
Seevalamuthu Mariappan081e2d62021-11-17 09:39:41 +0200198 if (ab->hw_params.wakeup_mhi &&
199 test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
Carl Huanga05bd852020-10-01 12:34:43 +0300200 offset >= ACCESS_ALWAYS_OFF)
201 mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
202
Govind Singh654e9592020-08-14 10:10:23 +0300203 if (offset < WINDOW_START) {
204 iowrite32(value, ab->mem + offset);
205 } else {
Karthikeyan Periyasamy480a7362021-02-16 09:16:17 +0200206 if (ab->bus_params.static_window_map)
207 window_start = ath11k_pci_get_window_start(ab, offset);
208 else
209 window_start = WINDOW_START;
210
211 if (window_start == WINDOW_START) {
212 spin_lock_bh(&ab_pci->window_lock);
213 ath11k_pci_select_window(ab_pci, offset);
214 iowrite32(value, ab->mem + window_start +
215 (offset & WINDOW_RANGE_MASK));
216 spin_unlock_bh(&ab_pci->window_lock);
217 } else {
218 iowrite32(value, ab->mem + window_start +
219 (offset & WINDOW_RANGE_MASK));
220 }
Govind Singh654e9592020-08-14 10:10:23 +0300221 }
Carl Huanga05bd852020-10-01 12:34:43 +0300222
Seevalamuthu Mariappan081e2d62021-11-17 09:39:41 +0200223 if (ab->hw_params.wakeup_mhi &&
224 test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
Carl Huanga05bd852020-10-01 12:34:43 +0300225 offset >= ACCESS_ALWAYS_OFF)
226 mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
Govind Singh654e9592020-08-14 10:10:23 +0300227}
228
Carl Huangf3c603d2020-08-17 13:31:55 +0300229u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
Govind Singh654e9592020-08-14 10:10:23 +0300230{
231 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Karthikeyan Periyasamy480a7362021-02-16 09:16:17 +0200232 u32 val, window_start;
Govind Singh654e9592020-08-14 10:10:23 +0300233
Carl Huanga05bd852020-10-01 12:34:43 +0300234 /* for offset beyond BAR + 4K - 32, may
235 * need to wakeup MHI to access.
236 */
Seevalamuthu Mariappan081e2d62021-11-17 09:39:41 +0200237 if (ab->hw_params.wakeup_mhi &&
238 test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
Carl Huanga05bd852020-10-01 12:34:43 +0300239 offset >= ACCESS_ALWAYS_OFF)
240 mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
241
Govind Singh654e9592020-08-14 10:10:23 +0300242 if (offset < WINDOW_START) {
243 val = ioread32(ab->mem + offset);
244 } else {
Karthikeyan Periyasamy480a7362021-02-16 09:16:17 +0200245 if (ab->bus_params.static_window_map)
246 window_start = ath11k_pci_get_window_start(ab, offset);
247 else
248 window_start = WINDOW_START;
249
250 if (window_start == WINDOW_START) {
251 spin_lock_bh(&ab_pci->window_lock);
252 ath11k_pci_select_window(ab_pci, offset);
253 val = ioread32(ab->mem + window_start +
254 (offset & WINDOW_RANGE_MASK));
255 spin_unlock_bh(&ab_pci->window_lock);
256 } else {
257 val = ioread32(ab->mem + window_start +
258 (offset & WINDOW_RANGE_MASK));
259 }
Govind Singh654e9592020-08-14 10:10:23 +0300260 }
261
Seevalamuthu Mariappan081e2d62021-11-17 09:39:41 +0200262 if (ab->hw_params.wakeup_mhi &&
263 test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
Carl Huanga05bd852020-10-01 12:34:43 +0300264 offset >= ACCESS_ALWAYS_OFF)
265 mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
266
Govind Singh654e9592020-08-14 10:10:23 +0300267 return val;
268}
269
Carl Huangf3c603d2020-08-17 13:31:55 +0300270static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
271{
272 u32 val, delay;
273
274 val = ath11k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
275
276 val |= PCIE_SOC_GLOBAL_RESET_V;
277
278 ath11k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
279
280 /* TODO: exact time to sleep is uncertain */
281 delay = 10;
282 mdelay(delay);
283
284 /* Need to toggle V bit back otherwise stuck in reset status */
285 val &= ~PCIE_SOC_GLOBAL_RESET_V;
286
287 ath11k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
288
289 mdelay(delay);
290
291 val = ath11k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
292 if (val == 0xffffffff)
293 ath11k_warn(ab, "link down error during global reset\n");
294}
295
296static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
297{
298 u32 val;
299
300 /* read cookie */
301 val = ath11k_pci_read32(ab, PCIE_Q6_COOKIE_ADDR);
302 ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val);
303
304 val = ath11k_pci_read32(ab, WLAON_WARM_SW_ENTRY);
305 ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
306
307 /* TODO: exact time to sleep is uncertain */
308 mdelay(10);
309
310 /* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from
311 * continuing warm path and entering dead loop.
312 */
313 ath11k_pci_write32(ab, WLAON_WARM_SW_ENTRY, 0);
314 mdelay(10);
315
316 val = ath11k_pci_read32(ab, WLAON_WARM_SW_ENTRY);
317 ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
318
319 /* A read clear register. clear the register to prevent
320 * Q6 from entering wrong code path.
321 */
322 val = ath11k_pci_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
323 ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
324}
325
Carl Huang06999402020-12-10 16:05:22 +0200326static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
327 u32 offset, u32 value, u32 mask)
328{
329 u32 v;
330 int i;
331
332 v = ath11k_pci_read32(ab, offset);
333 if ((v & mask) == value)
334 return 0;
335
336 for (i = 0; i < 10; i++) {
337 ath11k_pci_write32(ab, offset, (v & ~mask) | value);
338
339 v = ath11k_pci_read32(ab, offset);
340 if ((v & mask) == value)
341 return 0;
342
343 mdelay(2);
344 }
345
346 ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n",
347 offset, v & mask, value);
348
349 return -ETIMEDOUT;
350}
351
352static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
353{
354 int ret;
355
356 ret = ath11k_pci_set_link_reg(ab,
Karthikeyan Periyasamy6fe6f682021-02-16 09:16:22 +0200357 PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab),
Carl Huang06999402020-12-10 16:05:22 +0200358 PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
359 PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
Dan Carpenter30d08502020-12-16 11:32:12 +0300360 if (ret) {
Carl Huang06999402020-12-10 16:05:22 +0200361 ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
362 return ret;
363 }
364
365 ret = ath11k_pci_set_link_reg(ab,
Karthikeyan Periyasamy6fe6f682021-02-16 09:16:22 +0200366 PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab),
367 PCIE_PCS_OSC_DTCT_CONFIG1_VAL,
368 PCIE_PCS_OSC_DTCT_CONFIG_MSK);
Dan Carpenter30d08502020-12-16 11:32:12 +0300369 if (ret) {
Carl Huang06999402020-12-10 16:05:22 +0200370 ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
371 return ret;
372 }
373
374 ret = ath11k_pci_set_link_reg(ab,
Karthikeyan Periyasamy6fe6f682021-02-16 09:16:22 +0200375 PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab),
376 PCIE_PCS_OSC_DTCT_CONFIG2_VAL,
377 PCIE_PCS_OSC_DTCT_CONFIG_MSK);
Dan Carpenter30d08502020-12-16 11:32:12 +0300378 if (ret) {
Carl Huang06999402020-12-10 16:05:22 +0200379 ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
380 return ret;
381 }
382
383 ret = ath11k_pci_set_link_reg(ab,
Karthikeyan Periyasamy6fe6f682021-02-16 09:16:22 +0200384 PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab),
385 PCIE_PCS_OSC_DTCT_CONFIG4_VAL,
386 PCIE_PCS_OSC_DTCT_CONFIG_MSK);
Dan Carpenter30d08502020-12-16 11:32:12 +0300387 if (ret) {
Carl Huang06999402020-12-10 16:05:22 +0200388 ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
389 return ret;
390 }
391
392 return 0;
393}
394
Carl Huangbabb0ce2020-12-10 16:05:21 +0200395static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
396{
397 u32 val;
398 int i;
399
400 val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
401
402 /* PCIE link seems very unstable after the Hot Reset*/
403 for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {
404 if (val == 0xffffffff)
405 mdelay(5);
406
407 ath11k_pci_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);
408 val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
409 }
410
411 ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
412
413 val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
Kalle Valo562934a2020-12-16 20:24:11 +0200414 val |= GCC_GCC_PCIE_HOT_RST_VAL;
Carl Huangbabb0ce2020-12-10 16:05:21 +0200415 ath11k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
416 val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
417
418 ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
419
420 mdelay(5);
421}
422
423static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)
424{
425 /* This is a WAR for PCIE Hotreset.
426 * When target receive Hotreset, but will set the interrupt.
427 * So when download SBL again, SBL will open Interrupt and
428 * receive it, and crash immediately.
429 */
430 ath11k_pci_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);
431}
432
Carl Huang0ccdf432020-12-10 16:05:23 +0200433static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab)
434{
435 u32 val;
436
437 val = ath11k_pci_read32(ab, WLAON_QFPROM_PWR_CTRL_REG);
438 val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK;
439 ath11k_pci_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val);
440}
441
Carl Huangf3c603d2020-08-17 13:31:55 +0300442static void ath11k_pci_force_wake(struct ath11k_base *ab)
443{
444 ath11k_pci_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
445 mdelay(5);
446}
447
Carl Huangbabb0ce2020-12-10 16:05:21 +0200448static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
Carl Huangf3c603d2020-08-17 13:31:55 +0300449{
Baochen Qiang8a0b8992021-09-28 14:00:44 +0300450 mdelay(100);
451
Carl Huangbabb0ce2020-12-10 16:05:21 +0200452 if (power_on) {
453 ath11k_pci_enable_ltssm(ab);
454 ath11k_pci_clear_all_intrs(ab);
Carl Huang0ccdf432020-12-10 16:05:23 +0200455 ath11k_pci_set_wlaon_pwr_ctrl(ab);
Baochen Qiang5088df02021-05-31 17:41:28 +0300456 if (ab->hw_params.fix_l1ss)
457 ath11k_pci_fix_l1ss(ab);
Carl Huangbabb0ce2020-12-10 16:05:21 +0200458 }
459
Carl Huangf3c603d2020-08-17 13:31:55 +0300460 ath11k_mhi_clear_vector(ab);
Baochen Qiang8a0b8992021-09-28 14:00:44 +0300461 ath11k_pci_clear_dbg_registers(ab);
Carl Huangf3c603d2020-08-17 13:31:55 +0300462 ath11k_pci_soc_global_reset(ab);
463 ath11k_mhi_set_mhictrl_reset(ab);
Carl Huangf3c603d2020-08-17 13:31:55 +0300464}
465
Govind Singh1399fb82020-08-13 12:04:24 +0300466int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
467{
468 struct pci_dev *pci_dev = to_pci_dev(dev);
469
470 return pci_irq_vector(pci_dev, vector);
471}
472
Govind Singhc4eacab2020-08-14 10:10:24 +0300473static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
474 u32 *msi_addr_hi)
475{
Anilkumar Kollie8e55d82020-12-07 16:16:04 +0200476 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Govind Singhc4eacab2020-08-14 10:10:24 +0300477 struct pci_dev *pci_dev = to_pci_dev(ab->dev);
478
479 pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
480 msi_addr_lo);
481
Anilkumar Kollie8e55d82020-12-07 16:16:04 +0200482 if (test_bit(ATH11K_PCI_FLAG_IS_MSI_64, &ab_pci->flags)) {
483 pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
484 msi_addr_hi);
485 } else {
486 *msi_addr_hi = 0;
487 }
Govind Singhc4eacab2020-08-14 10:10:24 +0300488}
489
Govind Singh1399fb82020-08-13 12:04:24 +0300490int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
491 int *num_vectors, u32 *user_base_data,
492 u32 *base_vector)
493{
494 struct ath11k_base *ab = ab_pci->ab;
Anilkumar Kolli7a3aed02021-02-16 09:15:35 +0200495 const struct ath11k_msi_config *msi_config = ab_pci->msi_config;
Govind Singh1399fb82020-08-13 12:04:24 +0300496 int idx;
497
Anilkumar Kolli7a3aed02021-02-16 09:15:35 +0200498 for (idx = 0; idx < msi_config->total_users; idx++) {
499 if (strcmp(user_name, msi_config->users[idx].name) == 0) {
500 *num_vectors = msi_config->users[idx].num_vectors;
Carl Huangc41a6702021-11-19 15:36:26 +0200501 *base_vector = msi_config->users[idx].base_vector;
502 *user_base_data = *base_vector + ab_pci->msi_ep_base_data;
Govind Singh1399fb82020-08-13 12:04:24 +0300503
Carl Huangc41a6702021-11-19 15:36:26 +0200504 ath11k_dbg(ab, ATH11K_DBG_PCI,
505 "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
Govind Singh1399fb82020-08-13 12:04:24 +0300506 user_name, *num_vectors, *user_base_data,
507 *base_vector);
508
509 return 0;
510 }
511 }
512
513 ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
514
515 return -EINVAL;
516}
517
Karthikeyan Periyasamy6289ac22021-02-16 09:16:23 +0200518static void ath11k_pci_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
519 u32 *msi_idx)
520{
521 u32 i, msi_data_idx;
522
523 for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
524 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
525 continue;
526
527 if (ce_id == i)
528 break;
529
530 msi_data_idx++;
531 }
532 *msi_idx = msi_data_idx;
533}
534
Govind Singhc4eacab2020-08-14 10:10:24 +0300535static int ath11k_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
536 int *num_vectors, u32 *user_base_data,
537 u32 *base_vector)
538{
539 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
540
541 return ath11k_pci_get_user_msi_assignment(ab_pci, user_name,
542 num_vectors, user_base_data,
543 base_vector);
544}
545
Carl Huangd4ecb902020-08-17 13:31:52 +0300546static void ath11k_pci_free_ext_irq(struct ath11k_base *ab)
547{
548 int i, j;
549
550 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
551 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
552
553 for (j = 0; j < irq_grp->num_irq; j++)
554 free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
555
556 netif_napi_del(&irq_grp->napi);
557 }
558}
559
Govind Singh7f4beda2020-08-13 12:04:25 +0300560static void ath11k_pci_free_irq(struct ath11k_base *ab)
561{
562 int i, irq_idx;
563
Kalle Valod9d4b5f2020-08-17 13:31:48 +0300564 for (i = 0; i < ab->hw_params.ce_count; i++) {
Carl Huange3396b82020-08-17 13:31:47 +0300565 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
Govind Singh7f4beda2020-08-13 12:04:25 +0300566 continue;
567 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
568 free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
569 }
Carl Huangd4ecb902020-08-17 13:31:52 +0300570
571 ath11k_pci_free_ext_irq(ab);
Govind Singh7f4beda2020-08-13 12:04:25 +0300572}
573
Govind Singh2c3960c2020-08-14 10:10:25 +0300574static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
575{
Carl Huangc41a6702021-11-19 15:36:26 +0200576 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Govind Singh2c3960c2020-08-14 10:10:25 +0300577 u32 irq_idx;
578
Carl Huangc41a6702021-11-19 15:36:26 +0200579 /* In case of one MSI vector, we handle irq enable/disable in a
580 * uniform way since we only have one irq
581 */
582 if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
583 return;
584
Govind Singh2c3960c2020-08-14 10:10:25 +0300585 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
586 enable_irq(ab->irq_num[irq_idx]);
587}
588
Govind Singh7f4beda2020-08-13 12:04:25 +0300589static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
590{
Carl Huangc41a6702021-11-19 15:36:26 +0200591 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Govind Singh7f4beda2020-08-13 12:04:25 +0300592 u32 irq_idx;
593
Carl Huangc41a6702021-11-19 15:36:26 +0200594 /* In case of one MSI vector, we handle irq enable/disable in a
595 * uniform way since we only have one irq
596 */
597 if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
598 return;
599
Govind Singh7f4beda2020-08-13 12:04:25 +0300600 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
601 disable_irq_nosync(ab->irq_num[irq_idx]);
602}
603
Govind Singh2c3960c2020-08-14 10:10:25 +0300604static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
605{
606 int i;
607
Carl Huang01279bc2021-11-19 15:36:26 +0200608 clear_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
609
Kalle Valod9d4b5f2020-08-17 13:31:48 +0300610 for (i = 0; i < ab->hw_params.ce_count; i++) {
Carl Huange3396b82020-08-17 13:31:47 +0300611 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
Govind Singh2c3960c2020-08-14 10:10:25 +0300612 continue;
613 ath11k_pci_ce_irq_disable(ab, i);
614 }
615}
616
617static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
618{
619 int i;
620 int irq_idx;
621
Kalle Valod9d4b5f2020-08-17 13:31:48 +0300622 for (i = 0; i < ab->hw_params.ce_count; i++) {
Carl Huange3396b82020-08-17 13:31:47 +0300623 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
Govind Singh2c3960c2020-08-14 10:10:25 +0300624 continue;
625
626 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
627 synchronize_irq(ab->irq_num[irq_idx]);
628 }
629}
630
Allen Pais0f01dcb2020-10-07 16:03:09 +0530631static void ath11k_pci_ce_tasklet(struct tasklet_struct *t)
Govind Singh2c3960c2020-08-14 10:10:25 +0300632{
Allen Pais0f01dcb2020-10-07 16:03:09 +0530633 struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
Carl Huangac6e7342021-11-19 15:36:26 +0200634 int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
Govind Singh2c3960c2020-08-14 10:10:25 +0300635
636 ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
637
Carl Huangac6e7342021-11-19 15:36:26 +0200638 enable_irq(ce_pipe->ab->irq_num[irq_idx]);
Govind Singh2c3960c2020-08-14 10:10:25 +0300639}
640
Govind Singh7f4beda2020-08-13 12:04:25 +0300641static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
642{
643 struct ath11k_ce_pipe *ce_pipe = arg;
Carl Huang01279bc2021-11-19 15:36:26 +0200644 struct ath11k_base *ab = ce_pipe->ab;
Carl Huangac6e7342021-11-19 15:36:26 +0200645 int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
Carl Huang01279bc2021-11-19 15:36:26 +0200646
647 if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
648 return IRQ_HANDLED;
Govind Singh7f4beda2020-08-13 12:04:25 +0300649
Karthikeyan Periyasamy7dc67af2021-02-16 09:16:24 +0200650 /* last interrupt received for this CE */
651 ce_pipe->timestamp = jiffies;
652
Carl Huangac6e7342021-11-19 15:36:26 +0200653 disable_irq_nosync(ab->irq_num[irq_idx]);
654
Govind Singh2c3960c2020-08-14 10:10:25 +0300655 tasklet_schedule(&ce_pipe->intr_tq);
Govind Singh7f4beda2020-08-13 12:04:25 +0300656
657 return IRQ_HANDLED;
658}
659
Carl Huangd4ecb902020-08-17 13:31:52 +0300660static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
661{
Carl Huangc41a6702021-11-19 15:36:26 +0200662 struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
Carl Huangd4ecb902020-08-17 13:31:52 +0300663 int i;
664
Carl Huangc41a6702021-11-19 15:36:26 +0200665 /* In case of one MSI vector, we handle irq enable/disable
666 * in a uniform way since we only have one irq
667 */
668 if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
669 return;
670
Carl Huangd4ecb902020-08-17 13:31:52 +0300671 for (i = 0; i < irq_grp->num_irq; i++)
672 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
673}
674
675static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
676{
677 int i;
678
Carl Huang01279bc2021-11-19 15:36:26 +0200679 clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags);
680
Carl Huangd4ecb902020-08-17 13:31:52 +0300681 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
682 struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
683
684 ath11k_pci_ext_grp_disable(irq_grp);
685
Ben Greeard943fda2020-09-03 12:52:54 -0700686 if (irq_grp->napi_enabled) {
687 napi_synchronize(&irq_grp->napi);
688 napi_disable(&irq_grp->napi);
689 irq_grp->napi_enabled = false;
690 }
Carl Huangd4ecb902020-08-17 13:31:52 +0300691 }
692}
693
694static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
695{
Carl Huangc41a6702021-11-19 15:36:26 +0200696 struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
Carl Huangd4ecb902020-08-17 13:31:52 +0300697 int i;
698
Carl Huangc41a6702021-11-19 15:36:26 +0200699 /* In case of one MSI vector, we handle irq enable/disable in a
700 * uniform way since we only have one irq
701 */
702 if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
703 return;
704
Carl Huangd4ecb902020-08-17 13:31:52 +0300705 for (i = 0; i < irq_grp->num_irq; i++)
706 enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
707}
708
709static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
710{
711 int i;
712
Carl Huang01279bc2021-11-19 15:36:26 +0200713 set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
714
Carl Huangd4ecb902020-08-17 13:31:52 +0300715 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
716 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
717
Ben Greeard943fda2020-09-03 12:52:54 -0700718 if (!irq_grp->napi_enabled) {
719 napi_enable(&irq_grp->napi);
720 irq_grp->napi_enabled = true;
721 }
Carl Huangd4ecb902020-08-17 13:31:52 +0300722 ath11k_pci_ext_grp_enable(irq_grp);
723 }
724}
725
726static void ath11k_pci_sync_ext_irqs(struct ath11k_base *ab)
727{
728 int i, j, irq_idx;
729
730 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
731 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
732
733 for (j = 0; j < irq_grp->num_irq; j++) {
734 irq_idx = irq_grp->irqs[j];
735 synchronize_irq(ab->irq_num[irq_idx]);
736 }
737 }
738}
739
740static void ath11k_pci_ext_irq_disable(struct ath11k_base *ab)
741{
742 __ath11k_pci_ext_irq_disable(ab);
743 ath11k_pci_sync_ext_irqs(ab);
744}
745
746static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
747{
748 struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
749 struct ath11k_ext_irq_grp,
750 napi);
751 struct ath11k_base *ab = irq_grp->ab;
752 int work_done;
Carl Huangac6e7342021-11-19 15:36:26 +0200753 int i;
Carl Huangd4ecb902020-08-17 13:31:52 +0300754
755 work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
756 if (work_done < budget) {
757 napi_complete_done(napi, work_done);
Carl Huangac6e7342021-11-19 15:36:26 +0200758 for (i = 0; i < irq_grp->num_irq; i++)
759 enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
Carl Huangd4ecb902020-08-17 13:31:52 +0300760 }
761
762 if (work_done > budget)
763 work_done = budget;
764
765 return work_done;
766}
767
768static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
769{
770 struct ath11k_ext_irq_grp *irq_grp = arg;
Carl Huang01279bc2021-11-19 15:36:26 +0200771 struct ath11k_base *ab = irq_grp->ab;
Carl Huangac6e7342021-11-19 15:36:26 +0200772 int i;
Carl Huang01279bc2021-11-19 15:36:26 +0200773
774 if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
775 return IRQ_HANDLED;
Carl Huangd4ecb902020-08-17 13:31:52 +0300776
777 ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
778
Karthikeyan Periyasamy7dc67af2021-02-16 09:16:24 +0200779 /* last interrupt received for this group */
780 irq_grp->timestamp = jiffies;
781
Carl Huangac6e7342021-11-19 15:36:26 +0200782 for (i = 0; i < irq_grp->num_irq; i++)
783 disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
Carl Huangd4ecb902020-08-17 13:31:52 +0300784
785 napi_schedule(&irq_grp->napi);
786
787 return IRQ_HANDLED;
788}
789
790static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
791{
Carl Huangc41a6702021-11-19 15:36:26 +0200792 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Carl Huangd4ecb902020-08-17 13:31:52 +0300793 int i, j, ret, num_vectors = 0;
Carl Huang4ab46932021-11-19 15:36:26 +0200794 u32 user_base_data = 0, base_vector = 0;
Carl Huangd4ecb902020-08-17 13:31:52 +0300795
Colin Ian Kingb2c09452020-08-19 12:14:52 +0100796 ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
797 &num_vectors,
798 &user_base_data,
799 &base_vector);
800 if (ret < 0)
801 return ret;
Carl Huangd4ecb902020-08-17 13:31:52 +0300802
803 for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
804 struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
805 u32 num_irq = 0;
806
807 irq_grp->ab = ab;
808 irq_grp->grp_id = i;
809 init_dummy_netdev(&irq_grp->napi_ndev);
810 netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
811 ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
812
813 if (ab->hw_params.ring_mask->tx[i] ||
814 ab->hw_params.ring_mask->rx[i] ||
815 ab->hw_params.ring_mask->rx_err[i] ||
816 ab->hw_params.ring_mask->rx_wbm_rel[i] ||
817 ab->hw_params.ring_mask->reo_status[i] ||
818 ab->hw_params.ring_mask->rxdma2host[i] ||
819 ab->hw_params.ring_mask->host2rxdma[i] ||
820 ab->hw_params.ring_mask->rx_mon_status[i]) {
821 num_irq = 1;
822 }
823
824 irq_grp->num_irq = num_irq;
Carl Huang4ab46932021-11-19 15:36:26 +0200825 irq_grp->irqs[0] = ATH11K_PCI_IRQ_DP_OFFSET + i;
Carl Huangd4ecb902020-08-17 13:31:52 +0300826
827 for (j = 0; j < irq_grp->num_irq; j++) {
828 int irq_idx = irq_grp->irqs[j];
829 int vector = (i % num_vectors) + base_vector;
830 int irq = ath11k_pci_get_msi_irq(ab->dev, vector);
831
832 ab->irq_num[irq_idx] = irq;
833
834 ath11k_dbg(ab, ATH11K_DBG_PCI,
835 "irq:%d group:%d\n", irq, i);
Karthikeyan Periyasamy7dc67af2021-02-16 09:16:24 +0200836
837 irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
Carl Huangd4ecb902020-08-17 13:31:52 +0300838 ret = request_irq(irq, ath11k_pci_ext_interrupt_handler,
Carl Huangc41a6702021-11-19 15:36:26 +0200839 ab_pci->irq_flags,
Carl Huangd4ecb902020-08-17 13:31:52 +0300840 "DP_EXT_IRQ", irq_grp);
841 if (ret) {
842 ath11k_err(ab, "failed request irq %d: %d\n",
843 vector, ret);
844 return ret;
845 }
Carl Huangd4ecb902020-08-17 13:31:52 +0300846 }
Carl Huangc41a6702021-11-19 15:36:26 +0200847 ath11k_pci_ext_grp_disable(irq_grp);
Carl Huangd4ecb902020-08-17 13:31:52 +0300848 }
849
850 return 0;
851}
852
Baochen Qiange94b0742021-11-19 15:36:26 +0200853static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci,
854 const struct cpumask *m)
855{
856 if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
857 return 0;
858
859 return irq_set_affinity_hint(ab_pci->pdev->irq, m);
860}
861
Govind Singh7f4beda2020-08-13 12:04:25 +0300862static int ath11k_pci_config_irq(struct ath11k_base *ab)
863{
Carl Huangc41a6702021-11-19 15:36:26 +0200864 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Govind Singh7f4beda2020-08-13 12:04:25 +0300865 struct ath11k_ce_pipe *ce_pipe;
866 u32 msi_data_start;
Karthikeyan Periyasamy6289ac22021-02-16 09:16:23 +0200867 u32 msi_data_count, msi_data_idx;
Govind Singh7f4beda2020-08-13 12:04:25 +0300868 u32 msi_irq_start;
869 unsigned int msi_data;
870 int irq, i, ret, irq_idx;
871
872 ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab),
873 "CE", &msi_data_count,
874 &msi_data_start, &msi_irq_start);
875 if (ret)
876 return ret;
877
Baochen Qiange94b0742021-11-19 15:36:26 +0200878 ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));
879 if (ret) {
880 ath11k_err(ab, "failed to set irq affinity %d\n", ret);
881 return ret;
882 }
883
Govind Singh7f4beda2020-08-13 12:04:25 +0300884 /* Configure CE irqs */
Karthikeyan Periyasamy6289ac22021-02-16 09:16:23 +0200885 for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
Carl Huange3396b82020-08-17 13:31:47 +0300886 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
Govind Singh7f4beda2020-08-13 12:04:25 +0300887 continue;
888
Karthikeyan Periyasamy6289ac22021-02-16 09:16:23 +0200889 msi_data = (msi_data_idx % msi_data_count) + msi_irq_start;
890 irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
891 ce_pipe = &ab->ce.ce_pipe[i];
892
Govind Singh7f4beda2020-08-13 12:04:25 +0300893 irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
894
Allen Pais0f01dcb2020-10-07 16:03:09 +0530895 tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);
Govind Singh2c3960c2020-08-14 10:10:25 +0300896
Govind Singh7f4beda2020-08-13 12:04:25 +0300897 ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
Carl Huangc41a6702021-11-19 15:36:26 +0200898 ab_pci->irq_flags, irq_name[irq_idx],
Govind Singh7f4beda2020-08-13 12:04:25 +0300899 ce_pipe);
900 if (ret) {
901 ath11k_err(ab, "failed to request irq %d: %d\n",
902 irq_idx, ret);
Baochen Qiange94b0742021-11-19 15:36:26 +0200903 goto err_irq_affinity_cleanup;
Govind Singh7f4beda2020-08-13 12:04:25 +0300904 }
905
906 ab->irq_num[irq_idx] = irq;
Karthikeyan Periyasamy6289ac22021-02-16 09:16:23 +0200907 msi_data_idx++;
Karthikeyan Periyasamye678fbd2021-02-16 09:16:23 +0200908
Carl Huange5c860e2020-08-17 13:31:50 +0300909 ath11k_pci_ce_irq_disable(ab, i);
Govind Singh7f4beda2020-08-13 12:04:25 +0300910 }
911
Carl Huangd4ecb902020-08-17 13:31:52 +0300912 ret = ath11k_pci_ext_irq_config(ab);
913 if (ret)
Baochen Qiange94b0742021-11-19 15:36:26 +0200914 goto err_irq_affinity_cleanup;
Carl Huangd4ecb902020-08-17 13:31:52 +0300915
Govind Singh7f4beda2020-08-13 12:04:25 +0300916 return 0;
Baochen Qiange94b0742021-11-19 15:36:26 +0200917
918err_irq_affinity_cleanup:
919 ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
920 return ret;
Govind Singh7f4beda2020-08-13 12:04:25 +0300921}
922
923static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
924{
925 struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
926
Anilkumar Kolli967c1d12020-09-08 07:55:35 +0000927 cfg->tgt_ce = ab->hw_params.target_ce_config;
928 cfg->tgt_ce_len = ab->hw_params.target_ce_count;
Govind Singh7f4beda2020-08-13 12:04:25 +0300929
Anilkumar Kolli967c1d12020-09-08 07:55:35 +0000930 cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
931 cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
Anilkumar Kolli16001e42021-02-16 09:15:48 +0200932 ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
Carl Huange838c142020-10-01 12:34:44 +0300933
934 ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2,
935 &cfg->shadow_reg_v2_len);
Govind Singh7f4beda2020-08-13 12:04:25 +0300936}
937
Govind Singh7f4beda2020-08-13 12:04:25 +0300938static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
939{
940 int i;
941
Carl Huang01279bc2021-11-19 15:36:26 +0200942 set_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
943
Kalle Valod9d4b5f2020-08-17 13:31:48 +0300944 for (i = 0; i < ab->hw_params.ce_count; i++) {
Carl Huange3396b82020-08-17 13:31:47 +0300945 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
Govind Singh7f4beda2020-08-13 12:04:25 +0300946 continue;
947 ath11k_pci_ce_irq_enable(ab, i);
948 }
949}
950
Baochen Qiang96527d52021-10-11 09:33:08 +0300951static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable)
952{
953 struct pci_dev *dev = ab_pci->pdev;
954 u16 control;
955
956 pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
957
958 if (enable)
959 control |= PCI_MSI_FLAGS_ENABLE;
960 else
961 control &= ~PCI_MSI_FLAGS_ENABLE;
962
963 pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
964}
965
966static void ath11k_pci_msi_enable(struct ath11k_pci *ab_pci)
967{
968 ath11k_pci_msi_config(ab_pci, true);
969}
970
971static void ath11k_pci_msi_disable(struct ath11k_pci *ab_pci)
972{
973 ath11k_pci_msi_config(ab_pci, false);
974}
975
976static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
Govind Singh5697a562020-08-13 12:04:22 +0300977{
978 struct ath11k_base *ab = ab_pci->ab;
Anilkumar Kolli7a3aed02021-02-16 09:15:35 +0200979 const struct ath11k_msi_config *msi_config = ab_pci->msi_config;
Govind Singh5697a562020-08-13 12:04:22 +0300980 struct msi_desc *msi_desc;
981 int num_vectors;
982 int ret;
983
984 num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
Anilkumar Kolli7a3aed02021-02-16 09:15:35 +0200985 msi_config->total_vectors,
986 msi_config->total_vectors,
Govind Singh5697a562020-08-13 12:04:22 +0300987 PCI_IRQ_MSI);
Carl Huangac6e7342021-11-19 15:36:26 +0200988 if (num_vectors == msi_config->total_vectors) {
Carl Huangc41a6702021-11-19 15:36:26 +0200989 set_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
990 ab_pci->irq_flags = IRQF_SHARED;
Carl Huangac6e7342021-11-19 15:36:26 +0200991 } else {
992 num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
993 1,
994 1,
995 PCI_IRQ_MSI);
996 if (num_vectors < 0) {
997 ret = -EINVAL;
998 goto reset_msi_config;
999 }
1000 clear_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
1001 ab_pci->msi_config = &msi_config_one_msi;
1002 ab_pci->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
1003 ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n");
Govind Singh5697a562020-08-13 12:04:22 +03001004 }
Carl Huangac6e7342021-11-19 15:36:26 +02001005 ath11k_info(ab, "MSI vectors: %d\n", num_vectors);
1006
Baochen Qiang96527d52021-10-11 09:33:08 +03001007 ath11k_pci_msi_disable(ab_pci);
Govind Singh5697a562020-08-13 12:04:22 +03001008
1009 msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
1010 if (!msi_desc) {
1011 ath11k_err(ab, "msi_desc is NULL!\n");
1012 ret = -EINVAL;
1013 goto free_msi_vector;
1014 }
1015
1016 ab_pci->msi_ep_base_data = msi_desc->msg.data;
Thomas Gleixnere58f2252021-12-06 23:27:39 +01001017 if (msi_desc->pci.msi_attrib.is_64)
Anilkumar Kollie8e55d82020-12-07 16:16:04 +02001018 set_bit(ATH11K_PCI_FLAG_IS_MSI_64, &ab_pci->flags);
Govind Singh5697a562020-08-13 12:04:22 +03001019
1020 ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
1021
1022 return 0;
1023
1024free_msi_vector:
1025 pci_free_irq_vectors(ab_pci->pdev);
1026
Carl Huangac6e7342021-11-19 15:36:26 +02001027reset_msi_config:
Govind Singh5697a562020-08-13 12:04:22 +03001028 return ret;
1029}
1030
Baochen Qiang96527d52021-10-11 09:33:08 +03001031static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci)
Govind Singh5697a562020-08-13 12:04:22 +03001032{
1033 pci_free_irq_vectors(ab_pci->pdev);
1034}
1035
Carl Huang87b40722021-11-19 15:36:26 +02001036static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
1037{
1038 struct msi_desc *msi_desc;
1039
1040 msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
1041 if (!msi_desc) {
1042 ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");
1043 pci_free_irq_vectors(ab_pci->pdev);
1044 return -EINVAL;
1045 }
1046
1047 ab_pci->msi_ep_base_data = msi_desc->msg.data;
1048
1049 ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n",
1050 ab_pci->msi_ep_base_data);
1051
1052 return 0;
1053}
1054
Govind Singh57626132020-08-13 12:04:21 +03001055static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
1056{
1057 struct ath11k_base *ab = ab_pci->ab;
1058 u16 device_id;
1059 int ret = 0;
1060
1061 pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
1062 if (device_id != ab_pci->dev_id) {
1063 ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
1064 device_id, ab_pci->dev_id);
1065 ret = -EIO;
1066 goto out;
1067 }
1068
1069 ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
1070 if (ret) {
1071 ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
1072 goto out;
1073 }
1074
1075 ret = pci_enable_device(pdev);
1076 if (ret) {
1077 ath11k_err(ab, "failed to enable pci device: %d\n", ret);
1078 goto out;
1079 }
1080
1081 ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
1082 if (ret) {
1083 ath11k_err(ab, "failed to request pci region: %d\n", ret);
1084 goto disable_device;
1085 }
1086
Christophe JAILLET923a1342021-06-26 17:25:04 +02001087 ret = dma_set_mask_and_coherent(&pdev->dev,
1088 DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
Govind Singh57626132020-08-13 12:04:21 +03001089 if (ret) {
1090 ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
1091 ATH11K_PCI_DMA_MASK, ret);
1092 goto release_region;
1093 }
1094
Govind Singh57626132020-08-13 12:04:21 +03001095 pci_set_master(pdev);
1096
1097 ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
1098 ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
1099 if (!ab->mem) {
1100 ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
1101 ret = -EIO;
1102 goto clear_master;
1103 }
1104
1105 ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
1106 return 0;
1107
1108clear_master:
1109 pci_clear_master(pdev);
1110release_region:
1111 pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
1112disable_device:
1113 pci_disable_device(pdev);
1114out:
1115 return ret;
1116}
1117
1118static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
1119{
1120 struct ath11k_base *ab = ab_pci->ab;
1121 struct pci_dev *pci_dev = ab_pci->pdev;
1122
1123 pci_iounmap(pci_dev, ab->mem);
1124 ab->mem = NULL;
1125 pci_clear_master(pci_dev);
1126 pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
1127 if (pci_is_enabled(pci_dev))
1128 pci_disable_device(pci_dev);
1129}
1130
Carl Huange9603f42020-12-17 17:22:10 +02001131static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
1132{
1133 struct ath11k_base *ab = ab_pci->ab;
1134
1135 pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
1136 &ab_pci->link_ctl);
1137
1138 ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
1139 ab_pci->link_ctl,
1140 u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
1141 u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
1142
1143 /* disable L0s and L1 */
1144 pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
1145 ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
1146
1147 set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
1148}
1149
1150static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
1151{
1152 if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
1153 pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
1154 ab_pci->link_ctl);
1155}
1156
Govind Singh1399fb82020-08-13 12:04:24 +03001157static int ath11k_pci_power_up(struct ath11k_base *ab)
1158{
1159 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
1160 int ret;
1161
Carl Huanga05bd852020-10-01 12:34:43 +03001162 ab_pci->register_window = 0;
1163 clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
Carl Huangbabb0ce2020-12-10 16:05:21 +02001164 ath11k_pci_sw_reset(ab_pci->ab, true);
Carl Huangf3c603d2020-08-17 13:31:55 +03001165
Carl Huange9603f42020-12-17 17:22:10 +02001166 /* Disable ASPM during firmware download due to problems switching
1167 * to AMSS state.
1168 */
1169 ath11k_pci_aspm_disable(ab_pci);
1170
Baochen Qiang96527d52021-10-11 09:33:08 +03001171 ath11k_pci_msi_enable(ab_pci);
1172
Govind Singh1399fb82020-08-13 12:04:24 +03001173 ret = ath11k_mhi_start(ab_pci);
1174 if (ret) {
1175 ath11k_err(ab, "failed to start mhi: %d\n", ret);
1176 return ret;
1177 }
1178
Karthikeyan Periyasamy480a7362021-02-16 09:16:17 +02001179 if (ab->bus_params.static_window_map)
1180 ath11k_pci_select_static_window(ab_pci);
1181
Govind Singh1399fb82020-08-13 12:04:24 +03001182 return 0;
1183}
1184
1185static void ath11k_pci_power_down(struct ath11k_base *ab)
1186{
1187 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
1188
Carl Huange9603f42020-12-17 17:22:10 +02001189 /* restore aspm in case firmware bootup fails */
1190 ath11k_pci_aspm_restore(ab_pci);
1191
Carl Huangbabb0ce2020-12-10 16:05:21 +02001192 ath11k_pci_force_wake(ab_pci->ab);
Baochen Qiang96527d52021-10-11 09:33:08 +03001193
1194 ath11k_pci_msi_disable(ab_pci);
1195
Govind Singh1399fb82020-08-13 12:04:24 +03001196 ath11k_mhi_stop(ab_pci);
Carl Huanga05bd852020-10-01 12:34:43 +03001197 clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
Carl Huangbabb0ce2020-12-10 16:05:21 +02001198 ath11k_pci_sw_reset(ab_pci->ab, false);
Govind Singh1399fb82020-08-13 12:04:24 +03001199}
1200
Carl Huangfa5917e2020-12-11 19:35:42 +02001201static int ath11k_pci_hif_suspend(struct ath11k_base *ab)
1202{
1203 struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
1204
1205 ath11k_mhi_suspend(ar_pci);
1206
1207 return 0;
1208}
1209
1210static int ath11k_pci_hif_resume(struct ath11k_base *ab)
1211{
1212 struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
1213
1214 ath11k_mhi_resume(ar_pci);
1215
1216 return 0;
1217}
1218
Govind Singh2c3960c2020-08-14 10:10:25 +03001219static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
1220{
1221 int i;
1222
Kalle Valod9d4b5f2020-08-17 13:31:48 +03001223 for (i = 0; i < ab->hw_params.ce_count; i++) {
Govind Singh2c3960c2020-08-14 10:10:25 +03001224 struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
1225
Carl Huange3396b82020-08-17 13:31:47 +03001226 if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
Govind Singh2c3960c2020-08-14 10:10:25 +03001227 continue;
1228
1229 tasklet_kill(&ce_pipe->intr_tq);
1230 }
1231}
1232
Carl Huangd578ec2a2020-12-11 19:35:49 +02001233static void ath11k_pci_ce_irq_disable_sync(struct ath11k_base *ab)
Govind Singh7f4beda2020-08-13 12:04:25 +03001234{
Govind Singh2c3960c2020-08-14 10:10:25 +03001235 ath11k_pci_ce_irqs_disable(ab);
1236 ath11k_pci_sync_ce_irqs(ab);
1237 ath11k_pci_kill_tasklets(ab);
Carl Huangd578ec2a2020-12-11 19:35:49 +02001238}
1239
1240static void ath11k_pci_stop(struct ath11k_base *ab)
1241{
1242 ath11k_pci_ce_irq_disable_sync(ab);
Govind Singh7f4beda2020-08-13 12:04:25 +03001243 ath11k_ce_cleanup_pipes(ab);
1244}
1245
1246static int ath11k_pci_start(struct ath11k_base *ab)
1247{
Carl Huanga05bd852020-10-01 12:34:43 +03001248 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
1249
1250 set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
1251
Carl Huang915a0812021-11-19 15:36:26 +02001252 /* TODO: for now don't restore ASPM in case of single MSI
1253 * vector as MHI register reading in M2 causes system hang.
1254 */
1255 if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
1256 ath11k_pci_aspm_restore(ab_pci);
1257 else
1258 ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n");
Carl Huange9603f42020-12-17 17:22:10 +02001259
Govind Singh7f4beda2020-08-13 12:04:25 +03001260 ath11k_pci_ce_irqs_enable(ab);
Govind Singh2c3960c2020-08-14 10:10:25 +03001261 ath11k_ce_rx_post_buf(ab);
1262
1263 return 0;
1264}
1265
Carl Huangd578ec2a2020-12-11 19:35:49 +02001266static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab)
1267{
1268 ath11k_pci_ce_irqs_enable(ab);
1269}
1270
1271static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab)
1272{
1273 ath11k_pci_ce_irq_disable_sync(ab);
1274}
1275
Govind Singh2c3960c2020-08-14 10:10:25 +03001276static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
1277 u8 *ul_pipe, u8 *dl_pipe)
1278{
1279 const struct service_to_pipe *entry;
1280 bool ul_set = false, dl_set = false;
1281 int i;
1282
Anilkumar Kolli967c1d12020-09-08 07:55:35 +00001283 for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
1284 entry = &ab->hw_params.svc_to_ce_map[i];
Govind Singh2c3960c2020-08-14 10:10:25 +03001285
1286 if (__le32_to_cpu(entry->service_id) != service_id)
1287 continue;
1288
1289 switch (__le32_to_cpu(entry->pipedir)) {
1290 case PIPEDIR_NONE:
1291 break;
1292 case PIPEDIR_IN:
1293 WARN_ON(dl_set);
1294 *dl_pipe = __le32_to_cpu(entry->pipenum);
1295 dl_set = true;
1296 break;
1297 case PIPEDIR_OUT:
1298 WARN_ON(ul_set);
1299 *ul_pipe = __le32_to_cpu(entry->pipenum);
1300 ul_set = true;
1301 break;
1302 case PIPEDIR_INOUT:
1303 WARN_ON(dl_set);
1304 WARN_ON(ul_set);
1305 *dl_pipe = __le32_to_cpu(entry->pipenum);
1306 *ul_pipe = __le32_to_cpu(entry->pipenum);
1307 dl_set = true;
1308 ul_set = true;
1309 break;
1310 }
1311 }
1312
1313 if (WARN_ON(!ul_set || !dl_set))
1314 return -ENOENT;
Govind Singh7f4beda2020-08-13 12:04:25 +03001315
1316 return 0;
1317}
1318
1319static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
1320 .start = ath11k_pci_start,
1321 .stop = ath11k_pci_stop,
Govind Singh654e9592020-08-14 10:10:23 +03001322 .read32 = ath11k_pci_read32,
1323 .write32 = ath11k_pci_write32,
Govind Singh1399fb82020-08-13 12:04:24 +03001324 .power_down = ath11k_pci_power_down,
1325 .power_up = ath11k_pci_power_up,
Carl Huangfa5917e2020-12-11 19:35:42 +02001326 .suspend = ath11k_pci_hif_suspend,
1327 .resume = ath11k_pci_hif_resume,
Carl Huangd4ecb902020-08-17 13:31:52 +03001328 .irq_enable = ath11k_pci_ext_irq_enable,
1329 .irq_disable = ath11k_pci_ext_irq_disable,
Govind Singhc4eacab2020-08-14 10:10:24 +03001330 .get_msi_address = ath11k_pci_get_msi_address,
1331 .get_user_msi_vector = ath11k_get_user_msi_assignment,
Govind Singh2c3960c2020-08-14 10:10:25 +03001332 .map_service_to_pipe = ath11k_pci_map_service_to_pipe,
Carl Huangd578ec2a2020-12-11 19:35:49 +02001333 .ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
1334 .ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
Karthikeyan Periyasamy6289ac22021-02-16 09:16:23 +02001335 .get_ce_msi_idx = ath11k_pci_get_ce_msi_idx,
Govind Singh1399fb82020-08-13 12:04:24 +03001336};
1337
Baochen Qiang0fbf1952021-05-31 17:41:28 +03001338static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)
1339{
1340 u32 soc_hw_version;
1341
1342 soc_hw_version = ath11k_pci_read32(ab, TCSR_SOC_HW_VERSION);
1343 *major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
1344 soc_hw_version);
1345 *minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
1346 soc_hw_version);
1347
1348 ath11k_dbg(ab, ATH11K_DBG_PCI, "pci tcsr_soc_hw_version major %d minor %d\n",
1349 *major, *minor);
1350}
1351
Govind Singh6e0355a2020-08-13 12:04:20 +03001352static int ath11k_pci_probe(struct pci_dev *pdev,
1353 const struct pci_device_id *pci_dev)
1354{
1355 struct ath11k_base *ab;
Govind Singh57626132020-08-13 12:04:21 +03001356 struct ath11k_pci *ab_pci;
Anilkumar Kolli6ac04bd2021-12-14 17:39:43 +02001357 u32 soc_hw_version_major, soc_hw_version_minor, addr;
Govind Singh57626132020-08-13 12:04:21 +03001358 int ret;
Govind Singh6e0355a2020-08-13 12:04:20 +03001359
Govind Singh1ff8ed72020-08-13 12:04:26 +03001360 ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI,
1361 &ath11k_pci_bus_params);
Govind Singh6e0355a2020-08-13 12:04:20 +03001362 if (!ab) {
1363 dev_err(&pdev->dev, "failed to allocate ath11k base\n");
1364 return -ENOMEM;
1365 }
1366
1367 ab->dev = &pdev->dev;
Govind Singh6e0355a2020-08-13 12:04:20 +03001368 pci_set_drvdata(pdev, ab);
Govind Singh57626132020-08-13 12:04:21 +03001369 ab_pci = ath11k_pci_priv(ab);
1370 ab_pci->dev_id = pci_dev->device;
1371 ab_pci->ab = ab;
Govind Singh5697a562020-08-13 12:04:22 +03001372 ab_pci->pdev = pdev;
Govind Singh7f4beda2020-08-13 12:04:25 +03001373 ab->hif.ops = &ath11k_pci_hif_ops;
Govind Singh57626132020-08-13 12:04:21 +03001374 pci_set_drvdata(pdev, ab);
Govind Singh654e9592020-08-14 10:10:23 +03001375 spin_lock_init(&ab_pci->window_lock);
Govind Singh57626132020-08-13 12:04:21 +03001376
Anilkumar Kolli6ac04bd2021-12-14 17:39:43 +02001377 /* Set fixed_mem_region to true for platforms support reserved memory
1378 * from DT. If memory is reserved from DT for FW, ath11k driver need not
1379 * allocate memory.
1380 */
1381 ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr);
1382 if (!ret)
1383 set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags);
1384
Govind Singh57626132020-08-13 12:04:21 +03001385 ret = ath11k_pci_claim(ab_pci, pdev);
1386 if (ret) {
1387 ath11k_err(ab, "failed to claim device: %d\n", ret);
1388 goto err_free_core;
1389 }
Govind Singh6e0355a2020-08-13 12:04:20 +03001390
Wen Gongfc95d102021-11-15 11:29:55 +02001391 ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n",
1392 pdev->vendor, pdev->device,
1393 pdev->subsystem_vendor, pdev->subsystem_device);
1394
1395 ab->id.vendor = pdev->vendor;
1396 ab->id.device = pdev->device;
1397 ab->id.subsystem_vendor = pdev->subsystem_vendor;
1398 ab->id.subsystem_device = pdev->subsystem_device;
1399
Kalle Valo18ac1662020-09-29 20:15:32 +03001400 switch (pci_dev->device) {
1401 case QCA6390_DEVICE_ID:
Baochen Qiang0fbf1952021-05-31 17:41:28 +03001402 ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
1403 &soc_hw_version_minor);
Kalle Valo18ac1662020-09-29 20:15:32 +03001404 switch (soc_hw_version_major) {
1405 case 2:
1406 ab->hw_rev = ATH11K_HW_QCA6390_HW20;
1407 break;
1408 default:
1409 dev_err(&pdev->dev, "Unsupported QCA6390 SOC hardware version: %d %d\n",
1410 soc_hw_version_major, soc_hw_version_minor);
1411 ret = -EOPNOTSUPP;
1412 goto err_pci_free_region;
1413 }
Anilkumar Kolli4e809462021-02-16 09:16:25 +02001414 ab_pci->msi_config = &ath11k_msi_config[0];
1415 break;
1416 case QCN9074_DEVICE_ID:
1417 ab_pci->msi_config = &ath11k_msi_config[1];
1418 ab->bus_params.static_window_map = true;
1419 ab->hw_rev = ATH11K_HW_QCN9074_HW10;
Kalle Valo18ac1662020-09-29 20:15:32 +03001420 break;
Baochen Qiang0fbf1952021-05-31 17:41:28 +03001421 case WCN6855_DEVICE_ID:
Wen Gongfc95d102021-11-15 11:29:55 +02001422 ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD;
Baochen Qiang0fbf1952021-05-31 17:41:28 +03001423 ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
1424 &soc_hw_version_minor);
1425 switch (soc_hw_version_major) {
1426 case 2:
Baochen Qiangd1147a32021-11-29 10:56:12 +08001427 switch (soc_hw_version_minor) {
1428 case 0x00:
1429 case 0x01:
1430 ab->hw_rev = ATH11K_HW_WCN6855_HW20;
1431 break;
1432 case 0x10:
1433 case 0x11:
1434 ab->hw_rev = ATH11K_HW_WCN6855_HW21;
1435 break;
1436 default:
1437 goto unsupported_wcn6855_soc;
1438 }
Baochen Qiang0fbf1952021-05-31 17:41:28 +03001439 break;
1440 default:
Baochen Qiangd1147a32021-11-29 10:56:12 +08001441unsupported_wcn6855_soc:
Baochen Qiang0fbf1952021-05-31 17:41:28 +03001442 dev_err(&pdev->dev, "Unsupported WCN6855 SOC hardware version: %d %d\n",
1443 soc_hw_version_major, soc_hw_version_minor);
1444 ret = -EOPNOTSUPP;
1445 goto err_pci_free_region;
1446 }
1447 ab_pci->msi_config = &ath11k_msi_config[0];
1448 break;
Kalle Valo18ac1662020-09-29 20:15:32 +03001449 default:
1450 dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
1451 pci_dev->device);
1452 ret = -EOPNOTSUPP;
1453 goto err_pci_free_region;
1454 }
1455
Baochen Qiang96527d52021-10-11 09:33:08 +03001456 ret = ath11k_pci_alloc_msi(ab_pci);
Govind Singh5697a562020-08-13 12:04:22 +03001457 if (ret) {
1458 ath11k_err(ab, "failed to enable msi: %d\n", ret);
1459 goto err_pci_free_region;
1460 }
1461
Kalle Valob8246f82020-08-13 12:04:23 +03001462 ret = ath11k_core_pre_init(ab);
1463 if (ret)
1464 goto err_pci_disable_msi;
1465
Govind Singh1399fb82020-08-13 12:04:24 +03001466 ret = ath11k_mhi_register(ab_pci);
1467 if (ret) {
1468 ath11k_err(ab, "failed to register mhi: %d\n", ret);
1469 goto err_pci_disable_msi;
1470 }
1471
Govind Singh7f4beda2020-08-13 12:04:25 +03001472 ret = ath11k_hal_srng_init(ab);
1473 if (ret)
1474 goto err_mhi_unregister;
1475
1476 ret = ath11k_ce_alloc_pipes(ab);
1477 if (ret) {
1478 ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
1479 goto err_hal_srng_deinit;
1480 }
1481
1482 ath11k_pci_init_qmi_ce_config(ab);
1483
1484 ret = ath11k_pci_config_irq(ab);
1485 if (ret) {
1486 ath11k_err(ab, "failed to config irq: %d\n", ret);
1487 goto err_ce_free;
1488 }
1489
Carl Huang87b40722021-11-19 15:36:26 +02001490 /* kernel may allocate a dummy vector before request_irq and
1491 * then allocate a real vector when request_irq is called.
1492 * So get msi_data here again to avoid spurious interrupt
1493 * as msi_data will configured to srngs.
1494 */
1495 ret = ath11k_pci_config_msi_data(ab_pci);
1496 if (ret) {
1497 ath11k_err(ab, "failed to config msi_data: %d\n", ret);
1498 goto err_free_irq;
1499 }
1500
Govind Singh7f4beda2020-08-13 12:04:25 +03001501 ret = ath11k_core_init(ab);
1502 if (ret) {
1503 ath11k_err(ab, "failed to init core: %d\n", ret);
1504 goto err_free_irq;
1505 }
Govind Singh6e0355a2020-08-13 12:04:20 +03001506 return 0;
Govind Singh57626132020-08-13 12:04:21 +03001507
Govind Singh7f4beda2020-08-13 12:04:25 +03001508err_free_irq:
1509 ath11k_pci_free_irq(ab);
1510
1511err_ce_free:
1512 ath11k_ce_free_pipes(ab);
1513
1514err_hal_srng_deinit:
1515 ath11k_hal_srng_deinit(ab);
1516
1517err_mhi_unregister:
1518 ath11k_mhi_unregister(ab_pci);
1519
Kalle Valob8246f82020-08-13 12:04:23 +03001520err_pci_disable_msi:
Baochen Qiang96527d52021-10-11 09:33:08 +03001521 ath11k_pci_free_msi(ab_pci);
Kalle Valob8246f82020-08-13 12:04:23 +03001522
Govind Singh5697a562020-08-13 12:04:22 +03001523err_pci_free_region:
1524 ath11k_pci_free_region(ab_pci);
1525
Govind Singh57626132020-08-13 12:04:21 +03001526err_free_core:
1527 ath11k_core_free(ab);
Govind Singh5697a562020-08-13 12:04:22 +03001528
Govind Singh57626132020-08-13 12:04:21 +03001529 return ret;
Govind Singh6e0355a2020-08-13 12:04:20 +03001530}
1531
1532static void ath11k_pci_remove(struct pci_dev *pdev)
1533{
1534 struct ath11k_base *ab = pci_get_drvdata(pdev);
Govind Singh57626132020-08-13 12:04:21 +03001535 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
Govind Singh6e0355a2020-08-13 12:04:20 +03001536
Baochen Qiange94b0742021-11-19 15:36:26 +02001537 ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
1538
Anilkumar Kolli61a57e52020-12-08 09:52:55 +02001539 if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
1540 ath11k_pci_power_down(ab);
1541 ath11k_debugfs_soc_destroy(ab);
1542 ath11k_qmi_deinit_service(ab);
1543 goto qmi_fail;
1544 }
1545
Govind Singh6e0355a2020-08-13 12:04:20 +03001546 set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
Carl Huang6fbd8892020-09-30 13:51:10 +03001547
1548 ath11k_core_deinit(ab);
1549
Anilkumar Kolli61a57e52020-12-08 09:52:55 +02001550qmi_fail:
Govind Singh1399fb82020-08-13 12:04:24 +03001551 ath11k_mhi_unregister(ab_pci);
Carl Huang6fbd8892020-09-30 13:51:10 +03001552
1553 ath11k_pci_free_irq(ab);
Baochen Qiang96527d52021-10-11 09:33:08 +03001554 ath11k_pci_free_msi(ab_pci);
Govind Singh57626132020-08-13 12:04:21 +03001555 ath11k_pci_free_region(ab_pci);
Carl Huang6fbd8892020-09-30 13:51:10 +03001556
1557 ath11k_hal_srng_deinit(ab);
1558 ath11k_ce_free_pipes(ab);
Govind Singh6e0355a2020-08-13 12:04:20 +03001559 ath11k_core_free(ab);
1560}
1561
Govind Singh1399fb82020-08-13 12:04:24 +03001562static void ath11k_pci_shutdown(struct pci_dev *pdev)
1563{
1564 struct ath11k_base *ab = pci_get_drvdata(pdev);
1565
1566 ath11k_pci_power_down(ab);
1567}
1568
Carl Huangd1b0c3382020-12-11 19:35:50 +02001569static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
1570{
1571 struct ath11k_base *ab = dev_get_drvdata(dev);
1572 int ret;
1573
1574 ret = ath11k_core_suspend(ab);
1575 if (ret)
1576 ath11k_warn(ab, "failed to suspend core: %d\n", ret);
1577
1578 return ret;
1579}
1580
1581static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
1582{
1583 struct ath11k_base *ab = dev_get_drvdata(dev);
1584 int ret;
1585
1586 ret = ath11k_core_resume(ab);
1587 if (ret)
1588 ath11k_warn(ab, "failed to resume core: %d\n", ret);
1589
1590 return ret;
1591}
1592
1593static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
1594 ath11k_pci_pm_suspend,
1595 ath11k_pci_pm_resume);
1596
Govind Singh6e0355a2020-08-13 12:04:20 +03001597static struct pci_driver ath11k_pci_driver = {
1598 .name = "ath11k_pci",
1599 .id_table = ath11k_pci_id_table,
1600 .probe = ath11k_pci_probe,
1601 .remove = ath11k_pci_remove,
Govind Singh1399fb82020-08-13 12:04:24 +03001602 .shutdown = ath11k_pci_shutdown,
Carl Huangd1b0c3382020-12-11 19:35:50 +02001603#ifdef CONFIG_PM
1604 .driver.pm = &ath11k_pci_pm_ops,
1605#endif
Govind Singh6e0355a2020-08-13 12:04:20 +03001606};
1607
1608static int ath11k_pci_init(void)
1609{
1610 int ret;
1611
1612 ret = pci_register_driver(&ath11k_pci_driver);
1613 if (ret)
1614 pr_err("failed to register ath11k pci driver: %d\n",
1615 ret);
1616
1617 return ret;
1618}
1619module_init(ath11k_pci_init);
1620
1621static void ath11k_pci_exit(void)
1622{
1623 pci_unregister_driver(&ath11k_pci_driver);
1624}
1625
1626module_exit(ath11k_pci_exit);
1627
1628MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
1629MODULE_LICENSE("Dual BSD/GPL");
Devin Bayer3dbd7fe2020-12-07 18:16:55 +02001630
1631/* QCA639x 2.0 firmware files */
1632MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE);
1633MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE);
1634MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE);