1dd4f32aeSBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear
2dd4f32aeSBjoern A. Zeeb /*
3dd4f32aeSBjoern A. Zeeb * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4*28348caeSBjoern A. Zeeb * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5dd4f32aeSBjoern A. Zeeb */
6dd4f32aeSBjoern A. Zeeb
7dd4f32aeSBjoern A. Zeeb #include <linux/module.h>
8dd4f32aeSBjoern A. Zeeb #include <linux/msi.h>
9dd4f32aeSBjoern A. Zeeb #include <linux/pci.h>
10dd4f32aeSBjoern A. Zeeb #if defined(CONFIG_OF)
11dd4f32aeSBjoern A. Zeeb #include <linux/of.h>
12dd4f32aeSBjoern A. Zeeb #endif
13dd4f32aeSBjoern A. Zeeb #if defined(__FreeBSD__)
14dd4f32aeSBjoern A. Zeeb #include <linux/delay.h>
15*28348caeSBjoern A. Zeeb #include <linux/cpu.h>
16dd4f32aeSBjoern A. Zeeb #endif
17dd4f32aeSBjoern A. Zeeb
18dd4f32aeSBjoern A. Zeeb #include "pci.h"
19dd4f32aeSBjoern A. Zeeb #include "core.h"
20dd4f32aeSBjoern A. Zeeb #include "hif.h"
21dd4f32aeSBjoern A. Zeeb #include "mhi.h"
22dd4f32aeSBjoern A. Zeeb #include "debug.h"
23*28348caeSBjoern A. Zeeb #include "pcic.h"
24*28348caeSBjoern A. Zeeb #include "qmi.h"
25dd4f32aeSBjoern A. Zeeb
26dd4f32aeSBjoern A. Zeeb #define ATH11K_PCI_BAR_NUM 0
27dd4f32aeSBjoern A. Zeeb #define ATH11K_PCI_DMA_MASK 32
28dd4f32aeSBjoern A. Zeeb
29dd4f32aeSBjoern A. Zeeb #define TCSR_SOC_HW_VERSION 0x0224
30dd4f32aeSBjoern A. Zeeb #define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
31dd4f32aeSBjoern A. Zeeb #define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 0)
32dd4f32aeSBjoern A. Zeeb
33dd4f32aeSBjoern A. Zeeb #define QCA6390_DEVICE_ID 0x1101
34dd4f32aeSBjoern A. Zeeb #define QCN9074_DEVICE_ID 0x1104
35dd4f32aeSBjoern A. Zeeb #define WCN6855_DEVICE_ID 0x1103
36dd4f32aeSBjoern A. Zeeb
37dd4f32aeSBjoern A. Zeeb static const struct pci_device_id ath11k_pci_id_table[] = {
38dd4f32aeSBjoern A. Zeeb { PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
39dd4f32aeSBjoern A. Zeeb { PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) },
40dd4f32aeSBjoern A. Zeeb { PCI_VDEVICE(QCOM, QCN9074_DEVICE_ID) },
41dd4f32aeSBjoern A. Zeeb {0}
42dd4f32aeSBjoern A. Zeeb };
43dd4f32aeSBjoern A. Zeeb
44dd4f32aeSBjoern A. Zeeb MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
45dd4f32aeSBjoern A. Zeeb
ath11k_pci_bus_wake_up(struct ath11k_base * ab)46*28348caeSBjoern A. Zeeb static int ath11k_pci_bus_wake_up(struct ath11k_base *ab)
47*28348caeSBjoern A. Zeeb {
48*28348caeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
49*28348caeSBjoern A. Zeeb
50*28348caeSBjoern A. Zeeb return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
51*28348caeSBjoern A. Zeeb }
52*28348caeSBjoern A. Zeeb
ath11k_pci_bus_release(struct ath11k_base * ab)53*28348caeSBjoern A. Zeeb static void ath11k_pci_bus_release(struct ath11k_base *ab)
54*28348caeSBjoern A. Zeeb {
55*28348caeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
56*28348caeSBjoern A. Zeeb
57*28348caeSBjoern A. Zeeb mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
58*28348caeSBjoern A. Zeeb }
59*28348caeSBjoern A. Zeeb
ath11k_pci_get_window_start(struct ath11k_base * ab,u32 offset)60*28348caeSBjoern A. Zeeb static u32 ath11k_pci_get_window_start(struct ath11k_base *ab, u32 offset)
61*28348caeSBjoern A. Zeeb {
62*28348caeSBjoern A. Zeeb if (!ab->hw_params.static_window_map)
63*28348caeSBjoern A. Zeeb return ATH11K_PCI_WINDOW_START;
64*28348caeSBjoern A. Zeeb
65*28348caeSBjoern A. Zeeb if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK)
66*28348caeSBjoern A. Zeeb /* if offset lies within DP register range, use 3rd window */
67*28348caeSBjoern A. Zeeb return 3 * ATH11K_PCI_WINDOW_START;
68*28348caeSBjoern A. Zeeb else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) <
69*28348caeSBjoern A. Zeeb ATH11K_PCI_WINDOW_RANGE_MASK)
70*28348caeSBjoern A. Zeeb /* if offset lies within CE register range, use 2nd window */
71*28348caeSBjoern A. Zeeb return 2 * ATH11K_PCI_WINDOW_START;
72*28348caeSBjoern A. Zeeb else
73*28348caeSBjoern A. Zeeb return ATH11K_PCI_WINDOW_START;
74*28348caeSBjoern A. Zeeb }
75*28348caeSBjoern A. Zeeb
ath11k_pci_select_window(struct ath11k_pci * ab_pci,u32 offset)76*28348caeSBjoern A. Zeeb static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset)
77*28348caeSBjoern A. Zeeb {
78*28348caeSBjoern A. Zeeb struct ath11k_base *ab = ab_pci->ab;
79*28348caeSBjoern A. Zeeb
80*28348caeSBjoern A. Zeeb u32 window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, offset);
81*28348caeSBjoern A. Zeeb
82*28348caeSBjoern A. Zeeb lockdep_assert_held(&ab_pci->window_lock);
83*28348caeSBjoern A. Zeeb
84*28348caeSBjoern A. Zeeb if (window != ab_pci->register_window) {
85*28348caeSBjoern A. Zeeb #if defined(__linux__)
86*28348caeSBjoern A. Zeeb iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,
87*28348caeSBjoern A. Zeeb ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
88*28348caeSBjoern A. Zeeb ioread32(ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
89*28348caeSBjoern A. Zeeb #elif defined(__FreeBSD__)
90*28348caeSBjoern A. Zeeb iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,
91*28348caeSBjoern A. Zeeb (char *)ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
92*28348caeSBjoern A. Zeeb ioread32((char *)ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
93*28348caeSBjoern A. Zeeb #endif
94*28348caeSBjoern A. Zeeb ab_pci->register_window = window;
95*28348caeSBjoern A. Zeeb }
96*28348caeSBjoern A. Zeeb }
97*28348caeSBjoern A. Zeeb
98*28348caeSBjoern A. Zeeb static void
ath11k_pci_window_write32(struct ath11k_base * ab,u32 offset,u32 value)99*28348caeSBjoern A. Zeeb ath11k_pci_window_write32(struct ath11k_base *ab, u32 offset, u32 value)
100*28348caeSBjoern A. Zeeb {
101*28348caeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
102*28348caeSBjoern A. Zeeb u32 window_start;
103*28348caeSBjoern A. Zeeb
104*28348caeSBjoern A. Zeeb window_start = ath11k_pci_get_window_start(ab, offset);
105*28348caeSBjoern A. Zeeb
106*28348caeSBjoern A. Zeeb if (window_start == ATH11K_PCI_WINDOW_START) {
107*28348caeSBjoern A. Zeeb spin_lock_bh(&ab_pci->window_lock);
108*28348caeSBjoern A. Zeeb ath11k_pci_select_window(ab_pci, offset);
109*28348caeSBjoern A. Zeeb #if defined(__linux__)
110*28348caeSBjoern A. Zeeb iowrite32(value, ab->mem + window_start +
111*28348caeSBjoern A. Zeeb #elif defined(__FreeBSD__)
112*28348caeSBjoern A. Zeeb iowrite32(value, (char *)ab->mem + window_start +
113*28348caeSBjoern A. Zeeb #endif
114*28348caeSBjoern A. Zeeb (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
115*28348caeSBjoern A. Zeeb spin_unlock_bh(&ab_pci->window_lock);
116*28348caeSBjoern A. Zeeb } else {
117*28348caeSBjoern A. Zeeb #if defined(__linux__)
118*28348caeSBjoern A. Zeeb iowrite32(value, ab->mem + window_start +
119*28348caeSBjoern A. Zeeb #elif defined(__FreeBSD__)
120*28348caeSBjoern A. Zeeb iowrite32(value, (char *)ab->mem + window_start +
121*28348caeSBjoern A. Zeeb #endif
122*28348caeSBjoern A. Zeeb (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
123*28348caeSBjoern A. Zeeb }
124*28348caeSBjoern A. Zeeb }
125*28348caeSBjoern A. Zeeb
ath11k_pci_window_read32(struct ath11k_base * ab,u32 offset)126*28348caeSBjoern A. Zeeb static u32 ath11k_pci_window_read32(struct ath11k_base *ab, u32 offset)
127*28348caeSBjoern A. Zeeb {
128*28348caeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
129*28348caeSBjoern A. Zeeb u32 window_start, val;
130*28348caeSBjoern A. Zeeb
131*28348caeSBjoern A. Zeeb window_start = ath11k_pci_get_window_start(ab, offset);
132*28348caeSBjoern A. Zeeb
133*28348caeSBjoern A. Zeeb if (window_start == ATH11K_PCI_WINDOW_START) {
134*28348caeSBjoern A. Zeeb spin_lock_bh(&ab_pci->window_lock);
135*28348caeSBjoern A. Zeeb ath11k_pci_select_window(ab_pci, offset);
136*28348caeSBjoern A. Zeeb #if defined(__linux__)
137*28348caeSBjoern A. Zeeb val = ioread32(ab->mem + window_start +
138*28348caeSBjoern A. Zeeb #elif defined(__FreeBSD__)
139*28348caeSBjoern A. Zeeb val = ioread32((char *)ab->mem + window_start +
140*28348caeSBjoern A. Zeeb #endif
141*28348caeSBjoern A. Zeeb (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
142*28348caeSBjoern A. Zeeb spin_unlock_bh(&ab_pci->window_lock);
143*28348caeSBjoern A. Zeeb } else {
144*28348caeSBjoern A. Zeeb #if defined(__linux__)
145*28348caeSBjoern A. Zeeb val = ioread32(ab->mem + window_start +
146*28348caeSBjoern A. Zeeb #elif defined(__FreeBSD__)
147*28348caeSBjoern A. Zeeb val = ioread32((char *)ab->mem + window_start +
148*28348caeSBjoern A. Zeeb #endif
149*28348caeSBjoern A. Zeeb (offset & ATH11K_PCI_WINDOW_RANGE_MASK));
150*28348caeSBjoern A. Zeeb }
151*28348caeSBjoern A. Zeeb
152*28348caeSBjoern A. Zeeb return val;
153*28348caeSBjoern A. Zeeb }
154*28348caeSBjoern A. Zeeb
ath11k_pci_get_msi_irq(struct ath11k_base * ab,unsigned int vector)155*28348caeSBjoern A. Zeeb int ath11k_pci_get_msi_irq(struct ath11k_base *ab, unsigned int vector)
156*28348caeSBjoern A. Zeeb {
157*28348caeSBjoern A. Zeeb struct pci_dev *pci_dev = to_pci_dev(ab->dev);
158*28348caeSBjoern A. Zeeb
159*28348caeSBjoern A. Zeeb return pci_irq_vector(pci_dev, vector);
160*28348caeSBjoern A. Zeeb }
161*28348caeSBjoern A. Zeeb
162*28348caeSBjoern A. Zeeb static const struct ath11k_pci_ops ath11k_pci_ops_qca6390 = {
163*28348caeSBjoern A. Zeeb .wakeup = ath11k_pci_bus_wake_up,
164*28348caeSBjoern A. Zeeb .release = ath11k_pci_bus_release,
165*28348caeSBjoern A. Zeeb .get_msi_irq = ath11k_pci_get_msi_irq,
166*28348caeSBjoern A. Zeeb .window_write32 = ath11k_pci_window_write32,
167*28348caeSBjoern A. Zeeb .window_read32 = ath11k_pci_window_read32,
168dd4f32aeSBjoern A. Zeeb };
169dd4f32aeSBjoern A. Zeeb
170*28348caeSBjoern A. Zeeb static const struct ath11k_pci_ops ath11k_pci_ops_qcn9074 = {
171*28348caeSBjoern A. Zeeb .wakeup = NULL,
172*28348caeSBjoern A. Zeeb .release = NULL,
173*28348caeSBjoern A. Zeeb .get_msi_irq = ath11k_pci_get_msi_irq,
174*28348caeSBjoern A. Zeeb .window_write32 = ath11k_pci_window_write32,
175*28348caeSBjoern A. Zeeb .window_read32 = ath11k_pci_window_read32,
176dd4f32aeSBjoern A. Zeeb };
177dd4f32aeSBjoern A. Zeeb
178dd4f32aeSBjoern A. Zeeb static const struct ath11k_msi_config msi_config_one_msi = {
179dd4f32aeSBjoern A. Zeeb .total_vectors = 1,
180dd4f32aeSBjoern A. Zeeb .total_users = 4,
181dd4f32aeSBjoern A. Zeeb .users = (struct ath11k_msi_user[]) {
182dd4f32aeSBjoern A. Zeeb { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
183dd4f32aeSBjoern A. Zeeb { .name = "CE", .num_vectors = 1, .base_vector = 0 },
184dd4f32aeSBjoern A. Zeeb { .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
185dd4f32aeSBjoern A. Zeeb { .name = "DP", .num_vectors = 1, .base_vector = 0 },
186dd4f32aeSBjoern A. Zeeb },
187dd4f32aeSBjoern A. Zeeb };
188dd4f32aeSBjoern A. Zeeb
ath11k_pci_select_static_window(struct ath11k_pci * ab_pci)189dd4f32aeSBjoern A. Zeeb static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci)
190dd4f32aeSBjoern A. Zeeb {
191*28348caeSBjoern A. Zeeb u32 umac_window;
192*28348caeSBjoern A. Zeeb u32 ce_window;
193dd4f32aeSBjoern A. Zeeb u32 window;
194dd4f32aeSBjoern A. Zeeb
195*28348caeSBjoern A. Zeeb umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET);
196*28348caeSBjoern A. Zeeb ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE);
197dd4f32aeSBjoern A. Zeeb window = (umac_window << 12) | (ce_window << 6);
198dd4f32aeSBjoern A. Zeeb
199*28348caeSBjoern A. Zeeb iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,
200dd4f32aeSBjoern A. Zeeb #if defined(__linux__)
201*28348caeSBjoern A. Zeeb ab_pci->ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
202dd4f32aeSBjoern A. Zeeb #elif defined(__FreeBSD__)
203*28348caeSBjoern A. Zeeb (char *)ab_pci->ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
204dd4f32aeSBjoern A. Zeeb #endif
205dd4f32aeSBjoern A. Zeeb }
206dd4f32aeSBjoern A. Zeeb
ath11k_pci_soc_global_reset(struct ath11k_base * ab)207dd4f32aeSBjoern A. Zeeb static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
208dd4f32aeSBjoern A. Zeeb {
209dd4f32aeSBjoern A. Zeeb u32 val, delay;
210dd4f32aeSBjoern A. Zeeb
211*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
212dd4f32aeSBjoern A. Zeeb
213dd4f32aeSBjoern A. Zeeb val |= PCIE_SOC_GLOBAL_RESET_V;
214dd4f32aeSBjoern A. Zeeb
215*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
216dd4f32aeSBjoern A. Zeeb
217dd4f32aeSBjoern A. Zeeb /* TODO: exact time to sleep is uncertain */
218dd4f32aeSBjoern A. Zeeb delay = 10;
219dd4f32aeSBjoern A. Zeeb mdelay(delay);
220dd4f32aeSBjoern A. Zeeb
221dd4f32aeSBjoern A. Zeeb /* Need to toggle V bit back otherwise stuck in reset status */
222dd4f32aeSBjoern A. Zeeb val &= ~PCIE_SOC_GLOBAL_RESET_V;
223dd4f32aeSBjoern A. Zeeb
224*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
225dd4f32aeSBjoern A. Zeeb
226dd4f32aeSBjoern A. Zeeb mdelay(delay);
227dd4f32aeSBjoern A. Zeeb
228*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
229dd4f32aeSBjoern A. Zeeb if (val == 0xffffffff)
230dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "link down error during global reset\n");
231dd4f32aeSBjoern A. Zeeb }
232dd4f32aeSBjoern A. Zeeb
ath11k_pci_clear_dbg_registers(struct ath11k_base * ab)233dd4f32aeSBjoern A. Zeeb static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
234dd4f32aeSBjoern A. Zeeb {
235dd4f32aeSBjoern A. Zeeb u32 val;
236dd4f32aeSBjoern A. Zeeb
237dd4f32aeSBjoern A. Zeeb /* read cookie */
238*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR);
239*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_q6_cookie_addr 0x%x\n", val);
240dd4f32aeSBjoern A. Zeeb
241*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
242*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);
243dd4f32aeSBjoern A. Zeeb
244dd4f32aeSBjoern A. Zeeb /* TODO: exact time to sleep is uncertain */
245dd4f32aeSBjoern A. Zeeb mdelay(10);
246dd4f32aeSBjoern A. Zeeb
247dd4f32aeSBjoern A. Zeeb /* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from
248dd4f32aeSBjoern A. Zeeb * continuing warm path and entering dead loop.
249dd4f32aeSBjoern A. Zeeb */
250*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, WLAON_WARM_SW_ENTRY, 0);
251dd4f32aeSBjoern A. Zeeb mdelay(10);
252dd4f32aeSBjoern A. Zeeb
253*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
254*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);
255dd4f32aeSBjoern A. Zeeb
256dd4f32aeSBjoern A. Zeeb /* A read clear register. clear the register to prevent
257dd4f32aeSBjoern A. Zeeb * Q6 from entering wrong code path.
258dd4f32aeSBjoern A. Zeeb */
259*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
260*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause %d\n", val);
261dd4f32aeSBjoern A. Zeeb }
262dd4f32aeSBjoern A. Zeeb
ath11k_pci_set_link_reg(struct ath11k_base * ab,u32 offset,u32 value,u32 mask)263dd4f32aeSBjoern A. Zeeb static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
264dd4f32aeSBjoern A. Zeeb u32 offset, u32 value, u32 mask)
265dd4f32aeSBjoern A. Zeeb {
266dd4f32aeSBjoern A. Zeeb u32 v;
267dd4f32aeSBjoern A. Zeeb int i;
268dd4f32aeSBjoern A. Zeeb
269*28348caeSBjoern A. Zeeb v = ath11k_pcic_read32(ab, offset);
270dd4f32aeSBjoern A. Zeeb if ((v & mask) == value)
271dd4f32aeSBjoern A. Zeeb return 0;
272dd4f32aeSBjoern A. Zeeb
273dd4f32aeSBjoern A. Zeeb for (i = 0; i < 10; i++) {
274*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, offset, (v & ~mask) | value);
275dd4f32aeSBjoern A. Zeeb
276*28348caeSBjoern A. Zeeb v = ath11k_pcic_read32(ab, offset);
277dd4f32aeSBjoern A. Zeeb if ((v & mask) == value)
278dd4f32aeSBjoern A. Zeeb return 0;
279dd4f32aeSBjoern A. Zeeb
280dd4f32aeSBjoern A. Zeeb mdelay(2);
281dd4f32aeSBjoern A. Zeeb }
282dd4f32aeSBjoern A. Zeeb
283dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n",
284dd4f32aeSBjoern A. Zeeb offset, v & mask, value);
285dd4f32aeSBjoern A. Zeeb
286dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT;
287dd4f32aeSBjoern A. Zeeb }
288dd4f32aeSBjoern A. Zeeb
ath11k_pci_fix_l1ss(struct ath11k_base * ab)289dd4f32aeSBjoern A. Zeeb static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
290dd4f32aeSBjoern A. Zeeb {
291dd4f32aeSBjoern A. Zeeb int ret;
292dd4f32aeSBjoern A. Zeeb
293dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_set_link_reg(ab,
294dd4f32aeSBjoern A. Zeeb PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab),
295dd4f32aeSBjoern A. Zeeb PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
296dd4f32aeSBjoern A. Zeeb PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
297dd4f32aeSBjoern A. Zeeb if (ret) {
298dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
299dd4f32aeSBjoern A. Zeeb return ret;
300dd4f32aeSBjoern A. Zeeb }
301dd4f32aeSBjoern A. Zeeb
302dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_set_link_reg(ab,
303dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab),
304dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG1_VAL,
305dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG_MSK);
306dd4f32aeSBjoern A. Zeeb if (ret) {
307dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
308dd4f32aeSBjoern A. Zeeb return ret;
309dd4f32aeSBjoern A. Zeeb }
310dd4f32aeSBjoern A. Zeeb
311dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_set_link_reg(ab,
312dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab),
313dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG2_VAL,
314dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG_MSK);
315dd4f32aeSBjoern A. Zeeb if (ret) {
316dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
317dd4f32aeSBjoern A. Zeeb return ret;
318dd4f32aeSBjoern A. Zeeb }
319dd4f32aeSBjoern A. Zeeb
320dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_set_link_reg(ab,
321dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab),
322dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG4_VAL,
323dd4f32aeSBjoern A. Zeeb PCIE_PCS_OSC_DTCT_CONFIG_MSK);
324dd4f32aeSBjoern A. Zeeb if (ret) {
325dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
326dd4f32aeSBjoern A. Zeeb return ret;
327dd4f32aeSBjoern A. Zeeb }
328dd4f32aeSBjoern A. Zeeb
329dd4f32aeSBjoern A. Zeeb return 0;
330dd4f32aeSBjoern A. Zeeb }
331dd4f32aeSBjoern A. Zeeb
ath11k_pci_enable_ltssm(struct ath11k_base * ab)332dd4f32aeSBjoern A. Zeeb static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
333dd4f32aeSBjoern A. Zeeb {
334dd4f32aeSBjoern A. Zeeb u32 val;
335dd4f32aeSBjoern A. Zeeb int i;
336dd4f32aeSBjoern A. Zeeb
337*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);
338dd4f32aeSBjoern A. Zeeb
339dd4f32aeSBjoern A. Zeeb /* PCIE link seems very unstable after the Hot Reset*/
340dd4f32aeSBjoern A. Zeeb for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {
341dd4f32aeSBjoern A. Zeeb if (val == 0xffffffff)
342dd4f32aeSBjoern A. Zeeb mdelay(5);
343dd4f32aeSBjoern A. Zeeb
344*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);
345*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);
346dd4f32aeSBjoern A. Zeeb }
347dd4f32aeSBjoern A. Zeeb
348*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "ltssm 0x%x\n", val);
349dd4f32aeSBjoern A. Zeeb
350*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
351dd4f32aeSBjoern A. Zeeb val |= GCC_GCC_PCIE_HOT_RST_VAL;
352*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
353*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
354dd4f32aeSBjoern A. Zeeb
355*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_hot_rst 0x%x\n", val);
356dd4f32aeSBjoern A. Zeeb
357dd4f32aeSBjoern A. Zeeb mdelay(5);
358dd4f32aeSBjoern A. Zeeb }
359dd4f32aeSBjoern A. Zeeb
ath11k_pci_clear_all_intrs(struct ath11k_base * ab)360dd4f32aeSBjoern A. Zeeb static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)
361dd4f32aeSBjoern A. Zeeb {
362dd4f32aeSBjoern A. Zeeb /* This is a WAR for PCIE Hotreset.
363dd4f32aeSBjoern A. Zeeb * When target receive Hotreset, but will set the interrupt.
364dd4f32aeSBjoern A. Zeeb * So when download SBL again, SBL will open Interrupt and
365dd4f32aeSBjoern A. Zeeb * receive it, and crash immediately.
366dd4f32aeSBjoern A. Zeeb */
367*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);
368dd4f32aeSBjoern A. Zeeb }
369dd4f32aeSBjoern A. Zeeb
ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base * ab)370dd4f32aeSBjoern A. Zeeb static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab)
371dd4f32aeSBjoern A. Zeeb {
372dd4f32aeSBjoern A. Zeeb u32 val;
373dd4f32aeSBjoern A. Zeeb
374*28348caeSBjoern A. Zeeb val = ath11k_pcic_read32(ab, WLAON_QFPROM_PWR_CTRL_REG);
375dd4f32aeSBjoern A. Zeeb val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK;
376*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val);
377dd4f32aeSBjoern A. Zeeb }
378dd4f32aeSBjoern A. Zeeb
ath11k_pci_force_wake(struct ath11k_base * ab)379dd4f32aeSBjoern A. Zeeb static void ath11k_pci_force_wake(struct ath11k_base *ab)
380dd4f32aeSBjoern A. Zeeb {
381*28348caeSBjoern A. Zeeb ath11k_pcic_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
382dd4f32aeSBjoern A. Zeeb mdelay(5);
383dd4f32aeSBjoern A. Zeeb }
384dd4f32aeSBjoern A. Zeeb
ath11k_pci_sw_reset(struct ath11k_base * ab,bool power_on)385dd4f32aeSBjoern A. Zeeb static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
386dd4f32aeSBjoern A. Zeeb {
387dd4f32aeSBjoern A. Zeeb mdelay(100);
388dd4f32aeSBjoern A. Zeeb
389dd4f32aeSBjoern A. Zeeb if (power_on) {
390dd4f32aeSBjoern A. Zeeb ath11k_pci_enable_ltssm(ab);
391dd4f32aeSBjoern A. Zeeb ath11k_pci_clear_all_intrs(ab);
392dd4f32aeSBjoern A. Zeeb ath11k_pci_set_wlaon_pwr_ctrl(ab);
393dd4f32aeSBjoern A. Zeeb if (ab->hw_params.fix_l1ss)
394dd4f32aeSBjoern A. Zeeb ath11k_pci_fix_l1ss(ab);
395dd4f32aeSBjoern A. Zeeb }
396dd4f32aeSBjoern A. Zeeb
397dd4f32aeSBjoern A. Zeeb ath11k_mhi_clear_vector(ab);
398dd4f32aeSBjoern A. Zeeb ath11k_pci_clear_dbg_registers(ab);
399dd4f32aeSBjoern A. Zeeb ath11k_pci_soc_global_reset(ab);
400dd4f32aeSBjoern A. Zeeb ath11k_mhi_set_mhictrl_reset(ab);
401dd4f32aeSBjoern A. Zeeb }
402dd4f32aeSBjoern A. Zeeb
ath11k_pci_init_qmi_ce_config(struct ath11k_base * ab)403dd4f32aeSBjoern A. Zeeb static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
404dd4f32aeSBjoern A. Zeeb {
405dd4f32aeSBjoern A. Zeeb struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
406dd4f32aeSBjoern A. Zeeb
407dd4f32aeSBjoern A. Zeeb cfg->tgt_ce = ab->hw_params.target_ce_config;
408dd4f32aeSBjoern A. Zeeb cfg->tgt_ce_len = ab->hw_params.target_ce_count;
409dd4f32aeSBjoern A. Zeeb
410dd4f32aeSBjoern A. Zeeb cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
411dd4f32aeSBjoern A. Zeeb cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
412dd4f32aeSBjoern A. Zeeb ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
413dd4f32aeSBjoern A. Zeeb
414dd4f32aeSBjoern A. Zeeb ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2,
415dd4f32aeSBjoern A. Zeeb &cfg->shadow_reg_v2_len);
416dd4f32aeSBjoern A. Zeeb }
417dd4f32aeSBjoern A. Zeeb
ath11k_pci_msi_config(struct ath11k_pci * ab_pci,bool enable)418dd4f32aeSBjoern A. Zeeb static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable)
419dd4f32aeSBjoern A. Zeeb {
420dd4f32aeSBjoern A. Zeeb struct pci_dev *dev = ab_pci->pdev;
421dd4f32aeSBjoern A. Zeeb u16 control;
422dd4f32aeSBjoern A. Zeeb
423dd4f32aeSBjoern A. Zeeb pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
424dd4f32aeSBjoern A. Zeeb
425dd4f32aeSBjoern A. Zeeb if (enable)
426dd4f32aeSBjoern A. Zeeb control |= PCI_MSI_FLAGS_ENABLE;
427dd4f32aeSBjoern A. Zeeb else
428dd4f32aeSBjoern A. Zeeb control &= ~PCI_MSI_FLAGS_ENABLE;
429dd4f32aeSBjoern A. Zeeb
430dd4f32aeSBjoern A. Zeeb pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
431dd4f32aeSBjoern A. Zeeb }
432dd4f32aeSBjoern A. Zeeb
ath11k_pci_msi_enable(struct ath11k_pci * ab_pci)433dd4f32aeSBjoern A. Zeeb static void ath11k_pci_msi_enable(struct ath11k_pci *ab_pci)
434dd4f32aeSBjoern A. Zeeb {
435dd4f32aeSBjoern A. Zeeb ath11k_pci_msi_config(ab_pci, true);
436dd4f32aeSBjoern A. Zeeb }
437dd4f32aeSBjoern A. Zeeb
ath11k_pci_msi_disable(struct ath11k_pci * ab_pci)438dd4f32aeSBjoern A. Zeeb static void ath11k_pci_msi_disable(struct ath11k_pci *ab_pci)
439dd4f32aeSBjoern A. Zeeb {
440dd4f32aeSBjoern A. Zeeb ath11k_pci_msi_config(ab_pci, false);
441dd4f32aeSBjoern A. Zeeb }
442dd4f32aeSBjoern A. Zeeb
ath11k_pci_alloc_msi(struct ath11k_pci * ab_pci)443dd4f32aeSBjoern A. Zeeb static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
444dd4f32aeSBjoern A. Zeeb {
445dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ab_pci->ab;
446*28348caeSBjoern A. Zeeb const struct ath11k_msi_config *msi_config = ab->pci.msi.config;
447*28348caeSBjoern A. Zeeb struct pci_dev *pci_dev = ab_pci->pdev;
448dd4f32aeSBjoern A. Zeeb struct msi_desc *msi_desc;
449dd4f32aeSBjoern A. Zeeb int num_vectors;
450dd4f32aeSBjoern A. Zeeb int ret;
451dd4f32aeSBjoern A. Zeeb
452*28348caeSBjoern A. Zeeb num_vectors = pci_alloc_irq_vectors(pci_dev,
453dd4f32aeSBjoern A. Zeeb msi_config->total_vectors,
454dd4f32aeSBjoern A. Zeeb msi_config->total_vectors,
455dd4f32aeSBjoern A. Zeeb PCI_IRQ_MSI);
456dd4f32aeSBjoern A. Zeeb if (num_vectors == msi_config->total_vectors) {
457*28348caeSBjoern A. Zeeb set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
458dd4f32aeSBjoern A. Zeeb } else {
459dd4f32aeSBjoern A. Zeeb num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
460dd4f32aeSBjoern A. Zeeb 1,
461dd4f32aeSBjoern A. Zeeb 1,
462dd4f32aeSBjoern A. Zeeb PCI_IRQ_MSI);
463dd4f32aeSBjoern A. Zeeb if (num_vectors < 0) {
464dd4f32aeSBjoern A. Zeeb ret = -EINVAL;
465dd4f32aeSBjoern A. Zeeb goto reset_msi_config;
466dd4f32aeSBjoern A. Zeeb }
467*28348caeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
468*28348caeSBjoern A. Zeeb ab->pci.msi.config = &msi_config_one_msi;
469*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "request one msi vector\n");
470dd4f32aeSBjoern A. Zeeb }
471dd4f32aeSBjoern A. Zeeb ath11k_info(ab, "MSI vectors: %d\n", num_vectors);
472dd4f32aeSBjoern A. Zeeb
473dd4f32aeSBjoern A. Zeeb ath11k_pci_msi_disable(ab_pci);
474dd4f32aeSBjoern A. Zeeb
475dd4f32aeSBjoern A. Zeeb msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
476dd4f32aeSBjoern A. Zeeb if (!msi_desc) {
477dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "msi_desc is NULL!\n");
478dd4f32aeSBjoern A. Zeeb ret = -EINVAL;
479dd4f32aeSBjoern A. Zeeb goto free_msi_vector;
480dd4f32aeSBjoern A. Zeeb }
481dd4f32aeSBjoern A. Zeeb
482*28348caeSBjoern A. Zeeb ab->pci.msi.ep_base_data = msi_desc->msg.data;
483dd4f32aeSBjoern A. Zeeb
484*28348caeSBjoern A. Zeeb pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
485*28348caeSBjoern A. Zeeb &ab->pci.msi.addr_lo);
486*28348caeSBjoern A. Zeeb
487*28348caeSBjoern A. Zeeb if (msi_desc->pci.msi_attrib.is_64) {
488*28348caeSBjoern A. Zeeb pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
489*28348caeSBjoern A. Zeeb &ab->pci.msi.addr_hi);
490*28348caeSBjoern A. Zeeb } else {
491*28348caeSBjoern A. Zeeb ab->pci.msi.addr_hi = 0;
492*28348caeSBjoern A. Zeeb }
493*28348caeSBjoern A. Zeeb
494*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab->pci.msi.ep_base_data);
495dd4f32aeSBjoern A. Zeeb
496dd4f32aeSBjoern A. Zeeb return 0;
497dd4f32aeSBjoern A. Zeeb
498dd4f32aeSBjoern A. Zeeb free_msi_vector:
499dd4f32aeSBjoern A. Zeeb pci_free_irq_vectors(ab_pci->pdev);
500dd4f32aeSBjoern A. Zeeb
501dd4f32aeSBjoern A. Zeeb reset_msi_config:
502dd4f32aeSBjoern A. Zeeb return ret;
503dd4f32aeSBjoern A. Zeeb }
504dd4f32aeSBjoern A. Zeeb
ath11k_pci_free_msi(struct ath11k_pci * ab_pci)505dd4f32aeSBjoern A. Zeeb static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci)
506dd4f32aeSBjoern A. Zeeb {
507dd4f32aeSBjoern A. Zeeb pci_free_irq_vectors(ab_pci->pdev);
508dd4f32aeSBjoern A. Zeeb }
509dd4f32aeSBjoern A. Zeeb
ath11k_pci_config_msi_data(struct ath11k_pci * ab_pci)510dd4f32aeSBjoern A. Zeeb static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
511dd4f32aeSBjoern A. Zeeb {
512dd4f32aeSBjoern A. Zeeb struct msi_desc *msi_desc;
513dd4f32aeSBjoern A. Zeeb
514dd4f32aeSBjoern A. Zeeb msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
515dd4f32aeSBjoern A. Zeeb if (!msi_desc) {
516dd4f32aeSBjoern A. Zeeb ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");
517dd4f32aeSBjoern A. Zeeb pci_free_irq_vectors(ab_pci->pdev);
518dd4f32aeSBjoern A. Zeeb return -EINVAL;
519dd4f32aeSBjoern A. Zeeb }
520dd4f32aeSBjoern A. Zeeb
521*28348caeSBjoern A. Zeeb ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data;
522dd4f32aeSBjoern A. Zeeb
523*28348caeSBjoern A. Zeeb ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "after request_irq msi_ep_base_data %d\n",
524*28348caeSBjoern A. Zeeb ab_pci->ab->pci.msi.ep_base_data);
525dd4f32aeSBjoern A. Zeeb
526dd4f32aeSBjoern A. Zeeb return 0;
527dd4f32aeSBjoern A. Zeeb }
528dd4f32aeSBjoern A. Zeeb
ath11k_pci_claim(struct ath11k_pci * ab_pci,struct pci_dev * pdev)529dd4f32aeSBjoern A. Zeeb static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
530dd4f32aeSBjoern A. Zeeb {
531dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ab_pci->ab;
532dd4f32aeSBjoern A. Zeeb u16 device_id;
533dd4f32aeSBjoern A. Zeeb int ret = 0;
534dd4f32aeSBjoern A. Zeeb
535dd4f32aeSBjoern A. Zeeb pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
536dd4f32aeSBjoern A. Zeeb if (device_id != ab_pci->dev_id) {
537dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
538dd4f32aeSBjoern A. Zeeb device_id, ab_pci->dev_id);
539dd4f32aeSBjoern A. Zeeb ret = -EIO;
540dd4f32aeSBjoern A. Zeeb goto out;
541dd4f32aeSBjoern A. Zeeb }
542dd4f32aeSBjoern A. Zeeb
543dd4f32aeSBjoern A. Zeeb ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
544dd4f32aeSBjoern A. Zeeb if (ret) {
545dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
546dd4f32aeSBjoern A. Zeeb goto out;
547dd4f32aeSBjoern A. Zeeb }
548dd4f32aeSBjoern A. Zeeb
549dd4f32aeSBjoern A. Zeeb ret = pci_enable_device(pdev);
550dd4f32aeSBjoern A. Zeeb if (ret) {
551dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to enable pci device: %d\n", ret);
552dd4f32aeSBjoern A. Zeeb goto out;
553dd4f32aeSBjoern A. Zeeb }
554dd4f32aeSBjoern A. Zeeb
555dd4f32aeSBjoern A. Zeeb ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
556dd4f32aeSBjoern A. Zeeb if (ret) {
557dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to request pci region: %d\n", ret);
558dd4f32aeSBjoern A. Zeeb goto disable_device;
559dd4f32aeSBjoern A. Zeeb }
560dd4f32aeSBjoern A. Zeeb
561dd4f32aeSBjoern A. Zeeb ret = dma_set_mask_and_coherent(&pdev->dev,
562dd4f32aeSBjoern A. Zeeb DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
563dd4f32aeSBjoern A. Zeeb if (ret) {
564dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
565dd4f32aeSBjoern A. Zeeb ATH11K_PCI_DMA_MASK, ret);
566dd4f32aeSBjoern A. Zeeb goto release_region;
567dd4f32aeSBjoern A. Zeeb }
568dd4f32aeSBjoern A. Zeeb
569dd4f32aeSBjoern A. Zeeb pci_set_master(pdev);
570dd4f32aeSBjoern A. Zeeb
571dd4f32aeSBjoern A. Zeeb ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
572dd4f32aeSBjoern A. Zeeb ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
573dd4f32aeSBjoern A. Zeeb if (!ab->mem) {
574dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
575dd4f32aeSBjoern A. Zeeb ret = -EIO;
576*28348caeSBjoern A. Zeeb goto release_region;
577dd4f32aeSBjoern A. Zeeb }
578dd4f32aeSBjoern A. Zeeb
579*28348caeSBjoern A. Zeeb ab->mem_ce = ab->mem;
580*28348caeSBjoern A. Zeeb
581*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem);
582dd4f32aeSBjoern A. Zeeb return 0;
583dd4f32aeSBjoern A. Zeeb
584dd4f32aeSBjoern A. Zeeb release_region:
585dd4f32aeSBjoern A. Zeeb pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
586dd4f32aeSBjoern A. Zeeb disable_device:
587dd4f32aeSBjoern A. Zeeb pci_disable_device(pdev);
588dd4f32aeSBjoern A. Zeeb out:
589dd4f32aeSBjoern A. Zeeb return ret;
590dd4f32aeSBjoern A. Zeeb }
591dd4f32aeSBjoern A. Zeeb
ath11k_pci_free_region(struct ath11k_pci * ab_pci)592dd4f32aeSBjoern A. Zeeb static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
593dd4f32aeSBjoern A. Zeeb {
594dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ab_pci->ab;
595dd4f32aeSBjoern A. Zeeb struct pci_dev *pci_dev = ab_pci->pdev;
596dd4f32aeSBjoern A. Zeeb
597dd4f32aeSBjoern A. Zeeb pci_iounmap(pci_dev, ab->mem);
598dd4f32aeSBjoern A. Zeeb ab->mem = NULL;
599dd4f32aeSBjoern A. Zeeb pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
600dd4f32aeSBjoern A. Zeeb if (pci_is_enabled(pci_dev))
601dd4f32aeSBjoern A. Zeeb pci_disable_device(pci_dev);
602dd4f32aeSBjoern A. Zeeb }
603dd4f32aeSBjoern A. Zeeb
ath11k_pci_aspm_disable(struct ath11k_pci * ab_pci)604dd4f32aeSBjoern A. Zeeb static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
605dd4f32aeSBjoern A. Zeeb {
606dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = ab_pci->ab;
607dd4f32aeSBjoern A. Zeeb
608dd4f32aeSBjoern A. Zeeb pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
609dd4f32aeSBjoern A. Zeeb &ab_pci->link_ctl);
610dd4f32aeSBjoern A. Zeeb
611*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n",
612dd4f32aeSBjoern A. Zeeb ab_pci->link_ctl,
613dd4f32aeSBjoern A. Zeeb u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
614dd4f32aeSBjoern A. Zeeb u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
615dd4f32aeSBjoern A. Zeeb
616dd4f32aeSBjoern A. Zeeb /* disable L0s and L1 */
617dd4f32aeSBjoern A. Zeeb pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
618dd4f32aeSBjoern A. Zeeb ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
619dd4f32aeSBjoern A. Zeeb
620dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
621dd4f32aeSBjoern A. Zeeb }
622dd4f32aeSBjoern A. Zeeb
ath11k_pci_aspm_restore(struct ath11k_pci * ab_pci)623dd4f32aeSBjoern A. Zeeb static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
624dd4f32aeSBjoern A. Zeeb {
625dd4f32aeSBjoern A. Zeeb if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
626dd4f32aeSBjoern A. Zeeb pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
627dd4f32aeSBjoern A. Zeeb ab_pci->link_ctl);
628dd4f32aeSBjoern A. Zeeb }
629dd4f32aeSBjoern A. Zeeb
ath11k_pci_power_up(struct ath11k_base * ab)630dd4f32aeSBjoern A. Zeeb static int ath11k_pci_power_up(struct ath11k_base *ab)
631dd4f32aeSBjoern A. Zeeb {
632dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
633dd4f32aeSBjoern A. Zeeb int ret;
634dd4f32aeSBjoern A. Zeeb
635dd4f32aeSBjoern A. Zeeb ab_pci->register_window = 0;
636*28348caeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
637dd4f32aeSBjoern A. Zeeb ath11k_pci_sw_reset(ab_pci->ab, true);
638dd4f32aeSBjoern A. Zeeb
639dd4f32aeSBjoern A. Zeeb /* Disable ASPM during firmware download due to problems switching
640dd4f32aeSBjoern A. Zeeb * to AMSS state.
641dd4f32aeSBjoern A. Zeeb */
642dd4f32aeSBjoern A. Zeeb ath11k_pci_aspm_disable(ab_pci);
643dd4f32aeSBjoern A. Zeeb
644dd4f32aeSBjoern A. Zeeb ath11k_pci_msi_enable(ab_pci);
645dd4f32aeSBjoern A. Zeeb
646dd4f32aeSBjoern A. Zeeb ret = ath11k_mhi_start(ab_pci);
647dd4f32aeSBjoern A. Zeeb if (ret) {
648dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to start mhi: %d\n", ret);
649dd4f32aeSBjoern A. Zeeb return ret;
650dd4f32aeSBjoern A. Zeeb }
651dd4f32aeSBjoern A. Zeeb
652*28348caeSBjoern A. Zeeb if (ab->hw_params.static_window_map)
653dd4f32aeSBjoern A. Zeeb ath11k_pci_select_static_window(ab_pci);
654dd4f32aeSBjoern A. Zeeb
655dd4f32aeSBjoern A. Zeeb return 0;
656dd4f32aeSBjoern A. Zeeb }
657dd4f32aeSBjoern A. Zeeb
ath11k_pci_power_down(struct ath11k_base * ab)658dd4f32aeSBjoern A. Zeeb static void ath11k_pci_power_down(struct ath11k_base *ab)
659dd4f32aeSBjoern A. Zeeb {
660dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
661dd4f32aeSBjoern A. Zeeb
662dd4f32aeSBjoern A. Zeeb /* restore aspm in case firmware bootup fails */
663dd4f32aeSBjoern A. Zeeb ath11k_pci_aspm_restore(ab_pci);
664dd4f32aeSBjoern A. Zeeb
665dd4f32aeSBjoern A. Zeeb ath11k_pci_force_wake(ab_pci->ab);
666dd4f32aeSBjoern A. Zeeb
667dd4f32aeSBjoern A. Zeeb ath11k_pci_msi_disable(ab_pci);
668dd4f32aeSBjoern A. Zeeb
669dd4f32aeSBjoern A. Zeeb ath11k_mhi_stop(ab_pci);
670*28348caeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
671dd4f32aeSBjoern A. Zeeb ath11k_pci_sw_reset(ab_pci->ab, false);
672dd4f32aeSBjoern A. Zeeb }
673dd4f32aeSBjoern A. Zeeb
ath11k_pci_hif_suspend(struct ath11k_base * ab)674dd4f32aeSBjoern A. Zeeb static int ath11k_pci_hif_suspend(struct ath11k_base *ab)
675dd4f32aeSBjoern A. Zeeb {
676dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
677dd4f32aeSBjoern A. Zeeb
678*28348caeSBjoern A. Zeeb return ath11k_mhi_suspend(ar_pci);
679dd4f32aeSBjoern A. Zeeb }
680dd4f32aeSBjoern A. Zeeb
ath11k_pci_hif_resume(struct ath11k_base * ab)681dd4f32aeSBjoern A. Zeeb static int ath11k_pci_hif_resume(struct ath11k_base *ab)
682dd4f32aeSBjoern A. Zeeb {
683dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
684dd4f32aeSBjoern A. Zeeb
685*28348caeSBjoern A. Zeeb return ath11k_mhi_resume(ar_pci);
686dd4f32aeSBjoern A. Zeeb }
687dd4f32aeSBjoern A. Zeeb
ath11k_pci_hif_ce_irq_enable(struct ath11k_base * ab)688*28348caeSBjoern A. Zeeb static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab)
689dd4f32aeSBjoern A. Zeeb {
690*28348caeSBjoern A. Zeeb ath11k_pcic_ce_irqs_enable(ab);
691dd4f32aeSBjoern A. Zeeb }
692dd4f32aeSBjoern A. Zeeb
ath11k_pci_hif_ce_irq_disable(struct ath11k_base * ab)693*28348caeSBjoern A. Zeeb static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab)
694dd4f32aeSBjoern A. Zeeb {
695*28348caeSBjoern A. Zeeb ath11k_pcic_ce_irq_disable_sync(ab);
696dd4f32aeSBjoern A. Zeeb }
697dd4f32aeSBjoern A. Zeeb
ath11k_pci_start(struct ath11k_base * ab)698dd4f32aeSBjoern A. Zeeb static int ath11k_pci_start(struct ath11k_base *ab)
699dd4f32aeSBjoern A. Zeeb {
700dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
701dd4f32aeSBjoern A. Zeeb
702dd4f32aeSBjoern A. Zeeb /* TODO: for now don't restore ASPM in case of single MSI
703dd4f32aeSBjoern A. Zeeb * vector as MHI register reading in M2 causes system hang.
704dd4f32aeSBjoern A. Zeeb */
705*28348caeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
706dd4f32aeSBjoern A. Zeeb ath11k_pci_aspm_restore(ab_pci);
707dd4f32aeSBjoern A. Zeeb else
708dd4f32aeSBjoern A. Zeeb ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n");
709dd4f32aeSBjoern A. Zeeb
710*28348caeSBjoern A. Zeeb ath11k_pcic_start(ab);
711dd4f32aeSBjoern A. Zeeb
712dd4f32aeSBjoern A. Zeeb return 0;
713dd4f32aeSBjoern A. Zeeb }
714dd4f32aeSBjoern A. Zeeb
715dd4f32aeSBjoern A. Zeeb static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
716dd4f32aeSBjoern A. Zeeb .start = ath11k_pci_start,
717*28348caeSBjoern A. Zeeb .stop = ath11k_pcic_stop,
718*28348caeSBjoern A. Zeeb .read32 = ath11k_pcic_read32,
719*28348caeSBjoern A. Zeeb .write32 = ath11k_pcic_write32,
720*28348caeSBjoern A. Zeeb .read = ath11k_pcic_read,
721dd4f32aeSBjoern A. Zeeb .power_down = ath11k_pci_power_down,
722dd4f32aeSBjoern A. Zeeb .power_up = ath11k_pci_power_up,
723dd4f32aeSBjoern A. Zeeb .suspend = ath11k_pci_hif_suspend,
724dd4f32aeSBjoern A. Zeeb .resume = ath11k_pci_hif_resume,
725*28348caeSBjoern A. Zeeb .irq_enable = ath11k_pcic_ext_irq_enable,
726*28348caeSBjoern A. Zeeb .irq_disable = ath11k_pcic_ext_irq_disable,
727*28348caeSBjoern A. Zeeb .get_msi_address = ath11k_pcic_get_msi_address,
728*28348caeSBjoern A. Zeeb .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment,
729*28348caeSBjoern A. Zeeb .map_service_to_pipe = ath11k_pcic_map_service_to_pipe,
730dd4f32aeSBjoern A. Zeeb .ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
731dd4f32aeSBjoern A. Zeeb .ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
732*28348caeSBjoern A. Zeeb .get_ce_msi_idx = ath11k_pcic_get_ce_msi_idx,
733dd4f32aeSBjoern A. Zeeb };
734dd4f32aeSBjoern A. Zeeb
ath11k_pci_read_hw_version(struct ath11k_base * ab,u32 * major,u32 * minor)735dd4f32aeSBjoern A. Zeeb static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)
736dd4f32aeSBjoern A. Zeeb {
737dd4f32aeSBjoern A. Zeeb u32 soc_hw_version;
738dd4f32aeSBjoern A. Zeeb
739*28348caeSBjoern A. Zeeb soc_hw_version = ath11k_pcic_read32(ab, TCSR_SOC_HW_VERSION);
740dd4f32aeSBjoern A. Zeeb *major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
741dd4f32aeSBjoern A. Zeeb soc_hw_version);
742dd4f32aeSBjoern A. Zeeb *minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
743dd4f32aeSBjoern A. Zeeb soc_hw_version);
744dd4f32aeSBjoern A. Zeeb
745*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_PCI, "tcsr_soc_hw_version major %d minor %d\n",
746dd4f32aeSBjoern A. Zeeb *major, *minor);
747dd4f32aeSBjoern A. Zeeb }
748dd4f32aeSBjoern A. Zeeb
ath11k_pci_set_irq_affinity_hint(struct ath11k_pci * ab_pci,const struct cpumask * m)749*28348caeSBjoern A. Zeeb static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci,
750*28348caeSBjoern A. Zeeb #if defined(__linux__)
751*28348caeSBjoern A. Zeeb const struct cpumask *m)
752*28348caeSBjoern A. Zeeb #elif defined(__FreeBSD__)
753*28348caeSBjoern A. Zeeb const cpumask_t *m)
754*28348caeSBjoern A. Zeeb #endif
755*28348caeSBjoern A. Zeeb {
756*28348caeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab_pci->ab->dev_flags))
757*28348caeSBjoern A. Zeeb return 0;
758*28348caeSBjoern A. Zeeb
759*28348caeSBjoern A. Zeeb return irq_set_affinity_hint(ab_pci->pdev->irq, m);
760*28348caeSBjoern A. Zeeb }
761*28348caeSBjoern A. Zeeb
ath11k_pci_probe(struct pci_dev * pdev,const struct pci_device_id * pci_dev)762dd4f32aeSBjoern A. Zeeb static int ath11k_pci_probe(struct pci_dev *pdev,
763dd4f32aeSBjoern A. Zeeb const struct pci_device_id *pci_dev)
764dd4f32aeSBjoern A. Zeeb {
765dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab;
766dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ab_pci;
767dd4f32aeSBjoern A. Zeeb #if defined(__linux__)
768dd4f32aeSBjoern A. Zeeb u32 soc_hw_version_major, soc_hw_version_minor, addr;
769dd4f32aeSBjoern A. Zeeb #elif defined(__FreeBSD__)
770dd4f32aeSBjoern A. Zeeb u32 soc_hw_version_major, soc_hw_version_minor;
771dd4f32aeSBjoern A. Zeeb #endif
772*28348caeSBjoern A. Zeeb const struct ath11k_pci_ops *pci_ops;
773dd4f32aeSBjoern A. Zeeb int ret;
774dd4f32aeSBjoern A. Zeeb
775*28348caeSBjoern A. Zeeb ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI);
776*28348caeSBjoern A. Zeeb
777dd4f32aeSBjoern A. Zeeb if (!ab) {
778dd4f32aeSBjoern A. Zeeb dev_err(&pdev->dev, "failed to allocate ath11k base\n");
779dd4f32aeSBjoern A. Zeeb return -ENOMEM;
780dd4f32aeSBjoern A. Zeeb }
781dd4f32aeSBjoern A. Zeeb
782dd4f32aeSBjoern A. Zeeb ab->dev = &pdev->dev;
783dd4f32aeSBjoern A. Zeeb pci_set_drvdata(pdev, ab);
784dd4f32aeSBjoern A. Zeeb ab_pci = ath11k_pci_priv(ab);
785dd4f32aeSBjoern A. Zeeb ab_pci->dev_id = pci_dev->device;
786dd4f32aeSBjoern A. Zeeb ab_pci->ab = ab;
787dd4f32aeSBjoern A. Zeeb ab_pci->pdev = pdev;
788dd4f32aeSBjoern A. Zeeb ab->hif.ops = &ath11k_pci_hif_ops;
789*28348caeSBjoern A. Zeeb ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
790dd4f32aeSBjoern A. Zeeb pci_set_drvdata(pdev, ab);
791dd4f32aeSBjoern A. Zeeb spin_lock_init(&ab_pci->window_lock);
792dd4f32aeSBjoern A. Zeeb
793dd4f32aeSBjoern A. Zeeb /* Set fixed_mem_region to true for platforms support reserved memory
794dd4f32aeSBjoern A. Zeeb * from DT. If memory is reserved from DT for FW, ath11k driver need not
795dd4f32aeSBjoern A. Zeeb * allocate memory.
796dd4f32aeSBjoern A. Zeeb */
797dd4f32aeSBjoern A. Zeeb #if defined(__linux__)
798dd4f32aeSBjoern A. Zeeb ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr);
799dd4f32aeSBjoern A. Zeeb if (!ret)
800dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags);
801dd4f32aeSBjoern A. Zeeb #endif
802dd4f32aeSBjoern A. Zeeb
803dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_claim(ab_pci, pdev);
804dd4f32aeSBjoern A. Zeeb if (ret) {
805dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to claim device: %d\n", ret);
806dd4f32aeSBjoern A. Zeeb goto err_free_core;
807dd4f32aeSBjoern A. Zeeb }
808dd4f32aeSBjoern A. Zeeb
809dd4f32aeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n",
810dd4f32aeSBjoern A. Zeeb pdev->vendor, pdev->device,
811dd4f32aeSBjoern A. Zeeb pdev->subsystem_vendor, pdev->subsystem_device);
812dd4f32aeSBjoern A. Zeeb
813dd4f32aeSBjoern A. Zeeb ab->id.vendor = pdev->vendor;
814dd4f32aeSBjoern A. Zeeb ab->id.device = pdev->device;
815dd4f32aeSBjoern A. Zeeb ab->id.subsystem_vendor = pdev->subsystem_vendor;
816dd4f32aeSBjoern A. Zeeb ab->id.subsystem_device = pdev->subsystem_device;
817dd4f32aeSBjoern A. Zeeb
818dd4f32aeSBjoern A. Zeeb switch (pci_dev->device) {
819dd4f32aeSBjoern A. Zeeb case QCA6390_DEVICE_ID:
820dd4f32aeSBjoern A. Zeeb ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
821dd4f32aeSBjoern A. Zeeb &soc_hw_version_minor);
822dd4f32aeSBjoern A. Zeeb switch (soc_hw_version_major) {
823dd4f32aeSBjoern A. Zeeb case 2:
824dd4f32aeSBjoern A. Zeeb ab->hw_rev = ATH11K_HW_QCA6390_HW20;
825dd4f32aeSBjoern A. Zeeb break;
826dd4f32aeSBjoern A. Zeeb default:
827dd4f32aeSBjoern A. Zeeb dev_err(&pdev->dev, "Unsupported QCA6390 SOC hardware version: %d %d\n",
828dd4f32aeSBjoern A. Zeeb soc_hw_version_major, soc_hw_version_minor);
829dd4f32aeSBjoern A. Zeeb ret = -EOPNOTSUPP;
830dd4f32aeSBjoern A. Zeeb goto err_pci_free_region;
831dd4f32aeSBjoern A. Zeeb }
832*28348caeSBjoern A. Zeeb
833*28348caeSBjoern A. Zeeb pci_ops = &ath11k_pci_ops_qca6390;
834dd4f32aeSBjoern A. Zeeb break;
835dd4f32aeSBjoern A. Zeeb case QCN9074_DEVICE_ID:
836*28348caeSBjoern A. Zeeb pci_ops = &ath11k_pci_ops_qcn9074;
837dd4f32aeSBjoern A. Zeeb ab->hw_rev = ATH11K_HW_QCN9074_HW10;
838dd4f32aeSBjoern A. Zeeb break;
839dd4f32aeSBjoern A. Zeeb case WCN6855_DEVICE_ID:
840dd4f32aeSBjoern A. Zeeb ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD;
841dd4f32aeSBjoern A. Zeeb ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
842dd4f32aeSBjoern A. Zeeb &soc_hw_version_minor);
843dd4f32aeSBjoern A. Zeeb switch (soc_hw_version_major) {
844dd4f32aeSBjoern A. Zeeb case 2:
845dd4f32aeSBjoern A. Zeeb switch (soc_hw_version_minor) {
846dd4f32aeSBjoern A. Zeeb case 0x00:
847dd4f32aeSBjoern A. Zeeb case 0x01:
848dd4f32aeSBjoern A. Zeeb ab->hw_rev = ATH11K_HW_WCN6855_HW20;
849dd4f32aeSBjoern A. Zeeb break;
850dd4f32aeSBjoern A. Zeeb case 0x10:
851dd4f32aeSBjoern A. Zeeb case 0x11:
852dd4f32aeSBjoern A. Zeeb ab->hw_rev = ATH11K_HW_WCN6855_HW21;
853dd4f32aeSBjoern A. Zeeb break;
854dd4f32aeSBjoern A. Zeeb default:
855dd4f32aeSBjoern A. Zeeb goto unsupported_wcn6855_soc;
856dd4f32aeSBjoern A. Zeeb }
857dd4f32aeSBjoern A. Zeeb break;
858dd4f32aeSBjoern A. Zeeb default:
859dd4f32aeSBjoern A. Zeeb unsupported_wcn6855_soc:
860dd4f32aeSBjoern A. Zeeb dev_err(&pdev->dev, "Unsupported WCN6855 SOC hardware version: %d %d\n",
861dd4f32aeSBjoern A. Zeeb soc_hw_version_major, soc_hw_version_minor);
862dd4f32aeSBjoern A. Zeeb ret = -EOPNOTSUPP;
863dd4f32aeSBjoern A. Zeeb goto err_pci_free_region;
864dd4f32aeSBjoern A. Zeeb }
865*28348caeSBjoern A. Zeeb
866*28348caeSBjoern A. Zeeb pci_ops = &ath11k_pci_ops_qca6390;
867dd4f32aeSBjoern A. Zeeb break;
868dd4f32aeSBjoern A. Zeeb default:
869dd4f32aeSBjoern A. Zeeb dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
870dd4f32aeSBjoern A. Zeeb pci_dev->device);
871dd4f32aeSBjoern A. Zeeb ret = -EOPNOTSUPP;
872dd4f32aeSBjoern A. Zeeb goto err_pci_free_region;
873dd4f32aeSBjoern A. Zeeb }
874dd4f32aeSBjoern A. Zeeb
875*28348caeSBjoern A. Zeeb ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
876*28348caeSBjoern A. Zeeb if (ret) {
877*28348caeSBjoern A. Zeeb ath11k_err(ab, "failed to register PCI ops: %d\n", ret);
878*28348caeSBjoern A. Zeeb goto err_pci_free_region;
879*28348caeSBjoern A. Zeeb }
880*28348caeSBjoern A. Zeeb
881*28348caeSBjoern A. Zeeb ret = ath11k_pcic_init_msi_config(ab);
882*28348caeSBjoern A. Zeeb if (ret) {
883*28348caeSBjoern A. Zeeb ath11k_err(ab, "failed to init msi config: %d\n", ret);
884*28348caeSBjoern A. Zeeb goto err_pci_free_region;
885*28348caeSBjoern A. Zeeb }
886*28348caeSBjoern A. Zeeb
887dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_alloc_msi(ab_pci);
888dd4f32aeSBjoern A. Zeeb if (ret) {
889dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to enable msi: %d\n", ret);
890dd4f32aeSBjoern A. Zeeb goto err_pci_free_region;
891dd4f32aeSBjoern A. Zeeb }
892dd4f32aeSBjoern A. Zeeb
893dd4f32aeSBjoern A. Zeeb ret = ath11k_core_pre_init(ab);
894dd4f32aeSBjoern A. Zeeb if (ret)
895dd4f32aeSBjoern A. Zeeb goto err_pci_disable_msi;
896dd4f32aeSBjoern A. Zeeb
897dd4f32aeSBjoern A. Zeeb ret = ath11k_mhi_register(ab_pci);
898dd4f32aeSBjoern A. Zeeb if (ret) {
899dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to register mhi: %d\n", ret);
900dd4f32aeSBjoern A. Zeeb goto err_pci_disable_msi;
901dd4f32aeSBjoern A. Zeeb }
902dd4f32aeSBjoern A. Zeeb
903dd4f32aeSBjoern A. Zeeb ret = ath11k_hal_srng_init(ab);
904dd4f32aeSBjoern A. Zeeb if (ret)
905dd4f32aeSBjoern A. Zeeb goto err_mhi_unregister;
906dd4f32aeSBjoern A. Zeeb
907dd4f32aeSBjoern A. Zeeb ret = ath11k_ce_alloc_pipes(ab);
908dd4f32aeSBjoern A. Zeeb if (ret) {
909dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
910dd4f32aeSBjoern A. Zeeb goto err_hal_srng_deinit;
911dd4f32aeSBjoern A. Zeeb }
912dd4f32aeSBjoern A. Zeeb
913dd4f32aeSBjoern A. Zeeb ath11k_pci_init_qmi_ce_config(ab);
914dd4f32aeSBjoern A. Zeeb
915*28348caeSBjoern A. Zeeb ret = ath11k_pcic_config_irq(ab);
916dd4f32aeSBjoern A. Zeeb if (ret) {
917dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to config irq: %d\n", ret);
918dd4f32aeSBjoern A. Zeeb goto err_ce_free;
919dd4f32aeSBjoern A. Zeeb }
920dd4f32aeSBjoern A. Zeeb
921*28348caeSBjoern A. Zeeb ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));
922*28348caeSBjoern A. Zeeb if (ret) {
923*28348caeSBjoern A. Zeeb ath11k_err(ab, "failed to set irq affinity %d\n", ret);
924*28348caeSBjoern A. Zeeb goto err_free_irq;
925*28348caeSBjoern A. Zeeb }
926*28348caeSBjoern A. Zeeb
927dd4f32aeSBjoern A. Zeeb /* kernel may allocate a dummy vector before request_irq and
928dd4f32aeSBjoern A. Zeeb * then allocate a real vector when request_irq is called.
929dd4f32aeSBjoern A. Zeeb * So get msi_data here again to avoid spurious interrupt
930dd4f32aeSBjoern A. Zeeb * as msi_data will configured to srngs.
931dd4f32aeSBjoern A. Zeeb */
932dd4f32aeSBjoern A. Zeeb ret = ath11k_pci_config_msi_data(ab_pci);
933dd4f32aeSBjoern A. Zeeb if (ret) {
934dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to config msi_data: %d\n", ret);
935*28348caeSBjoern A. Zeeb goto err_irq_affinity_cleanup;
936dd4f32aeSBjoern A. Zeeb }
937dd4f32aeSBjoern A. Zeeb
938dd4f32aeSBjoern A. Zeeb ret = ath11k_core_init(ab);
939dd4f32aeSBjoern A. Zeeb if (ret) {
940dd4f32aeSBjoern A. Zeeb ath11k_err(ab, "failed to init core: %d\n", ret);
941*28348caeSBjoern A. Zeeb goto err_irq_affinity_cleanup;
942dd4f32aeSBjoern A. Zeeb }
943*28348caeSBjoern A. Zeeb ath11k_qmi_fwreset_from_cold_boot(ab);
944dd4f32aeSBjoern A. Zeeb return 0;
945dd4f32aeSBjoern A. Zeeb
946*28348caeSBjoern A. Zeeb err_irq_affinity_cleanup:
947*28348caeSBjoern A. Zeeb ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
948*28348caeSBjoern A. Zeeb
949dd4f32aeSBjoern A. Zeeb err_free_irq:
950*28348caeSBjoern A. Zeeb ath11k_pcic_free_irq(ab);
951dd4f32aeSBjoern A. Zeeb
952dd4f32aeSBjoern A. Zeeb err_ce_free:
953dd4f32aeSBjoern A. Zeeb ath11k_ce_free_pipes(ab);
954dd4f32aeSBjoern A. Zeeb
955dd4f32aeSBjoern A. Zeeb err_hal_srng_deinit:
956dd4f32aeSBjoern A. Zeeb ath11k_hal_srng_deinit(ab);
957dd4f32aeSBjoern A. Zeeb
958dd4f32aeSBjoern A. Zeeb err_mhi_unregister:
959dd4f32aeSBjoern A. Zeeb ath11k_mhi_unregister(ab_pci);
960dd4f32aeSBjoern A. Zeeb
961dd4f32aeSBjoern A. Zeeb err_pci_disable_msi:
962dd4f32aeSBjoern A. Zeeb ath11k_pci_free_msi(ab_pci);
963dd4f32aeSBjoern A. Zeeb
964dd4f32aeSBjoern A. Zeeb err_pci_free_region:
965dd4f32aeSBjoern A. Zeeb ath11k_pci_free_region(ab_pci);
966dd4f32aeSBjoern A. Zeeb
967dd4f32aeSBjoern A. Zeeb err_free_core:
968dd4f32aeSBjoern A. Zeeb ath11k_core_free(ab);
969dd4f32aeSBjoern A. Zeeb
970dd4f32aeSBjoern A. Zeeb return ret;
971dd4f32aeSBjoern A. Zeeb }
972dd4f32aeSBjoern A. Zeeb
ath11k_pci_remove(struct pci_dev * pdev)973dd4f32aeSBjoern A. Zeeb static void ath11k_pci_remove(struct pci_dev *pdev)
974dd4f32aeSBjoern A. Zeeb {
975dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = pci_get_drvdata(pdev);
976dd4f32aeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
977dd4f32aeSBjoern A. Zeeb
978dd4f32aeSBjoern A. Zeeb ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
979dd4f32aeSBjoern A. Zeeb
980dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
981dd4f32aeSBjoern A. Zeeb ath11k_pci_power_down(ab);
982dd4f32aeSBjoern A. Zeeb ath11k_debugfs_soc_destroy(ab);
983dd4f32aeSBjoern A. Zeeb ath11k_qmi_deinit_service(ab);
984dd4f32aeSBjoern A. Zeeb goto qmi_fail;
985dd4f32aeSBjoern A. Zeeb }
986dd4f32aeSBjoern A. Zeeb
987dd4f32aeSBjoern A. Zeeb set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
988dd4f32aeSBjoern A. Zeeb
989dd4f32aeSBjoern A. Zeeb ath11k_core_deinit(ab);
990dd4f32aeSBjoern A. Zeeb
991dd4f32aeSBjoern A. Zeeb qmi_fail:
992dd4f32aeSBjoern A. Zeeb ath11k_mhi_unregister(ab_pci);
993dd4f32aeSBjoern A. Zeeb
994*28348caeSBjoern A. Zeeb ath11k_pcic_free_irq(ab);
995dd4f32aeSBjoern A. Zeeb ath11k_pci_free_msi(ab_pci);
996dd4f32aeSBjoern A. Zeeb ath11k_pci_free_region(ab_pci);
997dd4f32aeSBjoern A. Zeeb
998dd4f32aeSBjoern A. Zeeb ath11k_hal_srng_deinit(ab);
999dd4f32aeSBjoern A. Zeeb ath11k_ce_free_pipes(ab);
1000dd4f32aeSBjoern A. Zeeb ath11k_core_free(ab);
1001dd4f32aeSBjoern A. Zeeb }
1002dd4f32aeSBjoern A. Zeeb
ath11k_pci_shutdown(struct pci_dev * pdev)1003dd4f32aeSBjoern A. Zeeb static void ath11k_pci_shutdown(struct pci_dev *pdev)
1004dd4f32aeSBjoern A. Zeeb {
1005dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = pci_get_drvdata(pdev);
1006*28348caeSBjoern A. Zeeb struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
1007dd4f32aeSBjoern A. Zeeb
1008*28348caeSBjoern A. Zeeb ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
1009dd4f32aeSBjoern A. Zeeb ath11k_pci_power_down(ab);
1010dd4f32aeSBjoern A. Zeeb }
1011dd4f32aeSBjoern A. Zeeb
1012dd4f32aeSBjoern A. Zeeb #ifdef CONFIG_PM
ath11k_pci_pm_suspend(struct device * dev)1013dd4f32aeSBjoern A. Zeeb static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
1014dd4f32aeSBjoern A. Zeeb {
1015dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = dev_get_drvdata(dev);
1016dd4f32aeSBjoern A. Zeeb int ret;
1017dd4f32aeSBjoern A. Zeeb
1018*28348caeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
1019*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci suspend as qmi is not initialised\n");
1020*28348caeSBjoern A. Zeeb return 0;
1021*28348caeSBjoern A. Zeeb }
1022*28348caeSBjoern A. Zeeb
1023dd4f32aeSBjoern A. Zeeb ret = ath11k_core_suspend(ab);
1024dd4f32aeSBjoern A. Zeeb if (ret)
1025dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to suspend core: %d\n", ret);
1026dd4f32aeSBjoern A. Zeeb
1027*28348caeSBjoern A. Zeeb return 0;
1028dd4f32aeSBjoern A. Zeeb }
1029dd4f32aeSBjoern A. Zeeb
ath11k_pci_pm_resume(struct device * dev)1030dd4f32aeSBjoern A. Zeeb static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
1031dd4f32aeSBjoern A. Zeeb {
1032dd4f32aeSBjoern A. Zeeb struct ath11k_base *ab = dev_get_drvdata(dev);
1033dd4f32aeSBjoern A. Zeeb int ret;
1034dd4f32aeSBjoern A. Zeeb
1035*28348caeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
1036*28348caeSBjoern A. Zeeb ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci resume as qmi is not initialised\n");
1037*28348caeSBjoern A. Zeeb return 0;
1038*28348caeSBjoern A. Zeeb }
1039*28348caeSBjoern A. Zeeb
1040dd4f32aeSBjoern A. Zeeb ret = ath11k_core_resume(ab);
1041dd4f32aeSBjoern A. Zeeb if (ret)
1042dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to resume core: %d\n", ret);
1043dd4f32aeSBjoern A. Zeeb
1044dd4f32aeSBjoern A. Zeeb return ret;
1045dd4f32aeSBjoern A. Zeeb }
1046dd4f32aeSBjoern A. Zeeb
1047dd4f32aeSBjoern A. Zeeb static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
1048dd4f32aeSBjoern A. Zeeb ath11k_pci_pm_suspend,
1049dd4f32aeSBjoern A. Zeeb ath11k_pci_pm_resume);
1050dd4f32aeSBjoern A. Zeeb #endif
1051dd4f32aeSBjoern A. Zeeb
1052dd4f32aeSBjoern A. Zeeb static struct pci_driver ath11k_pci_driver = {
1053dd4f32aeSBjoern A. Zeeb .name = "ath11k_pci",
1054dd4f32aeSBjoern A. Zeeb .id_table = ath11k_pci_id_table,
1055dd4f32aeSBjoern A. Zeeb .probe = ath11k_pci_probe,
1056dd4f32aeSBjoern A. Zeeb .remove = ath11k_pci_remove,
1057dd4f32aeSBjoern A. Zeeb .shutdown = ath11k_pci_shutdown,
1058dd4f32aeSBjoern A. Zeeb #ifdef CONFIG_PM
1059dd4f32aeSBjoern A. Zeeb .driver.pm = &ath11k_pci_pm_ops,
1060dd4f32aeSBjoern A. Zeeb #endif
1061dd4f32aeSBjoern A. Zeeb };
1062dd4f32aeSBjoern A. Zeeb
ath11k_pci_init(void)1063dd4f32aeSBjoern A. Zeeb static int ath11k_pci_init(void)
1064dd4f32aeSBjoern A. Zeeb {
1065dd4f32aeSBjoern A. Zeeb int ret;
1066dd4f32aeSBjoern A. Zeeb
1067dd4f32aeSBjoern A. Zeeb ret = pci_register_driver(&ath11k_pci_driver);
1068dd4f32aeSBjoern A. Zeeb if (ret)
1069dd4f32aeSBjoern A. Zeeb pr_err("failed to register ath11k pci driver: %d\n",
1070dd4f32aeSBjoern A. Zeeb ret);
1071dd4f32aeSBjoern A. Zeeb
1072dd4f32aeSBjoern A. Zeeb return ret;
1073dd4f32aeSBjoern A. Zeeb }
1074dd4f32aeSBjoern A. Zeeb module_init(ath11k_pci_init);
1075dd4f32aeSBjoern A. Zeeb
ath11k_pci_exit(void)1076dd4f32aeSBjoern A. Zeeb static void ath11k_pci_exit(void)
1077dd4f32aeSBjoern A. Zeeb {
1078dd4f32aeSBjoern A. Zeeb pci_unregister_driver(&ath11k_pci_driver);
1079dd4f32aeSBjoern A. Zeeb }
1080dd4f32aeSBjoern A. Zeeb
1081dd4f32aeSBjoern A. Zeeb module_exit(ath11k_pci_exit);
1082dd4f32aeSBjoern A. Zeeb
1083dd4f32aeSBjoern A. Zeeb MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
1084dd4f32aeSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
1085dd4f32aeSBjoern A. Zeeb #if defined(__FreeBSD__)
1086dd4f32aeSBjoern A. Zeeb MODULE_VERSION(ath11k_pci, 1);
1087dd4f32aeSBjoern A. Zeeb MODULE_DEPEND(ath11k_pci, linuxkpi, 1, 1, 1);
1088dd4f32aeSBjoern A. Zeeb MODULE_DEPEND(ath11k_pci, linuxkpi_wlan, 1, 1, 1);
1089dd4f32aeSBjoern A. Zeeb MODULE_DEPEND(ath11k_pci, athk_common, 1, 1, 1);
1090dd4f32aeSBjoern A. Zeeb #ifdef CONFIG_ATH11K_DEBUGFS
1091dd4f32aeSBjoern A. Zeeb MODULE_DEPEND(ath11k_pci, debugfs, 1, 1, 1);
1092dd4f32aeSBjoern A. Zeeb #endif
1093dd4f32aeSBjoern A. Zeeb #endif
1094dd4f32aeSBjoern A. Zeeb
1095*28348caeSBjoern A. Zeeb /* firmware files */
1096*28348caeSBjoern A. Zeeb MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*");
1097*28348caeSBjoern A. Zeeb MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*");
1098*28348caeSBjoern A. Zeeb MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*");
1099*28348caeSBjoern A. Zeeb MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*");
1100