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