1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of the copyright holder nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "fsl_dma.h"
32 
33 /*******************************************************************************
34  * Definitions
35  ******************************************************************************/
36 
37 /*******************************************************************************
38  * Prototypes
39  ******************************************************************************/
40 
41 /*!
42  * @brief Get instance number for DMA.
43  *
44  * @param base DMA peripheral base address.
45  */
46 static uint32_t DMA_GetInstance(DMA_Type *base);
47 
48 /*******************************************************************************
49  * Variables
50  ******************************************************************************/
51 
52 /*! @brief Array to map DMA instance number to base pointer. */
53 static DMA_Type *const s_dmaBases[] = DMA_BASE_PTRS;
54 
55 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
56 /*! @brief Array to map DMA instance number to clock name. */
57 static const clock_ip_name_t s_dmaClockName[] = DMA_CLOCKS;
58 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
59 
60 /*! @brief Array to map DMA instance number to IRQ number. */
61 static const IRQn_Type s_dmaIRQNumber[][FSL_FEATURE_DMA_MODULE_CHANNEL] = DMA_CHN_IRQS;
62 
63 /*! @brief Pointers to transfer handle for each DMA channel. */
64 static dma_handle_t *s_DMAHandle[FSL_FEATURE_DMA_MODULE_CHANNEL * FSL_FEATURE_SOC_DMA_COUNT];
65 
66 /*******************************************************************************
67  * Code
68  ******************************************************************************/
DMA_GetInstance(DMA_Type * base)69 static uint32_t DMA_GetInstance(DMA_Type *base)
70 {
71     uint32_t instance;
72 
73     /* Find the instance index from base address mappings. */
74     for (instance = 0; instance < ARRAY_SIZE(s_dmaBases); instance++)
75     {
76         if (s_dmaBases[instance] == base)
77         {
78             break;
79         }
80     }
81 
82     assert(instance < ARRAY_SIZE(s_dmaBases));
83 
84     return instance;
85 }
86 
DMA_Init(DMA_Type * base)87 void DMA_Init(DMA_Type *base)
88 {
89 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
90     CLOCK_EnableClock(s_dmaClockName[DMA_GetInstance(base)]);
91 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
92 }
93 
DMA_Deinit(DMA_Type * base)94 void DMA_Deinit(DMA_Type *base)
95 {
96 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
97     CLOCK_DisableClock(s_dmaClockName[DMA_GetInstance(base)]);
98 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
99 }
100 
DMA_ResetChannel(DMA_Type * base,uint32_t channel)101 void DMA_ResetChannel(DMA_Type *base, uint32_t channel)
102 {
103     assert(channel < FSL_FEATURE_DMA_MODULE_CHANNEL);
104 
105     /* clear all status bit */
106     base->DMA[channel].DSR_BCR |= DMA_DSR_BCR_DONE(true);
107     /* clear all registers */
108     base->DMA[channel].SAR = 0;
109     base->DMA[channel].DAR = 0;
110     base->DMA[channel].DSR_BCR = 0;
111     /* enable cycle steal and enable auto disable channel request */
112     base->DMA[channel].DCR = DMA_DCR_D_REQ(true) | DMA_DCR_CS(true);
113 }
114 
DMA_SetTransferConfig(DMA_Type * base,uint32_t channel,const dma_transfer_config_t * config)115 void DMA_SetTransferConfig(DMA_Type *base, uint32_t channel, const dma_transfer_config_t *config)
116 {
117     assert(channel < FSL_FEATURE_DMA_MODULE_CHANNEL);
118     assert(config != NULL);
119 
120     uint32_t tmpreg;
121 
122     /* Set source address */
123     base->DMA[channel].SAR = config->srcAddr;
124     /* Set destination address */
125     base->DMA[channel].DAR = config->destAddr;
126     /* Set transfer bytes */
127     base->DMA[channel].DSR_BCR = DMA_DSR_BCR_BCR(config->transferSize);
128     /* Set DMA Control Register */
129     tmpreg = base->DMA[channel].DCR;
130     tmpreg &= ~(DMA_DCR_DSIZE_MASK | DMA_DCR_DINC_MASK | DMA_DCR_SSIZE_MASK | DMA_DCR_SINC_MASK);
131     tmpreg |= (DMA_DCR_DSIZE(config->destSize) | DMA_DCR_DINC(config->enableDestIncrement) |
132                DMA_DCR_SSIZE(config->srcSize) | DMA_DCR_SINC(config->enableSrcIncrement));
133     base->DMA[channel].DCR = tmpreg;
134 }
135 
DMA_SetChannelLinkConfig(DMA_Type * base,uint32_t channel,const dma_channel_link_config_t * config)136 void DMA_SetChannelLinkConfig(DMA_Type *base, uint32_t channel, const dma_channel_link_config_t *config)
137 {
138     assert(channel < FSL_FEATURE_DMA_MODULE_CHANNEL);
139     assert(config != NULL);
140 
141     uint32_t tmpreg;
142 
143     tmpreg = base->DMA[channel].DCR;
144     tmpreg &= ~(DMA_DCR_LINKCC_MASK | DMA_DCR_LCH1_MASK | DMA_DCR_LCH2_MASK);
145     tmpreg |= (DMA_DCR_LINKCC(config->linkType) | DMA_DCR_LCH1(config->channel1) | DMA_DCR_LCH2(config->channel2));
146     base->DMA[channel].DCR = tmpreg;
147 }
148 
DMA_SetModulo(DMA_Type * base,uint32_t channel,dma_modulo_t srcModulo,dma_modulo_t destModulo)149 void DMA_SetModulo(DMA_Type *base, uint32_t channel, dma_modulo_t srcModulo, dma_modulo_t destModulo)
150 {
151     assert(channel < FSL_FEATURE_DMA_MODULE_CHANNEL);
152 
153     uint32_t tmpreg;
154 
155     tmpreg = base->DMA[channel].DCR;
156     tmpreg &= ~(DMA_DCR_SMOD_MASK | DMA_DCR_DMOD_MASK);
157     tmpreg |= (DMA_DCR_SMOD(srcModulo) | DMA_DCR_DMOD(destModulo));
158     base->DMA[channel].DCR = tmpreg;
159 }
160 
DMA_CreateHandle(dma_handle_t * handle,DMA_Type * base,uint32_t channel)161 void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel)
162 {
163     assert(handle != NULL);
164     assert(channel < FSL_FEATURE_DMA_MODULE_CHANNEL);
165 
166     uint32_t dmaInstance;
167     uint32_t channelIndex;
168 
169     /* Zero the handle */
170     memset(handle, 0, sizeof(*handle));
171 
172     handle->base = base;
173     handle->channel = channel;
174     /* Get the DMA instance number */
175     dmaInstance = DMA_GetInstance(base);
176     channelIndex = (dmaInstance * FSL_FEATURE_DMA_MODULE_CHANNEL) + channel;
177     /* Store handle */
178     s_DMAHandle[channelIndex] = handle;
179     /* Enable NVIC interrupt. */
180     EnableIRQ(s_dmaIRQNumber[dmaInstance][channelIndex]);
181 }
182 
DMA_PrepareTransfer(dma_transfer_config_t * config,void * srcAddr,uint32_t srcWidth,void * destAddr,uint32_t destWidth,uint32_t transferBytes,dma_transfer_type_t type)183 void DMA_PrepareTransfer(dma_transfer_config_t *config,
184                          void *srcAddr,
185                          uint32_t srcWidth,
186                          void *destAddr,
187                          uint32_t destWidth,
188                          uint32_t transferBytes,
189                          dma_transfer_type_t type)
190 {
191     assert(config != NULL);
192     assert(srcAddr != NULL);
193     assert(destAddr != NULL);
194     assert((srcWidth == 1U) || (srcWidth == 2U) || (srcWidth == 4U));
195     assert((destWidth == 1U) || (destWidth == 2U) || (destWidth == 4U));
196 
197     config->srcAddr = (uint32_t)srcAddr;
198     config->destAddr = (uint32_t)destAddr;
199     config->transferSize = transferBytes;
200     switch (srcWidth)
201     {
202         case 1U:
203             config->srcSize = kDMA_Transfersize8bits;
204             break;
205         case 2U:
206             config->srcSize = kDMA_Transfersize16bits;
207             break;
208         case 4U:
209             config->srcSize = kDMA_Transfersize32bits;
210             break;
211         default:
212             break;
213     }
214     switch (destWidth)
215     {
216         case 1U:
217             config->destSize = kDMA_Transfersize8bits;
218             break;
219         case 2U:
220             config->destSize = kDMA_Transfersize16bits;
221             break;
222         case 4U:
223             config->destSize = kDMA_Transfersize32bits;
224             break;
225         default:
226             break;
227     }
228     switch (type)
229     {
230         case kDMA_MemoryToMemory:
231             config->enableSrcIncrement = true;
232             config->enableDestIncrement = true;
233             break;
234         case kDMA_PeripheralToMemory:
235             config->enableSrcIncrement = false;
236             config->enableDestIncrement = true;
237             break;
238         case kDMA_MemoryToPeripheral:
239             config->enableSrcIncrement = true;
240             config->enableDestIncrement = false;
241             break;
242         default:
243             break;
244     }
245 }
246 
DMA_SetCallback(dma_handle_t * handle,dma_callback callback,void * userData)247 void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData)
248 {
249     assert(handle != NULL);
250 
251     handle->callback = callback;
252     handle->userData = userData;
253 }
254 
DMA_SubmitTransfer(dma_handle_t * handle,const dma_transfer_config_t * config,uint32_t options)255 status_t DMA_SubmitTransfer(dma_handle_t *handle, const dma_transfer_config_t *config, uint32_t options)
256 {
257     assert(handle != NULL);
258     assert(config != NULL);
259 
260     /* Check if DMA is busy */
261     if (handle->base->DMA[handle->channel].DSR_BCR & DMA_DSR_BCR_BSY_MASK)
262     {
263         return kStatus_DMA_Busy;
264     }
265     DMA_ResetChannel(handle->base, handle->channel);
266     DMA_SetTransferConfig(handle->base, handle->channel, config);
267     if (options & kDMA_EnableInterrupt)
268     {
269         DMA_EnableInterrupts(handle->base, handle->channel);
270     }
271     return kStatus_Success;
272 }
273 
DMA_AbortTransfer(dma_handle_t * handle)274 void DMA_AbortTransfer(dma_handle_t *handle)
275 {
276     assert(handle != NULL);
277 
278     handle->base->DMA[handle->channel].DCR &= ~DMA_DCR_ERQ_MASK;
279     /* clear all status bit */
280     handle->base->DMA[handle->channel].DSR_BCR |= DMA_DSR_BCR_DONE(true);
281 }
282 
DMA_HandleIRQ(dma_handle_t * handle)283 void DMA_HandleIRQ(dma_handle_t *handle)
284 {
285     assert(handle != NULL);
286 
287     /* Clear interrupt pending bit */
288     DMA_ClearChannelStatusFlags(handle->base, handle->channel, kDMA_TransactionsDoneFlag);
289     if (handle->callback)
290     {
291         (handle->callback)(handle, handle->userData);
292     }
293 }
294 
295 #if defined(FSL_FEATURE_DMA_MODULE_CHANNEL) && (FSL_FEATURE_DMA_MODULE_CHANNEL == 4U)
DMA0_DriverIRQHandler(void)296 void DMA0_DriverIRQHandler(void)
297 {
298     DMA_HandleIRQ(s_DMAHandle[0]);
299 }
300 
DMA1_DriverIRQHandler(void)301 void DMA1_DriverIRQHandler(void)
302 {
303     DMA_HandleIRQ(s_DMAHandle[1]);
304 }
305 
DMA2_DriverIRQHandler(void)306 void DMA2_DriverIRQHandler(void)
307 {
308     DMA_HandleIRQ(s_DMAHandle[2]);
309 }
310 
DMA3_DriverIRQHandler(void)311 void DMA3_DriverIRQHandler(void)
312 {
313     DMA_HandleIRQ(s_DMAHandle[3]);
314 }
315 #endif /* FSL_FEATURE_DMA_MODULE_CHANNEL */
316