gdma_hal_ahb_v2.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "soc/soc_caps.h"
  7. #include "hal/assert.h"
  8. #include "hal/gdma_hal_ahb.h"
  9. #include "hal/ahb_dma_ll.h"
  10. static gdma_hal_priv_data_t gdma_ahb_hal_priv_data = {
  11. .m2m_free_periph_mask = AHB_DMA_LL_M2M_FREE_PERIPH_ID_MASK,
  12. };
  13. void gdma_ahb_hal_start_with_desc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, intptr_t desc_base_addr)
  14. {
  15. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  16. ahb_dma_ll_rx_set_desc_addr(hal->ahb_dma_dev, chan_id, desc_base_addr);
  17. ahb_dma_ll_rx_start(hal->ahb_dma_dev, chan_id);
  18. } else {
  19. ahb_dma_ll_tx_set_desc_addr(hal->ahb_dma_dev, chan_id, desc_base_addr);
  20. ahb_dma_ll_tx_start(hal->ahb_dma_dev, chan_id);
  21. }
  22. }
  23. void gdma_ahb_hal_stop(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  24. {
  25. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  26. ahb_dma_ll_rx_stop(hal->ahb_dma_dev, chan_id);
  27. } else {
  28. ahb_dma_ll_tx_stop(hal->ahb_dma_dev, chan_id);
  29. }
  30. }
  31. void gdma_ahb_hal_append(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  32. {
  33. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  34. ahb_dma_ll_rx_restart(hal->ahb_dma_dev, chan_id);
  35. } else {
  36. ahb_dma_ll_tx_restart(hal->ahb_dma_dev, chan_id);
  37. }
  38. }
  39. void gdma_ahb_hal_reset(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  40. {
  41. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  42. ahb_dma_ll_rx_reset_channel(hal->ahb_dma_dev, chan_id);
  43. } else {
  44. ahb_dma_ll_tx_reset_channel(hal->ahb_dma_dev, chan_id);
  45. }
  46. }
  47. void gdma_ahb_hal_set_priority(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t priority)
  48. {
  49. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  50. ahb_dma_ll_rx_set_priority(hal->ahb_dma_dev, chan_id, priority);
  51. } else {
  52. ahb_dma_ll_tx_set_priority(hal->ahb_dma_dev, chan_id, priority);
  53. }
  54. }
  55. void gdma_ahb_hal_connect_peri(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, gdma_trigger_peripheral_t periph, int periph_sub_id)
  56. {
  57. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  58. ahb_dma_ll_rx_reset_channel(hal->ahb_dma_dev, chan_id); // reset channel
  59. ahb_dma_ll_rx_connect_to_periph(hal->ahb_dma_dev, chan_id, periph, periph_sub_id);
  60. } else {
  61. ahb_dma_ll_tx_reset_channel(hal->ahb_dma_dev, chan_id); // reset channel
  62. ahb_dma_ll_tx_connect_to_periph(hal->ahb_dma_dev, chan_id, periph, periph_sub_id);
  63. }
  64. }
  65. void gdma_ahb_hal_disconnect_peri(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  66. {
  67. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  68. ahb_dma_ll_rx_disconnect_from_periph(hal->ahb_dma_dev, chan_id);
  69. } else {
  70. ahb_dma_ll_tx_disconnect_from_periph(hal->ahb_dma_dev, chan_id);
  71. }
  72. }
  73. void gdma_ahb_hal_enable_burst(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_data_burst, bool en_desc_burst)
  74. {
  75. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  76. ahb_dma_ll_rx_enable_data_burst(hal->ahb_dma_dev, chan_id, en_data_burst);
  77. ahb_dma_ll_rx_enable_descriptor_burst(hal->ahb_dma_dev, chan_id, en_desc_burst);
  78. } else {
  79. ahb_dma_ll_tx_enable_data_burst(hal->ahb_dma_dev, chan_id, en_data_burst);
  80. ahb_dma_ll_tx_enable_descriptor_burst(hal->ahb_dma_dev, chan_id, en_desc_burst);
  81. }
  82. }
  83. void gdma_ahb_hal_set_strategy(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool en_owner_check, bool en_desc_write_back)
  84. {
  85. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  86. ahb_dma_ll_rx_enable_owner_check(hal->ahb_dma_dev, chan_id, en_owner_check);
  87. // RX direction always has the descriptor write-back feature enabled
  88. } else {
  89. ahb_dma_ll_tx_enable_owner_check(hal->ahb_dma_dev, chan_id, en_owner_check);
  90. ahb_dma_ll_tx_enable_auto_write_back(hal->ahb_dma_dev, chan_id, en_desc_write_back);
  91. }
  92. }
  93. void gdma_ahb_hal_enable_intr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask, bool en_or_dis)
  94. {
  95. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  96. ahb_dma_ll_rx_enable_interrupt(hal->ahb_dma_dev, chan_id, intr_event_mask, en_or_dis);
  97. } else {
  98. ahb_dma_ll_tx_enable_interrupt(hal->ahb_dma_dev, chan_id, intr_event_mask, en_or_dis);
  99. }
  100. }
  101. void gdma_ahb_hal_clear_intr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, uint32_t intr_event_mask)
  102. {
  103. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  104. ahb_dma_ll_rx_clear_interrupt_status(hal->ahb_dma_dev, chan_id, intr_event_mask);
  105. } else {
  106. ahb_dma_ll_tx_clear_interrupt_status(hal->ahb_dma_dev, chan_id, intr_event_mask);
  107. }
  108. }
  109. uint32_t gdma_ahb_hal_read_intr_status(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  110. {
  111. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  112. return ahb_dma_ll_rx_get_interrupt_status(hal->ahb_dma_dev, chan_id);
  113. } else {
  114. return ahb_dma_ll_tx_get_interrupt_status(hal->ahb_dma_dev, chan_id);
  115. }
  116. }
  117. uint32_t gdma_ahb_hal_get_intr_status_reg(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  118. {
  119. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  120. return (uint32_t)ahb_dma_ll_rx_get_interrupt_status_reg(hal->ahb_dma_dev, chan_id);
  121. } else {
  122. return (uint32_t)ahb_dma_ll_tx_get_interrupt_status_reg(hal->ahb_dma_dev, chan_id);
  123. }
  124. }
  125. uint32_t gdma_ahb_hal_get_eof_desc_addr(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, bool is_success)
  126. {
  127. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  128. if (is_success) {
  129. return ahb_dma_ll_rx_get_success_eof_desc_addr(hal->ahb_dma_dev, chan_id);
  130. }
  131. return ahb_dma_ll_rx_get_error_eof_desc_addr(hal->ahb_dma_dev, chan_id);
  132. } else {
  133. // The TX direction only has success EOF, parameter 'is_success' is ignored
  134. return ahb_dma_ll_tx_get_eof_desc_addr(hal->ahb_dma_dev, chan_id);
  135. }
  136. }
  137. #if SOC_GDMA_SUPPORT_CRC
  138. void gdma_ahb_hal_clear_crc(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  139. {
  140. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  141. ahb_dma_ll_rx_crc_clear(hal->ahb_dma_dev, chan_id);
  142. } else {
  143. ahb_dma_ll_tx_crc_clear(hal->ahb_dma_dev, chan_id);
  144. }
  145. }
  146. void gdma_ahb_hal_set_crc_poly(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir, const gdma_hal_crc_config_t *config)
  147. {
  148. uint32_t init_value = config->init_value;
  149. uint32_t crc_bit_width = config->crc_bit_width;
  150. uint32_t poly_hex = config->poly_hex;
  151. // bit matrix for parallel CRC
  152. uint32_t lfsr_matrix[crc_bit_width];
  153. uint32_t data_matrix[GDMA_LL_PARALLEL_CRC_DATA_WIDTH];
  154. uint32_t lfsr_mask = 0;
  155. uint32_t data_mask = 0;
  156. // build the parallel CRC matrix first, later we will extract the control mask from it
  157. gdma_hal_build_parallel_crc_matrix(crc_bit_width, poly_hex, GDMA_LL_PARALLEL_CRC_DATA_WIDTH,
  158. lfsr_matrix, data_matrix);
  159. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  160. ahb_dma_ll_rx_crc_set_init_value(hal->ahb_dma_dev, chan_id, init_value);
  161. ahb_dma_ll_rx_crc_set_width(hal->ahb_dma_dev, chan_id, crc_bit_width);
  162. for (uint32_t i = 0; i < crc_bit_width; i++) {
  163. // extract the control mask from the matrix, for each CRC bit
  164. data_mask = gdma_hal_get_data_mask_from_matrix(data_matrix, GDMA_LL_PARALLEL_CRC_DATA_WIDTH, i);
  165. lfsr_mask = gdma_hal_get_lfsr_mask_from_matrix(lfsr_matrix, crc_bit_width, i);
  166. ahb_dma_ll_rx_crc_set_lfsr_data_mask(hal->ahb_dma_dev, chan_id, i, lfsr_mask, data_mask, config->reverse_data_mask);
  167. ahb_dma_ll_rx_crc_latch_config(hal->ahb_dma_dev, chan_id);
  168. }
  169. } else {
  170. ahb_dma_ll_tx_crc_set_init_value(hal->ahb_dma_dev, chan_id, init_value);
  171. ahb_dma_ll_tx_crc_set_width(hal->ahb_dma_dev, chan_id, crc_bit_width);
  172. for (uint32_t i = 0; i < crc_bit_width; i++) {
  173. // extract the control mask from the matrix, for each CRC bit
  174. data_mask = gdma_hal_get_data_mask_from_matrix(data_matrix, GDMA_LL_PARALLEL_CRC_DATA_WIDTH, i);
  175. lfsr_mask = gdma_hal_get_lfsr_mask_from_matrix(lfsr_matrix, crc_bit_width, i);
  176. ahb_dma_ll_tx_crc_set_lfsr_data_mask(hal->ahb_dma_dev, chan_id, i, lfsr_mask, data_mask, config->reverse_data_mask);
  177. ahb_dma_ll_tx_crc_latch_config(hal->ahb_dma_dev, chan_id);
  178. }
  179. }
  180. }
  181. uint32_t gdma_ahb_hal_get_crc_result(gdma_hal_context_t *hal, int chan_id, gdma_channel_direction_t dir)
  182. {
  183. if (dir == GDMA_CHANNEL_DIRECTION_RX) {
  184. return ahb_dma_ll_rx_crc_get_result(hal->ahb_dma_dev, chan_id);
  185. } else {
  186. return ahb_dma_ll_tx_crc_get_result(hal->ahb_dma_dev, chan_id);
  187. }
  188. }
  189. #endif // SOC_GDMA_SUPPORT_CRC
  190. void gdma_ahb_hal_init(gdma_hal_context_t *hal, const gdma_hal_config_t *config)
  191. {
  192. hal->ahb_dma_dev = AHB_DMA_LL_GET_HW(config->group_id - GDMA_LL_AHB_GROUP_START_ID);
  193. hal->priv_data = &gdma_ahb_hal_priv_data;
  194. hal->start_with_desc = gdma_ahb_hal_start_with_desc;
  195. hal->stop = gdma_ahb_hal_stop;
  196. hal->append = gdma_ahb_hal_append;
  197. hal->reset = gdma_ahb_hal_reset;
  198. hal->set_priority = gdma_ahb_hal_set_priority;
  199. hal->connect_peri = gdma_ahb_hal_connect_peri;
  200. hal->disconnect_peri = gdma_ahb_hal_disconnect_peri;
  201. hal->enable_burst = gdma_ahb_hal_enable_burst;
  202. hal->set_strategy = gdma_ahb_hal_set_strategy;
  203. hal->enable_intr = gdma_ahb_hal_enable_intr;
  204. hal->clear_intr = gdma_ahb_hal_clear_intr;
  205. hal->read_intr_status = gdma_ahb_hal_read_intr_status;
  206. hal->get_intr_status_reg = gdma_ahb_hal_get_intr_status_reg;
  207. hal->get_eof_desc_addr = gdma_ahb_hal_get_eof_desc_addr;
  208. #if SOC_GDMA_SUPPORT_CRC
  209. hal->clear_crc = gdma_ahb_hal_clear_crc;
  210. hal->set_crc_poly = gdma_ahb_hal_set_crc_poly;
  211. hal->get_crc_result = gdma_ahb_hal_get_crc_result;
  212. #endif // SOC_GDMA_SUPPORT_CRC
  213. }