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