1 /*
2  * Copyright (c) 2022-2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <string.h>
9 #include "hpm_dma_mgr.h"
10 #include "hpm_soc.h"
11 
12 /*****************************************************************************************************************
13  *
14  *  Definitions
15  *
16  *****************************************************************************************************************/
17 
18 typedef struct _dma_instance_info {
19     DMA_Type *base;
20     int32_t irq_num;
21 } dma_chn_info_t;
22 
23 /**
24  * @brief DMA Channel Context Structure
25  */
26 typedef struct _dma_channel_context {
27     bool is_allocated;                               /**< Whether DMA channel was allocated */
28     void *tc_cb_data_ptr;                            /**< User data required by transfer complete callback */
29     void *half_tc_cb_data_ptr;                       /**< User data required by half transfer complete callback */
30     void *error_cb_data_ptr;                         /**< User data required by error callback */
31     void *abort_cb_data_ptr;                         /**< User data required by abort callback */
32     dma_mgr_chn_cb_t tc_cb;                          /**< DMA channel transfer complete callback */
33     dma_mgr_chn_cb_t half_tc_cb;                     /**< DMA channel half transfer complete callback */
34     dma_mgr_chn_cb_t error_cb;                       /**< DMA channel error callback */
35     dma_mgr_chn_cb_t abort_cb;                       /**< DMA channel abort callback */
36 } dma_chn_context_t;
37 
38 /**
39  * @brief DMA Manager Context Structure
40  *
41  */
42 typedef struct _dma_mgr_context {
43     dma_chn_info_t dma_instance[DMA_SOC_MAX_COUNT];                                  /**< DMA instances */
44     dma_chn_context_t channels[DMA_SOC_MAX_COUNT][DMA_SOC_CHANNEL_NUM];              /**< Array of DMA channels */
45 } dma_mgr_context_t;
46 
47 
48 /*****************************************************************************************************************
49  *
50  *  Prototypes
51  *
52  *****************************************************************************************************************/
53 
54 /**
55  * @brief Search DMA channel context for specified DMA channel resource
56  *
57  * @param [in] resource DMA Channel resource
58  * @return The request DMA channel context if resource is valid or NULL if resource in invalid
59  */
60 static dma_chn_context_t *dma_mgr_search_chn_context(const dma_resource_t *resource);
61 
62 static uint32_t dma_mgr_enter_critical(void);
63 static void dma_mgr_exit_critical(uint32_t level);
64 
65 static void dma0_isr(void);
66 SDK_DECLARE_EXT_ISR_M(IRQn_HDMA, dma0_isr);
67 
68 #if defined(DMA_SOC_MAX_COUNT) && (DMA_SOC_MAX_COUNT > 1)
69 static void dma1_isr(void);
70 SDK_DECLARE_EXT_ISR_M(IRQn_XDMA, dma1_isr);
71 #endif
72 
73 /*****************************************************************************************************************
74  *
75  *  Variables
76  *
77  *****************************************************************************************************************/
78 static dma_mgr_context_t s_dma_mngr_ctx;
79 #define HPM_DMA_MGR (&s_dma_mngr_ctx)
80 
81 /*****************************************************************************************************************
82  *
83  *  Codes
84  *
85  *****************************************************************************************************************/
dma_mgr_isr_handler(DMA_Type * ptr,uint32_t instance)86 void dma_mgr_isr_handler(DMA_Type *ptr, uint32_t instance)
87 {
88     uint32_t int_disable_mask;
89     uint32_t chn_int_stat;
90     dma_chn_context_t *chn_ctx;
91 
92     for (uint8_t channel = 0; channel < DMA_SOC_CHANNEL_NUM; channel++) {
93         int_disable_mask = dma_check_channel_interrupt_mask(ptr, channel);
94         chn_int_stat = dma_check_transfer_status(ptr, channel);
95         chn_ctx = &HPM_DMA_MGR->channels[instance][channel];
96 
97         if (((int_disable_mask & DMA_MGR_INTERRUPT_MASK_TC) == 0) && ((chn_int_stat & DMA_MGR_CHANNEL_STATUS_TC) != 0)) {
98             if (chn_ctx->tc_cb != NULL) {
99                 chn_ctx->tc_cb(ptr, channel, chn_ctx->tc_cb_data_ptr);
100             }
101         }
102         if (((int_disable_mask & DMA_MGR_INTERRUPT_MASK_HALF_TC) == 0) && ((chn_int_stat & DMA_MGR_CHANNEL_STATUS_HALF_TC) != 0)) {
103             if (chn_ctx->half_tc_cb != NULL) {
104                 chn_ctx->half_tc_cb(ptr, channel, chn_ctx->half_tc_cb_data_ptr);
105             }
106         }
107         if (((int_disable_mask & DMA_MGR_INTERRUPT_MASK_ERROR) == 0) && ((chn_int_stat & DMA_MGR_CHANNEL_STATUS_ERROR) != 0)) {
108             if (chn_ctx->error_cb != NULL) {
109                 chn_ctx->error_cb(ptr, channel, chn_ctx->error_cb_data_ptr);
110             }
111         }
112         if (((int_disable_mask & DMA_MGR_INTERRUPT_MASK_ABORT) == 0) && ((chn_int_stat & DMA_MGR_CHANNEL_STATUS_ABORT) != 0)) {
113             if (chn_ctx->abort_cb != NULL) {
114                 chn_ctx->abort_cb(ptr, channel, chn_ctx->abort_cb_data_ptr);
115             }
116         }
117     }
118 }
119 
dma0_isr(void)120 void dma0_isr(void)
121 {
122     dma_mgr_isr_handler(HPM_HDMA, 0);
123 }
124 
125 #if defined(DMA_SOC_MAX_COUNT) && (DMA_SOC_MAX_COUNT > 1)
dma1_isr(void)126 void dma1_isr(void)
127 {
128     dma_mgr_isr_handler(HPM_XDMA, 1);
129 }
130 #endif
131 
dma_mgr_enter_critical(void)132 static uint32_t dma_mgr_enter_critical(void)
133 {
134     return disable_global_irq(CSR_MSTATUS_MIE_MASK);
135 }
136 
dma_mgr_exit_critical(uint32_t level)137 static void dma_mgr_exit_critical(uint32_t level)
138 {
139     restore_global_irq(level);
140 }
141 
dma_mgr_init(void)142 void dma_mgr_init(void)
143 {
144     (void) memset(HPM_DMA_MGR, 0, sizeof(*HPM_DMA_MGR));
145     HPM_DMA_MGR->dma_instance[0].base = HPM_HDMA,
146     HPM_DMA_MGR->dma_instance[0].irq_num = IRQn_HDMA;
147  #if defined(DMA_SOC_MAX_COUNT) && (DMA_SOC_MAX_COUNT > 1)
148     HPM_DMA_MGR->dma_instance[1].base = HPM_XDMA;
149     HPM_DMA_MGR->dma_instance[1].irq_num = IRQn_XDMA;
150  #endif
151 }
152 
dma_mgr_request_resource(dma_resource_t * resource)153 hpm_stat_t dma_mgr_request_resource(dma_resource_t *resource)
154 {
155     hpm_stat_t status;
156 
157     if (resource == NULL) {
158         status = status_invalid_argument;
159     } else {
160         uint32_t instance;
161         uint32_t channel;
162         bool has_found = false;
163         uint32_t level = dma_mgr_enter_critical();
164         for (instance = 0; instance < DMA_SOC_MAX_COUNT; instance++) {
165             for (channel = 0; channel < DMA_SOC_CHANNEL_NUM; channel++) {
166                 if (!HPM_DMA_MGR->channels[instance][channel].is_allocated) {
167                     has_found = true;
168                     break;
169                 }
170             }
171             if (has_found) {
172                 break;
173             }
174         }
175 
176         if (has_found) {
177             HPM_DMA_MGR->channels[instance][channel].is_allocated = true;
178             resource->base = HPM_DMA_MGR->dma_instance[instance].base;
179             resource->channel = channel;
180             resource->irq_num = HPM_DMA_MGR->dma_instance[instance].irq_num;
181             status = status_success;
182         } else {
183             status = status_dma_mgr_no_resource;
184         }
185 
186         dma_mgr_exit_critical(level);
187     }
188 
189     return status;
190 }
191 
dma_mgr_search_chn_context(const dma_resource_t * resource)192 static dma_chn_context_t *dma_mgr_search_chn_context(const dma_resource_t *resource)
193 {
194     dma_chn_context_t *chn_ctx = NULL;
195 
196     if ((resource != NULL) && (resource->channel < DMA_SOC_CHANNEL_NUM)) {
197         uint32_t instance;
198         uint32_t channel;
199         bool has_found = false;
200         for (instance = 0; instance < DMA_SOC_MAX_COUNT; instance++) {
201             if (resource->base == HPM_DMA_MGR->dma_instance[instance].base) {
202                 has_found = true;
203                 break;
204             }
205         }
206 
207         channel = resource->channel;
208         if (has_found) {
209             if (HPM_DMA_MGR->channels[instance][channel].is_allocated) {
210                 chn_ctx = &HPM_DMA_MGR->channels[instance][channel];
211             }
212         }
213     }
214 
215     return chn_ctx;
216 }
217 
dma_mgr_release_resource(const dma_resource_t * resource)218 hpm_stat_t dma_mgr_release_resource(const dma_resource_t *resource)
219 {
220     hpm_stat_t status;
221 
222     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
223 
224     if (chn_ctx == NULL) {
225         status = status_invalid_argument;
226     } else {
227         uint32_t level = dma_mgr_enter_critical();
228         chn_ctx->is_allocated = false;
229         chn_ctx->tc_cb_data_ptr = NULL;
230         chn_ctx->half_tc_cb_data_ptr = NULL;
231         chn_ctx->error_cb_data_ptr = NULL;
232         chn_ctx->abort_cb_data_ptr = NULL;
233         chn_ctx->tc_cb = NULL;
234         chn_ctx->half_tc_cb = NULL;
235         chn_ctx->error_cb = NULL;
236         chn_ctx->abort_cb = NULL;
237         status = status_success;
238         dma_mgr_exit_critical(level);
239     }
240     return status;
241 }
242 
dma_mgr_enable_dma_irq_with_priority(const dma_resource_t * resource,uint32_t priority)243 hpm_stat_t dma_mgr_enable_dma_irq_with_priority(const dma_resource_t *resource, uint32_t priority)
244 {
245     hpm_stat_t status;
246 
247     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
248 
249     if (chn_ctx == NULL) {
250         status = status_invalid_argument;
251     } else {
252         intc_m_enable_irq_with_priority(resource->irq_num, priority);
253         status = status_success;
254     }
255     return status;
256 }
257 
dma_mgr_disable_dma_irq(const dma_resource_t * resource)258 hpm_stat_t dma_mgr_disable_dma_irq(const dma_resource_t *resource)
259 {
260     hpm_stat_t status;
261 
262     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
263 
264     if (chn_ctx == NULL) {
265         status = status_invalid_argument;
266     } else {
267         intc_m_disable_irq(resource->irq_num);
268         status = status_success;
269     }
270     return status;
271 }
272 
dma_mgr_install_chn_tc_callback(const dma_resource_t * resource,dma_mgr_chn_cb_t callback,void * user_data)273 hpm_stat_t dma_mgr_install_chn_tc_callback(const dma_resource_t *resource, dma_mgr_chn_cb_t callback, void *user_data)
274 {
275     hpm_stat_t status;
276 
277     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
278 
279     if (chn_ctx == NULL) {
280         status = status_invalid_argument;
281     } else {
282         chn_ctx->tc_cb_data_ptr = user_data;
283         chn_ctx->tc_cb = callback;
284         status = status_success;
285     }
286     return status;
287 }
288 
dma_mgr_install_chn_half_tc_callback(const dma_resource_t * resource,dma_mgr_chn_cb_t callback,void * user_data)289 hpm_stat_t dma_mgr_install_chn_half_tc_callback(const dma_resource_t *resource, dma_mgr_chn_cb_t callback, void *user_data)
290 {
291     hpm_stat_t status;
292 
293     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
294 
295     if (chn_ctx == NULL) {
296         status = status_invalid_argument;
297     } else {
298         chn_ctx->half_tc_cb_data_ptr = user_data;
299         chn_ctx->half_tc_cb = callback;
300         status = status_success;
301     }
302     return status;
303 }
304 
dma_mgr_install_chn_error_callback(const dma_resource_t * resource,dma_mgr_chn_cb_t callback,void * user_data)305 hpm_stat_t dma_mgr_install_chn_error_callback(const dma_resource_t *resource, dma_mgr_chn_cb_t callback, void *user_data)
306 {
307     hpm_stat_t status;
308 
309     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
310 
311     if (chn_ctx == NULL) {
312         status = status_invalid_argument;
313     } else {
314         chn_ctx->error_cb_data_ptr = user_data;
315         chn_ctx->error_cb = callback;
316         status = status_success;
317     }
318     return status;
319 }
320 
dma_mgr_install_chn_abort_callback(const dma_resource_t * resource,dma_mgr_chn_cb_t callback,void * user_data)321 hpm_stat_t dma_mgr_install_chn_abort_callback(const dma_resource_t *resource, dma_mgr_chn_cb_t callback, void *user_data)
322 {
323     hpm_stat_t status;
324 
325     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
326 
327     if (chn_ctx == NULL) {
328         status = status_invalid_argument;
329     } else {
330         chn_ctx->abort_cb_data_ptr = user_data;
331         chn_ctx->abort_cb = callback;
332         status = status_success;
333     }
334     return status;
335 }
336 
dma_mgr_get_default_chn_config(dma_mgr_chn_conf_t * config)337 void dma_mgr_get_default_chn_config(dma_mgr_chn_conf_t *config)
338 {
339     config->en_dmamux = false;
340     config->dmamux_src = 0;
341     config->priority = DMA_MGR_CHANNEL_PRIORITY_LOW;
342     config->src_burst_size = DMA_MGR_NUM_TRANSFER_PER_BURST_1T;
343     config->src_mode = DMA_MGR_HANDSHAKE_MODE_NORMAL;
344     config->dst_mode = DMA_MGR_HANDSHAKE_MODE_NORMAL;
345     config->src_width = DMA_MGR_TRANSFER_WIDTH_BYTE;
346     config->dst_width = DMA_MGR_TRANSFER_WIDTH_BYTE;
347     config->src_addr_ctrl = DMA_MGR_ADDRESS_CONTROL_INCREMENT;
348     config->dst_addr_ctrl = DMA_MGR_ADDRESS_CONTROL_INCREMENT;
349     config->src_addr = 0;
350     config->dst_addr = 0;
351     config->size_in_byte = 0;
352     config->linked_ptr = 0;
353     config->interrupt_mask = DMA_MGR_INTERRUPT_MASK_ALL;
354     config->en_infiniteloop = false;
355     config->handshake_opt = DMA_MGR_HANDSHAKE_OPT_ONE_BURST;
356     config->burst_opt = DMA_MGR_SRC_BURST_OPT_STANDAND_SIZE;
357     config->en_src_burst_in_fixed_trans = false;
358     config->en_dst_burst_in_fixed_trans = false;
359     config->swap_mode = DMA_MGR_SWAP_MODE_TABLE;
360     config->swap_table = 0;
361 }
362 
dma_mgr_setup_channel(const dma_resource_t * resource,dma_mgr_chn_conf_t * config)363 hpm_stat_t dma_mgr_setup_channel(const dma_resource_t *resource, dma_mgr_chn_conf_t *config)
364 {
365     hpm_stat_t status;
366     uint32_t dmamux_ch;
367     dma_channel_config_t dma_config;
368 
369     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
370 
371     if (chn_ctx == NULL) {
372         status = status_invalid_argument;
373     } else {
374         dmamux_ch = DMA_SOC_CHN_TO_DMAMUX_CHN(resource->base, resource->channel);
375         dmamux_config(HPM_DMAMUX, dmamux_ch, config->dmamux_src, config->en_dmamux);
376         dma_config.priority = config->priority;
377         dma_config.src_burst_size = config->src_burst_size;
378         dma_config.src_mode = config->src_mode;
379         dma_config.dst_mode = config->dst_mode;
380         dma_config.src_width = config->src_width;
381         dma_config.dst_width = config->dst_width;
382         dma_config.src_addr_ctrl = config->src_addr_ctrl;
383         dma_config.dst_addr_ctrl = config->dst_addr_ctrl;
384         dma_config.src_addr = config->src_addr;
385         dma_config.dst_addr = config->dst_addr;
386         dma_config.size_in_byte = config->size_in_byte;
387         dma_config.linked_ptr = config->linked_ptr;
388         dma_config.interrupt_mask = config->interrupt_mask;
389 #if defined(DMA_MGR_HAS_INFINITE_LOOP) && DMA_MGR_HAS_INFINITE_LOOP
390         dma_config.en_infiniteloop = config->en_infiniteloop;
391 #endif
392 #if defined(DMA_MGR_HAS_HANDSHAKE_OPT) && DMA_MGR_HAS_HANDSHAKE_OPT
393         dma_config.handshake_opt = config->handshake_opt;
394 #endif
395 #if defined(DMA_MGR_HAS_BURST_OPT) && DMA_MGR_HAS_BURST_OPT
396         dma_config.burst_opt = config->burst_opt;
397 #endif
398 #if defined(DMA_MGR_HAS_BURST_IN_FIXED_TRANS) && DMA_MGR_HAS_BURST_IN_FIXED_TRANS
399         dma_config.en_src_burst_in_fixed_trans = config->en_src_burst_in_fixed_trans;
400         dma_config.en_dst_burst_in_fixed_trans = config->en_dst_burst_in_fixed_trans;
401 #endif
402 #if defined(DMA_MGR_HAS_BYTE_ORDER_SWAP) && DMA_MGR_HAS_BYTE_ORDER_SWAP
403         dma_config.swap_mode = config->swap_mode;
404         dma_config.swap_table = config->swap_table;
405 #endif
406         status = dma_setup_channel(resource->base, resource->channel, &dma_config, false);
407     }
408     return status;
409 }
410 
dma_mgr_config_linked_descriptor(const dma_resource_t * resource,dma_mgr_chn_conf_t * config,dma_mgr_linked_descriptor_t * descriptor)411 hpm_stat_t dma_mgr_config_linked_descriptor(const dma_resource_t *resource, dma_mgr_chn_conf_t *config, dma_mgr_linked_descriptor_t *descriptor)
412 {
413     hpm_stat_t status;
414     dma_channel_config_t dma_config;
415 
416     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
417 
418     if (chn_ctx == NULL) {
419         status = status_invalid_argument;
420     } else {
421         dma_config.priority = config->priority;
422         dma_config.src_burst_size = config->src_burst_size;
423         dma_config.src_mode = config->src_mode;
424         dma_config.dst_mode = config->dst_mode;
425         dma_config.src_width = config->src_width;
426         dma_config.dst_width = config->dst_width;
427         dma_config.src_addr_ctrl = config->src_addr_ctrl;
428         dma_config.dst_addr_ctrl = config->dst_addr_ctrl;
429         dma_config.src_addr = config->src_addr;
430         dma_config.dst_addr = config->dst_addr;
431         dma_config.size_in_byte = config->size_in_byte;
432         dma_config.linked_ptr = config->linked_ptr;
433         dma_config.interrupt_mask = config->interrupt_mask;
434 #if defined(DMA_MGR_HAS_INFINITE_LOOP) && DMA_MGR_HAS_INFINITE_LOOP
435         dma_config.en_infiniteloop = config->en_infiniteloop;
436 #endif
437 #if defined(DMA_MGR_HAS_HANDSHAKE_OPT) && DMA_MGR_HAS_HANDSHAKE_OPT
438         dma_config.handshake_opt = config->handshake_opt;
439 #endif
440 #if defined(DMA_MGR_HAS_BURST_OPT) && DMA_MGR_HAS_BURST_OPT
441         dma_config.burst_opt = config->burst_opt;
442 #endif
443 #if defined(DMA_MGR_HAS_BURST_IN_FIXED_TRANS) && DMA_MGR_HAS_BURST_IN_FIXED_TRANS
444         dma_config.en_src_burst_in_fixed_trans = config->en_src_burst_in_fixed_trans;
445         dma_config.en_dst_burst_in_fixed_trans = config->en_dst_burst_in_fixed_trans;
446 #endif
447 #if defined(DMA_MGR_HAS_BYTE_ORDER_SWAP) && DMA_MGR_HAS_BYTE_ORDER_SWAP
448         dma_config.swap_mode = config->swap_mode;
449         dma_config.swap_table = config->swap_table;
450 #endif
451         status = dma_config_linked_descriptor(resource->base, (dma_linked_descriptor_t *)descriptor, resource->channel, &dma_config);
452     }
453     return status;
454 }
455 
dma_mgr_enable_channel(const dma_resource_t * resource)456 hpm_stat_t dma_mgr_enable_channel(const dma_resource_t *resource)
457 {
458     hpm_stat_t status;
459 
460     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
461 
462     if (chn_ctx == NULL) {
463         status = status_invalid_argument;
464     } else {
465         status = dma_enable_channel(resource->base, resource->channel);
466     }
467     return status;
468 }
469 
dma_mgr_disable_channel(const dma_resource_t * resource)470 hpm_stat_t dma_mgr_disable_channel(const dma_resource_t *resource)
471 {
472     hpm_stat_t status;
473 
474     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
475 
476     if (chn_ctx == NULL) {
477         status = status_invalid_argument;
478     } else {
479         dma_disable_channel(resource->base, resource->channel);
480         status = status_success;
481     }
482     return status;
483 }
484 
dma_mgr_check_chn_enable(const dma_resource_t * resource,bool * enable)485 hpm_stat_t dma_mgr_check_chn_enable(const dma_resource_t *resource, bool *enable)
486 {
487     hpm_stat_t status;
488 
489     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
490 
491     if (chn_ctx == NULL) {
492         status = status_invalid_argument;
493     } else {
494         *enable = dma_channel_is_enable(resource->base, resource->channel);
495         status = status_success;
496     }
497     return status;
498 }
499 
dma_mgr_enable_chn_irq(const dma_resource_t * resource,uint32_t irq_mask)500 hpm_stat_t dma_mgr_enable_chn_irq(const dma_resource_t *resource, uint32_t irq_mask)
501 {
502     hpm_stat_t status;
503 
504     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
505 
506     if (chn_ctx == NULL) {
507         status = status_invalid_argument;
508     } else {
509         dma_enable_channel_interrupt(resource->base, resource->channel, irq_mask);
510         status = status_success;
511     }
512     return status;
513 }
514 
dma_mgr_disable_chn_irq(const dma_resource_t * resource,uint32_t irq_mask)515 hpm_stat_t dma_mgr_disable_chn_irq(const dma_resource_t *resource, uint32_t irq_mask)
516 {
517     hpm_stat_t status;
518 
519     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
520 
521     if (chn_ctx == NULL) {
522         status = status_invalid_argument;
523     } else {
524         dma_disable_channel_interrupt(resource->base, resource->channel, irq_mask);
525         status = status_success;
526     }
527     return status;
528 }
529 
dma_mgr_set_chn_priority(const dma_resource_t * resource,uint8_t priority)530 hpm_stat_t dma_mgr_set_chn_priority(const dma_resource_t *resource, uint8_t priority)
531 {
532     hpm_stat_t status;
533 
534     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
535 
536     if (chn_ctx == NULL) {
537         status = status_invalid_argument;
538     } else {
539         dma_set_priority(resource->base, resource->channel, priority);
540         status = status_success;
541     }
542     return status;
543 }
544 
dma_mgr_set_chn_src_work_mode(const dma_resource_t * resource,uint8_t mode)545 hpm_stat_t dma_mgr_set_chn_src_work_mode(const dma_resource_t *resource, uint8_t mode)
546 {
547     hpm_stat_t status;
548 
549     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
550 
551     if (chn_ctx == NULL) {
552         status = status_invalid_argument;
553     } else {
554         dma_set_source_work_mode(resource->base, resource->channel, mode);
555         status = status_success;
556     }
557     return status;
558 }
559 
dma_mgr_set_chn_dst_work_mode(const dma_resource_t * resource,uint8_t mode)560 hpm_stat_t dma_mgr_set_chn_dst_work_mode(const dma_resource_t *resource, uint8_t mode)
561 {
562     hpm_stat_t status;
563 
564     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
565 
566     if (chn_ctx == NULL) {
567         status = status_invalid_argument;
568     } else {
569         dma_set_destination_work_mode(resource->base, resource->channel, mode);
570         status = status_success;
571     }
572     return status;
573 }
574 
dma_mgr_set_chn_src_burst_size(const dma_resource_t * resource,uint8_t burstsize)575 hpm_stat_t dma_mgr_set_chn_src_burst_size(const dma_resource_t *resource, uint8_t burstsize)
576 {
577     hpm_stat_t status;
578 
579     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
580 
581     if (chn_ctx == NULL) {
582         status = status_invalid_argument;
583     } else {
584         dma_set_source_burst_size(resource->base, resource->channel, burstsize);
585         status = status_success;
586     }
587     return status;
588 }
589 
dma_mgr_get_chn_remaining_transize(const dma_resource_t * resource,uint32_t * size)590 hpm_stat_t dma_mgr_get_chn_remaining_transize(const dma_resource_t *resource, uint32_t *size)
591 {
592     hpm_stat_t status;
593 
594     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
595 
596     if (chn_ctx == NULL) {
597         status = status_invalid_argument;
598     } else {
599         *size = dma_get_remaining_transfer_size(resource->base, resource->channel);
600         status = status_success;
601     }
602     return status;
603 }
604 
dma_mgr_set_chn_transize(const dma_resource_t * resource,uint32_t size)605 hpm_stat_t dma_mgr_set_chn_transize(const dma_resource_t *resource, uint32_t size)
606 {
607     hpm_stat_t status;
608 
609     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
610 
611     if (chn_ctx == NULL) {
612         status = status_invalid_argument;
613     } else {
614         dma_set_transfer_size(resource->base, resource->channel, size);
615         status = status_success;
616     }
617     return status;
618 }
619 
dma_mgr_set_chn_src_width(const dma_resource_t * resource,uint8_t width)620 hpm_stat_t dma_mgr_set_chn_src_width(const dma_resource_t *resource, uint8_t width)
621 {
622     hpm_stat_t status;
623 
624     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
625 
626     if (chn_ctx == NULL) {
627         status = status_invalid_argument;
628     } else {
629         dma_set_source_width(resource->base, resource->channel, width);
630         status = status_success;
631     }
632     return status;
633 }
634 
dma_mgr_set_chn_dst_width(const dma_resource_t * resource,uint8_t width)635 hpm_stat_t dma_mgr_set_chn_dst_width(const dma_resource_t *resource, uint8_t width)
636 {
637     hpm_stat_t status;
638 
639     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
640 
641     if (chn_ctx == NULL) {
642         status = status_invalid_argument;
643     } else {
644         dma_set_destination_width(resource->base, resource->channel, width);
645         status = status_success;
646     }
647     return status;
648 }
649 
dma_mgr_set_chn_src_addr(const dma_resource_t * resource,uint32_t addr)650 hpm_stat_t dma_mgr_set_chn_src_addr(const dma_resource_t *resource, uint32_t addr)
651 {
652     hpm_stat_t status;
653 
654     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
655 
656     if (chn_ctx == NULL) {
657         status = status_invalid_argument;
658     } else {
659         dma_set_source_address(resource->base, resource->channel, addr);
660         status = status_success;
661     }
662     return status;
663 }
664 
dma_mgr_set_chn_dst_addr(const dma_resource_t * resource,uint32_t addr)665 hpm_stat_t dma_mgr_set_chn_dst_addr(const dma_resource_t *resource, uint32_t addr)
666 {
667     hpm_stat_t status;
668 
669     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
670 
671     if (chn_ctx == NULL) {
672         status = status_invalid_argument;
673     } else {
674         dma_set_destination_address(resource->base, resource->channel, addr);
675         status = status_success;
676     }
677     return status;
678 }
679 
dma_mgr_set_chn_src_addr_ctrl(const dma_resource_t * resource,uint8_t addr_ctrl)680 hpm_stat_t dma_mgr_set_chn_src_addr_ctrl(const dma_resource_t *resource, uint8_t addr_ctrl)
681 {
682     hpm_stat_t status;
683 
684     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
685 
686     if (chn_ctx == NULL) {
687         status = status_invalid_argument;
688     } else {
689         dma_set_source_address_ctrl(resource->base, resource->channel, addr_ctrl);
690         status = status_success;
691     }
692     return status;
693 }
694 
dma_mgr_set_chn_dst_addr_ctrl(const dma_resource_t * resource,uint8_t addr_ctrl)695 hpm_stat_t dma_mgr_set_chn_dst_addr_ctrl(const dma_resource_t *resource, uint8_t addr_ctrl)
696 {
697     hpm_stat_t status;
698 
699     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
700 
701     if (chn_ctx == NULL) {
702         status = status_invalid_argument;
703     } else {
704         dma_set_destination_address_ctrl(resource->base, resource->channel, addr_ctrl);
705         status = status_success;
706     }
707     return status;
708 }
709 
dma_mgr_set_chn_infinite_loop_mode(const dma_resource_t * resource,bool infinite_loop)710 hpm_stat_t dma_mgr_set_chn_infinite_loop_mode(const dma_resource_t *resource, bool infinite_loop)
711 {
712     hpm_stat_t status;
713 
714     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
715 
716     if (chn_ctx == NULL) {
717         status = status_invalid_argument;
718     } else {
719 #if defined(DMA_MGR_HAS_INFINITE_LOOP) && DMA_MGR_HAS_INFINITE_LOOP
720         dma_set_infinite_loop_mode(resource->base, resource->channel, infinite_loop);
721         status = status_success;
722 #else
723         (void)infinite_loop;
724         status = status_fail;
725 #endif
726     }
727     return status;
728 }
729 
dma_mgr_set_chn_src_busrt_option(const dma_resource_t * resource,uint8_t burst_opt)730 hpm_stat_t dma_mgr_set_chn_src_busrt_option(const dma_resource_t *resource, uint8_t burst_opt)
731 {
732     hpm_stat_t status;
733 
734     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
735 
736     if (chn_ctx == NULL) {
737         status = status_invalid_argument;
738     } else {
739 #if defined(DMA_MGR_HAS_HANDSHAKE_OPT) && DMA_MGR_HAS_HANDSHAKE_OPT
740         dma_set_src_busrt_option(resource->base, resource->channel, burst_opt);
741         status = status_success;
742 #else
743         (void)burst_opt;
744         status = status_fail;
745 #endif
746     }
747     return status;
748 }
749 
dma_mgr_set_chn_handshake_option(const dma_resource_t * resource,uint8_t handshake_opt)750 hpm_stat_t dma_mgr_set_chn_handshake_option(const dma_resource_t *resource, uint8_t handshake_opt)
751 {
752     hpm_stat_t status;
753 
754     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
755 
756     if (chn_ctx == NULL) {
757         status = status_invalid_argument;
758     } else {
759 #if defined(DMA_MGR_HAS_HANDSHAKE_OPT) && DMA_MGR_HAS_HANDSHAKE_OPT
760         dma_set_handshake_option(resource->base, resource->channel, handshake_opt);
761         status = status_success;
762 #else
763         (void)handshake_opt;
764         status = status_fail;
765 #endif
766     }
767     return status;
768 }
769 
dma_mgr_abort_chn_transfer(const dma_resource_t * resource)770 hpm_stat_t dma_mgr_abort_chn_transfer(const dma_resource_t *resource)
771 {
772     hpm_stat_t status;
773 
774     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
775 
776     if (chn_ctx == NULL) {
777         status = status_invalid_argument;
778     } else {
779         dma_abort_channel(resource->base, 1u << resource->channel);
780         status = status_success;
781     }
782     return status;
783 }
784 
dma_mgr_check_chn_transfer_status(const dma_resource_t * resource,uint32_t * status)785 hpm_stat_t dma_mgr_check_chn_transfer_status(const dma_resource_t *resource, uint32_t *status)
786 {
787     hpm_stat_t stat;
788 
789     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
790 
791     if (chn_ctx == NULL) {
792         stat = status_invalid_argument;
793     } else {
794         *status = dma_check_transfer_status(resource->base, resource->channel);
795         stat = status_success;
796     }
797     return stat;
798 }
799 
dma_mgr_set_source_burst_in_fixed_transize_enable(const dma_resource_t * resource,bool enable)800 hpm_stat_t dma_mgr_set_source_burst_in_fixed_transize_enable(const dma_resource_t *resource, bool enable)
801 {
802     hpm_stat_t status;
803 
804     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
805 
806     if (chn_ctx == NULL) {
807         status = status_invalid_argument;
808     } else {
809 #if defined(DMA_MGR_HAS_BURST_IN_FIXED_TRANS) && DMA_MGR_HAS_BURST_IN_FIXED_TRANS
810         dma_set_source_burst_in_fixed_transize_enable(resource->base, resource->channel, enable);
811         status = status_success;
812 #else
813         (void)enable;
814         status = status_fail;
815 #endif
816     }
817     return status;
818 }
819 
dma_mgr_set_destination_burst_in_fix_transize_enable(const dma_resource_t * resource,bool enable)820 hpm_stat_t dma_mgr_set_destination_burst_in_fix_transize_enable(const dma_resource_t *resource, bool enable)
821 {
822     hpm_stat_t status;
823 
824     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
825 
826     if (chn_ctx == NULL) {
827         status = status_invalid_argument;
828     } else {
829 #if defined(DMA_MGR_HAS_BURST_IN_FIXED_TRANS) && DMA_MGR_HAS_BURST_IN_FIXED_TRANS
830         dma_set_destination_burst_in_fixed_transize_enable(resource->base, resource->channel, enable);
831         status = status_success;
832 #else
833         (void)enable;
834         status = status_fail;
835 #endif
836     }
837     return status;
838 }
839 
dma_mgr_set_swap_mode(const dma_resource_t * resource,uint8_t swap_mode)840 hpm_stat_t dma_mgr_set_swap_mode(const dma_resource_t *resource, uint8_t swap_mode)
841 {
842     hpm_stat_t status;
843 
844     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
845 
846     if (chn_ctx == NULL) {
847         status = status_invalid_argument;
848     } else {
849 #if defined(DMA_MGR_HAS_BYTE_ORDER_SWAP) && DMA_MGR_HAS_BYTE_ORDER_SWAP
850         dma_set_swap_mode(resource->base, resource->channel, swap_mode);
851         status = status_success;
852 #else
853         (void)swap_mode;
854         status = status_fail;
855 #endif
856     }
857     return status;
858 }
859 
dma_mgr_set_swap_table(const dma_resource_t * resource,uint32_t swap_table)860 hpm_stat_t dma_mgr_set_swap_table(const dma_resource_t *resource, uint32_t swap_table)
861 {
862     hpm_stat_t status;
863 
864     dma_chn_context_t *chn_ctx = dma_mgr_search_chn_context(resource);
865 
866     if (chn_ctx == NULL) {
867         status = status_invalid_argument;
868     } else {
869 #if defined(DMA_MGR_HAS_BYTE_ORDER_SWAP) && DMA_MGR_HAS_BYTE_ORDER_SWAP
870         dma_set_swap_table(resource->base, resource->channel, swap_table);
871         status = status_success;
872 #else
873         (void)swap_table;
874         status = status_fail;
875 #endif
876     }
877     return status;
878 }
879