1 /*
2 * Copyright (c) 2021-2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8
9 #ifndef HPM_DMAV1_DRV_H
10 #define HPM_DMAV1_DRV_H
11 #include "hpm_common.h"
12 #include "hpm_soc_feature.h"
13 #include "hpm_dma_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_CHANNEL_PRIORITY_LOW (0U)
24 #define DMA_CHANNEL_PRIORITY_HIGH (1U)
25
26 #define DMA_NUM_TRANSFER_PER_BURST_1T (0U)
27 #define DMA_NUM_TRANSFER_PER_BURST_2T (1U)
28 #define DMA_NUM_TRANSFER_PER_BURST_4T (2U)
29 #define DMA_NUM_TRANSFER_PER_BURST_8T (3U)
30 #define DMA_NUM_TRANSFER_PER_BURST_16T (4U)
31 #define DMA_NUM_TRANSFER_PER_BURST_32T (5U)
32 #define DMA_NUM_TRANSFER_PER_BURST_64T (6U)
33 #define DMA_NUM_TRANSFER_PER_BURST_128T (7U)
34 #define DMA_NUM_TRANSFER_PER_BURST_256T (8U)
35 #define DMA_NUM_TRANSFER_PER_BURST_512T (9U)
36 #define DMA_NUM_TRANSFER_PER_BURST_1024T (10U)
37
38 #define DMA_TRANSFER_WIDTH_BYTE (0U)
39 #define DMA_TRANSFER_WIDTH_HALF_WORD (1U)
40 #define DMA_TRANSFER_WIDTH_WORD (2U)
41 #define DMA_TRANSFER_WIDTH_DOUBLE_WORD (3U)
42
43 #define DMA_ALIGN_HALF_WORD(x) (x & ~(1u))
44 #define DMA_ALIGN_WORD(x) (x & ~(3u))
45 #define DMA_ALIGN_DOUBLE_WORD(x) (x & ~(7u))
46
47 #define DMA_STATUS_ERROR_SHIFT (0U)
48 #define DMA_STATUS_ABORT_SHIFT (8U)
49 #define DMA_STATUS_TC_SHIFT (16U)
50
51 #define DMA_CHANNEL_STATUS_ONGOING (1U)
52 #define DMA_CHANNEL_STATUS_ERROR (2U)
53 #define DMA_CHANNEL_STATUS_ABORT (4U)
54 #define DMA_CHANNEL_STATUS_TC (8U)
55
56 #define DMA_CHANNEL_IRQ_STATUS_ERROR(x) (uint32_t)(1 << (DMA_STATUS_ERROR_SHIFT + x))
57 #define DMA_CHANNEL_IRQ_STATUS_ABORT(x) (uint32_t)(1 << (DMA_STATUS_ABORT_SHIFT + x))
58 #define DMA_CHANNEL_IRQ_STATUS_TC(x) (uint32_t)(1 << (DMA_STATUS_TC_SHIFT + x))
59 #define DMA_CHANNEL_IRQ_STATUS(x) (uint32_t)(DMA_CHANNEL_IRQ_STATUS_TC(x) | \
60 DMA_CHANNEL_IRQ_STATUS_ABORT(x) | \
61 DMA_CHANNEL_IRQ_STATUS_ERROR(x))
62
63 #define DMA_CHANNEL_IRQ_STATUS_GET_ALL_TC(x) ((x) & (((0x01UL << DMA_SOC_CHANNEL_NUM) - 1) << DMA_STATUS_TC_SHIFT))
64 #define DMA_CHANNEL_IRQ_STATUS_GET_ALL_ABORT(x) ((x) & (((0x01UL << DMA_SOC_CHANNEL_NUM) - 1) << DMA_STATUS_ABORT_SHIFT))
65 #define DMA_CHANNEL_IRQ_STATUS_GET_ALL_ERROR(x) ((x) & (((0x01UL << DMA_SOC_CHANNEL_NUM) - 1) << DMA_STATUS_ERROR_SHIFT))
66
67 #define DMA_HANDSHAKE_MODE_NORMAL (0U)
68 #define DMA_HANDSHAKE_MODE_HANDSHAKE (1U)
69
70 #define DMA_ADDRESS_CONTROL_INCREMENT (0U)
71 #define DMA_ADDRESS_CONTROL_DECREMENT (1U)
72 #define DMA_ADDRESS_CONTROL_FIXED (2U)
73
74 #define DMA_INTERRUPT_MASK_NONE (0U)
75 #define DMA_INTERRUPT_MASK_ERROR DMA_CHCTRL_CTRL_INTERRMASK_MASK
76 #define DMA_INTERRUPT_MASK_ABORT DMA_CHCTRL_CTRL_INTABTMASK_MASK
77 #define DMA_INTERRUPT_MASK_TERMINAL_COUNT DMA_CHCTRL_CTRL_INTTCMASK_MASK
78 #define DMA_INTERRUPT_MASK_ALL \
79 (uint8_t)(DMA_INTERRUPT_MASK_TERMINAL_COUNT \
80 | DMA_INTERRUPT_MASK_ABORT \
81 | DMA_INTERRUPT_MASK_ERROR)
82
83 #ifndef DMA_SUPPORT_64BIT_ADDR
84 #define DMA_SUPPORT_64BIT_ADDR (0)
85 #endif
86
87 /**
88 * @brief Linked descriptor
89 *
90 * It is consumed by DMA controlled directly
91 */
92 typedef struct dma_linked_descriptor {
93 uint32_t ctrl; /**< Control */
94 uint32_t trans_size; /**< Transfer size in source width */
95 uint32_t src_addr; /**< Source address */
96 uint32_t src_addr_high; /**< Source address high 32-bit, only valid when bus width > 32bits */
97 uint32_t dst_addr; /**< Destination address */
98 uint32_t dst_addr_high; /**< Destination address high 32-bit, only valid when bus width > 32bits */
99 uint32_t linked_ptr; /**< Linked descriptor address */
100 uint32_t linked_ptr_high; /**< Linked descriptor address high 32-bit, , only valid when bus width > 32bits */
101 } dma_linked_descriptor_t;
102
103 /* @brief Channel config */
104 typedef struct dma_channel_config {
105 uint8_t priority; /**< Channel priority */
106 uint8_t src_burst_size; /**< Source burst size */
107 uint8_t src_mode; /**< Source work mode */
108 uint8_t dst_mode; /**< Destination work mode */
109 uint8_t src_width; /**< Source width */
110 uint8_t dst_width; /**< Destination width */
111 uint8_t src_addr_ctrl; /**< Source address control */
112 uint8_t dst_addr_ctrl; /**< Destination address control */
113 uint16_t interrupt_mask; /**< Interrupt mask */
114 uint32_t src_addr; /**< Source address */
115 uint32_t dst_addr; /**< Destination address */
116 uint32_t linked_ptr; /**< Next linked descriptor */
117 uint32_t size_in_byte; /**< Total size to be transferred in byte */
118 #if DMA_SUPPORT_64BIT_ADDR
119 uint32_t src_addr_high; /**< Source address high 32bits */
120 uint32_t dst_addr_high; /**< Destination address high 32bits */
121 uint32_t linked_ptr_high; /**< Linked descriptor high 32bits */
122 #endif
123 } dma_channel_config_t;
124
125
126 /* @brief Channel config */
127 typedef struct dma_handshake_config {
128 uint32_t dst;
129 uint32_t src;
130 uint32_t size_in_byte;
131 uint8_t data_width; /* data width, value defined by DMA_TRANSFER_WIDTH_xxx */
132 uint8_t ch_index;
133 bool dst_fixed;
134 bool src_fixed;
135 } dma_handshake_config_t;
136
137
138 /* @brief DMA specific status */
139 enum {
140 status_dma_transfer_done = MAKE_STATUS(status_group_dma, 0),
141 status_dma_transfer_error = MAKE_STATUS(status_group_dma, 1),
142 status_dma_transfer_abort = MAKE_STATUS(status_group_dma, 2),
143 status_dma_transfer_ongoing = MAKE_STATUS(status_group_dma, 3),
144 status_dma_alignment_error = MAKE_STATUS(status_group_dma, 4),
145 };
146
147 #ifdef __cplusplus
148 extern "C" {
149 #endif
150
151 /**
152 * @brief Reset DMA
153 *
154 * @param[in] ptr DMA base address
155 */
dma_reset(DMA_Type * ptr)156 static inline void dma_reset(DMA_Type *ptr)
157 {
158 ptr->DMACTRL |= DMA_DMACTRL_RESET_MASK;
159 }
160
161 /**
162 * @brief Enable DMA channel
163 *
164 * @param[in] ptr DMA base address
165 * @param[in] ch_index Index of the channel to be enabled
166 *
167 * @return status_success if everything's okay
168 */
dma_enable_channel(DMA_Type * ptr,uint32_t ch_index)169 static inline hpm_stat_t dma_enable_channel(DMA_Type *ptr, uint32_t ch_index)
170 {
171 ptr->CHCTRL[ch_index].CTRL |= DMA_CHCTRL_CTRL_ENABLE_MASK;
172
173 if ((ptr->CHEN == 0) || !(ptr->CHEN & 1 << ch_index)) {
174 return status_fail;
175 }
176 return status_success;
177 }
178
179 /**
180 * @brief Disable DMA channel
181 *
182 * @param[in] ptr DMA base address
183 * @param[in] ch_index Index of the channel to be disabled
184 *
185 */
dma_disable_channel(DMA_Type * ptr,uint32_t ch_index)186 static inline void dma_disable_channel(DMA_Type *ptr, uint32_t ch_index)
187 {
188 ptr->CHCTRL[ch_index].CTRL &= ~DMA_CHCTRL_CTRL_ENABLE_MASK;
189 }
190
191 /**
192 * @brief Check whether DMA channel is enable
193 *
194 * @param[in] ptr DMA base address
195 * @param[in] ch_index Index of the channel
196 *
197 * @return true if DMA channel is enable
198 *
199 */
dma_channel_is_enable(DMA_Type * ptr,uint32_t ch_index)200 static inline bool dma_channel_is_enable(DMA_Type *ptr, uint32_t ch_index)
201 {
202 return (ptr->CHCTRL[ch_index].CTRL & DMA_CHCTRL_CTRL_ENABLE_MASK) ? true : false;
203 }
204
205 /**
206 * @brief Set DMA channel priority
207 *
208 * @param[in] ptr DMA base address
209 * @param[in] ch_index Index of the channel
210 * @param[in] priority dma priority
211 * @arg @ref DMA_PRIORITY_LOW
212 * @arg @ref DMA_PRIORITY_HIGH
213 *
214 */
dma_set_priority(DMA_Type * ptr,uint32_t ch_index,uint8_t priority)215 static inline void dma_set_priority(DMA_Type *ptr, uint32_t ch_index, uint8_t priority)
216 {
217 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_PRIORITY_MASK) | DMA_CHCTRL_CTRL_PRIORITY_SET(priority);
218 }
219
220 /**
221 * @brief Set DMA channel source work mode
222 *
223 * @param[in] ptr DMA base address
224 * @param[in] ch_index Index of the channel
225 * @param[in] mode source work mode
226 * @arg @ref DMA_HANDSHAKE_MODE_NORMAL
227 * @arg @ref DMA_HANDSHAKE_MODE_HANDSHAKE
228 *
229 */
dma_set_source_work_mode(DMA_Type * ptr,uint32_t ch_index,uint8_t mode)230 static inline void dma_set_source_work_mode(DMA_Type *ptr, uint32_t ch_index, uint8_t mode)
231 {
232 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_SRCMODE_MASK) | DMA_CHCTRL_CTRL_SRCMODE_SET(mode);
233 }
234
235 /**
236 * @brief Set DMA channel destination work mode
237 *
238 * @param[in] ptr DMA base address
239 * @param[in] ch_index Index of the channel
240 * @param[in] mode destination work mode
241 * @arg @ref DMA_HANDSHAKE_MODE_NORMAL
242 * @arg @ref DMA_HANDSHAKE_MODE_HANDSHAKE
243 *
244 */
dma_set_destination_work_mode(DMA_Type * ptr,uint32_t ch_index,uint8_t mode)245 static inline void dma_set_destination_work_mode(DMA_Type *ptr, uint32_t ch_index, uint8_t mode)
246 {
247 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_DSTMODE_MASK) | DMA_CHCTRL_CTRL_DSTMODE_SET(mode);
248 }
249
250 /**
251 * @brief Set DMA channel source burst size
252 *
253 * @param[in] ptr DMA base address
254 * @param[in] ch_index Index of the channel
255 * @param[in] burstsize source burst size
256 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_1T
257 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_2T
258 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_4T
259 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_8T
260 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_16T
261 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_32T
262 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_64T
263 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_128T
264 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_256T
265 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_512T
266 * @arg @ref DMA_NUM_TRANSFER_PER_BURST_1024T
267 *
268 */
dma_set_source_burst_size(DMA_Type * ptr,uint32_t ch_index,uint8_t burstsize)269 static inline void dma_set_source_burst_size(DMA_Type *ptr, uint32_t ch_index, uint8_t burstsize)
270 {
271 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_SRCBURSTSIZE_MASK) | DMA_CHCTRL_CTRL_SRCBURSTSIZE_SET(burstsize);
272 }
273
274 /**
275 * @brief Get DMA channel remaining transfer size
276 *
277 * @param[in] ptr DMA base address
278 * @param[in] ch_index Index of the channel
279 *
280 * @return remaining transfer size
281 *
282 */
dma_get_remaining_transfer_size(DMA_Type * ptr,uint32_t ch_index)283 static inline uint32_t dma_get_remaining_transfer_size(DMA_Type *ptr, uint32_t ch_index)
284 {
285 return ptr->CHCTRL[ch_index].TRANSIZE;
286 }
287
288 /**
289 * @brief Set DMA channel transfer size
290 *
291 * @param[in] ptr DMA base address
292 * @param[in] ch_index Index of the channel
293 * @param[in] size_in_width transfer size of the channel. The width is current dma channel configured source width.
294 * Transfer total bytes are (size_in_width * source width).
295 *
296 */
dma_set_transfer_size(DMA_Type * ptr,uint32_t ch_index,uint32_t size_in_width)297 static inline void dma_set_transfer_size(DMA_Type *ptr, uint32_t ch_index, uint32_t size_in_width)
298 {
299 ptr->CHCTRL[ch_index].TRANSIZE = DMA_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_width);
300 }
301
302 /**
303 * @brief Set DMA channel source width
304 *
305 * @param[in] ptr DMA base address
306 * @param[in] ch_index Index of the channel
307 * @param[in] width transfer source width of the channel
308 * @arg @ref DMA_TRANSFER_WIDTH_BYTE
309 * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
310 * @arg @ref DMA_TRANSFER_WIDTH_WORD
311 * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
312 */
dma_set_source_width(DMA_Type * ptr,uint32_t ch_index,uint8_t width)313 static inline void dma_set_source_width(DMA_Type *ptr, uint32_t ch_index, uint8_t width)
314 {
315 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_SRCWIDTH_MASK) | DMA_CHCTRL_CTRL_SRCWIDTH_SET(width);
316 }
317
318 /**
319 * @brief Set DMA channel destination width
320 *
321 * @param[in] ptr DMA base address
322 * @param[in] ch_index Index of the channel
323 * @param[in] width transfer destination width of the channel
324 * @arg @ref DMA_TRANSFER_WIDTH_BYTE
325 * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
326 * @arg @ref DMA_TRANSFER_WIDTH_WORD
327 * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
328 */
dma_set_destination_width(DMA_Type * ptr,uint32_t ch_index,uint8_t width)329 static inline void dma_set_destination_width(DMA_Type *ptr, uint32_t ch_index, uint8_t width)
330 {
331 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_DSTWIDTH_MASK) | DMA_CHCTRL_CTRL_DSTWIDTH_SET(width);
332 }
333
334 /**
335 * @brief Set DMA channel transfer width and size in byte
336 *
337 * @param[in] ptr DMA base address
338 * @param[in] ch_index Index of the channel
339 * @param[in] src_width transfer source width of the channel
340 * @arg @ref DMA_TRANSFER_WIDTH_BYTE
341 * @arg @ref DMA_TRANSFER_WIDTH_HALF_WORD
342 * @arg @ref DMA_TRANSFER_WIDTH_WORD
343 * @arg @ref DMA_TRANSFER_WIDTH_DOUBLE_WORD
344 * @param[in] size_in_byte transfer size in byte of the channel. The dma transfer size is (size_in_byte >> src_width).
345 *
346 */
dma_set_transfer_src_width_byte_size(DMA_Type * ptr,uint32_t ch_index,uint8_t src_width,uint32_t size_in_byte)347 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)
348 {
349 assert((src_width == DMA_TRANSFER_WIDTH_BYTE) || (src_width == DMA_TRANSFER_WIDTH_HALF_WORD)
350 || (src_width == DMA_TRANSFER_WIDTH_WORD) || (src_width == DMA_TRANSFER_WIDTH_DOUBLE_WORD));
351
352 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_SRCWIDTH_MASK) | DMA_CHCTRL_CTRL_SRCWIDTH_SET(src_width);
353 ptr->CHCTRL[ch_index].TRANSIZE = DMA_CHCTRL_TRANSIZE_TRANSIZE_SET(size_in_byte >> src_width);
354 }
355
356 /**
357 * @brief Set DMA channel source address
358 *
359 * @param[in] ptr DMA base address
360 * @param[in] ch_index Index of the channel
361 * @param[in] addr source address
362 *
363 */
dma_set_source_address(DMA_Type * ptr,uint32_t ch_index,uint32_t addr)364 static inline void dma_set_source_address(DMA_Type *ptr, uint32_t ch_index, uint32_t addr)
365 {
366 ptr->CHCTRL[ch_index].SRCADDR = addr;
367 }
368
369 /**
370 * @brief Set DMA channel destination address
371 *
372 * @param[in] ptr DMA base address
373 * @param[in] ch_index Index of the channel
374 * @param[in] addr destination address
375 *
376 */
dma_set_destination_address(DMA_Type * ptr,uint32_t ch_index,uint32_t addr)377 static inline void dma_set_destination_address(DMA_Type *ptr, uint32_t ch_index, uint32_t addr)
378 {
379 ptr->CHCTRL[ch_index].DSTADDR = addr;
380 }
381
382 /**
383 * @brief Set DMA channel source address control mode
384 *
385 * @param[in] ptr DMA base address
386 * @param[in] ch_index Index of the channel
387 * @param[in] addr_ctrl source address control mode
388 * @arg @ref DMA_ADDRESS_CONTROL_INCREMENT
389 * @arg @ref DMA_ADDRESS_CONTROL_DECREMENT
390 * @arg @ref DMA_ADDRESS_CONTROL_FIXED
391 *
392 */
dma_set_source_address_ctrl(DMA_Type * ptr,uint32_t ch_index,uint8_t addr_ctrl)393 static inline void dma_set_source_address_ctrl(DMA_Type *ptr, uint32_t ch_index, uint8_t addr_ctrl)
394 {
395 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_SRCADDRCTRL_MASK) | DMA_CHCTRL_CTRL_SRCADDRCTRL_SET(addr_ctrl);
396 }
397
398 /**
399 * @brief Set DMA channel destination address control mode
400 *
401 * @param[in] ptr DMA base address
402 * @param[in] ch_index Index of the channel
403 * @param[in] addr_ctrl destination address control mode
404 * @arg @ref DMA_ADDRESS_CONTROL_INCREMENT
405 * @arg @ref DMA_ADDRESS_CONTROL_DECREMENT
406 * @arg @ref DMA_ADDRESS_CONTROL_FIXED
407 *
408 */
dma_set_destination_address_ctrl(DMA_Type * ptr,uint32_t ch_index,uint8_t addr_ctrl)409 static inline void dma_set_destination_address_ctrl(DMA_Type *ptr, uint32_t ch_index, uint8_t addr_ctrl)
410 {
411 ptr->CHCTRL[ch_index].CTRL = (ptr->CHCTRL[ch_index].CTRL & ~DMA_CHCTRL_CTRL_DSTADDRCTRL_MASK) | DMA_CHCTRL_CTRL_DSTADDRCTRL_SET(addr_ctrl);
412 }
413
414 /**
415 * @brief Abort channel transfer with mask
416 *
417 * @param[in] ptr DMA base address
418 * @param[in] ch_index_mask Mask of channels to be aborted
419 */
dma_abort_channel(DMA_Type * ptr,uint32_t ch_index_mask)420 static inline void dma_abort_channel(DMA_Type *ptr, uint32_t ch_index_mask)
421 {
422 ptr->CHABORT |= DMA_CHABORT_CHABORT_SET(ch_index_mask);
423 }
424
425 /**
426 * @brief Check if channels are enabled with mask
427 *
428 * @param[in] ptr DMA base address
429 * @param[in] ch_index_mask Mask of channels to be checked
430 *
431 * @return Enabled channel mask
432 */
dma_check_enabled_channel(DMA_Type * ptr,uint32_t ch_index_mask)433 static inline uint32_t dma_check_enabled_channel(DMA_Type *ptr,
434 uint32_t ch_index_mask)
435 {
436 return (ch_index_mask & ptr->CHEN);
437 }
438
439 /**
440 * @brief Check if linked pointer has been configured
441 *
442 * @param[in] ptr DMA base address
443 * @param[in] ch_index Target channel index to be checked
444 *
445 * @return true if linked pointer has been configured
446 */
dma_has_linked_pointer_configured(DMA_Type * ptr,uint32_t ch_index)447 static inline bool dma_has_linked_pointer_configured(DMA_Type *ptr, uint32_t ch_index)
448 {
449 return ptr->CHCTRL[ch_index].LLPOINTER != 0;
450 }
451
452 /**
453 * @brief Check transfer status
454 *
455 * @param[in] ptr DMA base address
456 * @param[in] ch_index Target channel index to be checked
457 *
458 * @retval DMA_CHANNEL_STATUS_ONGOING if transfer is still ongoing
459 * @retval DMA_CHANNEL_STATUS_ERROR if any error occurred during transferring
460 * @retval DMA_CHANNEL_STATUS_ABORT if transfer is aborted
461 * @retval DMA_CHANNEL_STATUS_TC if transfer is finished without error
462 */
dma_check_transfer_status(DMA_Type * ptr,uint8_t ch_index)463 static inline uint32_t dma_check_transfer_status(DMA_Type *ptr, uint8_t ch_index)
464 {
465 volatile uint32_t tmp = ptr->INTSTATUS;
466 volatile uint32_t tmp_channel;
467 uint32_t dma_status;
468
469 dma_status = 0;
470 tmp_channel = tmp & (1 << (DMA_STATUS_TC_SHIFT + ch_index));
471 if (tmp_channel) {
472 dma_status |= DMA_CHANNEL_STATUS_TC;
473 ptr->INTSTATUS = tmp_channel;
474 }
475 tmp_channel = tmp & (1 << (DMA_STATUS_ERROR_SHIFT + ch_index));
476 if (tmp_channel) {
477 dma_status |= DMA_CHANNEL_STATUS_ERROR;
478 ptr->INTSTATUS = tmp_channel;
479 }
480 tmp_channel = tmp & (1 << (DMA_STATUS_ABORT_SHIFT + ch_index));
481 if (tmp_channel) {
482 dma_status |= DMA_CHANNEL_STATUS_ABORT;
483 ptr->INTSTATUS = tmp_channel;
484 }
485 if (dma_status == 0) {
486 dma_status = DMA_CHANNEL_STATUS_ONGOING;
487 }
488 return dma_status;
489 }
490
491 /**
492 * @brief Clear transfer status
493 *
494 * @param[in] ptr DMA base address
495 * @param[in] ch_index Target channel index
496 *
497 */
dma_clear_transfer_status(DMA_Type * ptr,uint8_t ch_index)498 static inline void dma_clear_transfer_status(DMA_Type *ptr, uint8_t ch_index)
499 {
500 ptr->INTSTATUS &= ~((1 << (DMA_STATUS_TC_SHIFT + ch_index)) | (1 << (DMA_STATUS_ERROR_SHIFT + ch_index)) | (1 << (DMA_STATUS_ABORT_SHIFT + ch_index)));
501 }
502
503 /**
504 * @brief Enable DMA Channel interrupt
505 *
506 * @param [in] ptr DMA base address
507 * @param [in] ch_index Target channel index
508 * @param [in] interrupt_mask Interrupt mask
509 */
dma_enable_channel_interrupt(DMA_Type * ptr,uint8_t ch_index,int32_t interrupt_mask)510 static inline void dma_enable_channel_interrupt(DMA_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
511 {
512 ptr->CHCTRL[ch_index].CTRL &= ~(interrupt_mask & DMA_INTERRUPT_MASK_ALL);
513 }
514
515 /**
516 * @brief Disable DMA Channel interrupt
517 *
518 * @param [in] ptr DMA base address
519 * @param [in] ch_index Target channel index
520 * @param [in] interrupt_mask Interrupt mask
521 */
dma_disable_channel_interrupt(DMA_Type * ptr,uint8_t ch_index,int32_t interrupt_mask)522 static inline void dma_disable_channel_interrupt(DMA_Type *ptr, uint8_t ch_index, int32_t interrupt_mask)
523 {
524 ptr->CHCTRL[ch_index].CTRL |= (interrupt_mask & DMA_INTERRUPT_MASK_ALL);
525 }
526
527
528 /**
529 * @brief Check Channel interrupt master
530 *
531 * @param[in] ptr DMA base address
532 * @param[in] ch_index Target channel index to be checked
533 * @return uint32_t Interrupt mask
534 */
dma_check_channel_interrupt_mask(DMA_Type * ptr,uint8_t ch_index)535 static inline uint32_t dma_check_channel_interrupt_mask(DMA_Type *ptr, uint8_t ch_index)
536 {
537 return ptr->CHCTRL[ch_index].CTRL & DMA_INTERRUPT_MASK_ALL;
538 }
539
540 /**
541 * @brief Get clear IRQ status
542 *
543 * @param[in] ptr DMA base address
544 * @param[in] mask irq mask to be cleared
545 */
dma_clear_irq_status(DMA_Type * ptr,uint32_t mask)546 static inline void dma_clear_irq_status(DMA_Type *ptr, uint32_t mask)
547 {
548 ptr->INTSTATUS = mask; /* Write-1-Clear */
549 }
550
551 /**
552 * @brief Get IRQ status
553 *
554 * @param[in] ptr DMA base address
555 */
dma_get_irq_status(DMA_Type * ptr)556 static inline uint32_t dma_get_irq_status(DMA_Type *ptr)
557 {
558 return ptr->INTSTATUS;
559 }
560
561 /**
562 * @brief Get default channel config
563 *
564 * @param[in] ptr DMA base address
565 * @param[in] ch Channel config
566 */
567 void dma_default_channel_config(DMA_Type *ptr, dma_channel_config_t *ch);
568
569 /**
570 * @brief Setup DMA channel
571 *
572 * @param[in] ptr DMA base address
573 * @param[in] ch_num Target channel index to be configured
574 * @param[in] ch Channel config
575 * @param[in] start_transfer Set true to start transfer
576 *
577 * @return status_success if everything is okay
578 */
579 hpm_stat_t dma_setup_channel(DMA_Type *ptr, uint8_t ch_num,
580 dma_channel_config_t *ch, bool start_transfer);
581
582 /**
583 * @brief Config linked descriptor function
584 *
585 * @param[in] ptr DMA base address
586 * @param[in] descriptor Linked descriptor pointer
587 * @param[in] ch_num Target channel index to be configured
588 * @param[in] config Descriptor config pointer
589 *
590 * @return status_success if everything is okay
591 */
592 hpm_stat_t dma_config_linked_descriptor(DMA_Type *ptr, dma_linked_descriptor_t *descriptor, uint8_t ch_num, dma_channel_config_t *config);
593
594 /**
595 * @brief Start DMA copy
596 *
597 * @param[in] ptr DMA base address
598 * @param[in] ch_num Target channel index
599 * @param[in] dst Destination address
600 * @param[in] src Source Address
601 * @param[in] size_in_byte Size in byte
602 * @param[in] burst_len_in_byte Burst length in byte
603 *
604 * @return status_success if everthing is okay
605 * @note: dst, src, size should be aligned with burst_len_in_byte
606 */
607 hpm_stat_t dma_start_memcpy(DMA_Type *ptr, uint8_t ch_num,
608 uint32_t dst, uint32_t src,
609 uint32_t size_in_byte, uint32_t burst_len_in_byte);
610
611 /**
612 * @brief Get default handshake config
613 *
614 * @param[in] ptr DMA base address
615 * @param[in] config default config
616 */
617 void dma_default_handshake_config(DMA_Type *ptr, dma_handshake_config_t *config);
618
619 /**
620 * @brief config dma handshake function
621 *
622 * @param[in] ptr DMA base address
623 * @param[in] pconfig dma handshake config pointer
624 * @param[in] start_transfer Set true to start transfer
625 *
626 * @return status_success if everything is okay
627 */
628 hpm_stat_t dma_setup_handshake(DMA_Type *ptr, dma_handshake_config_t *pconfig, bool start_transfer);
629
630
631 #if defined(DMA_SOC_HAS_IDLE_FLAG) && (DMA_SOC_HAS_IDLE_FLAG == 1)
632 /**
633 * @brief Check whether DMA is idle
634 * @param [in] ptr DMA base address
635 * @return true DMA is idle
636 * @return false DMA is busy
637 */
dma_is_idle(DMA_Type * ptr)638 static inline bool dma_is_idle(DMA_Type *ptr)
639 {
640 return ((ptr->IDMISC & DMA_IDMISC_IDLE_FLAG_MASK) != 0U);
641 }
642 #endif
643
644
645 #ifdef __cplusplus
646 }
647 #endif
648 /**
649 * @}
650 */
651 #endif /* HPM_DMAV1_DRV_H */
652