xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/pcie/if_pci.h (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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 struct hif_msi_info {
83 	void *magic;
84 	dma_addr_t magic_da;
85 	OS_DMA_MEM_CONTEXT(dmacontext);
86 };
87 
88 /**
89  * struct hif_pci_stats - Account for hif pci based statistics
90  * @mhi_force_wake_request_vote: vote for mhi
91  * @mhi_force_wake_failure: mhi force wake failure
92  * @mhi_force_wake_success: mhi force wake success
93  * @soc_force_wake_register_write_success: write to soc wake
94  * @soc_force_wake_failure: soc force wake failure
95  * @soc_force_wake_success: soc force wake success
96  * @mhi_force_wake_release_success: mhi force wake release success
97  * @soc_force_wake_release_success: soc force wake release
98  */
99 struct hif_pci_stats {
100 	uint32_t mhi_force_wake_request_vote;
101 	uint32_t mhi_force_wake_failure;
102 	uint32_t mhi_force_wake_success;
103 	uint32_t soc_force_wake_register_write_success;
104 	uint32_t soc_force_wake_failure;
105 	uint32_t soc_force_wake_success;
106 	uint32_t mhi_force_wake_release_failure;
107 	uint32_t mhi_force_wake_release_success;
108 	uint32_t soc_force_wake_release_success;
109 };
110 
111 struct hif_soc_info {
112 	u32 family_number;
113 	u32 device_number;
114 	u32 major_version;
115 	u32 minor_version;
116 };
117 
118 struct hif_pci_softc {
119 	struct HIF_CE_state ce_sc;
120 	void __iomem *mem;      /* PCI address. */
121 	void __iomem *mem_ce;   /* PCI address for CE. */
122 	void __iomem *mem_cmem;   /* PCI address for CMEM. */
123 	size_t mem_len;
124 
125 	struct device *dev;	/* For efficiency, should be first in struct */
126 	struct pci_dev *pdev;
127 	int num_msi_intrs;      /* number of MSI interrupts granted */
128 	/* 0 --> using legacy PCI line interrupts */
129 	struct tasklet_struct intr_tq;  /* tasklet */
130 	struct hif_msi_info msi_info;
131 	int ce_irq_num[CE_COUNT_MAX];
132 	int irq;
133 	int irq_event;
134 	int cacheline_sz;
135 	u16 devid;
136 	struct hif_tasklet_entry tasklet_entries[HIF_MAX_TASKLET_NUM];
137 	bool pci_enabled;
138 	bool use_register_windowing;
139 	uint32_t register_window;
140 	qdf_spinlock_t register_access_lock;
141 	qdf_spinlock_t irq_lock;
142 	qdf_work_t reschedule_tasklet_work;
143 	uint32_t lcr_val;
144 	int (*hif_enable_pci)(struct hif_pci_softc *sc, struct pci_dev *pdev,
145 			      const struct pci_device_id *id);
146 	void (*hif_pci_deinit)(struct hif_pci_softc *sc);
147 	void (*hif_pci_get_soc_info)(struct hif_pci_softc *sc,
148 				     struct device *dev);
149 	struct hif_pci_stats stats;
150 #ifdef HIF_CPU_PERF_AFFINE_MASK
151 	/* Stores the affinity hint mask for each CE IRQ */
152 	qdf_cpu_mask ce_irq_cpu_mask[CE_COUNT_MAX];
153 #endif
154 	struct hif_soc_info device_version;
155 };
156 
157 bool hif_pci_targ_is_present(struct hif_softc *scn, void *__iomem *mem);
158 int hif_configure_irq(struct hif_softc *sc);
159 void hif_pci_cancel_deferred_target_sleep(struct hif_softc *scn);
160 void wlan_tasklet(unsigned long data);
161 irqreturn_t hif_pci_legacy_ce_interrupt_handler(int irq, void *arg);
162 int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset);
163 
164 /*
165  * A firmware interrupt to the Host is indicated by the
166  * low bit of SCRATCH_3_ADDRESS being set.
167  */
168 #define FW_EVENT_PENDING_REG_ADDRESS SCRATCH_3_ADDRESS
169 
170 /*
171  * Typically, MSI Interrupts are used with PCIe. To force use of legacy
172  * "ABCD" PCI line interrupts rather than MSI, define
173  * FORCE_LEGACY_PCI_INTERRUPTS.
174  * Even when NOT forced, the driver may attempt to use legacy PCI interrupts
175  * MSI allocation fails
176  */
177 #define LEGACY_INTERRUPTS(sc) ((sc)->num_msi_intrs == 0)
178 
179 /*
180  * There may be some pending tx frames during platform suspend.
181  * Suspend operation should be delayed until those tx frames are
182  * transferred from the host to target. This macro specifies how
183  * long suspend thread has to sleep before checking pending tx
184  * frame count.
185  */
186 #define OL_ATH_TX_DRAIN_WAIT_DELAY     50       /* ms */
187 
188 #define HIF_CE_DRAIN_WAIT_DELAY        10       /* ms */
189 /*
190  * Wait time (in unit of OL_ATH_TX_DRAIN_WAIT_DELAY) for pending
191  * tx frame completion before suspend. Refer: hif_pci_suspend()
192  */
193 #ifndef QCA_WIFI_3_0_EMU
194 #define OL_ATH_TX_DRAIN_WAIT_CNT       10
195 #else
196 #define OL_ATH_TX_DRAIN_WAIT_CNT       60
197 #endif
198 
199 #ifdef FORCE_WAKE
200 /**
201  * hif_print_pci_stats() - Display HIF PCI stats
202  * @hif_ctx - HIF pci handle
203  *
204  * Return: None
205  */
206 void hif_print_pci_stats(struct hif_pci_softc *pci_scn);
207 #else
208 static inline
209 void hif_print_pci_stats(struct hif_pci_softc *pci_scn)
210 {
211 }
212 #endif /* FORCE_WAKE */
213 #ifdef HIF_BUS_LOG_INFO
214 bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
215 		       unsigned int *offset);
216 #else
217 static inline
218 bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
219 		       unsigned int *offset)
220 {
221 	return false;
222 }
223 #endif
224 #endif /* __ATH_PCI_H__ */
225