1 | /* |
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. |
3 | * Copyright 2016-2020 NXP |
4 | * All rights reserved. |
5 | * |
6 | * SPDX-License-Identifier: BSD-3-Clause |
7 | */ |
8 | |
9 | #include "fsl_flexio.h" |
10 | |
11 | /******************************************************************************* |
12 | * Definitions |
13 | ******************************************************************************/ |
14 | |
15 | /* Component ID definition, used by tools. */ |
16 | #ifndef FSL_COMPONENT_ID |
17 | #define FSL_COMPONENT_ID "platform.drivers.flexio" |
18 | #endif |
19 | |
20 | /*< @brief user configurable flexio handle count. */ |
21 | #define FLEXIO_HANDLE_COUNT 2 |
22 | |
23 | /******************************************************************************* |
24 | * Variables |
25 | ******************************************************************************/ |
26 | /*! @brief Pointers to flexio bases for each instance. */ |
27 | FLEXIO_Type *const s_flexioBases[] = FLEXIO_BASE_PTRS; |
28 | |
29 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
30 | /*! @brief Pointers to flexio clocks for each instance. */ |
31 | const clock_ip_name_t s_flexioClocks[] = FLEXIO_CLOCKS; |
32 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
33 | |
34 | /*< @brief pointer to array of FLEXIO handle. */ |
35 | static void *s_flexioHandle[FLEXIO_HANDLE_COUNT]; |
36 | |
37 | /*< @brief pointer to array of FLEXIO IP types. */ |
38 | static void *s_flexioType[FLEXIO_HANDLE_COUNT]; |
39 | |
40 | /*< @brief pointer to array of FLEXIO Isr. */ |
41 | static flexio_isr_t s_flexioIsr[FLEXIO_HANDLE_COUNT]; |
42 | |
43 | /* FlexIO common IRQ Handler. */ |
44 | static void FLEXIO_CommonIRQHandler(void); |
45 | |
46 | /******************************************************************************* |
47 | * Codes |
48 | ******************************************************************************/ |
49 | |
50 | /*! |
51 | * brief Get instance number for FLEXIO module. |
52 | * |
53 | * param base FLEXIO peripheral base address. |
54 | */ |
55 | uint32_t FLEXIO_GetInstance(FLEXIO_Type *base) |
56 | { |
57 | uint32_t instance; |
58 | |
59 | /* Find the instance index from base address mappings. */ |
60 | for (instance = 0; instance < ARRAY_SIZE(s_flexioBases); instance++) |
61 | { |
62 | if (s_flexioBases[instance] == base) |
63 | { |
64 | break; |
65 | } |
66 | } |
67 | |
68 | assert(instance < ARRAY_SIZE(s_flexioBases)); |
69 | |
70 | return instance; |
71 | } |
72 | |
73 | /*! |
74 | * brief Configures the FlexIO with a FlexIO configuration. The configuration structure |
75 | * can be filled by the user or be set with default values by FLEXIO_GetDefaultConfig(). |
76 | * |
77 | * Example |
78 | code |
79 | flexio_config_t config = { |
80 | .enableFlexio = true, |
81 | .enableInDoze = false, |
82 | .enableInDebug = true, |
83 | .enableFastAccess = false |
84 | }; |
85 | FLEXIO_Configure(base, &config); |
86 | endcode |
87 | * |
88 | * param base FlexIO peripheral base address |
89 | * param userConfig pointer to flexio_config_t structure |
90 | */ |
91 | void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig) |
92 | { |
93 | uint32_t ctrlReg = 0; |
94 | |
95 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
96 | CLOCK_EnableClock(s_flexioClocks[FLEXIO_GetInstance(base)]); |
97 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
98 | |
99 | FLEXIO_Reset(base); |
100 | |
101 | ctrlReg = base->CTRL; |
102 | ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK); |
103 | ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) | |
104 | FLEXIO_CTRL_FLEXEN(userConfig->enableFlexio)); |
105 | if (!userConfig->enableInDoze) |
106 | { |
107 | ctrlReg |= FLEXIO_CTRL_DOZEN_MASK; |
108 | } |
109 | |
110 | base->CTRL = ctrlReg; |
111 | } |
112 | |
113 | /*! |
114 | * brief Gates the FlexIO clock. Call this API to stop the FlexIO clock. |
115 | * |
116 | * note After calling this API, call the FLEXO_Init to use the FlexIO module. |
117 | * |
118 | * param base FlexIO peripheral base address |
119 | */ |
120 | void FLEXIO_Deinit(FLEXIO_Type *base) |
121 | { |
122 | FLEXIO_Enable(base, false); |
123 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
124 | CLOCK_DisableClock(s_flexioClocks[FLEXIO_GetInstance(base)]); |
125 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
126 | } |
127 | |
128 | /*! |
129 | * brief Gets the default configuration to configure the FlexIO module. The configuration |
130 | * can used directly to call the FLEXIO_Configure(). |
131 | * |
132 | * Example: |
133 | code |
134 | flexio_config_t config; |
135 | FLEXIO_GetDefaultConfig(&config); |
136 | endcode |
137 | * |
138 | * param userConfig pointer to flexio_config_t structure |
139 | */ |
140 | void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig) |
141 | { |
142 | assert(userConfig != NULL); |
143 | |
144 | /* Initializes the configure structure to zero. */ |
145 | (void)memset(userConfig, 0, sizeof(*userConfig)); |
146 | |
147 | userConfig->enableFlexio = true; |
148 | userConfig->enableInDoze = false; |
149 | userConfig->enableInDebug = true; |
150 | userConfig->enableFastAccess = false; |
151 | } |
152 | |
153 | /*! |
154 | * brief Resets the FlexIO module. |
155 | * |
156 | * param base FlexIO peripheral base address |
157 | */ |
158 | void FLEXIO_Reset(FLEXIO_Type *base) |
159 | { |
160 | /*do software reset, software reset operation affect all other FLEXIO registers except CTRL*/ |
161 | base->CTRL |= FLEXIO_CTRL_SWRST_MASK; |
162 | base->CTRL = 0; |
163 | } |
164 | |
165 | /*! |
166 | * brief Gets the shifter buffer address for the DMA transfer usage. |
167 | * |
168 | * param base FlexIO peripheral base address |
169 | * param type Shifter type of flexio_shifter_buffer_type_t |
170 | * param index Shifter index |
171 | * return Corresponding shifter buffer index |
172 | */ |
173 | uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index) |
174 | { |
175 | assert(index < FLEXIO_SHIFTBUF_COUNT); |
176 | |
177 | uint32_t address = 0; |
178 | |
179 | switch (type) |
180 | { |
181 | case kFLEXIO_ShifterBuffer: |
182 | address = (uint32_t) & (base->SHIFTBUF[index]); |
183 | break; |
184 | |
185 | case kFLEXIO_ShifterBufferBitSwapped: |
186 | address = (uint32_t) & (base->SHIFTBUFBIS[index]); |
187 | break; |
188 | |
189 | case kFLEXIO_ShifterBufferByteSwapped: |
190 | address = (uint32_t) & (base->SHIFTBUFBYS[index]); |
191 | break; |
192 | |
193 | case kFLEXIO_ShifterBufferBitByteSwapped: |
194 | address = (uint32_t) & (base->SHIFTBUFBBS[index]); |
195 | break; |
196 | |
197 | #if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP |
198 | case kFLEXIO_ShifterBufferNibbleByteSwapped: |
199 | address = (uint32_t) & (base->SHIFTBUFNBS[index]); |
200 | break; |
201 | |
202 | #endif |
203 | #if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP |
204 | case kFLEXIO_ShifterBufferHalfWordSwapped: |
205 | address = (uint32_t) & (base->SHIFTBUFHWS[index]); |
206 | break; |
207 | |
208 | #endif |
209 | #if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP |
210 | case kFLEXIO_ShifterBufferNibbleSwapped: |
211 | address = (uint32_t) & (base->SHIFTBUFNIS[index]); |
212 | break; |
213 | |
214 | #endif |
215 | default: |
216 | address = (uint32_t) & (base->SHIFTBUF[index]); |
217 | break; |
218 | } |
219 | return address; |
220 | } |
221 | |
222 | /*! |
223 | * brief Configures the shifter with the shifter configuration. The configuration structure |
224 | * covers both the SHIFTCTL and SHIFTCFG registers. To configure the shifter to the proper |
225 | * mode, select which timer controls the shifter to shift, whether to generate start bit/stop |
226 | * bit, and the polarity of start bit and stop bit. |
227 | * |
228 | * Example |
229 | code |
230 | flexio_shifter_config_t config = { |
231 | .timerSelect = 0, |
232 | .timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive, |
233 | .pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection, |
234 | .pinPolarity = kFLEXIO_PinActiveLow, |
235 | .shifterMode = kFLEXIO_ShifterModeTransmit, |
236 | .inputSource = kFLEXIO_ShifterInputFromPin, |
237 | .shifterStop = kFLEXIO_ShifterStopBitHigh, |
238 | .shifterStart = kFLEXIO_ShifterStartBitLow |
239 | }; |
240 | FLEXIO_SetShifterConfig(base, &config); |
241 | endcode |
242 | * |
243 | * param base FlexIO peripheral base address |
244 | * param index Shifter index |
245 | * param shifterConfig Pointer to flexio_shifter_config_t structure |
246 | */ |
247 | void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig) |
248 | { |
249 | base->SHIFTCFG[index] = FLEXIO_SHIFTCFG_INSRC(shifterConfig->inputSource) |
250 | #if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH |
251 | | FLEXIO_SHIFTCFG_PWIDTH(shifterConfig->parallelWidth) |
252 | #endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */ |
253 | | FLEXIO_SHIFTCFG_SSTOP(shifterConfig->shifterStop) | |
254 | FLEXIO_SHIFTCFG_SSTART(shifterConfig->shifterStart); |
255 | |
256 | base->SHIFTCTL[index] = |
257 | FLEXIO_SHIFTCTL_TIMSEL(shifterConfig->timerSelect) | FLEXIO_SHIFTCTL_TIMPOL(shifterConfig->timerPolarity) | |
258 | FLEXIO_SHIFTCTL_PINCFG(shifterConfig->pinConfig) | FLEXIO_SHIFTCTL_PINSEL(shifterConfig->pinSelect) | |
259 | FLEXIO_SHIFTCTL_PINPOL(shifterConfig->pinPolarity) | FLEXIO_SHIFTCTL_SMOD(shifterConfig->shifterMode); |
260 | } |
261 | |
262 | /*! |
263 | * brief Configures the timer with the timer configuration. The configuration structure |
264 | * covers both the TIMCTL and TIMCFG registers. To configure the timer to the proper |
265 | * mode, select trigger source for timer and the timer pin output and the timing for timer. |
266 | * |
267 | * Example |
268 | code |
269 | flexio_timer_config_t config = { |
270 | .triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0), |
271 | .triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow, |
272 | .triggerSource = kFLEXIO_TimerTriggerSourceInternal, |
273 | .pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection, |
274 | .pinSelect = 0, |
275 | .pinPolarity = kFLEXIO_PinActiveHigh, |
276 | .timerMode = kFLEXIO_TimerModeDual8BitBaudBit, |
277 | .timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset, |
278 | .timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput, |
279 | .timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput, |
280 | .timerDisable = kFLEXIO_TimerDisableOnTimerCompare, |
281 | .timerEnable = kFLEXIO_TimerEnableOnTriggerHigh, |
282 | .timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable, |
283 | .timerStart = kFLEXIO_TimerStartBitEnabled |
284 | }; |
285 | FLEXIO_SetTimerConfig(base, &config); |
286 | endcode |
287 | * |
288 | * param base FlexIO peripheral base address |
289 | * param index Timer index |
290 | * param timerConfig Pointer to the flexio_timer_config_t structure |
291 | */ |
292 | void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig) |
293 | { |
294 | base->TIMCFG[index] = |
295 | FLEXIO_TIMCFG_TIMOUT(timerConfig->timerOutput) | FLEXIO_TIMCFG_TIMDEC(timerConfig->timerDecrement) | |
296 | FLEXIO_TIMCFG_TIMRST(timerConfig->timerReset) | FLEXIO_TIMCFG_TIMDIS(timerConfig->timerDisable) | |
297 | FLEXIO_TIMCFG_TIMENA(timerConfig->timerEnable) | FLEXIO_TIMCFG_TSTOP(timerConfig->timerStop) | |
298 | FLEXIO_TIMCFG_TSTART(timerConfig->timerStart); |
299 | |
300 | base->TIMCMP[index] = FLEXIO_TIMCMP_CMP(timerConfig->timerCompare); |
301 | |
302 | base->TIMCTL[index] = FLEXIO_TIMCTL_TRGSEL(timerConfig->triggerSelect) | |
303 | FLEXIO_TIMCTL_TRGPOL(timerConfig->triggerPolarity) | |
304 | FLEXIO_TIMCTL_TRGSRC(timerConfig->triggerSource) | |
305 | FLEXIO_TIMCTL_PINCFG(timerConfig->pinConfig) | FLEXIO_TIMCTL_PINSEL(timerConfig->pinSelect) | |
306 | FLEXIO_TIMCTL_PINPOL(timerConfig->pinPolarity) | FLEXIO_TIMCTL_TIMOD(timerConfig->timerMode); |
307 | } |
308 | |
309 | /*! |
310 | * brief Registers the handle and the interrupt handler for the FlexIO-simulated peripheral. |
311 | * |
312 | * param base Pointer to the FlexIO simulated peripheral type. |
313 | * param handle Pointer to the handler for FlexIO simulated peripheral. |
314 | * param isr FlexIO simulated peripheral interrupt handler. |
315 | * retval kStatus_Success Successfully create the handle. |
316 | * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range. |
317 | */ |
318 | status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr) |
319 | { |
320 | assert(base != NULL); |
321 | assert(handle != NULL); |
322 | assert(isr != NULL); |
323 | |
324 | uint8_t index; |
325 | |
326 | /* Find the an empty handle pointer to store the handle. */ |
327 | for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++) |
328 | { |
329 | if (s_flexioHandle[index] == NULL) |
330 | { |
331 | /* Register FLEXIO simulated driver base, handle and isr. */ |
332 | s_flexioType[index] = base; |
333 | s_flexioHandle[index] = handle; |
334 | s_flexioIsr[index] = isr; |
335 | break; |
336 | } |
337 | } |
338 | |
339 | if (index == (uint8_t)FLEXIO_HANDLE_COUNT) |
340 | { |
341 | return kStatus_OutOfRange; |
342 | } |
343 | else |
344 | { |
345 | return kStatus_Success; |
346 | } |
347 | } |
348 | |
349 | /*! |
350 | * brief Unregisters the handle and the interrupt handler for the FlexIO-simulated peripheral. |
351 | * |
352 | * param base Pointer to the FlexIO simulated peripheral type. |
353 | * retval kStatus_Success Successfully create the handle. |
354 | * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range. |
355 | */ |
356 | status_t FLEXIO_UnregisterHandleIRQ(void *base) |
357 | { |
358 | assert(base != NULL); |
359 | |
360 | uint8_t index; |
361 | |
362 | /* Find the index from base address mappings. */ |
363 | for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++) |
364 | { |
365 | if (s_flexioType[index] == base) |
366 | { |
367 | /* Unregister FLEXIO simulated driver handle and isr. */ |
368 | s_flexioType[index] = NULL; |
369 | s_flexioHandle[index] = NULL; |
370 | s_flexioIsr[index] = NULL; |
371 | break; |
372 | } |
373 | } |
374 | |
375 | if (index == (uint8_t)FLEXIO_HANDLE_COUNT) |
376 | { |
377 | return kStatus_OutOfRange; |
378 | } |
379 | else |
380 | { |
381 | return kStatus_Success; |
382 | } |
383 | } |
384 | |
385 | static void FLEXIO_CommonIRQHandler(void) |
386 | { |
387 | uint8_t index; |
388 | |
389 | for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++) |
390 | { |
391 | if (s_flexioHandle[index] != NULL) |
392 | { |
393 | s_flexioIsr[index](s_flexioType[index], s_flexioHandle[index]); |
394 | } |
395 | } |
396 | SDK_ISR_EXIT_BARRIER; |
397 | } |
398 | |
399 | void FLEXIO_DriverIRQHandler(void); |
400 | void FLEXIO_DriverIRQHandler(void) |
401 | { |
402 | FLEXIO_CommonIRQHandler(); |
403 | } |
404 | |
405 | void FLEXIO0_DriverIRQHandler(void); |
406 | void FLEXIO0_DriverIRQHandler(void) |
407 | { |
408 | FLEXIO_CommonIRQHandler(); |
409 | } |
410 | |
411 | void FLEXIO1_DriverIRQHandler(void); |
412 | void FLEXIO1_DriverIRQHandler(void) |
413 | { |
414 | FLEXIO_CommonIRQHandler(); |
415 | } |
416 | |
417 | void UART2_FLEXIO_DriverIRQHandler(void); |
418 | void UART2_FLEXIO_DriverIRQHandler(void) |
419 | { |
420 | FLEXIO_CommonIRQHandler(); |
421 | } |
422 | |
423 | void FLEXIO2_DriverIRQHandler(void); |
424 | void FLEXIO2_DriverIRQHandler(void) |
425 | { |
426 | FLEXIO_CommonIRQHandler(); |
427 | } |
428 | |
429 | void FLEXIO3_DriverIRQHandler(void); |
430 | void FLEXIO3_DriverIRQHandler(void) |
431 | { |
432 | FLEXIO_CommonIRQHandler(); |
433 | } |
434 | |