hal_generic_api.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. /*
  2. * Copyright (c) 2016-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. #ifndef _HAL_GENERIC_API_H_
  20. #define _HAL_GENERIC_API_H_
  21. #include <hal_rx.h>
  22. #define SRNG_ENABLE_BIT 0x40
  23. #define SRNG_IDLE_STATE_BIT 0x80
  24. /**
  25. * hal_get_radiotap_he_gi_ltf() - Convert HE ltf and GI value
  26. * from stats enum to radiotap enum
  27. * @he_gi: HE GI value used in stats
  28. * @he_ltf: HE LTF value used in stats
  29. *
  30. * Return: void
  31. */
  32. static inline void hal_get_radiotap_he_gi_ltf(uint16_t *he_gi, uint16_t *he_ltf)
  33. {
  34. switch (*he_gi) {
  35. case HE_GI_0_8:
  36. *he_gi = HE_GI_RADIOTAP_0_8;
  37. break;
  38. case HE_GI_1_6:
  39. *he_gi = HE_GI_RADIOTAP_1_6;
  40. break;
  41. case HE_GI_3_2:
  42. *he_gi = HE_GI_RADIOTAP_3_2;
  43. break;
  44. default:
  45. *he_gi = HE_GI_RADIOTAP_RESERVED;
  46. }
  47. switch (*he_ltf) {
  48. case HE_LTF_1_X:
  49. *he_ltf = HE_LTF_RADIOTAP_1_X;
  50. break;
  51. case HE_LTF_2_X:
  52. *he_ltf = HE_LTF_RADIOTAP_2_X;
  53. break;
  54. case HE_LTF_4_X:
  55. *he_ltf = HE_LTF_RADIOTAP_4_X;
  56. break;
  57. default:
  58. *he_ltf = HE_LTF_RADIOTAP_UNKNOWN;
  59. }
  60. }
  61. /* channel number to freq conversion */
  62. #define CHANNEL_NUM_14 14
  63. #define CHANNEL_NUM_15 15
  64. #define CHANNEL_NUM_27 27
  65. #define CHANNEL_NUM_35 35
  66. #define CHANNEL_NUM_182 182
  67. #define CHANNEL_NUM_197 197
  68. #define CHANNEL_FREQ_2484 2484
  69. #define CHANNEL_FREQ_2407 2407
  70. #define CHANNEL_FREQ_2512 2512
  71. #define CHANNEL_FREQ_5000 5000
  72. #define CHANNEL_FREQ_5950 5950
  73. #define CHANNEL_FREQ_4000 4000
  74. #define CHANNEL_FREQ_5150 5150
  75. #define CHANNEL_FREQ_5920 5920
  76. #define CHANNEL_FREQ_5935 5935
  77. #define FREQ_MULTIPLIER_CONST_5MHZ 5
  78. #define FREQ_MULTIPLIER_CONST_20MHZ 20
  79. /**
  80. * hal_rx_radiotap_num_to_freq() - Get frequency from chan number
  81. * @chan_num: Input channel number
  82. * @center_freq: Input Channel Center frequency
  83. *
  84. * Return - Channel frequency in Mhz
  85. */
  86. static inline uint16_t
  87. hal_rx_radiotap_num_to_freq(uint16_t chan_num, qdf_freq_t center_freq)
  88. {
  89. if (center_freq > CHANNEL_FREQ_5920 && center_freq < CHANNEL_FREQ_5950)
  90. return CHANNEL_FREQ_5935;
  91. if (center_freq < CHANNEL_FREQ_5950) {
  92. if (chan_num == CHANNEL_NUM_14)
  93. return CHANNEL_FREQ_2484;
  94. if (chan_num < CHANNEL_NUM_14)
  95. return CHANNEL_FREQ_2407 +
  96. (chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
  97. if (chan_num < CHANNEL_NUM_27)
  98. return CHANNEL_FREQ_2512 +
  99. ((chan_num - CHANNEL_NUM_15) *
  100. FREQ_MULTIPLIER_CONST_20MHZ);
  101. if (chan_num > CHANNEL_NUM_182 &&
  102. chan_num < CHANNEL_NUM_197)
  103. return ((chan_num * FREQ_MULTIPLIER_CONST_5MHZ) +
  104. CHANNEL_FREQ_4000);
  105. return CHANNEL_FREQ_5000 +
  106. (chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
  107. } else {
  108. return CHANNEL_FREQ_5950 +
  109. (chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
  110. }
  111. }
  112. /**
  113. * hal_get_hw_hptp_generic() - Get HW head and tail pointer value for any ring
  114. * @hal_soc: Opaque HAL SOC handle
  115. * @hal_ring_hdl: Source ring pointer
  116. * @headp: Head Pointer
  117. * @tailp: Tail Pointer
  118. * @ring: Ring type
  119. *
  120. * Return: Update tail pointer and head pointer in arguments.
  121. */
  122. static inline
  123. void hal_get_hw_hptp_generic(struct hal_soc *hal_soc,
  124. hal_ring_handle_t hal_ring_hdl,
  125. uint32_t *headp, uint32_t *tailp,
  126. uint8_t ring)
  127. {
  128. struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl;
  129. struct hal_hw_srng_config *ring_config;
  130. enum hal_ring_type ring_type = (enum hal_ring_type)ring;
  131. if (!hal_soc || !srng) {
  132. QDF_TRACE(QDF_MODULE_ID_HAL, QDF_TRACE_LEVEL_ERROR,
  133. "%s: Context is Null", __func__);
  134. return;
  135. }
  136. ring_config = HAL_SRNG_CONFIG(hal_soc, ring_type);
  137. if (!ring_config->lmac_ring) {
  138. if (srng->ring_dir == HAL_SRNG_SRC_RING) {
  139. *headp = SRNG_SRC_REG_READ(srng, HP);
  140. *tailp = SRNG_SRC_REG_READ(srng, TP);
  141. } else {
  142. *headp = SRNG_DST_REG_READ(srng, HP);
  143. *tailp = SRNG_DST_REG_READ(srng, TP);
  144. }
  145. }
  146. }
  147. #ifdef DP_UMAC_HW_RESET_SUPPORT
  148. /**
  149. * hal_srng_src_hw_write_cons_prefetch_timer() - Write cons prefetch timer reg
  150. * @srng: srng handle
  151. * @value: value to set
  152. *
  153. * Return: None
  154. */
  155. static inline
  156. void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng,
  157. uint32_t value)
  158. {
  159. SRNG_SRC_REG_WRITE(srng, CONSUMER_PREFETCH_TIMER, value);
  160. }
  161. /**
  162. * hal_srng_hw_disable_generic() - Private function to disable SRNG
  163. * source ring HW
  164. * @hal: HAL SOC handle
  165. * @srng: SRNG ring pointer
  166. */
  167. static inline
  168. void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng)
  169. {
  170. uint32_t reg_val = 0;
  171. struct hal_hw_srng_config *ring_config =
  172. HAL_SRNG_CONFIG(hal, srng->ring_type);
  173. if (ring_config->lmac_ring)
  174. return;
  175. if (srng->ring_dir == HAL_SRNG_DST_RING) {
  176. reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
  177. SRNG_DST_REG_WRITE(srng, MISC, reg_val);
  178. } else {
  179. reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
  180. SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
  181. srng->prefetch_timer =
  182. SRNG_SRC_REG_READ(srng, CONSUMER_PREFETCH_TIMER);
  183. hal_srng_src_hw_write_cons_prefetch_timer(srng, 0);
  184. }
  185. }
  186. #else
  187. static inline
  188. void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng)
  189. {
  190. }
  191. static inline
  192. void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng,
  193. uint32_t value)
  194. {
  195. }
  196. #endif
  197. #ifndef WLAN_SOFTUMAC_SUPPORT
  198. #if defined(WBM_IDLE_LSB_WRITE_CONFIRM_WAR)
  199. /**
  200. * hal_wbm_idle_lsb_write_confirm() - Check and update WBM_IDLE_LINK ring LSB
  201. * @srng: srng handle
  202. *
  203. * Return: None
  204. */
  205. static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng)
  206. {
  207. if (srng->ring_id == HAL_SRNG_WBM_IDLE_LINK) {
  208. while (SRNG_SRC_REG_READ(srng, BASE_LSB) !=
  209. ((unsigned int)srng->ring_base_paddr & 0xffffffff))
  210. SRNG_SRC_REG_WRITE(srng, BASE_LSB,
  211. srng->ring_base_paddr &
  212. 0xffffffff);
  213. }
  214. }
  215. #else
  216. static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng)
  217. {
  218. }
  219. #endif
  220. /**
  221. * hal_srng_src_hw_init_generic() - Private function to initialize SRNG
  222. * source ring HW
  223. * @hal: HAL SOC handle
  224. * @srng: SRNG ring pointer
  225. * @idle_check: Check if ring is idle
  226. * @idx: ring index
  227. */
  228. static inline
  229. void hal_srng_src_hw_init_generic(struct hal_soc *hal,
  230. struct hal_srng *srng, bool idle_check,
  231. uint32_t idx)
  232. {
  233. uint32_t reg_val = 0;
  234. uint64_t tp_addr = 0;
  235. hal_debug("hw_init srng %d", srng->ring_id);
  236. if (idle_check) {
  237. reg_val = SRNG_SRC_REG_READ(srng, MISC);
  238. if (!(reg_val & SRNG_IDLE_STATE_BIT)) {
  239. hal_err("ring_id %d not in idle state", srng->ring_id);
  240. qdf_assert_always(0);
  241. }
  242. hal_srng_src_hw_write_cons_prefetch_timer(srng,
  243. srng->prefetch_timer);
  244. } else {
  245. reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
  246. SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
  247. }
  248. reg_val = 0;
  249. if (srng->flags & HAL_SRNG_MSI_INTR) {
  250. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB,
  251. srng->msi_addr & 0xffffffff);
  252. reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR),
  253. (uint64_t)(srng->msi_addr) >> 32) |
  254. SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB,
  255. MSI1_ENABLE), 1);
  256. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
  257. SRNG_SRC_REG_WRITE(srng, MSI1_DATA,
  258. qdf_cpu_to_le32(srng->msi_data));
  259. }
  260. SRNG_SRC_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
  261. hal_wbm_idle_lsb_write_confirm(srng);
  262. reg_val = SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_BASE_ADDR_MSB),
  263. ((uint64_t)(srng->ring_base_paddr) >> 32)) |
  264. SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_SIZE),
  265. srng->entry_size * srng->num_entries);
  266. SRNG_SRC_REG_WRITE(srng, BASE_MSB, reg_val);
  267. reg_val = SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size);
  268. SRNG_SRC_REG_WRITE(srng, ID, reg_val);
  269. /**
  270. * Interrupt setup:
  271. * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
  272. * if level mode is required
  273. */
  274. reg_val = 0;
  275. /*
  276. * WAR - Hawkeye v1 has a hardware bug which requires timer value to be
  277. * programmed in terms of 1us resolution instead of 8us resolution as
  278. * given in MLD.
  279. */
  280. if (srng->intr_timer_thres_us) {
  281. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
  282. INTERRUPT_TIMER_THRESHOLD),
  283. srng->intr_timer_thres_us >> 3);
  284. /* For HK v2 this should be (srng->intr_timer_thres_us >> 3) */
  285. }
  286. if (srng->intr_batch_cntr_thres_entries) {
  287. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
  288. BATCH_COUNTER_THRESHOLD),
  289. srng->intr_batch_cntr_thres_entries *
  290. srng->entry_size);
  291. }
  292. SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val);
  293. reg_val = 0;
  294. if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
  295. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1,
  296. LOW_THRESHOLD), srng->u.src_ring.low_threshold);
  297. }
  298. SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX1, reg_val);
  299. /* As per HW team, TP_ADDR and HP_ADDR for Idle link ring should
  300. * remain 0 to avoid some WBM stability issues. Remote head/tail
  301. * pointers are not required since this ring is completely managed
  302. * by WBM HW
  303. */
  304. reg_val = 0;
  305. if (srng->ring_id != HAL_SRNG_WBM_IDLE_LINK) {
  306. tp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
  307. ((unsigned long)(srng->u.src_ring.tp_addr) -
  308. (unsigned long)(hal->shadow_rdptr_mem_vaddr)));
  309. SRNG_SRC_REG_WRITE(srng, TP_ADDR_LSB, tp_addr & 0xffffffff);
  310. SRNG_SRC_REG_WRITE(srng, TP_ADDR_MSB, tp_addr >> 32);
  311. } else {
  312. reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, RING_ID_DISABLE), 1);
  313. }
  314. /* Initilaize head and tail pointers to indicate ring is empty */
  315. SRNG_SRC_REG_WRITE(srng, HP, idx * srng->entry_size);
  316. SRNG_SRC_REG_WRITE(srng, TP, idx * srng->entry_size);
  317. *srng->u.src_ring.tp_addr = idx * srng->entry_size;
  318. srng->u.src_ring.hp = idx * srng->entry_size;
  319. reg_val |= ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ?
  320. SRNG_SM(SRNG_SRC_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) |
  321. ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ?
  322. SRNG_SM(SRNG_SRC_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) |
  323. ((srng->flags & HAL_SRNG_MSI_SWAP) ?
  324. SRNG_SM(SRNG_SRC_FLD(MISC, MSI_SWAP_BIT), 1) : 0);
  325. /* Loop count is not used for SRC rings */
  326. reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, LOOPCNT_DISABLE), 1);
  327. /*
  328. * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1);
  329. * todo: update fw_api and replace with above line
  330. * (when SRNG_ENABLE field for the MISC register is available in fw_api)
  331. * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC)
  332. */
  333. reg_val |= SRNG_ENABLE_BIT;
  334. SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
  335. }
  336. #ifdef WLAN_FEATURE_NEAR_FULL_IRQ
  337. /**
  338. * hal_srng_dst_msi2_setup() - Configure MSI2 register for a SRNG
  339. * @srng: SRNG handle
  340. *
  341. * Return: None
  342. */
  343. static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng)
  344. {
  345. uint32_t reg_val = 0;
  346. if (srng->u.dst_ring.nf_irq_support) {
  347. SRNG_DST_REG_WRITE(srng, MSI2_BASE_LSB,
  348. srng->msi2_addr & 0xffffffff);
  349. reg_val = SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, ADDR),
  350. (uint64_t)(srng->msi2_addr) >> 32) |
  351. SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB,
  352. MSI2_ENABLE), 1);
  353. SRNG_DST_REG_WRITE(srng, MSI2_BASE_MSB, reg_val);
  354. SRNG_DST_REG_WRITE(srng, MSI2_DATA,
  355. qdf_cpu_to_le32(srng->msi2_data));
  356. }
  357. }
  358. /**
  359. * hal_srng_dst_near_full_int_setup() - Configure near-full params for SRNG
  360. * @srng: SRNG handle
  361. *
  362. * Return: None
  363. */
  364. static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng)
  365. {
  366. uint32_t reg_val = 0;
  367. if (srng->u.dst_ring.nf_irq_support) {
  368. if (srng->intr_timer_thres_us) {
  369. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP,
  370. INTERRUPT2_TIMER_THRESHOLD),
  371. srng->intr_timer_thres_us >> 3);
  372. }
  373. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP,
  374. HIGH_THRESHOLD),
  375. srng->u.dst_ring.high_thresh *
  376. srng->entry_size);
  377. }
  378. SRNG_DST_REG_WRITE(srng, PRODUCER_INT2_SETUP, reg_val);
  379. }
  380. #else
  381. static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng)
  382. {
  383. }
  384. static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng)
  385. {
  386. }
  387. #endif
  388. /**
  389. * hal_srng_dst_hw_init_generic() - Private function to initialize SRNG
  390. * destination ring HW
  391. * @hal: HAL SOC handle
  392. * @srng: SRNG ring pointer
  393. * @idle_check: Check if ring is idle
  394. * @idx: Ring index
  395. */
  396. static inline
  397. void hal_srng_dst_hw_init_generic(struct hal_soc *hal,
  398. struct hal_srng *srng, bool idle_check,
  399. uint32_t idx)
  400. {
  401. uint32_t reg_val = 0;
  402. uint64_t hp_addr = 0;
  403. hal_debug("hw_init srng %d", srng->ring_id);
  404. if (idle_check) {
  405. reg_val = SRNG_DST_REG_READ(srng, MISC);
  406. if (!(reg_val & SRNG_IDLE_STATE_BIT)) {
  407. hal_err("ring_id %d not in idle state", srng->ring_id);
  408. qdf_assert_always(0);
  409. }
  410. } else {
  411. reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
  412. SRNG_DST_REG_WRITE(srng, MISC, reg_val);
  413. }
  414. reg_val = 0;
  415. if (srng->flags & HAL_SRNG_MSI_INTR) {
  416. SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB,
  417. srng->msi_addr & 0xffffffff);
  418. reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR),
  419. (uint64_t)(srng->msi_addr) >> 32) |
  420. SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB,
  421. MSI1_ENABLE), 1);
  422. SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
  423. SRNG_DST_REG_WRITE(srng, MSI1_DATA,
  424. qdf_cpu_to_le32(srng->msi_data));
  425. hal_srng_dst_msi2_setup(srng);
  426. }
  427. SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
  428. reg_val = SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_BASE_ADDR_MSB),
  429. ((uint64_t)(srng->ring_base_paddr) >> 32)) |
  430. SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_SIZE),
  431. srng->entry_size * srng->num_entries);
  432. SRNG_DST_REG_WRITE(srng, BASE_MSB, reg_val);
  433. reg_val = SRNG_SM(SRNG_DST_FLD(ID, RING_ID), srng->ring_id) |
  434. SRNG_SM(SRNG_DST_FLD(ID, ENTRY_SIZE), srng->entry_size);
  435. SRNG_DST_REG_WRITE(srng, ID, reg_val);
  436. /**
  437. * Interrupt setup:
  438. * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
  439. * if level mode is required
  440. */
  441. reg_val = 0;
  442. if (srng->intr_timer_thres_us) {
  443. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
  444. INTERRUPT_TIMER_THRESHOLD),
  445. srng->intr_timer_thres_us >> 3);
  446. }
  447. if (srng->intr_batch_cntr_thres_entries) {
  448. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
  449. BATCH_COUNTER_THRESHOLD),
  450. srng->intr_batch_cntr_thres_entries *
  451. srng->entry_size);
  452. }
  453. SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val);
  454. /**
  455. * Near-Full Interrupt setup:
  456. * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
  457. * if level mode is required
  458. */
  459. hal_srng_dst_near_full_int_setup(srng);
  460. hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
  461. ((unsigned long)(srng->u.dst_ring.hp_addr) -
  462. (unsigned long)(hal->shadow_rdptr_mem_vaddr)));
  463. SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, hp_addr & 0xffffffff);
  464. SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, hp_addr >> 32);
  465. /* Initilaize head and tail pointers to indicate ring is empty */
  466. SRNG_DST_REG_WRITE(srng, HP, idx * srng->entry_size);
  467. SRNG_DST_REG_WRITE(srng, TP, idx * srng->entry_size);
  468. *srng->u.dst_ring.hp_addr = idx * srng->entry_size;
  469. srng->u.dst_ring.tp = idx * srng->entry_size;
  470. reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ?
  471. SRNG_SM(SRNG_DST_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) |
  472. ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ?
  473. SRNG_SM(SRNG_DST_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) |
  474. ((srng->flags & HAL_SRNG_MSI_SWAP) ?
  475. SRNG_SM(SRNG_DST_FLD(MISC, MSI_SWAP_BIT), 1) : 0);
  476. /*
  477. * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1);
  478. * todo: update fw_api and replace with above line
  479. * (when SRNG_ENABLE field for the MISC register is available in fw_api)
  480. * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC)
  481. */
  482. reg_val |= SRNG_ENABLE_BIT;
  483. SRNG_DST_REG_WRITE(srng, MISC, reg_val);
  484. }
  485. /**
  486. * hal_srng_hw_reg_offset_init_generic() - Initialize the HW srng reg offset
  487. * @hal_soc: HAL Soc handle
  488. *
  489. * Return: None
  490. */
  491. static inline void hal_srng_hw_reg_offset_init_generic(struct hal_soc *hal_soc)
  492. {
  493. int32_t *hw_reg_offset = hal_soc->hal_hw_reg_offset;
  494. /* dst */
  495. hw_reg_offset[DST_HP] = REG_OFFSET(DST, HP);
  496. hw_reg_offset[DST_TP] = REG_OFFSET(DST, TP);
  497. hw_reg_offset[DST_ID] = REG_OFFSET(DST, ID);
  498. hw_reg_offset[DST_MISC] = REG_OFFSET(DST, MISC);
  499. hw_reg_offset[DST_HP_ADDR_LSB] = REG_OFFSET(DST, HP_ADDR_LSB);
  500. hw_reg_offset[DST_HP_ADDR_MSB] = REG_OFFSET(DST, HP_ADDR_MSB);
  501. hw_reg_offset[DST_MSI1_BASE_LSB] = REG_OFFSET(DST, MSI1_BASE_LSB);
  502. hw_reg_offset[DST_MSI1_BASE_MSB] = REG_OFFSET(DST, MSI1_BASE_MSB);
  503. hw_reg_offset[DST_MSI1_DATA] = REG_OFFSET(DST, MSI1_DATA);
  504. hw_reg_offset[DST_BASE_LSB] = REG_OFFSET(DST, BASE_LSB);
  505. hw_reg_offset[DST_BASE_MSB] = REG_OFFSET(DST, BASE_MSB);
  506. hw_reg_offset[DST_PRODUCER_INT_SETUP] =
  507. REG_OFFSET(DST, PRODUCER_INT_SETUP);
  508. /* src */
  509. hw_reg_offset[SRC_HP] = REG_OFFSET(SRC, HP);
  510. hw_reg_offset[SRC_TP] = REG_OFFSET(SRC, TP);
  511. hw_reg_offset[SRC_ID] = REG_OFFSET(SRC, ID);
  512. hw_reg_offset[SRC_MISC] = REG_OFFSET(SRC, MISC);
  513. hw_reg_offset[SRC_TP_ADDR_LSB] = REG_OFFSET(SRC, TP_ADDR_LSB);
  514. hw_reg_offset[SRC_TP_ADDR_MSB] = REG_OFFSET(SRC, TP_ADDR_MSB);
  515. hw_reg_offset[SRC_MSI1_BASE_LSB] = REG_OFFSET(SRC, MSI1_BASE_LSB);
  516. hw_reg_offset[SRC_MSI1_BASE_MSB] = REG_OFFSET(SRC, MSI1_BASE_MSB);
  517. hw_reg_offset[SRC_MSI1_DATA] = REG_OFFSET(SRC, MSI1_DATA);
  518. hw_reg_offset[SRC_BASE_LSB] = REG_OFFSET(SRC, BASE_LSB);
  519. hw_reg_offset[SRC_BASE_MSB] = REG_OFFSET(SRC, BASE_MSB);
  520. hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX0] =
  521. REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0);
  522. hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX1] =
  523. REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1);
  524. #ifdef DP_UMAC_HW_RESET_SUPPORT
  525. hw_reg_offset[SRC_CONSUMER_PREFETCH_TIMER] =
  526. REG_OFFSET(SRC, CONSUMER_PREFETCH_TIMER);
  527. #endif
  528. }
  529. #else
  530. static inline
  531. void hal_srng_src_hw_init_generic(struct hal_soc *hal,
  532. struct hal_srng *srng, bool idle_check,
  533. uint32_t idx) {}
  534. static inline
  535. void hal_srng_dst_hw_init_generic(struct hal_soc *hal,
  536. struct hal_srng *srng, bool idle_check,
  537. uint32_t idx) {}
  538. #endif
  539. #ifdef FEATURE_DIRECT_LINK
  540. /**
  541. * hal_srng_set_msi_config() - Set the MSI config and enable the SRNG
  542. * @ring_hdl: srng handle
  543. * @params: ring parameters
  544. *
  545. * Return: QDF status
  546. */
  547. static inline
  548. QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl,
  549. void *params)
  550. {
  551. struct hal_srng *srng = (struct hal_srng *)ring_hdl;
  552. struct hal_srng_params *ring_params = (struct hal_srng_params *)params;
  553. uint32_t reg_val;
  554. srng->intr_timer_thres_us = ring_params->intr_timer_thres_us;
  555. srng->intr_batch_cntr_thres_entries =
  556. ring_params->intr_batch_cntr_thres_entries;
  557. srng->msi_addr = ring_params->msi_addr;
  558. srng->msi_data = ring_params->msi_data;
  559. if (!srng->msi_addr && !srng->msi_data) {
  560. if (srng->ring_dir == HAL_SRNG_SRC_RING)
  561. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, 0);
  562. else
  563. SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, 0);
  564. return QDF_STATUS_SUCCESS;
  565. }
  566. if (srng->ring_dir == HAL_SRNG_SRC_RING) {
  567. reg_val = 0;
  568. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB,
  569. srng->msi_addr & 0xffffffff);
  570. reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR),
  571. (uint64_t)(srng->msi_addr) >> 32) |
  572. SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB,
  573. MSI1_ENABLE), 1);
  574. SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
  575. SRNG_SRC_REG_WRITE(srng, MSI1_DATA,
  576. qdf_cpu_to_le32(srng->msi_data));
  577. reg_val = 0;
  578. if (srng->intr_timer_thres_us) {
  579. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
  580. INTERRUPT_TIMER_THRESHOLD),
  581. srng->intr_timer_thres_us);
  582. }
  583. if (srng->intr_batch_cntr_thres_entries) {
  584. reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
  585. BATCH_COUNTER_THRESHOLD),
  586. srng->intr_batch_cntr_thres_entries *
  587. srng->entry_size);
  588. }
  589. SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val);
  590. } else {
  591. reg_val = 0;
  592. SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB,
  593. srng->msi_addr & 0xffffffff);
  594. reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR),
  595. (uint64_t)(srng->msi_addr) >> 32) |
  596. SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB,
  597. MSI1_ENABLE), 1);
  598. SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
  599. SRNG_DST_REG_WRITE(srng, MSI1_DATA,
  600. qdf_cpu_to_le32(srng->msi_data));
  601. reg_val = 0;
  602. if (srng->intr_timer_thres_us) {
  603. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
  604. INTERRUPT_TIMER_THRESHOLD),
  605. srng->intr_timer_thres_us >> 3);
  606. }
  607. if (srng->intr_batch_cntr_thres_entries) {
  608. reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
  609. BATCH_COUNTER_THRESHOLD),
  610. srng->intr_batch_cntr_thres_entries *
  611. srng->entry_size);
  612. }
  613. SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val);
  614. }
  615. return QDF_STATUS_SUCCESS;
  616. }
  617. #else
  618. static inline
  619. QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl,
  620. void *params)
  621. {
  622. return QDF_STATUS_E_NOSUPPORT;
  623. }
  624. #endif
  625. #endif /* HAL_GENERIC_API_H_ */