hpm_dma_drv.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * Copyright (c) 2021-2022 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #ifndef HPM_DMAV1_DRV_H
  8. #define HPM_DMAV1_DRV_H
  9. #include "hpm_common.h"
  10. #include "hpm_soc_feature.h"
  11. #include "hpm_dma_regs.h"
  12. /**
  13. *
  14. * @brief DMA driver APIs
  15. * @defgroup dma_interface DMA driver APIs
  16. * @ingroup io_interfaces
  17. * @{
  18. */
  19. #define DMA_NUM_TRANSFER_PER_BURST_1T (0U)
  20. #define DMA_NUM_TRANSFER_PER_BURST_2T (1U)
  21. #define DMA_NUM_TRANSFER_PER_BURST_4T (2U)
  22. #define DMA_NUM_TRANSFER_PER_BURST_8T (3U)
  23. #define DMA_NUM_TRANSFER_PER_BURST_16T (4U)
  24. #define DMA_NUM_TRANSFER_PER_BURST_32T (5U)
  25. #define DMA_NUM_TRANSFER_PER_BURST_64T (6U)
  26. #define DMA_NUM_TRANSFER_PER_BURST_128T (7U)
  27. #define DMA_NUM_TRANSFER_PER_BURST_256T (8U)
  28. #define DMA_NUM_TRANSFER_PER_BURST_512T (9U)
  29. #define DMA_NUM_TRANSFER_PER_BURST_1024T (10U)
  30. #define DMA_TRANSFER_WIDTH_BYTE (0U)
  31. #define DMA_TRANSFER_WIDTH_HALF_WORD (1U)
  32. #define DMA_TRANSFER_WIDTH_WORD (2U)
  33. #define DMA_TRANSFER_WIDTH_DOUBLE_WORD (3U)
  34. #define DMA_STATUS_ERROR_SHIFT (0U)
  35. #define DMA_STATUS_ABORT_SHIFT (8U)
  36. #define DMA_STATUS_TC_SHIFT (16U)
  37. #define DMA_CHANNEL_STATUS_ONGOING (1U)
  38. #define DMA_CHANNEL_STATUS_ERROR (2U)
  39. #define DMA_CHANNEL_STATUS_ABORT (4U)
  40. #define DMA_CHANNEL_STATUS_TC (8U)
  41. #define DMA_CHANNEL_IRQ_STATUS_ERROR(x) (uint32_t)(1 << (DMA_STATUS_ERROR_SHIFT + x))
  42. #define DMA_CHANNEL_IRQ_STATUS_ABORT(x) (uint32_t)(1 << (DMA_STATUS_ABORT_SHIFT + x))
  43. #define DMA_CHANNEL_IRQ_STATUS_TC(x) (uint32_t)(1 << (DMA_STATUS_TC_SHIFT + x))
  44. #define DMA_CHANNEL_IRQ_STATUS(x) (uint32_t)(DMA_CHANNEL_IRQ_STATUS_TC(x) | \
  45. DMA_CHANNEL_IRQ_STATUS_ABORT(x) | \
  46. DMA_CHANNEL_IRQ_STATUS_ERROR(x))
  47. #define DMA_CHANNEL_IRQ_STATUS_GET_ALL_TC(x) ((x) & (((0x01UL << DMA_SOC_CHANNEL_NUM) - 1) << DMA_STATUS_TC_SHIFT))
  48. #define DMA_CHANNEL_IRQ_STATUS_GET_ALL_ABORT(x) ((x) & (((0x01UL << DMA_SOC_CHANNEL_NUM) - 1) << DMA_STATUS_ABORT_SHIFT))
  49. #define DMA_CHANNEL_IRQ_STATUS_GET_ALL_ERROR(x) ((x) & (((0x01UL << DMA_SOC_CHANNEL_NUM) - 1) << DMA_STATUS_ERROR_SHIFT))
  50. #define DMA_HANDSHAKE_MODE_HANDSHAKE (1U)
  51. #define DMA_HANDSHAKE_MODE_NORMAL (0U)
  52. #define DMA_ADDRESS_CONTROL_INCREMENT (0U)
  53. #define DMA_ADDRESS_CONTROL_DECREMENT (1U)
  54. #define DMA_ADDRESS_CONTROL_FIXED (2U)
  55. #define DMA_INTERRUPT_MASK_NONE (0U)
  56. #define DMA_INTERRUPT_MASK_ERROR DMA_CHCTRL_CTRL_INTERRMASK_MASK
  57. #define DMA_INTERRUPT_MASK_ABORT DMA_CHCTRL_CTRL_INTABTMASK_MASK
  58. #define DMA_INTERRUPT_MASK_TERMINAL_COUNT DMA_CHCTRL_CTRL_INTTCMASK_MASK
  59. #define DMA_INTERRUPT_MASK_ALL \
  60. (uint8_t)(DMA_INTERRUPT_MASK_TERMINAL_COUNT \
  61. | DMA_INTERRUPT_MASK_ABORT \
  62. | DMA_INTERRUPT_MASK_ERROR)
  63. #ifndef DMA_SUPPORT_64BIT_ADDR
  64. #define DMA_SUPPORT_64BIT_ADDR (0)
  65. #endif
  66. /**
  67. * @brief Linked descriptor
  68. *
  69. * It is consumed by DMA controlled directly
  70. */
  71. typedef struct dma_linked_descriptor {
  72. uint32_t ctrl; /**< Control */
  73. uint32_t trans_size; /**< Transfer size in source width */
  74. uint32_t src_addr; /**< Source address */
  75. uint32_t src_addr_high; /**< Source address high 32-bit, only valid when bus width > 32bits */
  76. uint32_t dst_addr; /**< Destination address */
  77. uint32_t dst_addr_high; /**< Destination address high 32-bit, only valid when bus width > 32bits */
  78. uint32_t linked_ptr; /**< Linked descriptor address */
  79. uint32_t linked_ptr_high; /**< Linked descriptor address high 32-bit, , only valid when bus width > 32bits */
  80. } dma_linked_descriptor_t;
  81. /* @brief Channel config */
  82. typedef struct dma_channel_config {
  83. uint8_t priority; /**< Channel priority */
  84. uint8_t src_burst_size; /**< Source burst size */
  85. uint8_t src_mode; /**< Source work mode */
  86. uint8_t dst_mode; /**< Destination work mode */
  87. uint8_t src_width; /**< Source width */
  88. uint8_t dst_width; /**< Destination width */
  89. uint8_t src_addr_ctrl; /**< Source address control */
  90. uint8_t dst_addr_ctrl; /**< Destination address control */
  91. uint16_t interrupt_mask; /**< Interrupt mask */
  92. uint32_t src_addr; /**< Source address */
  93. uint32_t dst_addr; /**< Destination address */
  94. uint32_t linked_ptr; /**< Next linked descriptor */
  95. uint32_t size_in_byte; /**< Total size to be transferred in byte */
  96. #if DMA_SUPPORT_64BIT_ADDR
  97. uint32_t src_addr_high; /**< Source address high 32bits */
  98. uint32_t dst_addr_high; /**< Destination address high 32bits */
  99. uint32_t linked_ptr_high; /**< Linked descriptor high 32bits */
  100. #endif
  101. } dma_channel_config_t;
  102. /* @brief Channel config */
  103. typedef struct dma_handshake_config {
  104. uint32_t dst;
  105. uint32_t src;
  106. uint32_t size_in_byte;
  107. uint8_t data_width; /* data width, value defined by DMA_TRANSFER_WIDTH_xxx */
  108. uint8_t ch_index;
  109. bool dst_fixed;
  110. bool src_fixed;
  111. } dma_handshake_config_t;
  112. /* @brief DMA specific status */
  113. enum {
  114. status_dma_transfer_done = MAKE_STATUS(status_group_dma, 0),
  115. status_dma_transfer_error = MAKE_STATUS(status_group_dma, 1),
  116. status_dma_transfer_abort = MAKE_STATUS(status_group_dma, 2),
  117. status_dma_transfer_ongoing = MAKE_STATUS(status_group_dma, 3),
  118. status_dma_alignment_error = MAKE_STATUS(status_group_dma, 4),
  119. };
  120. #ifdef __cplusplus
  121. extern "C" {
  122. #endif
  123. /**
  124. * @brief Reset DMA
  125. *
  126. * @param[in] ptr DMA base address
  127. */
  128. static inline void dma_reset(DMA_Type *ptr)
  129. {
  130. ptr->DMACTRL |= DMA_DMACTRL_RESET_MASK;
  131. }
  132. /**
  133. * @brief Enable DMA channel
  134. *
  135. * @param[in] ptr DMA base address
  136. * @param[in] ch_index Index of the channel to be enabled
  137. *
  138. * @return status_success if everything's okay
  139. */
  140. static inline hpm_stat_t dma_enable_channel(DMA_Type *ptr, uint32_t ch_index)
  141. {
  142. ptr->CHCTRL[ch_index].CTRL |= DMA_CHCTRL_CTRL_ENABLE_MASK;
  143. if ((ptr->CHEN == 0) || !(ptr->CHEN & 1 << ch_index)) {
  144. return status_fail;
  145. }
  146. return status_success;
  147. }
  148. /**
  149. * @brief Disable DMA channel
  150. *
  151. * @param[in] ptr DMA base address
  152. * @param[in] ch_index Index of the channel to be disabled
  153. *
  154. */
  155. static inline void dma_disable_channel(DMA_Type *ptr, uint32_t ch_index)
  156. {
  157. ptr->CHCTRL[ch_index].CTRL &= ~DMA_CHCTRL_CTRL_ENABLE_MASK;
  158. }
  159. /**
  160. * @brief Check whether DMA channel is enable
  161. *
  162. * @param[in] ptr DMA base address
  163. * @param[in] ch_index Index of the channel
  164. *
  165. * @return true if DMA channel is enable
  166. *
  167. */
  168. static inline bool dma_channel_is_enable(DMA_Type *ptr, uint32_t ch_index)
  169. {
  170. return (ptr->CHCTRL[ch_index].CTRL & DMA_CHCTRL_CTRL_ENABLE_MASK) ? true : false;
  171. }
  172. /**
  173. * @brief Get DMA channel residue transfer size
  174. *
  175. * @param[in] ptr DMA base address
  176. * @param[in] ch_index Index of the channel
  177. *
  178. * @return residue transfer size
  179. *
  180. */
  181. static inline uint32_t dma_get_residue_transfer_size(DMA_Type *ptr, uint32_t ch_index)
  182. {
  183. return ptr->CHCTRL[ch_index].TRANSIZE;
  184. }
  185. /**
  186. * @brief Set DMA channel transfer size
  187. *
  188. * @param[in] ptr DMA base address
  189. * @param[in] ch_index Index of the channel
  190. * @param[in] size_in_width transfer size of the channel. The width is current dma channel configured source width.
  191. * Transfer total bytes are (size_in_width * source width).
  192. *
  193. */
  194. static inline void dma_set_transfer_size(DMA_Type *ptr, uint32_t ch_index, uint32_t size_in_width)
  195. {
  196. ptr->CHCTRL[ch_index].TRANSIZE = DMA_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_width);
  197. }
  198. /**
  199. * @brief Set DMA channel transfer width and size in byte
  200. *
  201. * @param[in] ptr DMA base address
  202. * @param[in] ch_index Index of the channel
  203. * @param[in] src_width transfer source width of the channel
  204. * @arg @ref DMA_TRANSFER_WIDTH_BYTE
  205. * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
  206. * @arg @ref DMA_TRANSFER_WIDTH_WORD
  207. * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
  208. * @param[in] size_in_byte transfer size in byte of the channel. The dma transfer size is (size_in_byte >> src_width).
  209. *
  210. */
  211. static inline void dma_set_transfer_src_width_byte_size(DMA_Type *ptr, uint32_t ch_index, uint8_t src_width, uint32_t size_in_byte)
  212. {
  213. assert((src_width == DMA_TRANSFER_WIDTH_BYTE) || (src_width == DMA_TRANSFER_WIDTH_HALF_WORD)
  214. || (src_width == DMA_TRANSFER_WIDTH_WORD) || (src_width == DMA_TRANSFER_WIDTH_DOUBLE_WORD));
  215. ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_SRCWIDTH_MASK) | DMA_CHCTRL_CTRL_SRCWIDTH_SET(src_width);
  216. ptr->CHCTRL[ch_index].TRANSIZE = DMA_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_byte >> src_width);
  217. }
  218. /**
  219. * @brief Set DMA channel source address
  220. *
  221. * @param[in] ptr DMA base address
  222. * @param[in] ch_index Index of the channel
  223. * @param[in] addr source address
  224. *
  225. */
  226. static inline void dma_set_source_address(DMA_Type *ptr, uint32_t ch_index, uint32_t addr)
  227. {
  228. ptr->CHCTRL[ch_index].SRCADDR = addr;
  229. }
  230. /**
  231. * @brief Set DMA channel destination address
  232. *
  233. * @param[in] ptr DMA base address
  234. * @param[in] ch_index Index of the channel
  235. * @param[in] addr destination address
  236. *
  237. */
  238. static inline void dma_set_destination_address(DMA_Type *ptr, uint32_t ch_index, uint32_t addr)
  239. {
  240. ptr->CHCTRL[ch_index].DSTADDR = addr;
  241. }
  242. /**
  243. * @brief Abort channel transfer with mask
  244. *
  245. * @param[in] ptr DMA base address
  246. * @param[in] ch_index_mask Mask of channels to be aborted
  247. */
  248. static inline void dma_abort_channel(DMA_Type *ptr, uint32_t ch_index_mask)
  249. {
  250. ptr->CHABORT |= DMA_CHABORT_CHABORT_SET(ch_index_mask);
  251. }
  252. /**
  253. * @brief Check if channels are enabled with mask
  254. *
  255. * @param[in] ptr DMA base address
  256. * @param[in] ch_index_mask Mask of channels to be checked
  257. *
  258. * @return Enabled channel mask
  259. */
  260. static inline uint32_t dma_check_enabled_channel(DMA_Type *ptr,
  261. uint32_t ch_index_mask)
  262. {
  263. return (ch_index_mask & ptr->CHEN);
  264. }
  265. /**
  266. * @brief Check if linked pointer has been configured
  267. *
  268. * @param[in] ptr DMA base address
  269. * @param[in] ch_index Target channel index to be checked
  270. *
  271. * @return true if linked pointer has been configured
  272. */
  273. static inline bool dma_has_linked_pointer_configured(DMA_Type *ptr, uint32_t ch_index)
  274. {
  275. return ptr->CHCTRL[ch_index].LLPOINTER != 0;
  276. }
  277. /**
  278. * @brief Check transfer status
  279. *
  280. * @param[in] ptr DMA base address
  281. * @param[in] ch_index Target channel index to be checked
  282. *
  283. * @retval 1 if transfer is still ongoing
  284. * @retval 2 if any error occurred during transferring
  285. * @retval 4 if transfer is aborted
  286. * @retval 8 if transfer is finished without error
  287. */
  288. static inline uint32_t dma_check_transfer_status(DMA_Type *ptr, uint8_t ch_index)
  289. {
  290. volatile uint32_t tmp = ptr->INTSTATUS;
  291. volatile uint32_t tmp_channel;
  292. uint32_t dma_status;
  293. dma_status = 0;
  294. tmp_channel = tmp & (1 << (DMA_STATUS_TC_SHIFT + ch_index));
  295. if (tmp_channel) {
  296. dma_status |= DMA_CHANNEL_STATUS_TC;
  297. ptr->INTSTATUS = tmp_channel;
  298. }
  299. tmp_channel = tmp & (1 << (DMA_STATUS_ERROR_SHIFT + ch_index));
  300. if (tmp_channel) {
  301. dma_status |= DMA_CHANNEL_STATUS_ERROR;
  302. ptr->INTSTATUS = tmp_channel;
  303. }
  304. tmp_channel = tmp & (1 << (DMA_STATUS_ABORT_SHIFT + ch_index));
  305. if (tmp_channel) {
  306. dma_status |= DMA_CHANNEL_STATUS_ABORT;
  307. ptr->INTSTATUS = tmp_channel;
  308. }
  309. if (dma_status == 0) {
  310. dma_status = DMA_CHANNEL_STATUS_ONGOING;
  311. }
  312. return dma_status;
  313. }
  314. /**
  315. * @brief Clear transfer status
  316. *
  317. * @param[in] ptr DMA base address
  318. * @param[in] ch_index Target channel index
  319. *
  320. */
  321. static inline void dma_clear_transfer_status(DMA_Type *ptr, uint8_t ch_index)
  322. {
  323. ptr->INTSTATUS &= ~((1 << (DMA_STATUS_TC_SHIFT + ch_index)) | (1 << (DMA_STATUS_ERROR_SHIFT + ch_index)) | (1 << (DMA_STATUS_ABORT_SHIFT + ch_index)));
  324. }
  325. /**
  326. * @brief Enable DMA Channel interrupt
  327. *
  328. * @param [in] ptr DMA base address
  329. * @param [in] ch_index Target channel index
  330. * @param [in] interrupt_mask Interrupt mask
  331. */
  332. static inline void dma_enable_channel_interrupt(DMA_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
  333. {
  334. ptr->CHCTRL[ch_index].CTRL &= ~(interrupt_mask & (DMA_INTERRUPT_MASK_ERROR | DMA_INTERRUPT_MASK_ABORT | DMA_INTERRUPT_MASK_TERMINAL_COUNT));
  335. }
  336. /**
  337. * @brief Disable DMA Channel interrupt
  338. *
  339. * @param [in] ptr DMA base address
  340. * @param [in] ch_index Target channel index
  341. * @param [in] interrupt_mask Interrupt mask
  342. */
  343. static inline void dma_disable_channel_interrupt(DMA_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
  344. {
  345. ptr->CHCTRL[ch_index].CTRL |= (interrupt_mask & (DMA_INTERRUPT_MASK_ERROR | DMA_INTERRUPT_MASK_ABORT | DMA_INTERRUPT_MASK_TERMINAL_COUNT));
  346. }
  347. /**
  348. * @brief Check Channel interrupt master
  349. *
  350. * @param[in] ptr DMA base address
  351. * @param[in] ch_index Target channel index to be checked
  352. * @return uint32_t Interrupt mask
  353. */
  354. static inline uint32_t dma_check_channel_interrupt_mask(DMA_Type *ptr, uint8_t ch_index)
  355. {
  356. return ptr->CHCTRL[ch_index].CTRL & (DMA_INTERRUPT_MASK_ERROR | DMA_INTERRUPT_MASK_ABORT | DMA_INTERRUPT_MASK_TERMINAL_COUNT);
  357. }
  358. /**
  359. * @brief Get clear IRQ status
  360. *
  361. * @param[in] ptr DMA base address
  362. * @param[in] mask irq mask to be cleared
  363. */
  364. static inline void dma_clear_irq_status(DMA_Type *ptr, uint32_t mask)
  365. {
  366. ptr->INTSTATUS = mask; /* Write-1-Clear */
  367. }
  368. /**
  369. * @brief Get IRQ status
  370. *
  371. * @param[in] ptr DMA base address
  372. */
  373. static inline uint32_t dma_get_irq_status(DMA_Type *ptr)
  374. {
  375. return ptr->INTSTATUS;
  376. }
  377. /**
  378. * @brief Get default channel config
  379. *
  380. * @param[in] ptr DMA base address
  381. * @param[in] ch Channel config
  382. */
  383. void dma_default_channel_config(DMA_Type *ptr, dma_channel_config_t *ch);
  384. /**
  385. * @brief Setup DMA channel
  386. *
  387. * @param[in] ptr DMA base address
  388. * @param[in] ch_num Target channel index to be configured
  389. * @param[in] ch Channel config
  390. * @param[in] start_transfer Set true to start transfer
  391. *
  392. * @return status_success if everything is okay
  393. */
  394. hpm_stat_t dma_setup_channel(DMA_Type *ptr, uint8_t ch_num,
  395. dma_channel_config_t *ch, bool start_transfer);
  396. /**
  397. * @brief Config linked descriptor function
  398. *
  399. * @param[in] ptr DMA base address
  400. * @param[in] descriptor Linked descriptor pointer
  401. * @param[in] ch_num Target channel index to be configured
  402. * @param[in] config Descriptor config pointer
  403. *
  404. * @return status_success if everything is okay
  405. */
  406. hpm_stat_t dma_config_linked_descriptor(DMA_Type *ptr, dma_linked_descriptor_t *descriptor, uint8_t ch_num, dma_channel_config_t *config);
  407. /**
  408. * @brief Start DMA copy
  409. *
  410. * @param[in] ptr DMA base address
  411. * @param[in] ch_num Target channel index
  412. * @param[in] dst Destination address
  413. * @param[in] src Source Address
  414. * @param[in] size_in_byte Size in byte
  415. * @param[in] burst_len_in_byte Burst length in byte
  416. *
  417. * @return status_success if everthing is okay
  418. * @note: dst, src, size should be aligned with burst_len_in_byte
  419. */
  420. hpm_stat_t dma_start_memcpy(DMA_Type *ptr, uint8_t ch_num,
  421. uint32_t dst, uint32_t src,
  422. uint32_t size_in_byte, uint32_t burst_len_in_byte);
  423. /**
  424. * @brief Get default handshake config
  425. *
  426. * @param[in] ptr DMA base address
  427. * @param[in] config default config
  428. */
  429. void dma_default_handshake_config(DMA_Type *ptr, dma_handshake_config_t *config);
  430. /**
  431. * @brief config dma handshake function
  432. *
  433. * @param[in] ptr DMA base address
  434. * @param[in] pconfig dma handshake config pointer
  435. * @param[in] start_transfer Set true to start transfer
  436. *
  437. * @return status_success if everything is okay
  438. */
  439. hpm_stat_t dma_setup_handshake(DMA_Type *ptr, dma_handshake_config_t *pconfig, bool start_transfer);
  440. #if defined(DMA_SOC_HAS_IDLE_FLAG) && (DMA_SOC_HAS_IDLE_FLAG == 1)
  441. /**
  442. * @brief Check whether DMA is idle
  443. * @param [in] ptr DMA base address
  444. * @return true DMA is idle
  445. * @return false DMA is busy
  446. */
  447. static inline bool dma_is_idle(DMA_Type *ptr)
  448. {
  449. return ((ptr->IDMISC & DMA_IDMISC_IDLE_FLAG_MASK) != 0U);
  450. }
  451. #endif
  452. #ifdef __cplusplus
  453. }
  454. #endif
  455. /**
  456. * @}
  457. */
  458. #endif /* HPM_DMAV1_DRV_H */