1 /***************************************************************************//**
2 * \file cyhal_dma_dmac.c
3 *
4 * \brief
5 * Implements a high level interface for interacting with the Infineon DMAC.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 #include "cyhal_dma.h"
28 #include "cyhal_dma_dmac.h"
29 #include "cyhal_dma_impl.h"
30 #include "cyhal_hwmgr_impl.h"
31 #include "cyhal_interconnect.h"
32 #include "cyhal_syspm.h"
33 #include "cyhal_utils.h"
34 #include "cyhal_irq_impl.h"
35 #include "cyhal_triggers.h"
36 
37 #if defined(__cplusplus)
38 extern "C" {
39 #endif
40 
41 #if (_CYHAL_DRIVER_AVAILABLE_DMA_DMAC)
42 
43 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC)
44 #define DMAC0_IRQn                  (cpuss_interrupts_dmac_0_IRQn)
45 #define GET_RESOURCE_DATA(x)        (x.dmac)
46 typedef DMAC_Type                   cyhal_dmac_hw_type;
47 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
48 #define DMAC0_IRQn                  (cpuss_interrupt_dma_IRQn)
49 #define GET_RESOURCE_DATA(x)        (x)
50 #define CY_TRIGGER_TWO_CYCLES       (2)
51 typedef DMAC_Type                   cyhal_dmac_hw_type;
52 #elif defined(CY_IP_MXAHBDMAC)
53 #define DMAC0_IRQn                  (cpuss_interrupts_dmac0_0_IRQn)
54 #define DMAC1_IRQn                  (cpuss_interrupts_dmac1_0_IRQn)
55 #define GET_RESOURCE_DATA(x)        (x.dmac)
56 typedef MXAHBDMAC_Type              cyhal_dmac_hw_type;
57 #elif defined(CY_IP_MXSAXIDMAC)
58 #define DMAC0_IRQn                  (m55appcpuss_interrupts_axidmac_0_IRQn)
59 typedef SAXI_DMAC_Type              cyhal_dmac_hw_type;
60 #define GET_RESOURCE_DATA(x)        (x.dmac)
61 #endif
62 
63 #if defined (AXI_DMAC_CH_NR)
64 #if APPCPUSS_AXIDMAC1_PRESENT
65 #define NUM_DMAC0_CHANNELS          (APPCPUSS_AXIDMAC0_CH_NR)
66 #define NUM_DMAC_CHANNELS           (APPCPUSS_AXIDMAC0_CH_NR + APPCPUSS_AXIDMAC1_CH_NR)
67 #else
68 #define NUM_DMAC0_CHANNELS          (APPCPUSS_AXIDMAC0_CH_NR)
69 #define NUM_DMAC_CHANNELS           (APPCPUSS_AXIDMAC0_CH_NR)
70 #endif
71 #elif defined(CPUSS_DMAC0_CH_NR) && defined(CPUSS_DMAC1_CH_NR) && (CPUSS_DMAC0_PRESENT > 0) && (CPUSS_DMAC1_PRESENT > 0)
72 #define NUM_DMAC_CHANNELS           (CPUSS_DMAC0_CH_NR + CPUSS_DMAC1_CH_NR)
73 #define NUM_DMAC0_CHANNELS          (CPUSS_DMAC0_CH_NR)
74 #elif defined(CPUSS_DMAC_CH_NR)
75 #define NUM_DMAC_CHANNELS           (CPUSS_DMAC_CH_NR)
76 #define CPUSS_DMAC0_CH_NR           (CPUSS_DMAC_CH_NR)
77 #define NUM_DMAC0_CHANNELS          (CPUSS_DMAC_CH_NR)
78 #define CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0   (CYHAL_TRIGGER_CPUSS_DMAC_TR_IN0)
79 #define _CYHAL_TRIGGER_CPUSS_DMAC0_TR_OUT0 (_CYHAL_TRIGGER_CPUSS_DMAC_TR_OUT0)
80 #endif
81 
82 //Wrappers for PDL functions and Macros for AXI DMAC differences
83 #if defined(CY_IP_MXSAXIDMAC)
84 #define _cyhal_dmac_channel_enable(base, channel)   Cy_AXIDMAC_Channel_Enable(base, channel)
85 #define _cyhal_dmac_channel_disable(base, channel)  Cy_AXIDMAC_Channel_Disable(base, channel)
86 #define _cyhal_dmac_get_active_channel(base)        Cy_AXIDMAC_GetActiveChannel(base)
87 #define _cyhal_dmac_channel_get_interrupt_status_masked(base, channel) Cy_AXIDMAC_Channel_GetInterruptStatusMasked(base, channel)
88 #define _CYHAL_DMAC_CHANNEL_ENABLED        (CY_AXIDMAC_CHANNEL_ENABLED)
89 #define _CYHAL_DMAC_CHANNEL_DISABLED       (CY_AXIDMAC_CHANNEL_DISABLED)
90 #define _CYHAL_DMAC_DESCR            (CY_AXIDMAC_DESCR)
91 #define _CYHAL_DMAC_M_LOOP           (CY_AXIDMAC_M_LOOP)
92 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Msk   (SAXI_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Msk)
93 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Msk   (SAXI_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Msk)
94 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE        (SAXI_DMAC_CH_DESCR_CTL_TR_IN_TYPE)
95 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE       (SAXI_DMAC_CH_DESCR_CTL_TR_OUT_TYPE)
96 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Pos    (SAXI_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Pos)
97 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Pos    (SAXI_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Pos)
98 #define _CYHAL_TRIGGER_CPUSS_ZERO                  (CYHAL_TRIGGER_M33SYSCPUSS_ZERO)
99 #elif defined(CY_IP_MXAHBDMAC) || defined(CY_IP_M0S8CPUSSV3_DMAC) || defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC)
100 #define _cyhal_dmac_channel_enable(base, channel)   Cy_DMAC_Channel_Enable(base, channel)
101 #define _cyhal_dmac_channel_disable(base, channel)  Cy_DMAC_Channel_Disable(base, channel)
102 #define _cyhal_dmac_get_active_channel(base)        Cy_DMAC_GetActiveChannel(base)
103 #define _cyhal_dmac_channel_get_interrupt_status_masked(base, channel) Cy_DMAC_Channel_GetInterruptStatusMasked(base, channel)
104 #define _CYHAL_DMAC_CHANNEL_ENABLED        (CY_DMAC_CHANNEL_ENABLED)
105 #define _CYHAL_DMAC_CHANNEL_DISABLED       (CY_DMAC_CHANNEL_DISABLED)
106 #define _CYHAL_DMAC_DESCR            (CY_DMAC_DESCR)
107 #define _CYHAL_DMAC_X_LOOP           (CY_DMAC_X_LOOP)
108 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Msk    (DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE_Msk)
109 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Msk   (DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE_Msk)
110 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE        (DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE)
111 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE       (DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE)
112 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Pos    (DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE_Pos)
113 #define _CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Pos   (DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE_Pos)
114 #define _CYHAL_TRIGGER_CPUSS_ZERO                  (CYHAL_TRIGGER_CPUSS_ZERO)
115 #endif
116 
117 
118 static cyhal_dma_t* _cyhal_dma_dmac_config_structs[NUM_DMAC_CHANNELS];
119 
120 /** Default dmac descriptor config */
121 #if defined(CY_IP_MXSAXIDMAC)
122 static const cy_stc_axidmac_descriptor_config_t _cyhal_dma_dmac_default_descriptor_config =
123 #else
124 static const cy_stc_dmac_descriptor_config_t _cyhal_dma_dmac_default_descriptor_config =
125 #endif
126 {
127     .srcAddress = 0,                                // Overriden by cyhal_dma_cfg_t.src_addr
128     .dstAddress = 0,                                // Overriden by cyhal_dma_cfg_t.dst_addr
129 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
130     .dataSize = CY_DMAC_WORD,                       // Overridden by cyhal_dma_cfg_t.transfer_width
131     .dstTransferSize = CY_DMAC_TRANSFER_SIZE_DATA,  // Overriden by direction
132     .srcTransferSize = CY_DMAC_TRANSFER_SIZE_DATA,  // Overriden by direction
133     .retrigger = CY_DMAC_RETRIG_IM,
134     .interruptType = CY_DMAC_DESCR,                 // Overridden by cyhal_dma_cfg_t.action
135     .triggerOutType = CY_DMAC_DESCR_CHAIN,          // Overridden by [en/dis]able_output()
136     .channelState = CY_DMAC_CHANNEL_ENABLED,
137     .triggerInType = CY_DMAC_DESCR,                 // Overridden by cyhal_dma_cfg_t.action & [dis]connect_digital()
138     .dataPrefetch = false,
139     .descriptorType = CY_DMAC_1D_TRANSFER,          // Overriden by cyhal_dma_cfg_t.burst_size
140     .srcXincrement = 1U,                            // Overriden by cyhal_dma_cfg_t.src_increment
141     .dstXincrement = 1U,                            // Overriden by cyhal_dma_cfg_t.dst_increment
142     .xCount = 1UL,                                  // Overriden by cyhal_dma_cfg_t.length/burst_size
143     .srcYincrement = 1U,                            // Overriden by cyhal_dma_cfg_t.burst_size
144     .dstYincrement = 1U,                            // Overriden by cyhal_dma_cfg_t.burst_size
145     .yCount = 1UL,                                  // Overriden by cyhal_dma_cfg_t.length
146     .nextDescriptor = 0,
147 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
148     .dataSize = CY_DMAC_WORD,                       // Overridden by cyhal_dma_cfg_t.transfer_width
149     .dstTransferSize = CY_DMAC_TRANSFER_SIZE_DATA,  // Overriden by direction
150     .srcTransferSize = CY_DMAC_TRANSFER_SIZE_DATA,  // Overriden by direction
151     .retrigger = CY_DMAC_RETRIG_IM,
152     .triggerType = CY_DMAC_SINGLE_DESCR,
153     .dataCount = 1,                                 // Overriden by cyhal_dma_cfg_t.length
154     .dstAddrIncrement = true,                       // Overriden by cyhal_dma_cfg_t.dst_increment
155     .srcAddrIncrement = true,                       // Overriden by cyhal_dma_cfg_t.src_increment
156     .interrupt = true,
157     .preemptable = true,
158     .flipping = false,
159 #elif defined(CY_IP_MXSAXIDMAC)
160     .retrigger = CY_AXIDMAC_RETRIG_IM,
161     .interruptType = CY_AXIDMAC_DESCR,              // Overridden by cyhal_dma_cfg_t.action
162     .triggerOutType = CY_AXIDMAC_DESCR_CHAIN,       // Overridden by [en/dis]able_output()
163     .channelState = CY_AXIDMAC_CHANNEL_DISABLED,
164     .triggerInType = CY_AXIDMAC_DESCR,              // Overridden by cyhal_dma_cfg_t.action & [dis]connect_digital()
165     .dataPrefetch = false,
166     .descriptorType = CY_AXIDMAC_1D_MEMORY_COPY,    // Overriden by cyhal_dma_cfg_t.burst_size
167     .mCount = 1U,                                   // Overriden by cyhal_dma_cfg_t.length
168     .srcXincrement = 0U,                            // Overriden by cyhal_dma_cfg_t.src_increment
169     .dstXincrement = 0U,                            // Overriden by cyhal_dma_cfg_t.dst_increment
170     .xCount = 1UL,                                  // Overriden by cyhal_dma_cfg_t.length/burst_size
171     .srcYincrement = 0U,
172     .dstYincrement = 0U,
173     .yCount = 1UL,
174     .nextDescriptor = NULL,
175 #endif
176 };
177 
178 /** Default dmac channel config */
179 #if defined(CY_IP_MXSAXIDMAC)
180 static const cy_stc_axidmac_channel_config_t _cyhal_dma_dmac_default_channel_config =
181 #else
182 static const cy_stc_dmac_channel_config_t _cyhal_dma_dmac_default_channel_config =
183 #endif
184 {
185     .priority = 1,                          // Overriden by config().priority
186     .enable = false,
187 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
188     .bufferable = false,
189     .descriptor = 0,                        // Overriden by config()
190 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
191     .descriptor = CY_DMAC_DESCRIPTOR_PING,  // Overriden by config()
192 #endif
193 };
194 
195 static bool _cyhal_dma_dmac_pm_transition_pending = false;
196 
197 #if CYHAL_DRIVER_AVAILABLE_SYSPM
198 static bool _cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
199 
200 static cyhal_syspm_callback_data_t _cyhal_dma_dmac_pm_callback_args = {
201     .callback = &_cyhal_dma_dmac_pm_callback,
202     .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
203     .next = NULL,
204     .args = NULL,
205     .ignore_modes = (cyhal_syspm_callback_mode_t)(CYHAL_SYSPM_BEFORE_TRANSITION | CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION),
206 };
207 
_cyhal_dma_dmac_has_enabled(void)208 static bool _cyhal_dma_dmac_has_enabled(void)
209 {
210     for (uint8_t i = 0; i < NUM_DMAC_CHANNELS; i++)
211         if (NULL != _cyhal_dma_dmac_config_structs[i])
212             return true;
213     return false;
214 }
215 
_cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)216 static bool _cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
217 {
218     CY_UNUSED_PARAMETER(state);
219     CY_UNUSED_PARAMETER(callback_arg);
220     bool block_transition = false;
221     switch(mode)
222     {
223         case CYHAL_SYSPM_CHECK_READY:
224             for (uint8_t i = 0; (i < NUM_DMAC_CHANNELS) && !block_transition; i++)
225             {
226                 block_transition |= (_cyhal_dma_dmac_config_structs[i] != NULL) && _cyhal_dma_dmac_is_busy(_cyhal_dma_dmac_config_structs[i]);
227             }
228             _cyhal_dma_dmac_pm_transition_pending = !block_transition;
229             break;
230         case CYHAL_SYSPM_CHECK_FAIL:
231         case CYHAL_SYSPM_AFTER_TRANSITION:
232             _cyhal_dma_dmac_pm_transition_pending = false;
233             break;
234         default:
235             CY_ASSERT(false);
236             break;
237     }
238     return _cyhal_dma_dmac_pm_transition_pending;
239 }
240 #endif
241 
242 /** Gets the dmac configuration struct offset */
_cyhal_dma_dmac_get_cfg_offset(const cyhal_dma_t * obj)243 static inline uint8_t _cyhal_dma_dmac_get_cfg_offset(const cyhal_dma_t* obj)
244 {
245     return (obj->resource.block_num * NUM_DMAC0_CHANNELS) + obj->resource.channel_num;
246 }
247 
248 /** Sets the dmac configuration struct */
_cyhal_dma_dmac_set_obj(cyhal_dma_t * obj)249 static inline void _cyhal_dma_dmac_set_obj(cyhal_dma_t *obj)
250 {
251     _cyhal_dma_dmac_config_structs[_cyhal_dma_dmac_get_cfg_offset(obj)] = obj;
252 }
253 
254 /** Zeros the dmac configuration struct */
_cyhal_dma_dmac_free_obj(cyhal_dma_t * obj)255 static inline void _cyhal_dma_dmac_free_obj(cyhal_dma_t *obj)
256 {
257     _cyhal_dma_dmac_config_structs[_cyhal_dma_dmac_get_cfg_offset(obj)] = NULL;
258 }
259 
260 /** Gets the dmac configuration struct from block and channel */
_cyhal_dma_dmac_get_obj(uint8_t block,uint8_t channel)261 static inline cyhal_dma_t* _cyhal_dma_dmac_get_obj(uint8_t block, uint8_t channel)
262 {
263 #if defined(CY_IP_MXSAXIDMAC)
264     return _cyhal_dma_dmac_config_structs[(block * APPCPUSS_AXIDMAC0_CH_NR) + channel];
265 #else
266     return _cyhal_dma_dmac_config_structs[(block * CPUSS_DMAC0_CH_NR) + channel];
267 #endif
268 }
269 
270 /** Gets the dmac block number from irq number */
271 /** This should never be called from a non-dma IRQn */
_cyhal_dma_dmac_get_block_from_irqn(_cyhal_system_irq_t irqn)272 static inline uint8_t _cyhal_dma_dmac_get_block_from_irqn(_cyhal_system_irq_t irqn)
273 {
274     uint8_t diff = irqn - DMAC0_IRQn;
275     CY_ASSERT(diff < NUM_DMAC_CHANNELS);
276     if (diff < NUM_DMAC0_CHANNELS)
277         return 0;
278 #if (NUM_DMAC0_CHANNELS < NUM_DMAC_CHANNELS)
279     if (diff < NUM_DMAC_CHANNELS)
280         return 1;
281 #endif
282     else
283     {
284         // Should never reach here. Just silencing compiler warnings.
285         CY_ASSERT(false);
286         return 0xFF;
287     }
288 }
289 
290 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
291 /** Gets the dmac channel number from irq number */
292 /** This should never be called from a non-dma IRQn */
_cyhal_dma_dmac_get_channel_from_irqn(_cyhal_system_irq_t irqn)293 static inline uint8_t _cyhal_dma_dmac_get_channel_from_irqn(_cyhal_system_irq_t irqn)
294 {
295     uint8_t diff = irqn - DMAC0_IRQn;
296     CY_ASSERT(diff < NUM_DMAC_CHANNELS);
297     if (diff < NUM_DMAC0_CHANNELS)
298         return diff;
299 #if (NUM_DMAC0_CHANNELS < NUM_DMAC_CHANNELS)
300     else
301         return diff - NUM_DMAC0_CHANNELS;
302 #endif
303     // Should never reach here. Just silencing compiler warnings.
304     CY_ASSERT(false);
305     return 0xFF;
306 }
307 #endif
308 
309 /** Gets the irqn corresponding to a particular cyhal_dma_t config struct */
_cyhal_dma_dmac_get_irqn(cyhal_dma_t * obj)310 static inline _cyhal_system_irq_t _cyhal_dma_dmac_get_irqn(cyhal_dma_t *obj)
311 {
312     #if defined(CY_IP_M0S8CPUSSV3_DMAC)
313         CY_UNUSED_PARAMETER(obj);
314         /* This IP has a single ganged IRQ for all DMA channels */
315         return DMAC0_IRQn;
316     #else
317         return (_cyhal_system_irq_t)((uint8_t)DMAC0_IRQn + _cyhal_dma_dmac_get_cfg_offset(obj));
318     #endif
319 }
320 
321 /** Gets the dmac base pointer from block number */
_cyhal_dma_dmac_get_base(uint8_t block_num)322 static inline cyhal_dmac_hw_type* _cyhal_dma_dmac_get_base(uint8_t block_num)
323 {
324 #if defined(CY_IP_MXSAXIDMAC)
325     CY_UNUSED_PARAMETER(block_num);
326     return SAXI_DMAC;
327 #elif defined(CPUSS_DMAC0_CH_NR) && !defined(CPUSS_DMAC1_CH_NR)
328     CY_UNUSED_PARAMETER(block_num);
329     return DMAC;
330 #elif defined(CPUSS_DMAC0_CH_NR) && defined(CPUSS_DMAC1_CH_NR)
331     return (block_num == 0) ? MXAHBDMAC0 : MXAHBDMAC1;
332 #else
333     //Should never get here
334     #error "Error: No corresponding base type"
335 #endif
336 }
337 
338 /** Uses tables provided as part of the hal interconnect driver to determine mux
339  * trigger group and mux trigger index and then construct the trigger line
340  * input parameter to Cy_TrigMux_SwTrigger. */
_cyhal_dma_dmac_get_trigger_line(uint8_t block_num,uint8_t channel_num)341 static inline uint32_t _cyhal_dma_dmac_get_trigger_line(uint8_t block_num, uint8_t channel_num)
342 {
343     /* cyhal_dest_t triggers are guaranteed to be sorted by trigger type, block
344      * num, then channel num, therefore, we can just directly find the proper
345      * trigger by calculating an offset. */
346 #if defined(CY_IP_MXSAXIDMAC)
347     cyhal_dest_t trigger = (cyhal_dest_t)(CYHAL_TRIGGER_M55APPCPUSS_AXIDMAC_TR_IN0 + (block_num * APPCPUSS_AXIDMAC0_CH_NR) + channel_num);
348 #else
349     cyhal_dest_t trigger = (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + (block_num * CPUSS_DMAC0_CH_NR) + channel_num);
350 #endif
351     uint32_t trigger_line = 0;
352 
353     /* One to one triggers have bit 8 set in cyhal_dest_to_mux but
354      * Cy_TrigMux_SwTrigger wants the trigger group field to have bit 5 set to
355      * denote one to one triggers. */
356     uint8_t trig_group = cyhal_dest_to_mux[trigger];
357     /* If hal one to one triggers bit is set: mask it out and set pdl one to
358      * one bit */
359     if(trig_group & _CYHAL_DMA_TRIGGERS_1TO1_MASK)
360         trig_group = (trig_group & ~_CYHAL_DMA_TRIGGERS_1TO1_MASK) | _CYHAL_DMA_PDL_TRIGGERS_1TO1_MASK;
361 
362     /* Construct trigger line which consists of three fields packed into a
363      * uint32_t:
364      * Bits   30: Input/output bit. Set to 1 for output.
365      * Bits 12-8: Trigger group selection.
366      * Bits  7-0: Select the output trigger number in the trigger group. */
367 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
368     trigger_line = PERI_TR_CMD_OUT_SEL_Msk | ((uint32_t)trig_group << 8) | cyhal_mux_dest_index[trigger];
369 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
370     trigger_line =  PERI_TR_CTL_TR_OUT_Msk | ((uint32_t)trig_group << 8) | cyhal_mux_dest_index[trigger];
371 #endif
372 
373 #if (((CY_IP_MXSPERI_INSTANCES) == 2U) && defined(CY_IP_MXSAXIDMAC))
374     /* Bits   16: The PERI 1 instance.
375         The trigger input for AXIDMAC is located on PERI 1
376     */
377     trigger_line |= PERI_INSTANCE_1_IDENT_Msk;
378 #endif
379 
380     return trigger_line;
381 }
382 
383 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
384 /** Convert PDL interrupt cause to hal dma event */
_cyhal_dma_dmac_convert_interrupt_cause(cyhal_dma_t * obj,uint32_t cause)385 static inline cyhal_dma_event_t _cyhal_dma_dmac_convert_interrupt_cause(cyhal_dma_t *obj, uint32_t cause)
386 {
387     static const cyhal_dma_event_t hal[] =
388     {
389         CYHAL_DMA_TRANSFER_COMPLETE,
390         CYHAL_DMA_SRC_BUS_ERROR,
391         CYHAL_DMA_DST_BUS_ERROR,
392         CYHAL_DMA_SRC_MISAL,
393         CYHAL_DMA_DST_MISAL,
394         CYHAL_DMA_CURR_PTR_NULL,
395         CYHAL_DMA_ACTIVE_CH_DISABLED,
396         CYHAL_DMA_DESCR_BUS_ERROR
397     };
398 
399     cyhal_dma_event_t hal_rslt = CYHAL_DMA_NO_INTR;
400     for (uint8_t i = 0; cause > 0 && i < sizeof(hal)/sizeof(cyhal_dma_event_t); i++)
401     {
402         if ((cause & (1 << i)) > 0)
403         hal_rslt |= hal[i];
404     }
405 
406     if ((uint32_t)(hal_rslt & CYHAL_DMA_TRANSFER_COMPLETE) > 0 && obj->expected_bursts > 0)
407     {
408         obj->expected_bursts--;
409         if (0 == obj->expected_bursts)
410         {
411             hal_rslt |= CYHAL_DMA_DESCRIPTOR_COMPLETE;
412         #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
413             obj->expected_bursts = (GET_RESOURCE_DATA(obj->descriptor_config).interruptType == _CYHAL_DMAC_X_LOOP)
414                 ? GET_RESOURCE_DATA(obj->descriptor_config).yCount
415                 : 1;
416         #elif defined(CY_IP_MXSAXIDMAC)
417             obj->expected_bursts = (GET_RESOURCE_DATA(obj->descriptor_config).interruptType == _CYHAL_DMAC_M_LOOP)
418                 ? GET_RESOURCE_DATA(obj->descriptor_config).xCount
419                 : 1;
420         #else
421             obj->expected_bursts = 1;
422         #endif
423         }
424     }
425 
426     return hal_rslt;
427 }
428 #endif
429 
430 /** DMAC irq handler */
_cyhal_dma_dmac_irq_handler(void)431 static void _cyhal_dma_dmac_irq_handler(void)
432 {
433     /* Use irqn to get appropriate config structure */
434     _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
435     uint8_t block = _cyhal_dma_dmac_get_block_from_irqn(irqn);
436 #if defined(CY_IP_MXSAXIDMAC)
437     SAXI_DMAC_Type* base = _cyhal_dma_dmac_get_base(block);
438 #else
439     DMAC_Type* base = _cyhal_dma_dmac_get_base(block);
440 #endif
441 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
442     uint8_t channel = _cyhal_dma_dmac_get_channel_from_irqn(irqn);
443     cyhal_dma_t *obj = _cyhal_dma_dmac_get_obj(block, channel);
444 
445     /* Get interrupt type and call users event callback if they have enabled that event */
446     uint32_t cause = _cyhal_dmac_channel_get_interrupt_status_masked(base, channel);
447     cyhal_dma_event_t event_type = _cyhal_dma_dmac_convert_interrupt_cause(obj, cause);
448     uint32_t events_to_callback = event_type & obj->irq_cause;
449     if(obj->callback_data.callback != NULL && events_to_callback)
450     {
451         ((cyhal_dma_event_callback_t)obj->callback_data.callback)(obj->callback_data.callback_arg, (cyhal_dma_event_t)events_to_callback);
452     }
453 
454     /* Clear all interrupts */
455 #if defined(CY_IP_MXSAXIDMAC)
456     Cy_AXIDMAC_Channel_ClearInterrupt(base, channel, CY_AXIDMAC_INTR_MASK);
457 #else
458     Cy_DMAC_Channel_ClearInterrupt(base, channel, CY_DMAC_INTR_MASK);
459 #endif
460 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
461     uint32_t channels = Cy_DMAC_GetInterruptStatusMasked(base);
462     for(int i = 0 ; ((uint32_t)(1 << i)) <= channels ; i++)
463     {
464         cyhal_dma_t *obj = _cyhal_dma_dmac_get_obj(block, i);
465         if (obj != NULL)
466         {
467             if (((channels & (1 << i)) != 0) && (obj->callback_data.callback != NULL))
468             {
469                 ((cyhal_dma_event_callback_t)obj->callback_data.callback)(obj->callback_data.callback_arg, CYHAL_DMA_TRANSFER_COMPLETE);
470             }
471         }
472     }
473     Cy_DMAC_ClearInterrupt(_cyhal_dma_dmac_get_base(block), channels);
474 #endif
475 }
476 
_cyhal_dma_dmac_get_src(uint8_t block_num,uint8_t channel_num)477 static cyhal_source_t _cyhal_dma_dmac_get_src(uint8_t block_num, uint8_t channel_num)
478 {
479 #if defined(CY_IP_MXSAXIDMAC)
480     return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE((_CYHAL_TRIGGER_M55APPCPUSS_AXIDMAC_TR_OUT0 + (block_num * APPCPUSS_AXIDMAC0_CH_NR) + channel_num), CYHAL_SIGNAL_TYPE_EDGE);
481 #else
482     return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE((_CYHAL_TRIGGER_CPUSS_DMAC0_TR_OUT0 + (block_num * CPUSS_DMAC0_CH_NR) + channel_num), CYHAL_SIGNAL_TYPE_EDGE);
483 #endif
484 }
485 
_cyhal_dma_dmac_get_dest(uint8_t block_num,uint8_t channel_num)486 static cyhal_dest_t _cyhal_dma_dmac_get_dest(uint8_t block_num, uint8_t channel_num)
487 {
488 #if defined(CY_IP_MXSAXIDMAC)
489     return (cyhal_dest_t)(CYHAL_TRIGGER_M55APPCPUSS_AXIDMAC_TR_IN0 + (block_num * APPCPUSS_AXIDMAC0_CH_NR) + channel_num);
490 #else
491     return (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + (block_num * CPUSS_DMAC0_CH_NR) + channel_num);
492 #endif
493 }
494 
_cyhal_dma_dmac_stage(cyhal_dma_t * obj)495 static cy_rslt_t _cyhal_dma_dmac_stage(cyhal_dma_t *obj)
496 {
497     cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
498 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
499 #if defined(CY_IP_MXSAXIDMAC)
500     cy_en_axidmac_descriptor_type_t descr_type = GET_RESOURCE_DATA(&obj->descriptor_config)->descriptorType;
501     GET_RESOURCE_DATA(&obj->descriptor_config)->descriptorType = CY_AXIDMAC_3D_MEMORY_COPY;
502     cy_rslt_t rslt = Cy_AXIDMAC_Descriptor_Init(GET_RESOURCE_DATA(&obj->descriptor), GET_RESOURCE_DATA(&obj->descriptor_config));
503     Cy_AXIDMAC_Descriptor_SetDescriptorType(GET_RESOURCE_DATA(&obj->descriptor), descr_type);
504     GET_RESOURCE_DATA(&obj->descriptor_config)->descriptorType = descr_type;
505 #else
506     cy_rslt_t rslt = Cy_DMAC_Descriptor_Init(GET_RESOURCE_DATA(&obj->descriptor), GET_RESOURCE_DATA(&obj->descriptor_config));
507 #endif
508 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
509     cy_rslt_t rslt = Cy_DMAC_Descriptor_Init(base, obj->resource.channel_num, obj->descriptor, GET_RESOURCE_DATA(&obj->descriptor_config));
510 #endif
511 #if defined(CY_IP_MXSAXIDMAC)
512     if(CY_AXIDMAC_SUCCESS != rslt)
513 #else
514     if(CY_DMAC_SUCCESS != rslt)
515 #endif
516         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
517 
518     /* Setup channel and enable */
519 #if defined(CY_IP_MXSAXIDMAC)
520     if(CY_AXIDMAC_SUCCESS != Cy_AXIDMAC_Channel_Init(base, obj->resource.channel_num, GET_RESOURCE_DATA(&obj->channel_config)))
521 #else
522     if(CY_DMAC_SUCCESS != Cy_DMAC_Channel_Init(base, obj->resource.channel_num, GET_RESOURCE_DATA(&obj->channel_config)))
523 #endif
524         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
525 
526 #if defined(CY_IP_MXSAXIDMAC)
527     Cy_AXIDMAC_Channel_SetInterruptMask(base, obj->resource.channel_num, CY_AXIDMAC_INTR_MASK);
528 #elif defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
529     Cy_DMAC_Channel_SetInterruptMask(base, obj->resource.channel_num, CY_DMAC_INTR_MASK);
530 #endif
531 #if defined(CY_IP_MXSAXIDMAC)
532     Cy_AXIDMAC_Enable(base);
533 #else
534     Cy_DMAC_Enable(base);
535 #endif
536 
537 #if defined(CY_IP_MXSAXIDMAC)
538     /* src_misal and dst_misal interrupts are triggered immediately on enable
539      * so return those errors here */
540     uint32_t status = Cy_AXIDMAC_Channel_GetInterruptStatus(base, obj->resource.channel_num);
541     if((status & CY_AXIDMAC_INTR_INVALID_DESCR_TYPE))
542     {
543         /* Clear all interrupts and return error */
544         Cy_AXIDMAC_Channel_ClearInterrupt(base, obj->resource.channel_num, CY_AXIDMAC_INTR_MASK);
545         return CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT;
546     }
547 #elif defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
548     /* src_misal and dst_misal interrupts are triggered immediately on enable
549      * so return those errors here */
550     uint32_t status = Cy_DMAC_Channel_GetInterruptStatus(base, obj->resource.channel_num);
551     if((status & CY_DMAC_INTR_SRC_MISAL) ||
552        (status & CY_DMAC_INTR_DST_MISAL))
553     {
554         /* Clear all interrupts and return error */
555         Cy_DMAC_Channel_ClearInterrupt(base, obj->resource.channel_num, CY_DMAC_INTR_MASK);
556         return CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT;
557     }
558 #endif
559 
560     /* Enable interrupt for this channel; preserve user priority if they enabled an interrupt */
561     _cyhal_system_irq_t irqn = _cyhal_dma_dmac_get_irqn(obj);
562     uint32_t priority = (CYHAL_DMA_NO_INTR == obj->irq_cause)
563         ? CYHAL_ISR_PRIORITY_DEFAULT
564         : _cyhal_irq_get_priority(irqn);
565 
566     if(CY_RSLT_SUCCESS != _cyhal_irq_register(irqn, priority, _cyhal_dma_dmac_irq_handler))
567         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
568     _cyhal_irq_enable(irqn);
569 
570     #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
571     SCB_CleanDCache_by_Addr((void *)&(obj->descriptor), sizeof(obj->descriptor));
572     #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
573 
574     return CY_RSLT_SUCCESS;
575 }
576 
_cyhal_dma_dmac_init(cyhal_dma_t * obj,cyhal_source_t * src,cyhal_dest_t * dest,uint8_t priority)577 cy_rslt_t _cyhal_dma_dmac_init(cyhal_dma_t *obj, cyhal_source_t *src, cyhal_dest_t *dest, uint8_t priority)
578 {
579 
580 #if defined(CY_IP_MXSAXIDMAC)
581     if(!CY_AXIDMAC_IS_PRIORITY_VALID(priority))
582 #else
583     if(!CY_DMAC_IS_PRIORITY_VALID(priority))
584 #endif
585         return CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY;
586 
587     if (_cyhal_dma_dmac_pm_transition_pending)
588     {
589         return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
590     }
591 
592     cy_rslt_t rslt = _cyhal_hwmgr_allocate_with_connection(
593         CYHAL_RSC_DMA, src, dest, _cyhal_dma_dmac_get_src, _cyhal_dma_dmac_get_dest, &obj->resource);
594     if(rslt != CY_RSLT_SUCCESS)
595         return rslt;
596 
597     obj->callback_data.callback = NULL;
598 
599     /* Setup descriptor and channel configs */
600     GET_RESOURCE_DATA(obj->descriptor_config) = _cyhal_dma_dmac_default_descriptor_config;
601     GET_RESOURCE_DATA(obj->channel_config) = _cyhal_dma_dmac_default_channel_config;
602 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
603     GET_RESOURCE_DATA(obj->channel_config).descriptor = GET_RESOURCE_DATA(&obj->descriptor);
604 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
605     obj->descriptor = obj->channel_config.descriptor;
606 #endif
607     GET_RESOURCE_DATA(obj->channel_config).priority = priority;
608 
609 #if CYHAL_DRIVER_AVAILABLE_SYSPM
610     if (!_cyhal_dma_dmac_has_enabled())
611     {
612         _cyhal_syspm_register_peripheral_callback(&_cyhal_dma_dmac_pm_callback_args);
613     }
614 #endif
615 
616     _cyhal_dma_dmac_set_obj(obj);
617 
618     return CY_RSLT_SUCCESS;
619 }
620 
_cyhal_dma_dmac_init_cfg(cyhal_dma_t * obj,const cyhal_dma_configurator_t * cfg)621 cy_rslt_t _cyhal_dma_dmac_init_cfg(cyhal_dma_t *obj, const cyhal_dma_configurator_t *cfg)
622 {
623     if (_cyhal_dma_dmac_pm_transition_pending)
624     {
625         return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
626     }
627 
628     obj->resource = *(cfg->resource);
629     obj->callback_data.callback = NULL;
630 
631     /* Setup descriptor and channel configs */
632 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
633     obj->descriptor_config.dmac = *(cfg->dmac_descriptor_config);
634     obj->channel_config.dmac = *(cfg->dmac_channel_config);
635     GET_RESOURCE_DATA(obj->channel_config).descriptor = GET_RESOURCE_DATA(&obj->descriptor);
636     #if defined(CY_IP_MXSAXIDMAC)
637         obj->expected_bursts = cfg->dmac_descriptor_config->xCount;
638     #else
639         obj->expected_bursts = cfg->dmac_descriptor_config->yCount;
640     #endif
641 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
642     obj->descriptor_config = *(cfg->descriptor_config);
643     obj->channel_config = *(cfg->channel_config);
644     obj->descriptor = obj->channel_config.descriptor;
645     obj->expected_bursts = 1;
646 #endif
647 
648 #if CYHAL_DRIVER_AVAILABLE_SYSPM
649     if (!_cyhal_dma_dmac_has_enabled())
650     {
651         _cyhal_syspm_register_peripheral_callback(&_cyhal_dma_dmac_pm_callback_args);
652     }
653 #endif
654 
655     _cyhal_dma_dmac_set_obj(obj);
656 
657     return _cyhal_dma_dmac_stage(obj);
658 }
659 
_cyhal_dma_dmac_free(cyhal_dma_t * obj)660 void _cyhal_dma_dmac_free(cyhal_dma_t *obj)
661 {
662     cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
663 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
664     Cy_DMAC_Descriptor_DeInit(GET_RESOURCE_DATA(&obj->descriptor));
665     Cy_DMAC_Channel_DeInit(base, obj->resource.channel_num);
666 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
667     Cy_DMAC_Descriptor_DeInit(base, obj->resource.channel_num, obj->descriptor);
668     Cy_DMAC_Channel_DeInit(base, obj->resource.channel_num);
669 #elif defined(CY_IP_MXSAXIDMAC)
670     Cy_AXIDMAC_Descriptor_DeInit(GET_RESOURCE_DATA(&obj->descriptor));
671     Cy_AXIDMAC_Channel_DeInit(base, obj->resource.channel_num);
672 #endif
673 
674     _cyhal_irq_free(_cyhal_dma_dmac_get_irqn(obj));
675 
676     _cyhal_dma_dmac_free_obj(obj);
677 
678 #if CYHAL_DRIVER_AVAILABLE_SYSPM
679     if (!_cyhal_dma_dmac_has_enabled())
680     {
681         _cyhal_syspm_unregister_peripheral_callback(&_cyhal_dma_dmac_pm_callback_args);
682         _cyhal_dma_dmac_pm_transition_pending = false;
683     }
684 #endif
685 }
686 
687 /* Initialize descriptor, initialize channel, enable channel, enable channel
688  * interrupt, and enable DMAC controller */
_cyhal_dma_dmac_configure(cyhal_dma_t * obj,const cyhal_dma_cfg_t * cfg)689 cy_rslt_t _cyhal_dma_dmac_configure(cyhal_dma_t *obj, const cyhal_dma_cfg_t *cfg)
690 {
691     uint32_t total_length = cfg->length;
692 
693     /* Do not reconfigure if transfer is pending/active already */
694     if(_cyhal_dma_dmac_is_busy(obj))
695         return CYHAL_DMA_RSLT_ERR_CHANNEL_BUSY;
696 
697     // DMAC only supports <=65536 byte burst and <=65536 bytes per burst
698     if ((cfg->burst_size > 65536) ||
699         ((cfg->burst_size <= 1) && (cfg->length > 65536)) ||
700         ((cfg->burst_size > 0) && (cfg->length > (cfg->burst_size * 65536))))
701         return CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_SIZE;
702 
703 #if defined(CY_IP_M0S8CPUSSV3_DMAC)
704     // PSoC™ 4 devices do not support automatically disabling the channel on completion
705     if ((cfg->action == CYHAL_DMA_TRANSFER_BURST_DISABLE) ||
706         (cfg->action == CYHAL_DMA_TRANSFER_FULL_DISABLE))
707     {
708         return CYHAL_DMA_RSLT_FATAL_UNSUPPORTED_HARDWARE;
709     }
710 #endif
711 
712     GET_RESOURCE_DATA(obj->descriptor_config).srcAddress = (void*)cfg->src_addr;
713     GET_RESOURCE_DATA(obj->descriptor_config).dstAddress = (void*)cfg->dst_addr;
714 
715     if ((cfg->transfer_width != 8) && (cfg->transfer_width != 16) && (cfg->transfer_width != 32))
716         return CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH;
717 
718 #if !defined(CY_IP_MXSAXIDMAC)
719     total_length = cfg->length;
720 
721     if(cfg->transfer_width == 8)
722         GET_RESOURCE_DATA(obj->descriptor_config).dataSize = CY_DMAC_BYTE;
723     else if(cfg->transfer_width == 16)
724         GET_RESOURCE_DATA(obj->descriptor_config).dataSize = CY_DMAC_HALFWORD;
725     else if(cfg->transfer_width == 32)
726         GET_RESOURCE_DATA(obj->descriptor_config).dataSize = CY_DMAC_WORD;
727     else
728         return CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH;
729 
730     /* By default, transfer what the user set for dataSize. However, if transfering between memory
731      * and a peripheral, make sure the peripheral access is using words. */
732     GET_RESOURCE_DATA(obj->descriptor_config).srcTransferSize =
733         GET_RESOURCE_DATA(obj->descriptor_config).dstTransferSize = CY_DMAC_TRANSFER_SIZE_DATA;
734     if (obj->direction == CYHAL_DMA_DIRECTION_PERIPH2MEM)
735         GET_RESOURCE_DATA(obj->descriptor_config).srcTransferSize = CY_DMAC_TRANSFER_SIZE_WORD;
736     else if (obj->direction == CYHAL_DMA_DIRECTION_MEM2PERIPH)
737         GET_RESOURCE_DATA(obj->descriptor_config).dstTransferSize = CY_DMAC_TRANSFER_SIZE_WORD;
738 #else
739     /* Need to convert number of elements to the total number of bytes for transfer */
740     total_length = cfg->length * (cfg->transfer_width / 8);
741     if (!CY_AXIDMAC_IS_LOOP_COUNT_VALID(total_length))
742     {
743         return CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_SIZE;
744     }
745 #endif
746 
747 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
748     GET_RESOURCE_DATA(obj->descriptor_config).nextDescriptor = GET_RESOURCE_DATA(&obj->descriptor);
749     if ((cfg->action == CYHAL_DMA_TRANSFER_BURST) || (cfg->action == CYHAL_DMA_TRANSFER_FULL))
750     {
751         GET_RESOURCE_DATA(obj->descriptor_config).channelState = _CYHAL_DMAC_CHANNEL_ENABLED;
752     }
753     else
754     {
755         GET_RESOURCE_DATA(obj->descriptor_config).channelState = _CYHAL_DMAC_CHANNEL_DISABLED;
756     }
757 
758     GET_RESOURCE_DATA(obj->descriptor_config).srcXincrement = cfg->src_increment;
759     GET_RESOURCE_DATA(obj->descriptor_config).dstXincrement = cfg->dst_increment;
760 
761     /* Setup 2D transfer if burst_size is being used otherwise set up 1D
762      * transfer */
763     if(cfg->burst_size != 0)
764     {
765         /* Length must be a multiple of burst_size */
766         if(total_length % cfg->burst_size != 0)
767             return CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE;
768 
769     #if defined(CY_IP_MXSAXIDMAC)
770         GET_RESOURCE_DATA(obj->descriptor_config).descriptorType = CY_AXIDMAC_2D_MEMORY_COPY;
771         GET_RESOURCE_DATA(obj->descriptor_config).mCount = cfg->burst_size * (cfg->transfer_width / 8);
772         GET_RESOURCE_DATA(obj->descriptor_config).xCount = (cfg->length / cfg->burst_size);
773         GET_RESOURCE_DATA(obj->descriptor_config).srcXincrement = cfg->src_increment * cfg->burst_size * (cfg->transfer_width / 8);
774         GET_RESOURCE_DATA(obj->descriptor_config).dstXincrement = cfg->dst_increment * cfg->burst_size * (cfg->transfer_width / 8);
775     #else
776         GET_RESOURCE_DATA(obj->descriptor_config).descriptorType = CY_DMAC_2D_TRANSFER;
777         GET_RESOURCE_DATA(obj->descriptor_config).xCount = cfg->burst_size;
778         GET_RESOURCE_DATA(obj->descriptor_config).yCount = total_length / cfg->burst_size;
779         GET_RESOURCE_DATA(obj->descriptor_config).srcYincrement = cfg->src_increment * cfg->burst_size;
780         GET_RESOURCE_DATA(obj->descriptor_config).dstYincrement = cfg->dst_increment * cfg->burst_size;
781     #endif
782 
783     }
784     else
785     {
786     #if defined(CY_IP_MXSAXIDMAC)
787         GET_RESOURCE_DATA(obj->descriptor_config).descriptorType = CY_AXIDMAC_1D_MEMORY_COPY;
788         GET_RESOURCE_DATA(obj->descriptor_config).mCount = total_length;
789     #else
790         GET_RESOURCE_DATA(obj->descriptor_config).descriptorType = CY_DMAC_1D_TRANSFER;
791         GET_RESOURCE_DATA(obj->descriptor_config).xCount = total_length;
792     #endif
793     }
794 
795     /* If burst action, configure trigger and interrupt actions */
796     if (cfg->burst_size != 0 &&
797         (cfg->action == CYHAL_DMA_TRANSFER_BURST || cfg->action == CYHAL_DMA_TRANSFER_BURST_DISABLE))
798     {
799     #if defined(CY_IP_MXSAXIDMAC)
800         obj->expected_bursts = GET_RESOURCE_DATA(obj->descriptor_config).xCount;
801         GET_RESOURCE_DATA(obj->descriptor_config).interruptType = _CYHAL_DMAC_M_LOOP;
802         if (obj->source == _CYHAL_TRIGGER_CPUSS_ZERO) // If not overridden by connect_digital()
803             GET_RESOURCE_DATA(obj->descriptor_config).triggerInType = _CYHAL_DMAC_M_LOOP;
804     #else
805         obj->expected_bursts = GET_RESOURCE_DATA(obj->descriptor_config).yCount;
806         GET_RESOURCE_DATA(obj->descriptor_config).interruptType = _CYHAL_DMAC_X_LOOP;
807         if (obj->source == _CYHAL_TRIGGER_CPUSS_ZERO) // If not overridden by connect_digital()
808             GET_RESOURCE_DATA(obj->descriptor_config).triggerInType = _CYHAL_DMAC_X_LOOP;
809     #endif
810     }
811     else
812     {
813         obj->expected_bursts = 1;
814         GET_RESOURCE_DATA(obj->descriptor_config).interruptType = _CYHAL_DMAC_DESCR;
815         if (obj->source == _CYHAL_TRIGGER_CPUSS_ZERO) // If not overridden by connect_digital()
816             GET_RESOURCE_DATA(obj->descriptor_config).triggerInType = _CYHAL_DMAC_DESCR;
817      }
818 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
819     if(cfg->burst_size != 0)
820     {
821         return CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE;
822     }
823     else
824     {
825         GET_RESOURCE_DATA(obj->descriptor_config).dataCount = total_length;
826         GET_RESOURCE_DATA(obj->descriptor_config).srcAddrIncrement = cfg->src_increment;
827         GET_RESOURCE_DATA(obj->descriptor_config).dstAddrIncrement = cfg->dst_increment;
828         obj->expected_bursts = 1;
829     }
830 #endif
831 
832     return _cyhal_dma_dmac_stage(obj);
833 }
834 
_cyhal_dma_dmac_enable(cyhal_dma_t * obj)835 cy_rslt_t _cyhal_dma_dmac_enable(cyhal_dma_t *obj)
836 {
837     cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
838     _cyhal_dmac_channel_enable(base, obj->resource.channel_num);
839     return CY_RSLT_SUCCESS;
840 }
841 
_cyhal_dma_dmac_disable(cyhal_dma_t * obj)842 cy_rslt_t _cyhal_dma_dmac_disable(cyhal_dma_t *obj)
843 {
844     cyhal_dmac_hw_type* base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
845     _cyhal_dmac_channel_disable(base, obj->resource.channel_num);
846     return CY_RSLT_SUCCESS;
847 }
848 
_cyhal_dma_dmac_start_transfer(cyhal_dma_t * obj)849 cy_rslt_t _cyhal_dma_dmac_start_transfer(cyhal_dma_t *obj)
850 {
851     /* Return warning if channel is busy */
852     if(_cyhal_dma_dmac_is_busy(obj))
853         return CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED;
854 
855     if (_cyhal_dma_dmac_pm_transition_pending)
856         return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
857 
858     uint32_t trigline = _cyhal_dma_dmac_get_trigger_line(obj->resource.block_num, obj->resource.channel_num);
859     cy_en_trigmux_status_t trig_status = Cy_TrigMux_SwTrigger(trigline, CY_TRIGGER_TWO_CYCLES);
860 
861     /* Also return warning if SW trigger is already initiated but DMA hardware
862      * has not seen it yet */
863     if(trig_status == CY_TRIGMUX_INVALID_STATE)
864         return CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED;
865     else
866         return CY_RSLT_SUCCESS;
867 }
868 
_cyhal_dma_dmac_enable_event(cyhal_dma_t * obj,cyhal_dma_event_t event,uint8_t intr_priority,bool enable)869 void _cyhal_dma_dmac_enable_event(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable)
870 {
871 #if defined (CY_IP_M0S8CPUSSV3_DMAC)
872     DMAC_Type *base = _cyhal_dma_dmac_get_base(obj->resource.block_num);
873     uint32_t mask = Cy_DMAC_GetInterruptMask(base);
874 #endif
875     if(enable)
876     {
877 #if defined (CY_IP_M0S8CPUSSV3_DMAC)
878         Cy_DMAC_SetInterruptMask(base, mask | (1 << obj->resource.channel_num));
879 #endif
880         obj->irq_cause |= event;
881     }
882     else
883     {
884 #if defined (CY_IP_M0S8CPUSSV3_DMAC)
885         Cy_DMAC_SetInterruptMask(base, mask & ~(1 << obj->resource.channel_num));
886 #endif
887         obj->irq_cause &= ~event;
888     }
889 
890     _cyhal_irq_set_priority(_cyhal_dma_dmac_get_irqn(obj), intr_priority);
891 }
892 
_cyhal_dma_dmac_is_busy(cyhal_dma_t * obj)893 bool _cyhal_dma_dmac_is_busy(cyhal_dma_t *obj)
894 {
895     /* The value is a bit field of all pending or active channels */
896     return _cyhal_dmac_get_active_channel(_cyhal_dma_dmac_get_base(obj->resource.block_num)) & (1 << obj->resource.channel_num);
897 }
898 #if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) || defined(CY_IP_MXSAXIDMAC)
899 #if defined(CY_IP_MXSAXIDMAC)
_cyhal_convert_input_t(cyhal_dma_input_t input)900 static cy_en_axidmac_trigger_type_t _cyhal_convert_input_t(cyhal_dma_input_t input)
901 {
902     switch(input)
903     {
904         case CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT:
905             return CY_AXIDMAC_M_LOOP;
906         case CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST:
907             return CY_AXIDMAC_X_LOOP;
908         case CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS:
909             return CY_AXIDMAC_DESCR;
910         default:
911             // Should never reach here. Just silencing compiler warnings.
912             CY_ASSERT(false);
913             return CY_AXIDMAC_DESCR;
914     }
915 }
916 #elif defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC)
_cyhal_convert_input_t(cyhal_dma_input_t input)917 static cy_en_dmac_trigger_type_t _cyhal_convert_input_t(cyhal_dma_input_t input)
918 {
919     switch(input)
920     {
921         case CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT:
922             return CY_DMAC_1ELEMENT;
923         case CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST:
924             return CY_DMAC_X_LOOP;
925         case CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS:
926             return CY_DMAC_DESCR;
927         default:
928             // Should never reach here. Just silencing compiler warnings.
929             CY_ASSERT(false);
930             return CY_DMAC_DESCR;
931     }
932 }
933 #endif
934 
935 #if defined(CY_IP_MXSAXIDMAC)
_cyhal_convert_output_t(cyhal_dma_output_t output)936 static cy_en_axidmac_trigger_type_t _cyhal_convert_output_t(cyhal_dma_output_t output)
937 {
938     switch(output)
939     {
940         case CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT:
941             return CY_AXIDMAC_M_LOOP;
942         case CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST:
943             return CY_AXIDMAC_X_LOOP;
944         case CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS:
945             return CY_AXIDMAC_DESCR;
946         default:
947             // Should never reach here. Just silencing compiler warnings.
948             CY_ASSERT(false);
949             return CY_AXIDMAC_DESCR;
950     }
951 }
952 #else
_cyhal_convert_output_t(cyhal_dma_output_t output)953 static cy_en_dmac_trigger_type_t _cyhal_convert_output_t(cyhal_dma_output_t output)
954 {
955     switch(output)
956     {
957         case CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT:
958             return CY_DMAC_1ELEMENT;
959         case CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST:
960             return CY_DMAC_X_LOOP;
961         case CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS:
962             return CY_DMAC_DESCR;
963         default:
964             // Should never reach here. Just silencing compiler warnings.
965             CY_ASSERT(false);
966             return CY_DMAC_DESCR;
967     }
968 }
969 #endif
970 
_cyhal_dma_dmac_connect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)971 cy_rslt_t _cyhal_dma_dmac_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
972 {
973     if(input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT &&
974        input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST &&
975        input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS)
976         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
977 
978     obj->descriptor_config.dmac.triggerInType = _cyhal_convert_input_t(input);
979 
980     _cyhal_dmac_channel_disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
981 
982     obj->descriptor.dmac.ctl &= ~_CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Msk;
983     obj->descriptor.dmac.ctl |= _VAL2FLD(_CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE, obj->descriptor_config.dmac.triggerInType);
984     #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
985     SCB_CleanDCache_by_Addr((void *)&(obj->descriptor), sizeof(obj->descriptor));
986     #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
987 
988     _cyhal_dmac_channel_enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
989 
990     cyhal_dest_t dest = _cyhal_dma_dmac_get_dest(obj->resource.block_num, obj->resource.channel_num);
991 
992     return _cyhal_connect_signal(source, dest);
993 }
994 
_cyhal_dma_dmac_enable_output(cyhal_dma_t * obj,cyhal_dma_output_t output,cyhal_source_t * source)995 cy_rslt_t _cyhal_dma_dmac_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source)
996 {
997     if(output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT &&
998        output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST &&
999        output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS)
1000         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1001 
1002     _cyhal_dmac_channel_disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
1003 
1004     obj->descriptor.dmac.ctl &= ~_CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Msk;
1005     obj->descriptor.dmac.ctl |= _VAL2FLD(_CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE, _cyhal_convert_output_t(output));
1006     #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
1007     SCB_CleanDCache_by_Addr((void *)&(obj->descriptor), sizeof(obj->descriptor));
1008     #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
1009 
1010     _cyhal_dmac_channel_enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
1011     *source = _cyhal_dma_dmac_get_src(obj->resource.block_num, obj->resource.channel_num);
1012 
1013     return CY_RSLT_SUCCESS;
1014 }
1015 
_cyhal_dma_dmac_disconnect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)1016 cy_rslt_t _cyhal_dma_dmac_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
1017 {
1018     if(input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT &&
1019        input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST &&
1020        input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS)
1021         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1022 
1023 
1024     // There is no option to totally disable. Just reset to default.
1025     // NOTE: Use .interruptType since it matches the desired .triggerInType from configure(), but
1026     // is not modified by connect/disconnect functions
1027     _cyhal_dmac_channel_disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
1028 
1029     obj->descriptor.dmac.ctl &= ~_CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE_Msk;
1030     obj->descriptor.dmac.ctl |= _VAL2FLD(_CYHAL_DMAC_CH_DESCR_CTL_TR_IN_TYPE, _cyhal_dma_dmac_default_descriptor_config.interruptType);
1031     #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
1032     SCB_CleanDCache_by_Addr((void *)&(obj->descriptor), sizeof(obj->descriptor));
1033     #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
1034 
1035     _cyhal_dmac_channel_enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
1036 
1037     cyhal_dest_t dest = _cyhal_dma_dmac_get_dest(obj->resource.block_num, obj->resource.channel_num);
1038 
1039     return _cyhal_disconnect_signal(source, dest);
1040 }
1041 
_cyhal_dma_dmac_disable_output(cyhal_dma_t * obj,cyhal_dma_output_t output)1042 cy_rslt_t _cyhal_dma_dmac_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output)
1043 {
1044     if(output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT &&
1045        output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST &&
1046        output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS)
1047         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1048 
1049     // There is no option to totally disable. Just reset to default.
1050     _cyhal_dmac_channel_disable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
1051 
1052     obj->descriptor.dmac.ctl &= ~_CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE_Msk;
1053     obj->descriptor.dmac.ctl |= _VAL2FLD(_CYHAL_DMAC_CH_DESCR_CTL_TR_OUT_TYPE, _cyhal_dma_dmac_default_descriptor_config.triggerOutType);
1054     #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
1055     SCB_CleanDCache_by_Addr((void *)&(obj->descriptor), sizeof(obj->descriptor));
1056     #endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
1057 
1058     _cyhal_dmac_channel_enable(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num);
1059 
1060     return CY_RSLT_SUCCESS;
1061 
1062 }
1063 #elif defined(CY_IP_M0S8CPUSSV3_DMAC)
1064 
_cyhal_dma_dmac_connect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)1065 cy_rslt_t _cyhal_dma_dmac_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
1066 {
1067     if((input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT) &&
1068        (input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS))
1069         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1070 
1071     Cy_DMAC_Channel_SetCurrentDescriptor(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num, obj->descriptor);
1072 
1073     cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + obj->resource.channel_num);
1074 
1075 
1076     return _cyhal_connect_signal(source, dest);
1077 }
1078 
1079 // M0S8 output triggers are always active. This is a noop except to return the source.
_cyhal_dma_dmac_enable_output(cyhal_dma_t * obj,cyhal_dma_output_t output,cyhal_source_t * source)1080 cy_rslt_t _cyhal_dma_dmac_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source)
1081 {
1082     if((output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT) &&
1083        (output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS))
1084         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1085 
1086     *source = _cyhal_dma_dmac_get_src(obj->resource.block_num, obj->resource.channel_num);
1087 
1088     return CY_RSLT_SUCCESS;
1089 }
1090 
_cyhal_dma_dmac_disconnect_digital(cyhal_dma_t * obj,cyhal_source_t source,cyhal_dma_input_t input)1091 cy_rslt_t _cyhal_dma_dmac_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input)
1092 {
1093     if((input != CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT) &&
1094        (input != CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS))
1095         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1096 
1097     // Reset to default
1098     Cy_DMAC_Channel_SetCurrentDescriptor(_cyhal_dma_dmac_get_base(obj->resource.block_num), obj->resource.channel_num, obj->descriptor);
1099 
1100     cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_CPUSS_DMAC0_TR_IN0 + obj->resource.channel_num);
1101 
1102     return _cyhal_disconnect_signal(source, dest);
1103 }
1104 
1105 // M0S8 output triggers are always active. This is a noop.
_cyhal_dma_dmac_disable_output(cyhal_dma_t * obj,cyhal_dma_output_t output)1106 cy_rslt_t _cyhal_dma_dmac_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output)
1107 {
1108     CY_UNUSED_PARAMETER(obj);
1109 
1110     if((output != CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT) &&
1111        (output != CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS))
1112         return CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER;
1113 
1114     return CY_RSLT_SUCCESS;
1115 }
1116 
1117 #endif /* defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M7CPUSS_DMAC) || defined(CY_IP_MXAHBDMAC) */
1118 
1119 #endif /* (_CYHAL_DRIVER_AVAILABLE_DMA_DMAC) */
1120 
1121 #if defined(__cplusplus)
1122 }
1123 #endif
1124