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