hif_io32.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2021-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. #ifndef __HIF_IO32_H__
  20. #define __HIF_IO32_H__
  21. #include <linux/io.h>
  22. #include "hif.h"
  23. #include "hif_main.h"
  24. #include "pld_common.h"
  25. /* Device memory is 32MB but bar size is only 1MB.
  26. * Register remapping logic is used to access 32MB device memory.
  27. * 0-512KB : Fixed address, 512KB-1MB : remapped address.
  28. * Use PCIE_REMAP_1M_BAR_CTRL register to set window
  29. * for pcie based wifi chipsets.
  30. */
  31. #define MAX_UNWINDOWED_ADDRESS 0x80000
  32. #if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \
  33. defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6750) || \
  34. defined(QCA_WIFI_QCN6432) || \
  35. defined(QCA_WIFI_QCN9224) || defined(QCA_WIFI_KIWI)
  36. #define WINDOW_ENABLE_BIT 0x40000000
  37. #else
  38. #define WINDOW_ENABLE_BIT 0x80000000
  39. #endif
  40. #ifdef QCA_WIFI_PEACH
  41. #define WINDOW_REG_ADDRESS 0x3278
  42. #else
  43. #define WINDOW_REG_ADDRESS 0x310C
  44. #endif
  45. #define WINDOW_SHIFT 19
  46. #define WINDOW_VALUE_MASK 0x3F
  47. #define WINDOW_START MAX_UNWINDOWED_ADDRESS
  48. #define WINDOW_RANGE_MASK 0x7FFFF
  49. #if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI)
  50. static inline
  51. void hif_write32_mb_reg_window(void *sc,
  52. void __iomem *addr, uint32_t value);
  53. static inline
  54. uint32_t hif_read32_mb_reg_window(void *sc,
  55. void __iomem *addr);
  56. #define hif_read32_mb(scn, addr) \
  57. hif_read32_mb_reg_window((void *)scn, \
  58. (void __iomem *)addr)
  59. #define hif_write32_mb(scn, addr, value) \
  60. hif_write32_mb_reg_window((void *)scn, \
  61. (void __iomem *)addr, value)
  62. #else
  63. #define hif_read32_mb(scn, addr) ioread32((void __iomem *)addr)
  64. #define hif_write32_mb(scn, addr, value) \
  65. iowrite32((u32)(value), (void __iomem *)(addr))
  66. #endif
  67. #define Q_TARGET_ACCESS_BEGIN(scn) \
  68. hif_target_sleep_state_adjust(scn, false, true)
  69. #define Q_TARGET_ACCESS_END(scn) \
  70. hif_target_sleep_state_adjust(scn, true, false)
  71. #define TARGET_REGISTER_ACCESS_ALLOWED(scn)\
  72. hif_is_target_register_access_allowed(scn)
  73. /*
  74. * A_TARGET_ACCESS_LIKELY will not wait for the target to wake up before
  75. * continuing execution. Because A_TARGET_ACCESS_LIKELY does not guarantee
  76. * that the target is awake before continuing, Q_TARGET_ACCESS macros must
  77. * protect the actual target access. Since Q_TARGET_ACCESS protect the actual
  78. * target access, A_TARGET_ACCESS_LIKELY hints are optional.
  79. *
  80. * To ignore "LIKELY" hints, set CONFIG_TARGET_ACCESS_LIKELY to 0
  81. * (slightly worse performance, less power)
  82. *
  83. * To use "LIKELY" hints, set CONFIG_TARGET_ACCESS_LIKELY to 1
  84. * (slightly better performance, more power)
  85. *
  86. * note: if a bus doesn't use hif_target_sleep_state_adjust, this will have
  87. * no impact.
  88. */
  89. #define CONFIG_TARGET_ACCESS_LIKELY 0
  90. #if CONFIG_TARGET_ACCESS_LIKELY
  91. #define A_TARGET_ACCESS_LIKELY(scn) \
  92. hif_target_sleep_state_adjust(scn, false, false)
  93. #define A_TARGET_ACCESS_UNLIKELY(scn) \
  94. hif_target_sleep_state_adjust(scn, true, false)
  95. #else /* CONFIG_ATH_PCIE_ACCESS_LIKELY */
  96. #define A_TARGET_ACCESS_LIKELY(scn) \
  97. do { \
  98. unsigned long unused = (unsigned long)(scn); \
  99. unused = unused; \
  100. } while (0)
  101. #define A_TARGET_ACCESS_UNLIKELY(scn) \
  102. do { \
  103. unsigned long unused = (unsigned long)(scn); \
  104. unused = unused; \
  105. } while (0)
  106. #endif /* CONFIG_ATH_PCIE_ACCESS_LIKELY */
  107. #ifdef HIF_PCI
  108. #include "hif_io32_pci.h"
  109. #endif
  110. #ifdef HIF_SNOC
  111. #include "hif_io32_snoc.h"
  112. #endif
  113. #ifdef HIF_IPCI
  114. #include "hif_io32_ipci.h"
  115. #endif
  116. #ifdef HIF_IPCI
  117. /**
  118. * hif_target_access_allowed(): Check if target access is allowed
  119. *
  120. * @scn: HIF handler
  121. *
  122. * Return: True if access is allowed else False
  123. */
  124. static inline
  125. bool hif_target_access_allowed(struct hif_softc *scn)
  126. {
  127. return !(scn->recovery);
  128. }
  129. #define TARGET_ACCESS_ALLOWED(scn) \
  130. hif_target_access_allowed(scn)
  131. #else
  132. #define TARGET_ACCESS_ALLOWED(scn) (1)
  133. #endif
  134. #if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI)
  135. #include "qdf_lock.h"
  136. #include "qdf_util.h"
  137. /**
  138. * hif_reg_write_result_check() - check register writing result
  139. * @sc: hif pcie context
  140. * @offset: register offset to read
  141. * @exp_val: the expected value of register
  142. *
  143. * Return: none
  144. */
  145. static inline void hif_reg_write_result_check(struct hif_pci_softc *sc,
  146. uint32_t offset,
  147. uint32_t exp_val)
  148. {
  149. uint32_t value;
  150. value = qdf_ioread32(sc->mem + offset);
  151. if (exp_val != value) {
  152. hif_err("Reg write failed. write val 0x%x read val 0x%x offset 0x%x",
  153. exp_val,
  154. value,
  155. offset);
  156. }
  157. }
  158. #ifdef PCIE_REG_WINDOW_LOCAL_NO_CACHE
  159. /**
  160. * hif_select_window_confirm(): Update the register window
  161. * @sc: HIF pci handle
  162. * @offset: reg offset to read from or write to
  163. *
  164. * Calculate the window using the offset provided and update
  165. * the window reg value accordingly for windowed read/write reg
  166. * access.
  167. * Read back to make sure the window is written to the register.
  168. * Return: None
  169. */
  170. static inline
  171. void hif_select_window_confirm(struct hif_pci_softc *sc, uint32_t offset)
  172. {
  173. uint32_t window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK;
  174. qdf_iowrite32(sc->mem + WINDOW_REG_ADDRESS,
  175. WINDOW_ENABLE_BIT | window);
  176. sc->register_window = window;
  177. hif_reg_write_result_check(sc, WINDOW_REG_ADDRESS,
  178. WINDOW_ENABLE_BIT | window);
  179. }
  180. #else /* PCIE_REG_WINDOW_LOCAL_NO_CACHE */
  181. static inline
  182. void hif_select_window_confirm(struct hif_pci_softc *sc, uint32_t offset)
  183. {
  184. uint32_t window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK;
  185. if (window != sc->register_window) {
  186. qdf_iowrite32(sc->mem + WINDOW_REG_ADDRESS,
  187. WINDOW_ENABLE_BIT | window);
  188. sc->register_window = window;
  189. hif_reg_write_result_check(sc, WINDOW_REG_ADDRESS,
  190. WINDOW_ENABLE_BIT | window);
  191. }
  192. }
  193. #endif /* PCIE_REG_WINDOW_LOCAL_NO_CACHE */
  194. #ifdef WINDOW_REG_PLD_LOCK_ENABLE
  195. /**
  196. * hif_lock_reg_access() - Lock window register access spinlock
  197. * @sc: HIF handle
  198. * @flags: variable pointer to save CPU states
  199. *
  200. * Lock register window spinlock
  201. *
  202. * Return: void
  203. */
  204. static inline void hif_lock_reg_access(struct hif_pci_softc *sc,
  205. unsigned long *flags)
  206. {
  207. pld_lock_reg_window(sc->dev, flags);
  208. }
  209. /**
  210. * hif_unlock_reg_access() - Unlock window register access spinlock
  211. * @sc: HIF handle
  212. * @flags: variable pointer to save CPU states
  213. *
  214. * Unlock register window spinlock
  215. *
  216. * Return: void
  217. */
  218. static inline void hif_unlock_reg_access(struct hif_pci_softc *sc,
  219. unsigned long *flags)
  220. {
  221. pld_unlock_reg_window(sc->dev, flags);
  222. }
  223. #else
  224. static inline void hif_lock_reg_access(struct hif_pci_softc *sc,
  225. unsigned long *flags)
  226. {
  227. qdf_spin_lock_irqsave(&sc->register_access_lock);
  228. }
  229. static inline void hif_unlock_reg_access(struct hif_pci_softc *sc,
  230. unsigned long *flags)
  231. {
  232. qdf_spin_unlock_irqrestore(&sc->register_access_lock);
  233. }
  234. #endif
  235. /*
  236. * note1: WINDOW_RANGE_MASK = (1 << WINDOW_SHIFT) -1
  237. * note2: 1 << WINDOW_SHIFT = MAX_UNWINDOWED_ADDRESS
  238. * note3: WINDOW_VALUE_MASK = big enough that trying to write past that window
  239. * would be a bug
  240. */
  241. static inline void hif_write32_mb_reg_window(void *scn,
  242. void __iomem *addr, uint32_t value)
  243. {
  244. struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
  245. uint32_t offset = addr - sc->mem;
  246. unsigned long flags;
  247. if (!sc->use_register_windowing ||
  248. offset < MAX_UNWINDOWED_ADDRESS) {
  249. qdf_iowrite32(addr, value);
  250. } else {
  251. hif_lock_reg_access(sc, &flags);
  252. hif_select_window_confirm(sc, offset);
  253. qdf_iowrite32(sc->mem + WINDOW_START +
  254. (offset & WINDOW_RANGE_MASK), value);
  255. hif_unlock_reg_access(sc, &flags);
  256. }
  257. }
  258. static inline uint32_t hif_read32_mb_reg_window(void *scn, void __iomem *addr)
  259. {
  260. struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
  261. uint32_t ret;
  262. uint32_t offset = addr - sc->mem;
  263. unsigned long flags;
  264. if (!sc->use_register_windowing ||
  265. offset < MAX_UNWINDOWED_ADDRESS) {
  266. return qdf_ioread32(addr);
  267. }
  268. hif_lock_reg_access(sc, &flags);
  269. hif_select_window_confirm(sc, offset);
  270. ret = qdf_ioread32(sc->mem + WINDOW_START +
  271. (offset & WINDOW_RANGE_MASK));
  272. hif_unlock_reg_access(sc, &flags);
  273. return ret;
  274. }
  275. #endif
  276. #if defined(HIF_HAL_REG_ACCESS_SUPPORT)
  277. #define A_TARGET_READ(scn, offset) \
  278. hif_reg_window_read(scn, offset)
  279. #define A_TARGET_WRITE(scn, offset, value) \
  280. hif_reg_window_write(scn, offset, value)
  281. #elif defined(CONFIG_IO_MEM_ACCESS_DEBUG)
  282. uint32_t hif_target_read_checked(struct hif_softc *scn,
  283. uint32_t offset);
  284. void hif_target_write_checked(struct hif_softc *scn, uint32_t offset,
  285. uint32_t value);
  286. #define A_TARGET_READ(scn, offset) \
  287. hif_target_read_checked(scn, (offset))
  288. #define A_TARGET_WRITE(scn, offset, value) \
  289. hif_target_write_checked(scn, (offset), (value))
  290. #else /* CONFIG_ATH_PCIE_ACCESS_DEBUG */
  291. #define A_TARGET_READ(scn, offset) \
  292. hif_read32_mb(scn, scn->mem + (offset))
  293. #define A_TARGET_WRITE(scn, offset, value) \
  294. hif_write32_mb(scn, (scn->mem) + (offset), value)
  295. #endif
  296. #ifdef FEATURE_HIF_DELAYED_REG_WRITE
  297. #define A_TARGET_DELAYED_REG_WRITE(scn, ctrl_addr, val) \
  298. hif_delayed_reg_write(scn, ctrl_addr, val)
  299. #endif
  300. void hif_irq_enable(struct hif_softc *scn, int irq_id);
  301. void hif_irq_disable(struct hif_softc *scn, int irq_id);
  302. #endif /* __HIF_IO32_H__ */