1 /*
2  * Copyright (c) 2021-2022 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 
9 #ifndef HPM_DMAV2_DRV_H
10 #define HPM_DMAV2_DRV_H
11 #include "hpm_common.h"
12 #include "hpm_soc_feature.h"
13 #include "hpm_dmav2_regs.h"
14 
15 /**
16  *
17  * @brief DMA driver APIs
18  * @defgroup dma_interface DMA driver APIs
19  * @ingroup io_interfaces
20  * @{
21  */
22 
23 #define DMA_Type DMAV2_Type
24 
25 #define DMA_CHANNEL_PRIORITY_LOW                (0U)
26 #define DMA_CHANNEL_PRIORITY_HIGH               (1U)
27 
28 #define DMA_NUM_TRANSFER_PER_BURST_1T           (0U)
29 #define DMA_NUM_TRANSFER_PER_BURST_2T           (1U)
30 #define DMA_NUM_TRANSFER_PER_BURST_4T           (2U)
31 #define DMA_NUM_TRANSFER_PER_BURST_8T           (3U)
32 #define DMA_NUM_TRANSFER_PER_BURST_16T          (4U)
33 #define DMA_NUM_TRANSFER_PER_BURST_32T          (5U)
34 #define DMA_NUM_TRANSFER_PER_BURST_64T          (6U)
35 #define DMA_NUM_TRANSFER_PER_BURST_128T         (7U)
36 #define DMA_NUM_TRANSFER_PER_BURST_256T         (8U)
37 #define DMA_NUM_TRANSFER_PER_BURST_512T         (9U)
38 #define DMA_NUM_TRANSFER_PER_BURST_1024T        (10U)
39 
40 #define DMA_TRANSFER_WIDTH_BYTE                 (0U)
41 #define DMA_TRANSFER_WIDTH_HALF_WORD            (1U)
42 #define DMA_TRANSFER_WIDTH_WORD                 (2U)
43 #define DMA_TRANSFER_WIDTH_DOUBLE_WORD          (3U)
44 
45 #define DMA_ALIGN_HALF_WORD(x)                  (x & ~(1u))
46 #define DMA_ALIGN_WORD(x)                       (x & ~(3u))
47 #define DMA_ALIGN_DOUBLE_WORD(x)                (x & ~(7u))
48 
49 #define DMA_CHANNEL_STATUS_ONGOING              (1U)
50 #define DMA_CHANNEL_STATUS_ERROR                (2U)
51 #define DMA_CHANNEL_STATUS_ABORT                (4U)
52 #define DMA_CHANNEL_STATUS_TC                   (8U)
53 #define DMA_CHANNEL_STATUS_HALF_TC              (16U)
54 
55 #define DMA_CHANNEL_IRQ_STATUS_ERROR(x)         (uint32_t)(1 << x)
56 #define DMA_CHANNEL_IRQ_STATUS_ABORT(x)         (uint32_t)(1 << x)
57 #define DMA_CHANNEL_IRQ_STATUS_TC(x)            (uint32_t)(1 << x)
58 #define DMA_CHANNEL_IRQ_STATUS_HALF_TC(x)       (uint32_t)(1 << x)
59 
60 #define DMA_HANDSHAKE_MODE_NORMAL               (0U)
61 #define DMA_HANDSHAKE_MODE_HANDSHAKE            (1U)
62 
63 #define DMA_ADDRESS_CONTROL_INCREMENT           (0U)
64 #define DMA_ADDRESS_CONTROL_DECREMENT           (1U)
65 #define DMA_ADDRESS_CONTROL_FIXED               (2U)
66 
67 #define DMA_SRC_BURST_OPT_STANDAND_SIZE         (0U)
68 #define DMA_SRC_BURST_OPT_CUSTOM_SIZE           (1U)
69 
70 #define DMA_HANDSHAKE_OPT_ONE_BURST             (0U)
71 #define DMA_HANDSHAKE_OPT_ALL_TRANSIZE          (1U)
72 
73 #define DMA_SWAP_MODE_TABLE                     (0U)
74 #define DMA_SWAP_MODE_BYTE                      (1U)
75 #define DMA_SWAP_MODE_HALF_WORD                 (2U)
76 #define DMA_SWAP_MODE_WORD                      (3U)
77 
78 #define DMA_INTERRUPT_MASK_NONE                 (0U)
79 #define DMA_INTERRUPT_MASK_ERROR  DMAV2_CHCTRL_CTRL_INTERRMASK_MASK
80 #define DMA_INTERRUPT_MASK_ABORT  DMAV2_CHCTRL_CTRL_INTABTMASK_MASK
81 #define DMA_INTERRUPT_MASK_TERMINAL_COUNT DMAV2_CHCTRL_CTRL_INTTCMASK_MASK
82 #define DMA_INTERRUPT_MASK_HALF_TC DMAV2_CHCTRL_CTRL_INTHALFCNTMASK_MASK
83 #define DMA_INTERRUPT_MASK_ALL \
84     (uint8_t)(DMA_INTERRUPT_MASK_TERMINAL_COUNT \
85             | DMA_INTERRUPT_MASK_ABORT \
86             | DMA_INTERRUPT_MASK_ERROR \
87             | DMA_INTERRUPT_MASK_HALF_TC)
88 
89 #define DMA_SUPPORT_64BIT_ADDR (0)
90 
91 
92 enum {
93     dmav2_state_idle = 0,
94     dmav2_state_read,
95     dmav2_state_read_ack,
96     dmav2_state_write,
97     dmav2_state_write_ack,
98     dmav2_state_ll,
99     dmav2_state_end,
100     dmav2_state_end_wait,
101 };
102 
103 /**
104  * @brief Linked descriptor
105  *
106  * It is consumed by DMA controlled directly
107  */
108 typedef struct dma_linked_descriptor {
109     uint32_t ctrl;              /**< Control */
110     uint32_t trans_size;        /**< Transfer size in source width */
111     uint32_t src_addr;          /**< Source address */
112     uint32_t req_ctrl;          /**< Request select */
113     uint32_t dst_addr;          /**< Destination address */
114     uint32_t swap_table;        /**< Swap table */
115     uint32_t linked_ptr;        /**< Linked descriptor address */
116     uint32_t reserved0;         /**< not used on dmav2 */
117 } dma_linked_descriptor_t;
118 
119 /* @brief Channel config */
120 typedef struct dma_channel_config {
121     uint8_t priority;               /**< Channel priority */
122     uint8_t src_burst_size;         /**< Source burst size */
123     uint8_t src_mode;               /**< Source work mode */
124     uint8_t dst_mode;               /**< Destination work mode */
125     uint8_t src_width;              /**< Source width */
126     uint8_t dst_width;              /**< Destination width */
127     uint8_t src_addr_ctrl;          /**< Source address control */
128     uint8_t dst_addr_ctrl;          /**< Destination address control */
129     uint16_t interrupt_mask;        /**< Interrupt mask */
130     uint32_t src_addr;              /**< Source address */
131     uint32_t dst_addr;              /**< Destination address */
132     uint32_t linked_ptr;            /**< Next linked descriptor */
133     uint32_t size_in_byte;          /**< Total size to be transferred in byte */
134     bool en_infiniteloop;           /**< Infinite loop transfer enable. Attention: only DMAV2 support */
135     uint8_t handshake_opt;          /**< Handshake transfer option. Attention: only DMAV2 support */
136     uint8_t burst_opt;              /**< Burst size option. Attention: only DMAV2 support */
137 #if defined(HPM_IP_FEATURE_DMAV2_BURST_IN_FIXED_TRANS) && (HPM_IP_FEATURE_DMAV2_BURST_IN_FIXED_TRANS == 1)
138     bool en_src_burst_in_fixed_trans;          /**< Source burst in fix transfer size enable, discard src_addr_ctrl setting. Attention: only DMAV2 support */
139     bool en_dst_burst_in_fixed_trans;          /**< Destination burst in fix transfer size enable, discard dst_addr_ctrl setting. Attention: only DMAV2 support */
140 #endif
141 #if defined(HPM_IP_FEATURE_DMAV2_BYTE_ORDER_SWAP) && (HPM_IP_FEATURE_DMAV2_BYTE_ORDER_SWAP == 1)
142     uint8_t swap_mode;              /**< Swap Mode. Attention: only DMAV2 support */
143     uint32_t swap_table;            /**< Swap Table. Attention: only DMAV2 support */
144 #endif
145 } dma_channel_config_t;
146 
147 /* @brief Channel config */
148 typedef struct dma_handshake_config {
149     uint32_t dst;
150     uint32_t src;
151     uint32_t size_in_byte;
152     uint8_t data_width;            /* data width, value defined by DMA_TRANSFER_WIDTH_xxx */
153     uint8_t ch_index;
154     bool dst_fixed;
155     bool src_fixed;
156     bool en_infiniteloop;
157     uint16_t interrupt_mask;
158 } dma_handshake_config_t;
159 
160 
161 /* @brief DMA specific status */
162 enum {
163     status_dma_transfer_done = MAKE_STATUS(status_group_dma, 0),
164     status_dma_transfer_error = MAKE_STATUS(status_group_dma, 1),
165     status_dma_transfer_abort = MAKE_STATUS(status_group_dma, 2),
166     status_dma_transfer_ongoing = MAKE_STATUS(status_group_dma, 3),
167     status_dma_alignment_error = MAKE_STATUS(status_group_dma, 4),
168     status_dma_transfer_half_done = MAKE_STATUS(status_group_dma, 5),
169 };
170 
171 #ifdef __cplusplus
172 extern "C" {
173 #endif
174 
175 /**
176  * @brief Reset DMA
177  *
178  * @param[in] ptr DMA base address
179  */
dma_reset(DMAV2_Type * ptr)180 static inline void dma_reset(DMAV2_Type *ptr)
181 {
182     ptr->DMACTRL |= DMAV2_DMACTRL_RESET_MASK;
183 }
184 
185 /**
186  * @brief   Enable DMA channel
187  *
188  * @param[in] ptr DMA base address
189  * @param[in] ch_index Index of the channel to be enabled
190  *
191  * @return status_success if everything's okay
192  */
dma_enable_channel(DMAV2_Type * ptr,uint32_t ch_index)193 static inline hpm_stat_t dma_enable_channel(DMAV2_Type *ptr, uint32_t ch_index)
194 {
195     ptr->CHCTRL[ch_index].CTRL |= DMAV2_CHCTRL_CTRL_ENABLE_MASK;
196 
197     if ((ptr->CHEN == 0) || !(ptr->CHEN & 1 << ch_index)) {
198         return status_fail;
199     }
200     return status_success;
201 }
202 
203 /**
204  * @brief   Disable DMA channel
205  *
206  * @param[in] ptr DMA base address
207  * @param[in] ch_index Index of the channel to be disabled
208  *
209  */
dma_disable_channel(DMAV2_Type * ptr,uint32_t ch_index)210 static inline void dma_disable_channel(DMAV2_Type *ptr, uint32_t ch_index)
211 {
212     ptr->CHCTRL[ch_index].CTRL &= ~DMAV2_CHCTRL_CTRL_ENABLE_MASK;
213 }
214 
215 /**
216  * @brief   Check whether DMA channel is enable
217  *
218  * @param[in] ptr DMA base address
219  * @param[in] ch_index Index of the channel
220  *
221  * @return   true if DMA channel is enable
222  *
223  */
dma_channel_is_enable(DMAV2_Type * ptr,uint32_t ch_index)224 static inline bool dma_channel_is_enable(DMAV2_Type *ptr, uint32_t ch_index)
225 {
226     return (ptr->CHCTRL[ch_index].CTRL & DMAV2_CHCTRL_CTRL_ENABLE_MASK) ? true : false;
227 }
228 
229 /**
230  * @brief   Set DMA channel priority
231  *
232  * @param[in] ptr DMA base address
233  * @param[in] ch_index Index of the channel
234  * @param[in] priority dma priority
235  *  @arg @ref DMA_CHANNEL_PRIORITY_LOW
236  *  @arg @ref DMA_CHANNEL_PRIORITY_HIGH
237  *
238  */
dma_set_priority(DMAV2_Type * ptr,uint32_t ch_index,uint8_t priority)239 static inline void dma_set_priority(DMAV2_Type *ptr, uint32_t ch_index, uint8_t priority)
240 {
241     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_PRIORITY_MASK) | DMAV2_CHCTRL_CTRL_PRIORITY_SET(priority);
242 }
243 
244 /**
245  * @brief   Set DMA channel source work mode
246  *
247  * @param[in] ptr DMA base address
248  * @param[in] ch_index Index of the channel
249  * @param[in] mode source work mode
250  *  @arg @ref DMA_HANDSHAKE_MODE_NORMAL
251  *  @arg @ref DMA_HANDSHAKE_MODE_HANDSHAKE
252  *
253  */
dma_set_source_work_mode(DMAV2_Type * ptr,uint32_t ch_index,uint8_t mode)254 static inline void dma_set_source_work_mode(DMAV2_Type *ptr, uint32_t ch_index, uint8_t mode)
255 {
256     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCMODE_MASK) | DMAV2_CHCTRL_CTRL_SRCMODE_SET(mode);
257 }
258 
259 /**
260  * @brief   Set DMA channel destination work mode
261  *
262  * @param[in] ptr DMA base address
263  * @param[in] ch_index Index of the channel
264  * @param[in] mode destination work mode
265  *  @arg @ref DMA_HANDSHAKE_MODE_NORMAL
266  *  @arg @ref DMA_HANDSHAKE_MODE_HANDSHAKE
267  *
268  */
dma_set_destination_work_mode(DMAV2_Type * ptr,uint32_t ch_index,uint8_t mode)269 static inline void dma_set_destination_work_mode(DMAV2_Type *ptr, uint32_t ch_index, uint8_t mode)
270 {
271     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DSTMODE_MASK) | DMAV2_CHCTRL_CTRL_DSTMODE_SET(mode);
272 }
273 
274 /**
275  * @brief   Set DMA channel source burst size
276  *
277  * @param[in] ptr DMA base address
278  * @param[in] ch_index Index of the channel
279  * @param[in] burstsize source burst size
280  *  when BURSTOPT is 0, please reference follows:
281  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_1T
282  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_2T
283  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_4T
284  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_8T
285  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_16T
286  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_32T
287  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_64T
288  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_128T
289  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_256T
290  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_512T
291  *      @arg @ref DMA_NUM_TRANSFER_PER_BURST_1024T
292  *  when BURSTOPT is 1, burst size is (burstsize + 1).
293  *
294  */
dma_set_source_burst_size(DMAV2_Type * ptr,uint32_t ch_index,uint8_t burstsize)295 static inline void dma_set_source_burst_size(DMAV2_Type *ptr, uint32_t ch_index, uint8_t burstsize)
296 {
297     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCBURSTSIZE_MASK) | DMAV2_CHCTRL_CTRL_SRCBURSTSIZE_SET(burstsize);
298 }
299 
300 /**
301  * @brief   Get DMA channel remaining transfer size
302  *
303  * @param[in] ptr DMA base address
304  * @param[in] ch_index Index of the channel
305  *
306  * @return remaining transfer size
307  *
308  */
dma_get_remaining_transfer_size(DMAV2_Type * ptr,uint32_t ch_index)309 static inline uint32_t dma_get_remaining_transfer_size(DMAV2_Type *ptr, uint32_t ch_index)
310 {
311     return ptr->CHCTRL[ch_index].TRANSIZE;
312 }
313 
314 /**
315  * @brief   Set DMA channel transfer size
316  *
317  * @param[in] ptr DMA base address
318  * @param[in] ch_index Index of the channel
319  * @param[in] size_in_width transfer size of the channel. The width is current dma channel configured source width.
320  *            Transfer total bytes are (size_in_width * source width).
321  *
322  */
dma_set_transfer_size(DMAV2_Type * ptr,uint32_t ch_index,uint32_t size_in_width)323 static inline void dma_set_transfer_size(DMAV2_Type *ptr, uint32_t ch_index, uint32_t size_in_width)
324 {
325     ptr->CHCTRL[ch_index].TRANSIZE = DMAV2_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_width);
326 }
327 
328 /**
329  * @brief   Set DMA channel source width
330  *
331  * @param[in] ptr DMA base address
332  * @param[in] ch_index Index of the channel
333  * @param[in] width transfer source width of the channel
334  *  @arg @ref DMA_TRANSFER_WIDTH_BYTE
335  *  @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
336  *  @arg @ref DMA_TRANSFER_WIDTH_WORD
337  *  @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
338  */
dma_set_source_width(DMAV2_Type * ptr,uint32_t ch_index,uint8_t width)339 static inline void dma_set_source_width(DMAV2_Type *ptr, uint32_t ch_index, uint8_t width)
340 {
341     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCWIDTH_MASK) | DMAV2_CHCTRL_CTRL_SRCWIDTH_SET(width);
342 }
343 
344 /**
345  * @brief   Set DMA channel destination width
346  *
347  * @param[in] ptr DMA base address
348  * @param[in] ch_index Index of the channel
349  * @param[in] width transfer destination width of the channel
350  *  @arg @ref DMA_TRANSFER_WIDTH_BYTE
351  *  @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
352  *  @arg @ref DMA_TRANSFER_WIDTH_WORD
353  *  @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
354  */
dma_set_destination_width(DMAV2_Type * ptr,uint32_t ch_index,uint8_t width)355 static inline void dma_set_destination_width(DMAV2_Type *ptr, uint32_t ch_index, uint8_t width)
356 {
357     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DSTWIDTH_MASK) | DMAV2_CHCTRL_CTRL_DSTWIDTH_SET(width);
358 }
359 
360 /**
361  * @brief   Set DMA channel transfer width and size in byte
362  *
363  * @param[in] ptr DMA base address
364  * @param[in] ch_index Index of the channel
365  * @param[in] src_width transfer source width of the channel
366  *  @arg @ref DMA_TRANSFER_WIDTH_BYTE
367  *  @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
368  *  @arg @ref DMA_TRANSFER_WIDTH_WORD
369  *  @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
370  * @param[in] size_in_byte transfer size in byte of the channel. The dma transfer size is (size_in_byte >> src_width).
371  *
372  */
dma_set_transfer_src_width_byte_size(DMAV2_Type * ptr,uint32_t ch_index,uint8_t src_width,uint32_t size_in_byte)373 static inline void dma_set_transfer_src_width_byte_size(DMAV2_Type *ptr, uint32_t ch_index, uint8_t src_width, uint32_t size_in_byte)
374 {
375     assert((src_width == DMA_TRANSFER_WIDTH_BYTE) || (src_width == DMA_TRANSFER_WIDTH_HALF_WORD)
376         || (src_width == DMA_TRANSFER_WIDTH_WORD) || (src_width == DMA_TRANSFER_WIDTH_DOUBLE_WORD));
377 
378     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCWIDTH_MASK) | DMAV2_CHCTRL_CTRL_SRCWIDTH_SET(src_width);
379     ptr->CHCTRL[ch_index].TRANSIZE = DMAV2_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_byte >> src_width);
380 }
381 
382 /**
383  * @brief   Set DMA channel source address
384  *
385  * @param[in] ptr DMA base address
386  * @param[in] ch_index Index of the channel
387  * @param[in] addr source address
388  *
389  */
dma_set_source_address(DMAV2_Type * ptr,uint32_t ch_index,uint32_t addr)390 static inline void dma_set_source_address(DMAV2_Type *ptr, uint32_t ch_index, uint32_t addr)
391 {
392     ptr->CHCTRL[ch_index].SRCADDR = addr;
393 }
394 
395 /**
396  * @brief   Set DMA channel destination address
397  *
398  * @param[in] ptr DMA base address
399  * @param[in] ch_index Index of the channel
400  * @param[in] addr destination address
401  *
402  */
dma_set_destination_address(DMAV2_Type * ptr,uint32_t ch_index,uint32_t addr)403 static inline void dma_set_destination_address(DMAV2_Type *ptr, uint32_t ch_index, uint32_t addr)
404 {
405     ptr->CHCTRL[ch_index].DSTADDR = addr;
406 }
407 
408 /**
409  * @brief   Set DMA channel source address control mode
410  *
411  * @param[in] ptr DMA base address
412  * @param[in] ch_index Index of the channel
413  * @param[in] addr_ctrl source address control mode
414  *  @arg @ref DMA_ADDRESS_CONTROL_INCREMENT
415  *  @arg @ref DMA_ADDRESS_CONTROL_DECREMENT
416  *  @arg @ref DMA_ADDRESS_CONTROL_FIXED
417  *
418  */
dma_set_source_address_ctrl(DMAV2_Type * ptr,uint32_t ch_index,uint8_t addr_ctrl)419 static inline void dma_set_source_address_ctrl(DMAV2_Type *ptr, uint32_t ch_index, uint8_t addr_ctrl)
420 {
421     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRCADDRCTRL_MASK) | DMAV2_CHCTRL_CTRL_SRCADDRCTRL_SET(addr_ctrl);
422 }
423 
424 /**
425  * @brief   Set DMA channel destination address control mode
426  *
427  * @param[in] ptr DMA base address
428  * @param[in] ch_index Index of the channel
429  * @param[in] addr_ctrl destination address control mode
430  *  @arg @ref DMA_ADDRESS_CONTROL_INCREMENT
431  *  @arg @ref DMA_ADDRESS_CONTROL_DECREMENT
432  *  @arg @ref DMA_ADDRESS_CONTROL_FIXED
433  *
434  */
dma_set_destination_address_ctrl(DMAV2_Type * ptr,uint32_t ch_index,uint8_t addr_ctrl)435 static inline void dma_set_destination_address_ctrl(DMAV2_Type *ptr, uint32_t ch_index, uint8_t addr_ctrl)
436 {
437     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DSTADDRCTRL_MASK) | DMAV2_CHCTRL_CTRL_DSTADDRCTRL_SET(addr_ctrl);
438 }
439 
440 /**
441  * @brief   Set DMA channel infinite loop mode
442  *
443  * @param[in] ptr DMA base address
444  * @param[in] ch_index Index of the channel
445  * @param[in] infinite_loop false - normal mode(single times mode); true - infinite loop mode(cycle mode)
446  *
447  */
dma_set_infinite_loop_mode(DMAV2_Type * ptr,uint32_t ch_index,bool infinite_loop)448 static inline void dma_set_infinite_loop_mode(DMAV2_Type *ptr, uint32_t ch_index, bool infinite_loop)
449 {
450     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_INFINITELOOP_MASK) | DMAV2_CHCTRL_CTRL_INFINITELOOP_SET(infinite_loop);
451 }
452 
453 /**
454  * @brief   Set DMA channel source burst option
455  *
456  * @param[in] ptr DMA base address
457  * @param[in] ch_index Index of the channel
458  * @param[in] burst_opt burst option
459  *  @arg @ref DMA_SRC_BURST_OPT_STANDAND_SIZE
460  *  @arg @ref DMA_SRC_BURST_OPT_CUSTOM_SIZE
461  *
462  */
dma_set_src_busrt_option(DMAV2_Type * ptr,uint32_t ch_index,uint8_t burst_opt)463 static inline void dma_set_src_busrt_option(DMAV2_Type *ptr, uint32_t ch_index, uint8_t burst_opt)
464 {
465     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_BURSTOPT_MASK) | DMAV2_CHCTRL_CTRL_BURSTOPT_SET(burst_opt);
466 }
467 
468 /**
469  * @brief   Set DMA channel handshake option
470  *
471  * @param[in] ptr DMA base address
472  * @param[in] ch_index Index of the channel
473  * @param[in] handshake_opt handshake option
474  *  @arg @ref DMA_HANDSHAKE_OPT_ONE_BURST
475  *  @arg @ref DMA_HANDSHAKE_OPT_ALL_TRANSIZE
476  *
477  */
dma_set_handshake_option(DMAV2_Type * ptr,uint32_t ch_index,uint8_t handshake_opt)478 static inline void dma_set_handshake_option(DMAV2_Type *ptr, uint32_t ch_index, uint8_t handshake_opt)
479 {
480     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_HANDSHAKEOPT_MASK) | DMAV2_CHCTRL_CTRL_HANDSHAKEOPT_SET(handshake_opt);
481 }
482 
483 #if defined(HPM_IP_FEATURE_DMAV2_BURST_IN_FIXED_TRANS) && (HPM_IP_FEATURE_DMAV2_BURST_IN_FIXED_TRANS == 1)
484 /**
485  * @brief   Set DMA channel source burst in fixed transfer size enable or disable
486  *
487  * @param[in] ptr DMA base address
488  * @param[in] ch_index Index of the channel
489  * @param[in] enable false - disable; true - enable
490  *
491  */
dma_set_source_burst_in_fixed_transize_enable(DMAV2_Type * ptr,uint32_t ch_index,bool enable)492 static inline void dma_set_source_burst_in_fixed_transize_enable(DMAV2_Type *ptr, uint32_t ch_index, bool enable)
493 {
494     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SRC_FIXBURST_MASK) | DMAV2_CHCTRL_CTRL_SRC_FIXBURST_SET(enable);
495 }
496 
497 /**
498  * @brief   Set DMA channel destination burst in fixed transfer size enable or disable
499  *
500  * @param[in] ptr DMA base address
501  * @param[in] ch_index Index of the channel
502  * @param[in] enable false - disable; true - enable
503  *
504  */
dma_set_destination_burst_in_fixed_transize_enable(DMAV2_Type * ptr,uint32_t ch_index,bool enable)505 static inline void dma_set_destination_burst_in_fixed_transize_enable(DMAV2_Type *ptr, uint32_t ch_index, bool enable)
506 {
507     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_DST_FIXBURST_MASK) | DMAV2_CHCTRL_CTRL_DST_FIXBURST_SET(enable);
508 }
509 #endif
510 
511 #if defined(HPM_IP_FEATURE_DMAV2_BYTE_ORDER_SWAP) && (HPM_IP_FEATURE_DMAV2_BYTE_ORDER_SWAP == 1)
512 /**
513  * @brief   Set DMA channel swap mode
514  *
515  * @param[in] ptr DMA base address
516  * @param[in] ch_index Index of the channel
517  * @param[in] swap_mode swap mode
518  *  @arg @ref DMA_SWAP_MODE_TABLE
519  *  @arg @ref DMA_SWAP_MODE_BYTE
520  *  @arg @ref DMA_SWAP_MODE_HALF_WORD
521  *  @arg @ref DMA_SWAP_MODE_WORD
522  *
523  */
dma_set_swap_mode(DMAV2_Type * ptr,uint32_t ch_index,uint8_t swap_mode)524 static inline void dma_set_swap_mode(DMAV2_Type *ptr, uint32_t ch_index, uint8_t swap_mode)
525 {
526     ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMAV2_CHCTRL_CTRL_SWAP_CTL_MASK) | DMAV2_CHCTRL_CTRL_SWAP_CTL_SET(swap_mode);
527 }
528 
529 /**
530  * @brief   Set DMA channel swap table
531  *
532  * @param[in] ptr DMA base address
533  * @param[in] ch_index Index of the channel
534  * @param[in] swap_table swap table
535  *
536  */
dma_set_swap_table(DMAV2_Type * ptr,uint32_t ch_index,uint32_t swap_table)537 static inline void dma_set_swap_table(DMAV2_Type *ptr, uint32_t ch_index, uint32_t swap_table)
538 {
539     ptr->CHCTRL[ch_index].SWAPTABLE = swap_table;
540 }
541 #endif
542 
543 /**
544  * @brief   Abort channel transfer with mask
545  *
546  * @param[in] ptr DMA base address
547  * @param[in] ch_index_mask Mask of channels to be aborted
548  */
dma_abort_channel(DMAV2_Type * ptr,uint32_t ch_index_mask)549 static inline void dma_abort_channel(DMAV2_Type *ptr, uint32_t ch_index_mask)
550 {
551     ptr->CHABORT |= DMAV2_CHABORT_CHABORT_SET(ch_index_mask);
552 }
553 
554 /**
555  * @brief   Check if channels are enabled with mask
556  *
557  * @param[in] ptr DMA base address
558  * @param[in] ch_index_mask Mask of channels to be checked
559  *
560  * @return Enabled channel mask
561  */
dma_check_enabled_channel(DMAV2_Type * ptr,uint32_t ch_index_mask)562 static inline uint32_t dma_check_enabled_channel(DMAV2_Type *ptr,
563                                                   uint32_t ch_index_mask)
564 {
565     return (ch_index_mask & ptr->CHEN);
566 }
567 
568 /**
569  * @brief   Check if linked pointer has been configured
570  *
571  * @param[in] ptr DMA base address
572  * @param[in] ch_index Target channel index to be checked
573  *
574  * @return true if linked pointer has been configured
575  */
dma_has_linked_pointer_configured(DMAV2_Type * ptr,uint32_t ch_index)576 static inline bool dma_has_linked_pointer_configured(DMAV2_Type *ptr, uint32_t ch_index)
577 {
578     return ptr->CHCTRL[ch_index].LLPOINTER != 0;
579 }
580 
581 /**
582  * @brief   Check transfer status
583  *
584  * @param[in] ptr DMA base address
585  * @param[in] ch_index Target channel index to be checked
586  *
587  * @retval DMA_CHANNEL_STATUS_ONGOING if transfer is still ongoing
588  * @retval DMA_CHANNEL_STATUS_ERROR if any error occurred during transferring
589  * @retval DMA_CHANNEL_STATUS_ABORT if transfer is aborted
590  * @retval DMA_CHANNEL_STATUS_TC if transfer is finished without error
591  * @retval DMA_CHANNEL_STATUS_HALF_TC if half transfer complete without error
592  */
dma_check_transfer_status(DMAV2_Type * ptr,uint8_t ch_index)593 static inline uint32_t dma_check_transfer_status(DMAV2_Type *ptr, uint8_t ch_index)
594 {
595     uint32_t dma_status = 0;
596 
597     if (ptr->INTTCSTS & (1 << ch_index)) {
598         dma_status |= DMA_CHANNEL_STATUS_TC;
599         ptr->INTTCSTS = (1 << ch_index); /* W1C clear status*/
600     }
601     if (ptr->INTHALFSTS & (1 << ch_index)) {
602         dma_status |= DMA_CHANNEL_STATUS_HALF_TC;
603         ptr->INTHALFSTS = (1 << ch_index); /* W1C clear status*/
604     }
605     if (ptr->INTERRSTS & (1 << ch_index)) {
606         dma_status |= DMA_CHANNEL_STATUS_ERROR;
607         ptr->INTERRSTS = (1 << ch_index); /* W1C clear status*/
608     }
609     if (ptr->INTABORTSTS & (1 << ch_index)) {
610         dma_status |= DMA_CHANNEL_STATUS_ABORT;
611         ptr->INTABORTSTS = (1 << ch_index); /* W1C clear status*/
612     }
613     if (dma_status == 0) {
614         dma_status = DMA_CHANNEL_STATUS_ONGOING;
615     }
616     return dma_status;
617 }
618 
619 /**
620  * @brief   Clear transfer status
621  *
622  * @param[in] ptr DMA base address
623  * @param[in] ch_index Target channel index
624  *
625  */
dma_clear_transfer_status(DMAV2_Type * ptr,uint8_t ch_index)626 static inline void dma_clear_transfer_status(DMAV2_Type *ptr, uint8_t ch_index)
627 {
628     /* W1C */
629     ptr->INTHALFSTS  = (1 << ch_index);
630     ptr->INTTCSTS    = (1 << ch_index);
631     ptr->INTABORTSTS = (1 << ch_index);
632     ptr->INTERRSTS   = (1 << ch_index);
633 }
634 
635 /**
636  * @brief Enable DMA Channel interrupt
637  *
638  * @param [in] ptr DMA base address
639  * @param [in] ch_index Target channel index
640  * @param [in] interrupt_mask Interrupt mask
641  */
dma_enable_channel_interrupt(DMAV2_Type * ptr,uint8_t ch_index,int32_t interrupt_mask)642 static inline void dma_enable_channel_interrupt(DMAV2_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
643 {
644     ptr->CHCTRL[ch_index].CTRL &= ~(interrupt_mask & DMA_INTERRUPT_MASK_ALL);
645 }
646 
647 /**
648  * @brief Disable DMA Channel interrupt
649  *
650  * @param [in] ptr DMA base address
651  * @param [in] ch_index Target channel index
652  * @param [in] interrupt_mask Interrupt mask
653  */
dma_disable_channel_interrupt(DMAV2_Type * ptr,uint8_t ch_index,int32_t interrupt_mask)654 static inline void dma_disable_channel_interrupt(DMAV2_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
655 {
656     ptr->CHCTRL[ch_index].CTRL |= (interrupt_mask & DMA_INTERRUPT_MASK_ALL);
657 }
658 
659 
660 /**
661  * @brief Check Channel interrupt master
662  *
663  * @param[in] ptr DMA base address
664  * @param[in] ch_index Target channel index to be checked
665  * @return uint32_t Interrupt mask
666  */
dma_check_channel_interrupt_mask(DMAV2_Type * ptr,uint8_t ch_index)667 static inline uint32_t dma_check_channel_interrupt_mask(DMAV2_Type *ptr, uint8_t ch_index)
668 {
669     return ptr->CHCTRL[ch_index].CTRL & DMA_INTERRUPT_MASK_ALL;
670 }
671 
672 /**
673  * @brief   Get default channel config
674  *
675  * @param[in] ptr DMA base address
676  * @param[in] ch Channel config
677  */
678 void dma_default_channel_config(DMAV2_Type *ptr, dma_channel_config_t *ch);
679 
680 /**
681  * @brief   Setup DMA channel
682  *
683  * @param[in] ptr DMA base address
684  * @param[in] ch_num Target channel index to be configured
685  * @param[in] ch Channel config
686  * @param[in] start_transfer Set true to start transfer
687  *
688  * @return  status_success if everything is okay
689  */
690 hpm_stat_t dma_setup_channel(DMAV2_Type *ptr, uint8_t ch_num,
691                             dma_channel_config_t *ch, bool start_transfer);
692 
693 /**
694  * @brief   Config linked descriptor function
695  *
696  * @param[in] ptr DMA base address
697  * @param[in] descriptor Linked descriptor pointer
698  * @param[in] ch_num Target channel index to be configured
699  * @param[in] config Descriptor config pointer
700  *
701  * @return status_success if everything is okay
702  */
703 hpm_stat_t dma_config_linked_descriptor(DMAV2_Type *ptr, dma_linked_descriptor_t *descriptor, uint8_t ch_num, dma_channel_config_t *config);
704 
705 /**
706  * @brief   Start DMA copy
707  *
708  * @param[in] ptr DMA base address
709  * @param[in] ch_num Target channel index
710  * @param[in] dst Destination address
711  * @param[in] src Source Address
712  * @param[in] size_in_byte Size in byte
713  * @param[in] burst_len_in_byte Burst length in byte
714  *
715  * @return status_success if everthing is okay
716  * @note: dst, src, size should be aligned with burst_len_in_byte
717  */
718 hpm_stat_t dma_start_memcpy(DMAV2_Type *ptr, uint8_t ch_num,
719                                uint32_t dst, uint32_t src,
720                                uint32_t size_in_byte, uint32_t burst_len_in_byte);
721 
722 /**
723  * @brief   Get default handshake config
724  *
725  * @param[in] ptr DMA base address
726  * @param[in] config default config
727  */
728 void dma_default_handshake_config(DMAV2_Type *ptr, dma_handshake_config_t *config);
729 
730 /**
731  * @brief   config dma handshake function
732  *
733  * @param[in] ptr DMA base address
734  * @param[in] pconfig dma handshake config pointer
735  * @param[in] start_transfer Set true to start transfer
736  *
737  * @return status_success if everything is okay
738  */
739 hpm_stat_t dma_setup_handshake(DMAV2_Type *ptr,  dma_handshake_config_t *pconfig, bool start_transfer);
740 
741 /**
742  * @brief Check whether DMA is idle
743  * @param [in] ptr DMA base address
744  * @return true DMA is idle
745  * @return false DMA is busy
746  */
dma_is_idle(DMAV2_Type * ptr)747 static inline bool dma_is_idle(DMAV2_Type *ptr)
748 {
749     return (DMAV2_IDMISC_DMASTATE_GET(ptr->IDMISC) == dmav2_state_idle) ? true : false;
750 }
751 
752 
753 #ifdef __cplusplus
754 }
755 #endif
756 /**
757  * @}
758  */
759 #endif /* HPM_DMAV2_DRV_H */
760