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