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 }; 161 162 bool hif_pci_targ_is_present(struct hif_softc *scn, void *__iomem *mem); 163 int hif_configure_irq(struct hif_softc *sc); 164 void hif_pci_cancel_deferred_target_sleep(struct hif_softc *scn); 165 void wlan_tasklet(unsigned long data); 166 irqreturn_t hif_pci_legacy_ce_interrupt_handler(int irq, void *arg); 167 int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset); 168 169 /* 170 * A firmware interrupt to the Host is indicated by the 171 * low bit of SCRATCH_3_ADDRESS being set. 172 */ 173 #define FW_EVENT_PENDING_REG_ADDRESS SCRATCH_3_ADDRESS 174 175 /* 176 * Typically, MSI Interrupts are used with PCIe. To force use of legacy 177 * "ABCD" PCI line interrupts rather than MSI, define 178 * FORCE_LEGACY_PCI_INTERRUPTS. 179 * Even when NOT forced, the driver may attempt to use legacy PCI interrupts 180 * MSI allocation fails 181 */ 182 #define LEGACY_INTERRUPTS(sc) ((sc)->num_msi_intrs == 0) 183 184 /* 185 * There may be some pending tx frames during platform suspend. 186 * Suspend operation should be delayed until those tx frames are 187 * transferred from the host to target. This macro specifies how 188 * long suspend thread has to sleep before checking pending tx 189 * frame count. 190 */ 191 #define OL_ATH_TX_DRAIN_WAIT_DELAY 50 /* ms */ 192 193 #define HIF_CE_DRAIN_WAIT_DELAY 10 /* ms */ 194 /* 195 * Wait time (in unit of OL_ATH_TX_DRAIN_WAIT_DELAY) for pending 196 * tx frame completion before suspend. Refer: hif_pci_suspend() 197 */ 198 #ifndef QCA_WIFI_3_0_EMU 199 #define OL_ATH_TX_DRAIN_WAIT_CNT 10 200 #else 201 #define OL_ATH_TX_DRAIN_WAIT_CNT 60 202 #endif 203 204 #ifdef FORCE_WAKE 205 /** 206 * hif_print_pci_stats() - Display HIF PCI stats 207 * @pci_scn: HIF pci handle 208 * 209 * Return: None 210 */ 211 void hif_print_pci_stats(struct hif_pci_softc *pci_scn); 212 #else 213 static inline 214 void hif_print_pci_stats(struct hif_pci_softc *pci_scn) 215 { 216 } 217 #endif /* FORCE_WAKE */ 218 #ifdef HIF_BUS_LOG_INFO 219 bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data, 220 unsigned int *offset); 221 #else 222 static inline 223 bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data, 224 unsigned int *offset) 225 { 226 return false; 227 } 228 #endif 229 #endif /* __ATH_PCI_H__ */ 230