1 /***************************************************************************//**
2 * \file cy_axidmac.c
3 * \version 1.0
4 *
5 * \brief
6 * The source code file for the AXIDMAC driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2021 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_MXSAXIDMAC) || defined (CY_IP_MXAXIDMAC)
29 
30 #include "cy_axidmac.h"
31 
32 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 10.3', 5, \
33 'Implicit conversion from essential type "unsigned 32-bit int" to different or narrower essential type "signed 16-bit int".')
34 
35 /*******************************************************************************
36 * Function Name: Cy_AXIDMAC_Descriptor_Init
37 ****************************************************************************//**
38 *
39 * Initializes the descriptor structure in SRAM from a pre-initialized
40 * configuration structure.
41 * This function initializes only the descriptor and not the channel.
42 *
43 *******************************************************************************/
Cy_AXIDMAC_Descriptor_Init(cy_stc_axidmac_descriptor_t * descriptor,const cy_stc_axidmac_descriptor_config_t * config)44 cy_en_axidmac_status_t Cy_AXIDMAC_Descriptor_Init(cy_stc_axidmac_descriptor_t * descriptor, const cy_stc_axidmac_descriptor_config_t * config)
45 {
46     cy_en_axidmac_status_t ret = CY_AXIDMAC_BAD_PARAM;
47 
48     if ((NULL != descriptor) && (NULL != config))
49     {
50         CY_ASSERT_L3(CY_AXIDMAC_IS_RETRIGGER_VALID(config->retrigger));
51         CY_ASSERT_L3(CY_AXIDMAC_IS_TRIG_TYPE_VALID(config->interruptType));
52         CY_ASSERT_L3(CY_AXIDMAC_IS_TRIG_TYPE_VALID(config->triggerOutType));
53         CY_ASSERT_L3(CY_AXIDMAC_IS_TRIG_TYPE_VALID(config->triggerInType));
54         CY_ASSERT_L3(CY_AXIDMAC_IS_CHANNEL_STATE_VALID(config->channelState));
55         CY_ASSERT_L3(CY_AXIDMAC_IS_TYPE_VALID(config->descriptorType));
56 
57         descriptor->ctl =
58             _VAL2FLD(AXI_DMAC_CH_DESCR_CTL_WAIT_FOR_DEACT, config->retrigger) |
59             _VAL2FLD(AXI_DMAC_CH_DESCR_CTL_INTR_TYPE, config->interruptType) |
60             _VAL2FLD(AXI_DMAC_CH_DESCR_CTL_TR_OUT_TYPE, config->triggerOutType) |
61             _VAL2FLD(AXI_DMAC_CH_DESCR_CTL_TR_IN_TYPE, config->triggerInType) |
62            _BOOL2FLD(AXI_DMAC_CH_DESCR_CTL_DATA_PREFETCH, config->dataPrefetch) |
63             _VAL2FLD(AXI_DMAC_CH_DESCR_CTL_CH_DISABLE, config->channelState) |
64             _VAL2FLD(AXI_DMAC_CH_DESCR_CTL_DESCR_TYPE, config->descriptorType);
65 
66         descriptor->src = (uint32_t)config->srcAddress;
67 
68         Cy_AXIDMAC_Descriptor_SetDstAddress(descriptor, config->dstAddress);
69 
70         Cy_AXIDMAC_Descriptor_SetMloopDataCount(descriptor, config->mCount);
71 
72         if(CY_AXIDMAC_1D_MEMORY_COPY != config->descriptorType)
73         {
74             Cy_AXIDMAC_Descriptor_SetXloopDataCount(descriptor, config->xCount);
75         }
76 
77         Cy_AXIDMAC_Descriptor_SetNextDescriptor(descriptor, config->nextDescriptor);
78 
79         if((CY_AXIDMAC_2D_MEMORY_COPY == config->descriptorType) ||
80            (CY_AXIDMAC_3D_MEMORY_COPY == config->descriptorType))
81         {
82 
83             descriptor->xIncr = _VAL2FLD(AXI_DMAC_CH_DESCR_X_INCR_SRC_X, config->srcXincrement) |
84                                 _VAL2FLD(AXI_DMAC_CH_DESCR_X_INCR_DST_X, config->dstXincrement);
85         }
86 
87         if(CY_AXIDMAC_3D_MEMORY_COPY == config->descriptorType)
88         {
89             Cy_AXIDMAC_Descriptor_SetYloopDataCount(descriptor, config->yCount);
90 
91             descriptor->yIncr = _VAL2FLD(AXI_DMAC_CH_DESCR_Y_INCR_SRC_Y, config->srcYincrement) |
92                                 _VAL2FLD(AXI_DMAC_CH_DESCR_Y_INCR_DST_Y, config->dstYincrement);
93         }
94 
95         ret = CY_AXIDMAC_SUCCESS;
96     }
97 
98     return ret;
99 }
100 
101 
102 /*******************************************************************************
103 * Function Name: Cy_AXIDMAC_Descriptor_DeInit
104 ****************************************************************************//**
105 *
106 * Clears the content of the specified descriptor.
107 *
108 *******************************************************************************/
Cy_AXIDMAC_Descriptor_DeInit(cy_stc_axidmac_descriptor_t * descriptor)109 void Cy_AXIDMAC_Descriptor_DeInit(cy_stc_axidmac_descriptor_t * descriptor)
110 {
111     descriptor->ctl = 0UL;
112     descriptor->src = 0UL;
113     descriptor->dst = 0UL;
114     descriptor->mSize = 0UL;
115     descriptor->xSize = 0UL;
116     descriptor->xIncr = 0UL;
117     descriptor->ySize = 0UL;
118     descriptor->yIncr = 0UL;
119     descriptor->nextPtr = 0UL;
120 }
121 
122 
123 /*******************************************************************************
124 * Function Name: Cy_AXIDMAC_Channel_Init
125 ****************************************************************************//**
126 *
127 * Initializes the AXIDMAC channel with a descriptor and other parameters.
128 *
129 *
130 *******************************************************************************/
Cy_AXIDMAC_Channel_Init(AXI_DMAC_Type * base,uint32_t channel,cy_stc_axidmac_channel_config_t const * config)131 cy_en_axidmac_status_t Cy_AXIDMAC_Channel_Init(AXI_DMAC_Type * base, uint32_t channel, cy_stc_axidmac_channel_config_t const * config)
132 {
133     cy_en_axidmac_status_t ret = CY_AXIDMAC_BAD_PARAM;
134 
135     if ((NULL != base) && (CY_AXIDMAC_IS_CH_NR_VALID(channel)) && (NULL != config) && (NULL != config->descriptor))
136     {
137         CY_ASSERT_L2(CY_AXIDMAC_IS_PRIORITY_VALID(config->priority));
138 
139         /* Set the current descriptor */
140         AXIDMAC_CH_CURR(base, channel) = (uint32_t)config->descriptor;
141 
142         /* Set the channel configuration */
143         AXIDMAC_CH_CTL(base, channel) = _VAL2FLD(AXI_DMAC_CH_CTL_PRIO,    config->priority) |
144                                     _BOOL2FLD(AXI_DMAC_CH_CTL_ENABLED, config->enable)   |
145                                     _BOOL2FLD(AXI_DMAC_CH_CTL_B,       config->bufferable);
146         ret = CY_AXIDMAC_SUCCESS;
147     }
148 
149     return (ret);
150 }
151 
152 
153 /*******************************************************************************
154 * Function Name: Cy_AXIDMAC_Channel_DeInit
155 ****************************************************************************//**
156 *
157 * Clears the content of registers corresponding to the channel.
158 *
159 *
160 *******************************************************************************/
Cy_AXIDMAC_Channel_DeInit(AXI_DMAC_Type * base,uint32_t channel)161 void Cy_AXIDMAC_Channel_DeInit(AXI_DMAC_Type * base, uint32_t channel)
162 {
163     CY_ASSERT_L1(CY_AXIDMAC_IS_CH_NR_VALID(channel));
164 
165     AXIDMAC_CH_CTL(base, channel) = 0UL;
166     AXIDMAC_CH_CURR(base, channel) = 0UL;
167     AXIDMAC_CH_INTR_MASK(base, channel) = 0UL;
168 }
169 
170 
171 /*******************************************************************************
172 * Function Name: Cy_AXIDMAC_Descriptor_GetXloopDataCount
173 ****************************************************************************//**
174 *
175 * Returns the number of data elements for the X loop of the specified
176 * descriptor (for 2D and 3D memory copy descriptors).
177 *
178 *******************************************************************************/
Cy_AXIDMAC_Descriptor_GetXloopDataCount(cy_stc_axidmac_descriptor_t const * descriptor)179 uint32_t Cy_AXIDMAC_Descriptor_GetXloopDataCount(cy_stc_axidmac_descriptor_t const * descriptor)
180 {
181     uint32_t retVal = 0UL;
182 
183     CY_ASSERT_L1(CY_AXIDMAC_1D_MEMORY_COPY != Cy_AXIDMAC_Descriptor_GetDescriptorType(descriptor));
184 
185 
186      /* Convert the data count from the machine range (0-65535) into the user's range (1-65536). */
187      retVal = _FLD2VAL(AXI_DMAC_CH_DESCR_X_SIZE_X_COUNT, descriptor->xSize) + 1UL;
188 
189     return (retVal);
190 }
191 
192 
193 /*******************************************************************************
194 * Function Name: Cy_AXIDMAC_Descriptor_SetXloopDataCount
195 ****************************************************************************//**
196 *
197 * Sets the number of data elements to transfer in the X loop
198 * for the specified descriptor (for 2D and 3D memory copy descriptors).
199 *
200 *******************************************************************************/
Cy_AXIDMAC_Descriptor_SetXloopDataCount(cy_stc_axidmac_descriptor_t * descriptor,uint32_t xCount)201 void Cy_AXIDMAC_Descriptor_SetXloopDataCount(cy_stc_axidmac_descriptor_t * descriptor, uint32_t xCount)
202 {
203 
204     CY_ASSERT_L1(CY_AXIDMAC_1D_MEMORY_COPY != Cy_AXIDMAC_Descriptor_GetDescriptorType(descriptor));
205 
206     CY_ASSERT_L2(CY_AXIDMAC_IS_LOOP_COUNT_VALID(xCount));
207     /* Convert the data count from the user's range (1-65536) into the machine range (0-65535). */
208     descriptor->xSize = _VAL2FLD(AXI_DMAC_CH_DESCR_X_SIZE_X_COUNT, xCount - 1UL);
209 }
210 
211 
212 /*******************************************************************************
213 * Function Name: Cy_DMAC_Descriptor_SetNextDescriptor
214 ****************************************************************************//**
215 *
216 * Sets a Next Descriptor parameter for the specified descriptor.
217 *
218 * Based on the descriptor type, the offset of the address for the next descriptor
219 * register may vary:
220 * For the 1D memory copy descriptor type, this register is at offset 0x10.
221 * For the 2D memory copy descriptor type, this register is at offset 0x18.
222 * For the 3D memory copy descriptor type, this register is at offset 0x20.
223 *
224 *******************************************************************************/
Cy_AXIDMAC_Descriptor_SetNextDescriptor(cy_stc_axidmac_descriptor_t * descriptor,cy_stc_axidmac_descriptor_t const * nextDescriptor)225 void Cy_AXIDMAC_Descriptor_SetNextDescriptor(cy_stc_axidmac_descriptor_t * descriptor, cy_stc_axidmac_descriptor_t const * nextDescriptor)
226 {
227     CY_ASSERT_L1(NULL != descriptor);
228     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to cy_en_axidmac_descriptor_type_t enum.');
229     switch((cy_en_axidmac_descriptor_type_t)_FLD2VAL(AXI_DMAC_CH_DESCR_CTL_DESCR_TYPE, descriptor->ctl))
230     {
231         case CY_AXIDMAC_1D_MEMORY_COPY:
232             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 11.3','Intentional typecast to cy_stc_axidmac_dscr_1d_t.');
233             ((cy_stc_axidmac_dscr_1d_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
234             break;
235 
236         case CY_AXIDMAC_2D_MEMORY_COPY:
237             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 11.3','Intentional typecast to cy_stc_axidmac_dscr_2d_t.');
238             ((cy_stc_axidmac_dscr_2d_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
239             break;
240 
241         case CY_AXIDMAC_3D_MEMORY_COPY:
242             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 11.3','Intentional typecast to cy_stc_axidmac_dscr_3d_t.');
243             ((cy_stc_axidmac_dscr_3d_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
244             break;
245 
246         default:
247             /* Unsupported type of descriptor */
248             break;
249     }
250 }
251 
252 
253 /*******************************************************************************
254 * Function Name: Cy_DMAC_Descriptor_GetNextDescriptor
255 ****************************************************************************//**
256 *
257 * Returns a next descriptor address of the specified descriptor.
258 *
259 * Based on the descriptor type, the offset of the address for the next descriptor
260 * register may vary:
261 * For the 1D memory copy descriptor type, this register is at offset 0x10.
262 * For the 2D memory copy descriptor type, this register is at offset 0x18.
263 * For the 3D memory copy descriptor type, this register is at offset 0x20.
264 *
265 *
266 *******************************************************************************/
Cy_AXIDMAC_Descriptor_GetNextDescriptor(cy_stc_axidmac_descriptor_t const * descriptor)267 cy_stc_axidmac_descriptor_t * Cy_AXIDMAC_Descriptor_GetNextDescriptor(cy_stc_axidmac_descriptor_t const * descriptor)
268 {
269     uint32_t retVal = 0UL;
270     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to cy_en_axidmac_descriptor_type_t enum.');
271     switch((cy_en_axidmac_descriptor_type_t)_FLD2VAL(AXI_DMAC_CH_DESCR_CTL_DESCR_TYPE, descriptor->ctl))
272     {
273 
274         case CY_AXIDMAC_1D_MEMORY_COPY:
275             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 11.3','Intentional typecast to cy_stc_axidmac_dscr_1d_t.');
276             retVal = ((cy_stc_axidmac_dscr_1d_t const*)descriptor)->nextPtr;
277             break;
278 
279         case CY_AXIDMAC_2D_MEMORY_COPY:
280             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 11.3','Intentional typecast to cy_stc_axidmac_dscr_2d_t.');
281             retVal = ((cy_stc_axidmac_dscr_2d_t const*)descriptor)->nextPtr;
282             break;
283 
284         case CY_AXIDMAC_3D_MEMORY_COPY:
285             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 11.3','Intentional typecast to cy_stc_axidmac_dscr_3d_t.');
286             retVal = ((cy_stc_axidmac_dscr_3d_t const*)descriptor)->nextPtr;
287             break;
288 
289         default:
290             /* An unsupported type of the descriptor */
291             break;
292     }
293 
294     return ((cy_stc_axidmac_descriptor_t*)retVal);
295 }
296 
297 
298 /*******************************************************************************
299 * Function Name: Cy_AXIDMAC_Descriptor_SetDescriptorType
300 ****************************************************************************//**
301 *
302 * Sets the descriptor's type for the specified descriptor.
303 * Moves the next descriptor pointer and M data count values into the proper
304 * offset in accordance to the actual descriptor type.
305 *
306 * During the descriptor's type change, carefully set up the settings starting
307 * from dstAddress and all the rest below in the \ref cy_stc_axidmac_descriptor_config_t
308 * structure. This is because the content of the descriptor registers might be
309 * lost/overridden by other descriptor settings due to the
310 * different registers structure for different descriptor types.
311 *
312 *******************************************************************************/
Cy_AXIDMAC_Descriptor_SetDescriptorType(cy_stc_axidmac_descriptor_t * descriptor,cy_en_axidmac_descriptor_type_t descriptorType)313 void Cy_AXIDMAC_Descriptor_SetDescriptorType(cy_stc_axidmac_descriptor_t * descriptor, cy_en_axidmac_descriptor_type_t descriptorType)
314 {
315     CY_ASSERT_L3(CY_AXIDMAC_IS_TYPE_VALID(descriptorType));
316 
317     if (descriptorType != Cy_AXIDMAC_Descriptor_GetDescriptorType(descriptor)) /* Do not perform if the type is not changed */
318     {
319         /* Store the current nextDescriptor pointer. */
320         cy_stc_axidmac_descriptor_t const *locNextDescriptor = Cy_AXIDMAC_Descriptor_GetNextDescriptor(descriptor);
321         /* Store the current M data counter. */
322         uint32_t locMcount = Cy_AXIDMAC_Descriptor_GetMloopDataCount(descriptor);
323         /* Change the descriptor type. */
324         CY_REG32_CLR_SET(descriptor->ctl, AXI_DMAC_CH_DESCR_CTL_DESCR_TYPE, descriptorType);
325         /* Restore the current M data counter. */
326         Cy_AXIDMAC_Descriptor_SetMloopDataCount(descriptor, locMcount);
327         /* Restore the nextDescriptor pointer into the proper place. */
328         Cy_AXIDMAC_Descriptor_SetNextDescriptor(descriptor, locNextDescriptor);
329     }
330 }
331 
332 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 10.3')
333 #endif /* CY_IP_MXSAXIDMAC || CY_IP_MXAXIDMAC */
334 
335 /* [] END OF FILE */
336 
337