1 /* 2 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef __ATH_PCI_H__ 20 #define __ATH_PCI_H__ 21 22 #include <linux/version.h> 23 #include <linux/semaphore.h> 24 #include <linux/interrupt.h> 25 26 #define ATH_DBG_DEFAULT 0 27 #define DRAM_SIZE 0x000a8000 28 #include "hif.h" 29 #include "cepci.h" 30 #include "ce_main.h" 31 32 /* An address (e.g. of a buffer) in Copy Engine space. */ 33 34 #define HIF_MAX_TASKLET_NUM 11 35 struct hif_tasklet_entry { 36 uint8_t id; /* 0 - 9: maps to CE, 10: fw */ 37 void *hif_handler; /* struct hif_pci_softc */ 38 }; 39 40 /** 41 * enum hif_pm_runtime_state - Driver States for Runtime Power Management 42 * HIF_PM_RUNTIME_STATE_NONE: runtime pm is off 43 * HIF_PM_RUNTIME_STATE_ON: runtime pm is active and link is active 44 * HIF_PM_RUNTIME_STATE_INPROGRESS: a runtime suspend or resume is in progress 45 * HIF_PM_RUNTIME_STATE_SUSPENDED: the driver is runtime suspended 46 */ 47 enum hif_pm_runtime_state { 48 HIF_PM_RUNTIME_STATE_NONE, 49 HIF_PM_RUNTIME_STATE_ON, 50 HIF_PM_RUNTIME_STATE_INPROGRESS, 51 HIF_PM_RUNTIME_STATE_SUSPENDED, 52 }; 53 54 #ifdef FEATURE_RUNTIME_PM 55 56 /** 57 * struct hif_pm_runtime_lock - data structure for preventing runtime suspend 58 * @list - global list of runtime locks 59 * @active - true if this lock is preventing suspend 60 * @name - character string for tracking this lock 61 */ 62 struct hif_pm_runtime_lock { 63 struct list_head list; 64 bool active; 65 uint32_t timeout; 66 const char *name; 67 }; 68 69 /* Debugging stats for Runtime PM */ 70 struct hif_pci_pm_stats { 71 u32 suspended; 72 u32 suspend_err; 73 u32 resumed; 74 u32 runtime_get; 75 u32 runtime_put; 76 u32 request_resume; 77 u32 allow_suspend; 78 u32 prevent_suspend; 79 u32 prevent_suspend_timeout; 80 u32 allow_suspend_timeout; 81 u32 runtime_get_err; 82 void *last_resume_caller; 83 unsigned long suspend_jiffies; 84 }; 85 #endif 86 87 /** 88 * struct hif_msi_info - Structure to hold msi info 89 * @magic: cookie 90 * @magic_da: dma address 91 * @dmaContext: dma address 92 * 93 * Structure to hold MSI information for PCIe interrupts 94 */ 95 struct hif_msi_info { 96 void *magic; 97 dma_addr_t magic_da; 98 OS_DMA_MEM_CONTEXT(dmacontext); 99 }; 100 101 struct hif_pci_softc { 102 struct HIF_CE_state ce_sc; 103 void __iomem *mem; /* PCI address. */ 104 size_t mem_len; 105 106 struct device *dev; /* For efficiency, should be first in struct */ 107 struct pci_dev *pdev; 108 int num_msi_intrs; /* number of MSI interrupts granted */ 109 /* 0 --> using legacy PCI line interrupts */ 110 struct tasklet_struct intr_tq; /* tasklet */ 111 struct hif_msi_info msi_info; 112 int ce_msi_irq_num[CE_COUNT_MAX]; 113 int irq; 114 int irq_event; 115 int cacheline_sz; 116 u16 devid; 117 struct hif_tasklet_entry tasklet_entries[HIF_MAX_TASKLET_NUM]; 118 bool pci_enabled; 119 bool use_register_windowing; 120 uint32_t register_window; 121 qdf_spinlock_t register_access_lock; 122 qdf_spinlock_t irq_lock; 123 qdf_work_t reschedule_tasklet_work; 124 uint32_t lcr_val; 125 #ifdef FEATURE_RUNTIME_PM 126 atomic_t pm_state; 127 uint32_t prevent_suspend_cnt; 128 struct hif_pci_pm_stats pm_stats; 129 struct work_struct pm_work; 130 spinlock_t runtime_lock; 131 struct timer_list runtime_timer; 132 struct list_head prevent_suspend_list; 133 unsigned long runtime_timer_expires; 134 qdf_runtime_lock_t prevent_linkdown_lock; 135 #ifdef WLAN_OPEN_SOURCE 136 struct dentry *pm_dentry; 137 #endif 138 #endif 139 }; 140 141 bool hif_pci_targ_is_present(struct hif_softc *scn, void *__iomem *mem); 142 int hif_configure_irq(struct hif_softc *sc); 143 void hif_pci_cancel_deferred_target_sleep(struct hif_softc *scn); 144 void wlan_tasklet(unsigned long data); 145 irqreturn_t hif_pci_legacy_ce_interrupt_handler(int irq, void *arg); 146 int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset); 147 148 /* 149 * A firmware interrupt to the Host is indicated by the 150 * low bit of SCRATCH_3_ADDRESS being set. 151 */ 152 #define FW_EVENT_PENDING_REG_ADDRESS SCRATCH_3_ADDRESS 153 154 /* 155 * Typically, MSI Interrupts are used with PCIe. To force use of legacy 156 * "ABCD" PCI line interrupts rather than MSI, define 157 * FORCE_LEGACY_PCI_INTERRUPTS. 158 * Even when NOT forced, the driver may attempt to use legacy PCI interrupts 159 * MSI allocation fails 160 */ 161 #define LEGACY_INTERRUPTS(sc) ((sc)->num_msi_intrs == 0) 162 163 /* 164 * There may be some pending tx frames during platform suspend. 165 * Suspend operation should be delayed until those tx frames are 166 * transferred from the host to target. This macro specifies how 167 * long suspend thread has to sleep before checking pending tx 168 * frame count. 169 */ 170 #define OL_ATH_TX_DRAIN_WAIT_DELAY 50 /* ms */ 171 172 #define HIF_CE_DRAIN_WAIT_DELAY 10 /* ms */ 173 /* 174 * Wait time (in unit of OL_ATH_TX_DRAIN_WAIT_DELAY) for pending 175 * tx frame completion before suspend. Refer: hif_pci_suspend() 176 */ 177 #ifndef QCA_WIFI_3_0_EMU 178 #define OL_ATH_TX_DRAIN_WAIT_CNT 10 179 #else 180 #define OL_ATH_TX_DRAIN_WAIT_CNT 60 181 #endif 182 183 #ifdef FEATURE_RUNTIME_PM 184 #include <linux/pm_runtime.h> 185 186 static inline int hif_pm_request_resume(struct device *dev) 187 { 188 return pm_request_resume(dev); 189 } 190 static inline int __hif_pm_runtime_get(struct device *dev) 191 { 192 return pm_runtime_get(dev); 193 } 194 195 static inline int hif_pm_runtime_put_auto(struct device *dev) 196 { 197 return pm_runtime_put_autosuspend(dev); 198 } 199 200 static inline void hif_pm_runtime_mark_last_busy(struct device *dev) 201 { 202 pm_runtime_mark_last_busy(dev); 203 } 204 205 static inline int hif_pm_runtime_resume(struct device *dev) 206 { 207 return pm_runtime_resume(dev); 208 } 209 #else 210 static inline void hif_pm_runtime_mark_last_busy(struct device *dev) { } 211 #endif /* FEATURE_RUNTIME_PM */ 212 #endif /* __ATH_PCI_H__ */ 213