1 /***************************************************************************//**
2 * \file cy_dma.c
3 * \version 2.90
4 *
5 * \brief
6 * The source code file for the DMA driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2016-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 *     http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25 
26 #include "cy_device.h"
27 #include <assert.h>
28 
29 #if defined (CY_IP_M4CPUSS_DMA) || defined (CY_IP_MXDW) || defined (CY_IP_M7CPUSS_DMA)
30 
31 #include "cy_dma.h"
32 
33 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 5, \
34 'DW_Type will typecast to either DW_V1_Type or DW_V2_Type but not both on PDL initialization based on the target device at compile time.')
35 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 10.8', 2, \
36 'Value extracted from _VAL2FLD macro will not exceed enum range.')
37 
38 /*******************************************************************************
39 * Function Name: Cy_DMA_Crc_Init
40 ****************************************************************************//**
41 *
42 * Initializes the DMA CRC functionality.
43 *
44 * \param base The pointer to the hardware DMA block.
45 *
46 * \param crcConfig The pointer to the CRC configuration structure
47 *                  \ref cy_stc_dma_crc_config_t.
48 *
49 * \return The status /ref cy_en_dma_status_t.
50 *
51 * \funcusage
52 * \snippet dma/snippet/main.c snippet_Cy_DMA_Crc_Init
53 *
54 *******************************************************************************/
Cy_DMA_Crc_Init(DW_Type * base,cy_stc_dma_crc_config_t const * crcConfig)55 cy_en_dma_status_t Cy_DMA_Crc_Init(DW_Type * base, cy_stc_dma_crc_config_t const * crcConfig)
56 {
57     cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
58 #ifdef CY_IP_MXDW
59     if((NULL != base) && (NULL != crcConfig) )
60 #else
61     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 14.3','Intentional check for the macro CY_DW_CRC.');
62     if((NULL != base) && (NULL != crcConfig) && (CY_DW_CRC == 1UL))
63 #endif /* CY_IP_MXDW */
64     {
65         DW_CRC_CTL(base) = _BOOL2FLD(DW_V2_CRC_CTL_DATA_REVERSE, crcConfig->dataReverse) |
66                            _BOOL2FLD(DW_V2_CRC_CTL_REM_REVERSE,  crcConfig->reminderReverse);
67 
68         DW_CRC_DATA_CTL(base) = _VAL2FLD(DW_V2_CRC_DATA_CTL_DATA_XOR,  crcConfig->dataXor);
69         DW_CRC_REM_CTL(base)  = _VAL2FLD(DW_V2_CRC_REM_CTL_REM_XOR,    crcConfig->reminderXor);
70         DW_CRC_POL_CTL(base)  = _VAL2FLD(DW_V2_CRC_POL_CTL_POLYNOMIAL, crcConfig->polynomial);
71         DW_CRC_LFSR_CTL(base) = _VAL2FLD(DW_V2_CRC_LFSR_CTL_LFSR32,    crcConfig->lfsrInitVal);
72 
73         ret = CY_DMA_SUCCESS;
74     }
75 
76     return ret;
77 }
78 
79 
80 /*******************************************************************************
81 * Function Name: Cy_DMA_Descriptor_Init
82 ****************************************************************************//**
83 *
84 * Initializes the descriptor structure in SRAM from a pre-initialized
85 * configuration structure.
86 * This function initializes only the descriptor and not the channel.
87 *
88 * \param descriptor
89 * The descriptor structure instance declared by the user/component.
90 *
91 * \param config
92 * This is a configuration structure that has all initialization information for
93 * the descriptor.
94 *
95 * \return
96 * The status /ref cy_en_dma_status_t.
97 *
98 * \note Based on the descriptor type, the offset of the address for the next descriptor may
99 * vary. For a single-transfer descriptor type, this register is at offset 0x0c.
100 * For the 1D-transfer descriptor type, this register is at offset 0x10.
101 * For the 2D-transfer descriptor type, this register is at offset 0x14.
102 *
103 * \funcusage
104 * \snippet dma/snippet/main.c snippet_Cy_DMA_Enable
105 *
106 *******************************************************************************/
Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor,const cy_stc_dma_descriptor_config_t * config)107 cy_en_dma_status_t Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor, const cy_stc_dma_descriptor_config_t * config)
108 {
109     cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
110 
111     if ((NULL != descriptor) && (NULL != config))
112     {
113         CY_ASSERT_L3(CY_DMA_IS_RETRIG_VALID(config->retrigger));
114         CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->interruptType));
115         CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerOutType));
116         CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerInType));
117         CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->srcTransferSize));
118         CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->dstTransferSize));
119         CY_ASSERT_L3(CY_DMA_IS_CHANNEL_STATE_VALID(config->channelState));
120         CY_ASSERT_L3(CY_DMA_IS_DATA_SIZE_VALID(config->dataSize));
121         CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(config->descriptorType));
122 
123         descriptor->ctl =
124             _VAL2FLD(CY_DMA_CTL_RETRIG, config->retrigger) |
125             _VAL2FLD(CY_DMA_CTL_INTR_TYPE, config->interruptType) |
126             _VAL2FLD(CY_DMA_CTL_TR_OUT_TYPE, config->triggerOutType) |
127             _VAL2FLD(CY_DMA_CTL_TR_IN_TYPE, config->triggerInType) |
128             _VAL2FLD(CY_DMA_CTL_SRC_SIZE, config->srcTransferSize) |
129             _VAL2FLD(CY_DMA_CTL_DST_SIZE, config->dstTransferSize) |
130             _VAL2FLD(CY_DMA_CTL_CH_DISABLE, config->channelState) |
131             _VAL2FLD(CY_DMA_CTL_DATA_SIZE, config->dataSize) |
132             _VAL2FLD(CY_DMA_CTL_TYPE, config->descriptorType);
133 
134         descriptor->src = (uint32_t)config->srcAddress;
135 
136         descriptor->dst = (uint32_t)config->dstAddress;
137 
138         switch(config->descriptorType)
139         {
140             case CY_DMA_SINGLE_TRANSFER:
141                 descriptor->xCtl = (uint32_t)config->nextDescriptor;
142                 ret = CY_DMA_SUCCESS;
143                 break;
144 
145             case CY_DMA_1D_TRANSFER:
146                 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
147                 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstXincrement));
148                 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
149 
150                 descriptor->xCtl =
151                     _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
152                     _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
153     /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
154                     _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
155                 /* offset varies based on the descriptor type */
156                 descriptor->yCtl = (uint32_t)config->nextDescriptor;
157                 ret = CY_DMA_SUCCESS;
158                 break;
159 
160             case CY_DMA_2D_TRANSFER:
161                 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
162                 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstXincrement));
163                 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
164                 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcYincrement));
165                 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstYincrement));
166                 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->yCount));
167 
168                 descriptor->xCtl =
169                     _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
170                     _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
171     /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
172                     _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
173 
174                 descriptor->yCtl =
175                     _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcYincrement) |
176                     _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstYincrement) |
177     /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
178                     _VAL2FLD(CY_DMA_CTL_COUNT, config->yCount - 1UL);
179 
180                 descriptor->nextPtr = (uint32_t)config->nextDescriptor;
181                 ret = CY_DMA_SUCCESS;
182                 break;
183 
184             case CY_DMA_CRC_TRANSFER:
185                 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 14.3','CY_DW_CRC is available for all CAT1B devices.');
186                 if (CY_DW_CRC != 0UL)
187                 {
188                     CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
189                     CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
190 
191                     descriptor->xCtl =
192                         _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
193         /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
194                         _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
195                     /* offset varies based on the descriptor type */
196                     descriptor->yCtl = (uint32_t)config->nextDescriptor;
197                     ret = CY_DMA_SUCCESS;
198                 }
199                 break;
200 
201             default: /* An unsupported type of a descriptor */
202                 break;
203         }
204     }
205 
206     return ret;
207 }
208 
209 
210 /*******************************************************************************
211 * Function Name: Cy_DMA_Descriptor_DeInit
212 ****************************************************************************//**
213 *
214 * Clears the content of the specified descriptor.
215 *
216 * \param descriptor
217 * The descriptor structure instance declared by the user/component.
218 *
219 * \funcusage
220 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_Deinit
221 *
222 *******************************************************************************/
Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor)223 void Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor)
224 {
225     CY_ASSERT_L1(descriptor);
226 
227     descriptor->ctl = 0UL;
228     descriptor->src = 0UL;
229     descriptor->dst = 0UL;
230     descriptor->xCtl = 0UL;
231     descriptor->yCtl = 0UL;
232     descriptor->nextPtr = 0UL;
233 }
234 
235 
236 /*******************************************************************************
237 * Function Name: Cy_DMA_Channel_Init
238 ****************************************************************************//**
239 *
240 * Initializes the DMA channel with a descriptor and other parameters.
241 *
242 * \param base
243 * The pointer to the hardware DMA block.
244 *
245 * \param channel
246 * A channel number.
247 *
248 * \param channelConfig
249 * The structure that has the initialization information for the
250 * channel.
251 *
252 * \return
253 * The status /ref cy_en_dma_status_t.
254 *
255 * \funcusage
256 * \snippet dma/snippet/main.c snippet_Cy_DMA_Enable
257 *
258 *******************************************************************************/
Cy_DMA_Channel_Init(DW_Type * base,uint32_t channel,cy_stc_dma_channel_config_t const * channelConfig)259 cy_en_dma_status_t Cy_DMA_Channel_Init(DW_Type * base, uint32_t channel, cy_stc_dma_channel_config_t const * channelConfig)
260 {
261     cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
262 
263     if ((NULL != base) &&
264         (NULL != channelConfig) &&
265         (NULL != channelConfig->descriptor) &&
266         (CY_DMA_IS_CH_NR_VALID(base, channel)))
267     {
268         CY_ASSERT_L2(CY_DMA_IS_PRIORITY_VALID(channelConfig->priority));
269 
270         /* Set the current descriptor */
271         Cy_DMA_Channel_SetDescriptor(base, channel, channelConfig->descriptor);
272 
273         /* Set the channel configuration */
274         DW_CH_CTL(base, channel) =
275             _BOOL2FLD(CY_DW_CH_CTL_PREEMPTABLE,    channelConfig->preemptable) |
276              _VAL2FLD(CY_DW_CH_CTL_PRIO,           channelConfig->priority)    |
277             _BOOL2FLD(DW_CH_STRUCT_CH_CTL_ENABLED, channelConfig->enable)      |
278             _BOOL2FLD(DW_CH_STRUCT_CH_CTL_B,       channelConfig->bufferable);
279         ret = CY_DMA_SUCCESS;
280     }
281 
282     return (ret);
283 }
284 
285 
286 /*******************************************************************************
287 * Function Name: Cy_DMA_Channel_DeInit
288 ****************************************************************************//**
289 *
290 * Clears the content of registers corresponding to the channel.
291 *
292 * \param base
293 * The pointer to the hardware DMA block.
294 *
295 * \param channel
296 * A channel number.
297 *
298 * \funcusage
299 * \snippet dma/snippet/main.c snippet_Cy_DMA_Disable
300 *
301 *******************************************************************************/
Cy_DMA_Channel_DeInit(DW_Type * base,uint32_t channel)302 void Cy_DMA_Channel_DeInit(DW_Type * base, uint32_t channel)
303 {
304     CY_ASSERT_L1(CY_DMA_IS_CH_NR_VALID(base, channel));
305 
306     DW_CH_CTL(base, channel) = 0UL;
307     DW_CH_IDX(base, channel) = 0UL;
308     DW_CH_CURR_PTR(base, channel) = 0UL;
309     DW_CH_INTR_MASK(base, channel) = 0UL;
310 }
311 
312 
313 /*******************************************************************************
314 * Function Name: Cy_DMA_Descriptor_SetNextDescriptor
315 ****************************************************************************//**
316 *
317 * Sets a Next Descriptor for the specified descriptor.
318 *
319 * Based on the descriptor type, the offset of the address for the next descriptor may
320 * vary. For the single-transfer descriptor type, this register is at offset 0x0c.
321 * For the 1D-transfer descriptor type, this register is at offset 0x10.
322 * For the 2D-transfer descriptor type, this register is at offset 0x14.
323 *
324 * \param descriptor
325 * The descriptor structure instance declared by the user/component.
326 *
327 * \param nextDescriptor
328 * The pointer to the next descriptor.
329 * For CAT1C devices this pointer needs to point to 32 byte aligned structure.
330 *
331 * \funcusage
332 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_SetterFunctions
333 *
334 *******************************************************************************/
Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor,cy_stc_dma_descriptor_t const * nextDescriptor)335 void Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_t const * nextDescriptor)
336 {
337     CY_ASSERT_L1(descriptor);
338     cy_en_dma_descriptor_type_t transferType = (cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl);
339 
340     if (transferType == CY_DMA_SINGLE_TRANSFER)
341     {
342         descriptor->xCtl = (uint32_t)nextDescriptor;
343     }
344     else if (transferType == CY_DMA_CRC_TRANSFER || transferType == CY_DMA_1D_TRANSFER)
345     {
346         descriptor->yCtl = (uint32_t)nextDescriptor;
347     }
348     else if ( transferType == CY_DMA_2D_TRANSFER)
349     {
350         descriptor->nextPtr = (uint32_t)nextDescriptor;
351     }
352     else
353     {
354        /* Unsupported type of descriptor */
355     }
356 
357 }
358 
359 
360 /*******************************************************************************
361 * Function Name: Cy_DMA_Descriptor_GetNextDescriptor
362 ****************************************************************************//**
363 *
364 * Returns a next descriptor address of the specified descriptor.
365 *
366 * Based on the descriptor type, the offset of the address for the next descriptor may
367 * vary. For a single-transfer descriptor type, this register is at offset 0x0c.
368 * For the 1D-transfer descriptor type, this register is at offset 0x10.
369 * For the 2D-transfer descriptor type, this register is at offset 0x14.
370 *
371 * \param descriptor
372 * The descriptor structure instance declared by the user/component.
373 *
374 * \return
375 * The pointer to the next descriptor.
376 *
377 * \funcusage
378 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_GetterFunctions
379 *
380 *******************************************************************************/
Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor)381 cy_stc_dma_descriptor_t * Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor)
382 {
383     cy_stc_dma_descriptor_t * retVal = NULL;
384     CY_ASSERT_L1(descriptor);
385     cy_en_dma_descriptor_type_t transferType = (cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl);
386 
387     if (transferType == CY_DMA_SINGLE_TRANSFER)
388     {
389         retVal = (cy_stc_dma_descriptor_t*) descriptor->xCtl;
390     }
391     else if (transferType == CY_DMA_CRC_TRANSFER ||  transferType == CY_DMA_1D_TRANSFER)
392     {
393         retVal = (cy_stc_dma_descriptor_t*) descriptor->yCtl;
394     }
395     else if (transferType == CY_DMA_2D_TRANSFER)
396     {
397         retVal = (cy_stc_dma_descriptor_t*) descriptor->nextPtr;
398     }
399     else
400     {
401        /* An unsupported type of the descriptor */
402     }
403 
404     return (retVal);
405 }
406 
407 
408 /*******************************************************************************
409 * Function Name: Cy_DMA_Descriptor_SetDescriptorType
410 ****************************************************************************//**
411 *
412 * Sets the descriptor's type for the specified descriptor.
413 * Moves the next descriptor register value into the proper place in accordance
414 * to the actual descriptor type.
415 * During the descriptor's type changing, the Xloop and Yloop settings, such as
416 * data count and source/destination increment (i.e. the content of the
417 * xCtl and yCtl descriptor registers) might be lost (overridden by the
418 * next descriptor value) because of the different descriptor registers structures
419 * for different descriptor types. Carefully set up the Xloop
420 * (and Yloop, if used) data count and source/destination increment if the
421 * descriptor type is changed from a simpler to a more complicated type
422 * ("single transfer" -> "1D", "1D" -> "2D", etc.).
423 *
424 * \param descriptor
425 * The descriptor structure instance declared by the user/component.
426 *
427 * \param descriptorType
428 * The descriptor type \ref cy_en_dma_descriptor_type_t.
429 *
430 * \funcusage
431 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_SetterFunctions
432 *
433 *******************************************************************************/
Cy_DMA_Descriptor_SetDescriptorType(cy_stc_dma_descriptor_t * descriptor,cy_en_dma_descriptor_type_t descriptorType)434 void Cy_DMA_Descriptor_SetDescriptorType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_descriptor_type_t descriptorType)
435 {
436     CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(descriptorType));
437     CY_ASSERT_L1(descriptor);
438     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 14.3','CY_DW_CRC is available for all CAT1B devices.');
439     if ((CY_DMA_CRC_TRANSFER != descriptorType) || (CY_DW_CRC == 1UL))
440     {
441         if (descriptorType != Cy_DMA_Descriptor_GetDescriptorType(descriptor)) /* Do not perform if the type is not changed */
442         {
443             /* Store the current nextDescriptor pointer. */
444             cy_stc_dma_descriptor_t const * locNextDescriptor = Cy_DMA_Descriptor_GetNextDescriptor(descriptor);
445             /* Change the descriptor type. */
446             CY_REG32_CLR_SET(descriptor->ctl, CY_DMA_CTL_TYPE, descriptorType);
447             /* Restore the nextDescriptor pointer into the proper place. */
448             Cy_DMA_Descriptor_SetNextDescriptor(descriptor, locNextDescriptor);
449         }
450     }
451 }
452 
453 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3')
454 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 10.8')
455 
456 #endif /* CY_IP_M4CPUSS_DMA, CY_IP_MXDW */
457 
458 /* [] END OF FILE */
459