1 /*
2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #ifndef __ATH_PCI_H__
21 #define __ATH_PCI_H__
22
23 #include <linux/version.h>
24 #include <linux/semaphore.h>
25 #include <linux/interrupt.h>
26
27 #define ATH_DBG_DEFAULT 0
28 #define DRAM_SIZE 0x000a8000
29 #include "hif.h"
30 #include "hif_runtime_pm.h"
31 #include "cepci.h"
32 #include "ce_main.h"
33
34 #ifdef FORCE_WAKE
35 /* Register offset to wake the UMAC from power collapse */
36 #define PCIE_REG_WAKE_UMAC_OFFSET 0x3004
37 /* Register used for handshake mechanism to validate UMAC is awake */
38 #define PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG (0x01E04000 + 0x40)
39
40 /* Timeout duration to validate UMAC wake status */
41 #ifdef HAL_CONFIG_SLUB_DEBUG_ON
42 #define FORCE_WAKE_DELAY_TIMEOUT_MS 500
43 #else
44 #define FORCE_WAKE_DELAY_TIMEOUT_MS 50
45 #endif /* HAL_CONFIG_SLUB_DEBUG_ON */
46 /* Validate UMAC status every 5ms */
47 #define FORCE_WAKE_DELAY_MS 5
48 #endif /* FORCE_WAKE */
49
50 #ifdef CONFIG_PCI_LOW_POWER_INT_REG
51 /* PCIe low power interrupt mask register */
52 #define PCIE_LOW_POWER_INT_MASK_OFFSET 0x38044
53 #define INTR_L1SS BIT(3)
54 #define INTR_CLKPM BIT(4)
55 #endif
56
57 #ifdef QCA_HIF_HIA_EXTND
58 extern int32_t frac, intval, ar900b_20_targ_clk, qca9888_20_targ_clk;
59 #endif
60
61 /* An address (e.g. of a buffer) in Copy Engine space. */
62
63 #define HIF_MAX_TASKLET_NUM 11
64 struct hif_tasklet_entry {
65 uint8_t id; /* 0 - 9: maps to CE, 10: fw */
66 void *hif_handler; /* struct hif_pci_softc */
67 };
68
69 struct hang_event_bus_info {
70 uint16_t tlv_header;
71 uint16_t dev_id;
72 } qdf_packed;
73
74 /*
75 * struct hif_msi_info - Structure to hold msi info
76 * @magic: cookie
77 * @magic_da: dma address
78 * @dmacontext: dma address
79 *
80 * Structure to hold MSI information for PCIe interrupts
81 *
82 * NB: Intentionally not using kernel-doc comment since the kernel-doc
83 * script doesn't handle the OS_DMA_MEM_CONTEXT() macro
84 */
85 struct hif_msi_info {
86 void *magic;
87 dma_addr_t magic_da;
88 OS_DMA_MEM_CONTEXT(dmacontext);
89 };
90
91 /**
92 * struct hif_pci_stats - Account for hif pci based statistics
93 * @mhi_force_wake_request_vote: vote for mhi
94 * @mhi_force_wake_failure: mhi force wake failure
95 * @mhi_force_wake_success: mhi force wake success
96 * @soc_force_wake_register_write_success: write to soc wake
97 * @soc_force_wake_failure: soc force wake failure
98 * @soc_force_wake_success: soc force wake success
99 * @mhi_force_wake_release_failure: mhi force wake release failure
100 * @mhi_force_wake_release_success: mhi force wake release success
101 * @soc_force_wake_release_success: soc force wake release
102 */
103 struct hif_pci_stats {
104 uint32_t mhi_force_wake_request_vote;
105 uint32_t mhi_force_wake_failure;
106 uint32_t mhi_force_wake_success;
107 uint32_t soc_force_wake_register_write_success;
108 uint32_t soc_force_wake_failure;
109 uint32_t soc_force_wake_success;
110 uint32_t mhi_force_wake_release_failure;
111 uint32_t mhi_force_wake_release_success;
112 uint32_t soc_force_wake_release_success;
113 };
114
115 struct hif_soc_info {
116 u32 family_number;
117 u32 device_number;
118 u32 major_version;
119 u32 minor_version;
120 };
121
122 struct hif_pci_softc {
123 struct HIF_CE_state ce_sc;
124 void __iomem *mem; /* PCI address. */
125 void __iomem *mem_ce; /* PCI address for CE. */
126 void __iomem *mem_cmem; /* PCI address for CMEM. */
127 void __iomem *mem_pmm_base; /* address for PMM. */
128 size_t mem_len;
129
130 struct device *dev; /* For efficiency, should be first in struct */
131 struct pci_dev *pdev;
132 int num_msi_intrs; /* number of MSI interrupts granted */
133 /* 0 --> using legacy PCI line interrupts */
134 struct tasklet_struct intr_tq; /* tasklet */
135 struct hif_msi_info msi_info;
136 int ce_irq_num[CE_COUNT_MAX];
137 int irq;
138 int irq_event;
139 int cacheline_sz;
140 u16 devid;
141 struct hif_tasklet_entry tasklet_entries[HIF_MAX_TASKLET_NUM];
142 bool pci_enabled;
143 bool use_register_windowing;
144 uint32_t register_window;
145 qdf_spinlock_t register_access_lock;
146 qdf_spinlock_t irq_lock;
147 qdf_work_t reschedule_tasklet_work;
148 uint32_t lcr_val;
149 int (*hif_enable_pci)(struct hif_pci_softc *sc, struct pci_dev *pdev,
150 const struct pci_device_id *id);
151 void (*hif_pci_deinit)(struct hif_pci_softc *sc);
152 void (*hif_pci_get_soc_info)(struct hif_pci_softc *sc,
153 struct device *dev);
154 struct hif_pci_stats stats;
155 #ifdef HIF_CPU_PERF_AFFINE_MASK
156 /* Stores the affinity hint mask for each CE IRQ */
157 qdf_cpu_mask ce_irq_cpu_mask[CE_COUNT_MAX];
158 #endif
159 struct hif_soc_info device_version;
160 qdf_spinlock_t force_wake_lock;
161 };
162
163 bool hif_pci_targ_is_present(struct hif_softc *scn, void *__iomem *mem);
164 int hif_configure_irq(struct hif_softc *sc);
165 void hif_pci_cancel_deferred_target_sleep(struct hif_softc *scn);
166 void wlan_tasklet(unsigned long data);
167 irqreturn_t hif_pci_legacy_ce_interrupt_handler(int irq, void *arg);
168 int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset);
169
170 /*
171 * A firmware interrupt to the Host is indicated by the
172 * low bit of SCRATCH_3_ADDRESS being set.
173 */
174 #define FW_EVENT_PENDING_REG_ADDRESS SCRATCH_3_ADDRESS
175
176 /*
177 * Typically, MSI Interrupts are used with PCIe. To force use of legacy
178 * "ABCD" PCI line interrupts rather than MSI, define
179 * FORCE_LEGACY_PCI_INTERRUPTS.
180 * Even when NOT forced, the driver may attempt to use legacy PCI interrupts
181 * MSI allocation fails
182 */
183 #define LEGACY_INTERRUPTS(sc) ((sc)->num_msi_intrs == 0)
184
185 /*
186 * There may be some pending tx frames during platform suspend.
187 * Suspend operation should be delayed until those tx frames are
188 * transferred from the host to target. This macro specifies how
189 * long suspend thread has to sleep before checking pending tx
190 * frame count.
191 */
192 #define OL_ATH_TX_DRAIN_WAIT_DELAY 50 /* ms */
193
194 #define HIF_CE_DRAIN_WAIT_DELAY 10 /* ms */
195 /*
196 * Wait time (in unit of OL_ATH_TX_DRAIN_WAIT_DELAY) for pending
197 * tx frame completion before suspend. Refer: hif_pci_suspend()
198 */
199 #ifndef QCA_WIFI_3_0_EMU
200 #define OL_ATH_TX_DRAIN_WAIT_CNT 10
201 #else
202 #define OL_ATH_TX_DRAIN_WAIT_CNT 60
203 #endif
204
205 #ifdef FORCE_WAKE
206 /**
207 * hif_print_pci_stats() - Display HIF PCI stats
208 * @pci_scn: HIF pci handle
209 *
210 * Return: None
211 */
212 void hif_print_pci_stats(struct hif_pci_softc *pci_scn);
213 #else
214 static inline
hif_print_pci_stats(struct hif_pci_softc * pci_scn)215 void hif_print_pci_stats(struct hif_pci_softc *pci_scn)
216 {
217 }
218 #endif /* FORCE_WAKE */
219 #ifdef HIF_BUS_LOG_INFO
220 bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
221 unsigned int *offset);
222 #else
223 static inline
hif_log_pcie_info(struct hif_softc * scn,uint8_t * data,unsigned int * offset)224 bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
225 unsigned int *offset)
226 {
227 return false;
228 }
229 #endif
230 #endif /* __ATH_PCI_H__ */
231