hal_generic_api.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright (c) 2016-2021 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. #ifndef _HAL_GENERIC_API_H_
  19. #define _HAL_GENERIC_API_H_
  20. #include <hal_rx.h>
  21. /**
  22. * hal_get_radiotap_he_gi_ltf() - Convert HE ltf and GI value
  23. * from stats enum to radiotap enum
  24. * @he_gi: HE GI value used in stats
  25. * @he_ltf: HE LTF value used in stats
  26. *
  27. * Return: void
  28. */
  29. static inline void hal_get_radiotap_he_gi_ltf(uint16_t *he_gi, uint16_t *he_ltf)
  30. {
  31. switch (*he_gi) {
  32. case HE_GI_0_8:
  33. *he_gi = HE_GI_RADIOTAP_0_8;
  34. break;
  35. case HE_GI_1_6:
  36. *he_gi = HE_GI_RADIOTAP_1_6;
  37. break;
  38. case HE_GI_3_2:
  39. *he_gi = HE_GI_RADIOTAP_3_2;
  40. break;
  41. default:
  42. *he_gi = HE_GI_RADIOTAP_RESERVED;
  43. }
  44. switch (*he_ltf) {
  45. case HE_LTF_1_X:
  46. *he_ltf = HE_LTF_RADIOTAP_1_X;
  47. break;
  48. case HE_LTF_2_X:
  49. *he_ltf = HE_LTF_RADIOTAP_2_X;
  50. break;
  51. case HE_LTF_4_X:
  52. *he_ltf = HE_LTF_RADIOTAP_4_X;
  53. break;
  54. default:
  55. *he_ltf = HE_LTF_RADIOTAP_UNKNOWN;
  56. }
  57. }
  58. /* channel number to freq conversion */
  59. #define CHANNEL_NUM_14 14
  60. #define CHANNEL_NUM_15 15
  61. #define CHANNEL_NUM_27 27
  62. #define CHANNEL_NUM_35 35
  63. #define CHANNEL_NUM_182 182
  64. #define CHANNEL_NUM_197 197
  65. #define CHANNEL_FREQ_2484 2484
  66. #define CHANNEL_FREQ_2407 2407
  67. #define CHANNEL_FREQ_2512 2512
  68. #define CHANNEL_FREQ_5000 5000
  69. #define CHANNEL_FREQ_5950 5950
  70. #define CHANNEL_FREQ_4000 4000
  71. #define CHANNEL_FREQ_5150 5150
  72. #define CHANNEL_FREQ_5920 5920
  73. #define CHANNEL_FREQ_5935 5935
  74. #define FREQ_MULTIPLIER_CONST_5MHZ 5
  75. #define FREQ_MULTIPLIER_CONST_20MHZ 20
  76. /**
  77. * hal_rx_radiotap_num_to_freq() - Get frequency from chan number
  78. * @chan_num - Input channel number
  79. * @center_freq - Input Channel Center frequency
  80. *
  81. * Return - Channel frequency in Mhz
  82. */
  83. static uint16_t
  84. hal_rx_radiotap_num_to_freq(uint16_t chan_num, qdf_freq_t center_freq)
  85. {
  86. if (center_freq > CHANNEL_FREQ_5920 && center_freq < CHANNEL_FREQ_5950)
  87. return CHANNEL_FREQ_5935;
  88. if (center_freq < CHANNEL_FREQ_5950) {
  89. if (chan_num == CHANNEL_NUM_14)
  90. return CHANNEL_FREQ_2484;
  91. if (chan_num < CHANNEL_NUM_14)
  92. return CHANNEL_FREQ_2407 +
  93. (chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
  94. if (chan_num < CHANNEL_NUM_27)
  95. return CHANNEL_FREQ_2512 +
  96. ((chan_num - CHANNEL_NUM_15) *
  97. FREQ_MULTIPLIER_CONST_20MHZ);
  98. if (chan_num > CHANNEL_NUM_182 &&
  99. chan_num < CHANNEL_NUM_197)
  100. return ((chan_num * FREQ_MULTIPLIER_CONST_5MHZ) +
  101. CHANNEL_FREQ_4000);
  102. return CHANNEL_FREQ_5000 +
  103. (chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
  104. } else {
  105. return CHANNEL_FREQ_5950 +
  106. (chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
  107. }
  108. }
  109. /**
  110. * hal_get_hw_hptp_generic() - Get HW head and tail pointer value for any ring
  111. * @hal_soc: Opaque HAL SOC handle
  112. * @hal_ring: Source ring pointer
  113. * @headp: Head Pointer
  114. * @tailp: Tail Pointer
  115. * @ring: Ring type
  116. *
  117. * Return: Update tail pointer and head pointer in arguments.
  118. */
  119. static inline
  120. void hal_get_hw_hptp_generic(struct hal_soc *hal_soc,
  121. hal_ring_handle_t hal_ring_hdl,
  122. uint32_t *headp, uint32_t *tailp,
  123. uint8_t ring)
  124. {
  125. struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl;
  126. struct hal_hw_srng_config *ring_config;
  127. enum hal_ring_type ring_type = (enum hal_ring_type)ring;
  128. if (!hal_soc || !srng) {
  129. QDF_TRACE(QDF_MODULE_ID_HAL, QDF_TRACE_LEVEL_ERROR,
  130. "%s: Context is Null", __func__);
  131. return;
  132. }
  133. ring_config = HAL_SRNG_CONFIG(hal_soc, ring_type);
  134. if (!ring_config->lmac_ring) {
  135. if (srng->ring_dir == HAL_SRNG_SRC_RING) {
  136. *headp = SRNG_SRC_REG_READ(srng, HP);
  137. *tailp = SRNG_SRC_REG_READ(srng, TP);
  138. } else {
  139. *headp = SRNG_DST_REG_READ(srng, HP);
  140. *tailp = SRNG_DST_REG_READ(srng, TP);
  141. }
  142. }
  143. }
  144. #if defined(WBM_IDLE_LSB_WRITE_CONFIRM_WAR)
  145. /**
  146. * hal_wbm_idle_lsb_write_confirm() - Check and update WBM_IDLE_LINK ring LSB
  147. * @srng: srng handle
  148. *
  149. * Return: None
  150. */
  151. static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng)
  152. {
  153. if (srng->ring_id == HAL_SRNG_WBM_IDLE_LINK) {
  154. while (SRNG_SRC_REG_READ(srng, BASE_LSB) !=
  155. ((unsigned int)srng->ring_base_paddr & 0xffffffff))
  156. SRNG_SRC_REG_WRITE(srng, BASE_LSB,
  157. srng->ring_base_paddr &
  158. 0xffffffff);
  159. }
  160. }
  161. #else
  162. static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng)
  163. {
  164. }
  165. #endif
  166. /**
  167. * hal_srng_src_hw_init - Private function to initialize SRNG
  168. * source ring HW
  169. * @hal_soc: HAL SOC handle
  170. * @srng: SRNG ring pointer
  171. */
  172. static inline
  173. void hal_srng_src_hw_init_generic(struct hal_soc *hal,
  174. struct hal_srng *srng)
  175. {
  176. uint32_t reg_val = 0;
  177. uint64_t tp_addr = 0;
  178. hal_debug("hw_init srng %d", srng->ring_id);
  179. if (srng->flags & HAL_SRNG_MSI_INTR) {
  180. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB,
  181. srng->msi_addr & 0xffffffff);
  182. reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR),
  183. (uint64_t)(srng->msi_addr) >> 32) |
  184. SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB,
  185. MSI1_ENABLE), 1);
  186. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
  187. SRNG_SRC_REG_WRITE(srng, MSI1_DATA,
  188. qdf_cpu_to_le32(srng->msi_data));
  189. }
  190. SRNG_SRC_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
  191. hal_wbm_idle_lsb_write_confirm(srng);
  192. reg_val = SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_BASE_ADDR_MSB),
  193. ((uint64_t)(srng->ring_base_paddr) >> 32)) |
  194. SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_SIZE),
  195. srng->entry_size * srng->num_entries);
  196. SRNG_SRC_REG_WRITE(srng, BASE_MSB, reg_val);
  197. reg_val = SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size);
  198. SRNG_SRC_REG_WRITE(srng, ID, reg_val);
  199. /**
  200. * Interrupt setup:
  201. * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
  202. * if level mode is required
  203. */
  204. reg_val = 0;
  205. /*
  206. * WAR - Hawkeye v1 has a hardware bug which requires timer value to be
  207. * programmed in terms of 1us resolution instead of 8us resolution as
  208. * given in MLD.
  209. */
  210. if (srng->intr_timer_thres_us) {
  211. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
  212. INTERRUPT_TIMER_THRESHOLD),
  213. srng->intr_timer_thres_us);
  214. /* For HK v2 this should be (srng->intr_timer_thres_us >> 3) */
  215. }
  216. if (srng->intr_batch_cntr_thres_entries) {
  217. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
  218. BATCH_COUNTER_THRESHOLD),
  219. srng->intr_batch_cntr_thres_entries *
  220. srng->entry_size);
  221. }
  222. SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val);
  223. reg_val = 0;
  224. if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
  225. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1,
  226. LOW_THRESHOLD), srng->u.src_ring.low_threshold);
  227. }
  228. SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX1, reg_val);
  229. /* As per HW team, TP_ADDR and HP_ADDR for Idle link ring should
  230. * remain 0 to avoid some WBM stability issues. Remote head/tail
  231. * pointers are not required since this ring is completely managed
  232. * by WBM HW
  233. */
  234. reg_val = 0;
  235. if (srng->ring_id != HAL_SRNG_WBM_IDLE_LINK) {
  236. tp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
  237. ((unsigned long)(srng->u.src_ring.tp_addr) -
  238. (unsigned long)(hal->shadow_rdptr_mem_vaddr)));
  239. SRNG_SRC_REG_WRITE(srng, TP_ADDR_LSB, tp_addr & 0xffffffff);
  240. SRNG_SRC_REG_WRITE(srng, TP_ADDR_MSB, tp_addr >> 32);
  241. } else {
  242. reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, RING_ID_DISABLE), 1);
  243. }
  244. /* Initilaize head and tail pointers to indicate ring is empty */
  245. SRNG_SRC_REG_WRITE(srng, HP, 0);
  246. SRNG_SRC_REG_WRITE(srng, TP, 0);
  247. *(srng->u.src_ring.tp_addr) = 0;
  248. reg_val |= ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ?
  249. SRNG_SM(SRNG_SRC_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) |
  250. ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ?
  251. SRNG_SM(SRNG_SRC_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) |
  252. ((srng->flags & HAL_SRNG_MSI_SWAP) ?
  253. SRNG_SM(SRNG_SRC_FLD(MISC, MSI_SWAP_BIT), 1) : 0);
  254. /* Loop count is not used for SRC rings */
  255. reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, LOOPCNT_DISABLE), 1);
  256. /*
  257. * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1);
  258. * todo: update fw_api and replace with above line
  259. * (when SRNG_ENABLE field for the MISC register is available in fw_api)
  260. * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC)
  261. */
  262. reg_val |= 0x40;
  263. SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
  264. }
  265. /**
  266. * hal_srng_dst_hw_init - Private function to initialize SRNG
  267. * destination ring HW
  268. * @hal_soc: HAL SOC handle
  269. * @srng: SRNG ring pointer
  270. */
  271. static inline
  272. void hal_srng_dst_hw_init_generic(struct hal_soc *hal,
  273. struct hal_srng *srng)
  274. {
  275. uint32_t reg_val = 0;
  276. uint64_t hp_addr = 0;
  277. hal_debug("hw_init srng %d", srng->ring_id);
  278. if (srng->flags & HAL_SRNG_MSI_INTR) {
  279. SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB,
  280. srng->msi_addr & 0xffffffff);
  281. reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR),
  282. (uint64_t)(srng->msi_addr) >> 32) |
  283. SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB,
  284. MSI1_ENABLE), 1);
  285. SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
  286. SRNG_DST_REG_WRITE(srng, MSI1_DATA,
  287. qdf_cpu_to_le32(srng->msi_data));
  288. }
  289. SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
  290. reg_val = SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_BASE_ADDR_MSB),
  291. ((uint64_t)(srng->ring_base_paddr) >> 32)) |
  292. SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_SIZE),
  293. srng->entry_size * srng->num_entries);
  294. SRNG_DST_REG_WRITE(srng, BASE_MSB, reg_val);
  295. reg_val = SRNG_SM(SRNG_DST_FLD(ID, RING_ID), srng->ring_id) |
  296. SRNG_SM(SRNG_DST_FLD(ID, ENTRY_SIZE), srng->entry_size);
  297. SRNG_DST_REG_WRITE(srng, ID, reg_val);
  298. /**
  299. * Interrupt setup:
  300. * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
  301. * if level mode is required
  302. */
  303. reg_val = 0;
  304. if (srng->intr_timer_thres_us) {
  305. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
  306. INTERRUPT_TIMER_THRESHOLD),
  307. srng->intr_timer_thres_us >> 3);
  308. }
  309. if (srng->intr_batch_cntr_thres_entries) {
  310. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
  311. BATCH_COUNTER_THRESHOLD),
  312. srng->intr_batch_cntr_thres_entries *
  313. srng->entry_size);
  314. }
  315. SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val);
  316. hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
  317. ((unsigned long)(srng->u.dst_ring.hp_addr) -
  318. (unsigned long)(hal->shadow_rdptr_mem_vaddr)));
  319. SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, hp_addr & 0xffffffff);
  320. SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, hp_addr >> 32);
  321. /* Initilaize head and tail pointers to indicate ring is empty */
  322. SRNG_DST_REG_WRITE(srng, HP, 0);
  323. SRNG_DST_REG_WRITE(srng, TP, 0);
  324. *(srng->u.dst_ring.hp_addr) = 0;
  325. reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ?
  326. SRNG_SM(SRNG_DST_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) |
  327. ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ?
  328. SRNG_SM(SRNG_DST_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) |
  329. ((srng->flags & HAL_SRNG_MSI_SWAP) ?
  330. SRNG_SM(SRNG_DST_FLD(MISC, MSI_SWAP_BIT), 1) : 0);
  331. /*
  332. * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1);
  333. * todo: update fw_api and replace with above line
  334. * (when SRNG_ENABLE field for the MISC register is available in fw_api)
  335. * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC)
  336. */
  337. reg_val |= 0x40;
  338. SRNG_DST_REG_WRITE(srng, MISC, reg_val);
  339. }
  340. #endif /* HAL_GENERIC_API_H_ */