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 #if defined(FLEXIO_RSTS)
24 #define FLEXIO_RESETS_ARRAY FLEXIO_RSTS
25 #elif defined(FLEXIO_RSTS_N)
26 #define FLEXIO_RESETS_ARRAY FLEXIO_RSTS_N
27 #endif
28
29 /*******************************************************************************
30 * Variables
31 ******************************************************************************/
32 /*! @brief Pointers to flexio bases for each instance. */
33 FLEXIO_Type *const s_flexioBases[] = FLEXIO_BASE_PTRS;
34
35 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
36 /*! @brief Pointers to flexio clocks for each instance. */
37 const clock_ip_name_t s_flexioClocks[] = FLEXIO_CLOCKS;
38 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
39
40 /*< @brief pointer to array of FLEXIO handle. */
41 static void *s_flexioHandle[FLEXIO_HANDLE_COUNT];
42
43 /*< @brief pointer to array of FLEXIO IP types. */
44 static void *s_flexioType[FLEXIO_HANDLE_COUNT];
45
46 /*< @brief pointer to array of FLEXIO Isr. */
47 static flexio_isr_t s_flexioIsr[FLEXIO_HANDLE_COUNT];
48
49 /* FlexIO common IRQ Handler. */
50 static void FLEXIO_CommonIRQHandler(void);
51
52 #if defined(FLEXIO_RESETS_ARRAY)
53 /* Reset array */
54 static const reset_ip_name_t s_flexioResets[] = FLEXIO_RESETS_ARRAY;
55 #endif
56
57 /*******************************************************************************
58 * Codes
59 ******************************************************************************/
60
61 /*!
62 * brief Get instance number for FLEXIO module.
63 *
64 * param base FLEXIO peripheral base address.
65 */
FLEXIO_GetInstance(FLEXIO_Type * base)66 uint32_t FLEXIO_GetInstance(FLEXIO_Type *base)
67 {
68 uint32_t instance;
69
70 /* Find the instance index from base address mappings. */
71 for (instance = 0; instance < ARRAY_SIZE(s_flexioBases); instance++)
72 {
73 if (s_flexioBases[instance] == base)
74 {
75 break;
76 }
77 }
78
79 assert(instance < ARRAY_SIZE(s_flexioBases));
80
81 return instance;
82 }
83
84 /*!
85 * brief Configures the FlexIO with a FlexIO configuration. The configuration structure
86 * can be filled by the user or be set with default values by FLEXIO_GetDefaultConfig().
87 *
88 * Example
89 code
90 flexio_config_t config = {
91 .enableFlexio = true,
92 .enableInDoze = false,
93 .enableInDebug = true,
94 .enableFastAccess = false
95 };
96 FLEXIO_Configure(base, &config);
97 endcode
98 *
99 * param base FlexIO peripheral base address
100 * param userConfig pointer to flexio_config_t structure
101 */
FLEXIO_Init(FLEXIO_Type * base,const flexio_config_t * userConfig)102 void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig)
103 {
104 uint32_t ctrlReg = 0;
105
106 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
107 CLOCK_EnableClock(s_flexioClocks[FLEXIO_GetInstance(base)]);
108 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
109
110 #if defined(FLEXIO_RESETS_ARRAY)
111 RESET_ReleasePeripheralReset(s_flexioResets[FLEXIO_GetInstance(base)]);
112 #endif
113
114 FLEXIO_Reset(base);
115
116 ctrlReg = base->CTRL;
117 #if !(defined(FSL_FEATURE_FLEXIO_HAS_DOZE_MODE_SUPPORT) && (FSL_FEATURE_FLEXIO_HAS_DOZE_MODE_SUPPORT == 0))
118 ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
119 #else
120 ctrlReg &= ~(FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
121 #endif
122 ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) |
123 FLEXIO_CTRL_FLEXEN(userConfig->enableFlexio));
124 #if !(defined(FSL_FEATURE_FLEXIO_HAS_DOZE_MODE_SUPPORT) && (FSL_FEATURE_FLEXIO_HAS_DOZE_MODE_SUPPORT == 0))
125 if (!userConfig->enableInDoze)
126 {
127 ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
128 }
129 #endif
130
131 base->CTRL = ctrlReg;
132 }
133
134 /*!
135 * brief Gates the FlexIO clock. Call this API to stop the FlexIO clock.
136 *
137 * note After calling this API, call the FLEXO_Init to use the FlexIO module.
138 *
139 * param base FlexIO peripheral base address
140 */
FLEXIO_Deinit(FLEXIO_Type * base)141 void FLEXIO_Deinit(FLEXIO_Type *base)
142 {
143 FLEXIO_Enable(base, false);
144 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
145 CLOCK_DisableClock(s_flexioClocks[FLEXIO_GetInstance(base)]);
146 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
147 }
148
149 /*!
150 * brief Gets the default configuration to configure the FlexIO module. The configuration
151 * can used directly to call the FLEXIO_Configure().
152 *
153 * Example:
154 code
155 flexio_config_t config;
156 FLEXIO_GetDefaultConfig(&config);
157 endcode
158 *
159 * param userConfig pointer to flexio_config_t structure
160 */
FLEXIO_GetDefaultConfig(flexio_config_t * userConfig)161 void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig)
162 {
163 assert(userConfig != NULL);
164
165 /* Initializes the configure structure to zero. */
166 (void)memset(userConfig, 0, sizeof(*userConfig));
167
168 userConfig->enableFlexio = true;
169 #if !(defined(FSL_FEATURE_FLEXIO_HAS_DOZE_MODE_SUPPORT) && (FSL_FEATURE_FLEXIO_HAS_DOZE_MODE_SUPPORT == 0))
170 userConfig->enableInDoze = false;
171 #endif
172 userConfig->enableInDebug = true;
173 userConfig->enableFastAccess = false;
174 }
175
176 /*!
177 * brief Resets the FlexIO module.
178 *
179 * param base FlexIO peripheral base address
180 */
FLEXIO_Reset(FLEXIO_Type * base)181 void FLEXIO_Reset(FLEXIO_Type *base)
182 {
183 /*do software reset, software reset operation affect all other FLEXIO registers except CTRL*/
184 base->CTRL |= FLEXIO_CTRL_SWRST_MASK;
185 base->CTRL = 0;
186 }
187
188 /*!
189 * brief Gets the shifter buffer address for the DMA transfer usage.
190 *
191 * param base FlexIO peripheral base address
192 * param type Shifter type of flexio_shifter_buffer_type_t
193 * param index Shifter index
194 * return Corresponding shifter buffer index
195 */
FLEXIO_GetShifterBufferAddress(FLEXIO_Type * base,flexio_shifter_buffer_type_t type,uint8_t index)196 uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index)
197 {
198 assert(index < FLEXIO_SHIFTBUF_COUNT);
199
200 uint32_t address = 0;
201
202 switch (type)
203 {
204 case kFLEXIO_ShifterBuffer:
205 address = (uint32_t) & (base->SHIFTBUF[index]);
206 break;
207
208 case kFLEXIO_ShifterBufferBitSwapped:
209 address = (uint32_t) & (base->SHIFTBUFBIS[index]);
210 break;
211
212 case kFLEXIO_ShifterBufferByteSwapped:
213 address = (uint32_t) & (base->SHIFTBUFBYS[index]);
214 break;
215
216 case kFLEXIO_ShifterBufferBitByteSwapped:
217 address = (uint32_t) & (base->SHIFTBUFBBS[index]);
218 break;
219
220 #if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
221 case kFLEXIO_ShifterBufferNibbleByteSwapped:
222 address = (uint32_t) & (base->SHIFTBUFNBS[index]);
223 break;
224
225 #endif
226 #if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
227 case kFLEXIO_ShifterBufferHalfWordSwapped:
228 address = (uint32_t) & (base->SHIFTBUFHWS[index]);
229 break;
230
231 #endif
232 #if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
233 case kFLEXIO_ShifterBufferNibbleSwapped:
234 address = (uint32_t) & (base->SHIFTBUFNIS[index]);
235 break;
236
237 #endif
238 default:
239 address = (uint32_t) & (base->SHIFTBUF[index]);
240 break;
241 }
242 return address;
243 }
244
245 /*!
246 * brief Configures the shifter with the shifter configuration. The configuration structure
247 * covers both the SHIFTCTL and SHIFTCFG registers. To configure the shifter to the proper
248 * mode, select which timer controls the shifter to shift, whether to generate start bit/stop
249 * bit, and the polarity of start bit and stop bit.
250 *
251 * Example
252 code
253 flexio_shifter_config_t config = {
254 .timerSelect = 0,
255 .timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive,
256 .pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
257 .pinPolarity = kFLEXIO_PinActiveLow,
258 .shifterMode = kFLEXIO_ShifterModeTransmit,
259 .inputSource = kFLEXIO_ShifterInputFromPin,
260 .shifterStop = kFLEXIO_ShifterStopBitHigh,
261 .shifterStart = kFLEXIO_ShifterStartBitLow
262 };
263 FLEXIO_SetShifterConfig(base, &config);
264 endcode
265 *
266 * param base FlexIO peripheral base address
267 * param index Shifter index
268 * param shifterConfig Pointer to flexio_shifter_config_t structure
269 */
FLEXIO_SetShifterConfig(FLEXIO_Type * base,uint8_t index,const flexio_shifter_config_t * shifterConfig)270 void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig)
271 {
272 base->SHIFTCFG[index] = FLEXIO_SHIFTCFG_INSRC(shifterConfig->inputSource)
273 #if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
274 | FLEXIO_SHIFTCFG_PWIDTH(shifterConfig->parallelWidth)
275 #endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
276 | FLEXIO_SHIFTCFG_SSTOP(shifterConfig->shifterStop) |
277 FLEXIO_SHIFTCFG_SSTART(shifterConfig->shifterStart);
278
279 base->SHIFTCTL[index] =
280 FLEXIO_SHIFTCTL_TIMSEL(shifterConfig->timerSelect) | FLEXIO_SHIFTCTL_TIMPOL(shifterConfig->timerPolarity) |
281 FLEXIO_SHIFTCTL_PINCFG(shifterConfig->pinConfig) | FLEXIO_SHIFTCTL_PINSEL(shifterConfig->pinSelect) |
282 FLEXIO_SHIFTCTL_PINPOL(shifterConfig->pinPolarity) | FLEXIO_SHIFTCTL_SMOD(shifterConfig->shifterMode);
283 }
284
285 /*!
286 * brief Configures the timer with the timer configuration. The configuration structure
287 * covers both the TIMCTL and TIMCFG registers. To configure the timer to the proper
288 * mode, select trigger source for timer and the timer pin output and the timing for timer.
289 *
290 * Example
291 code
292 flexio_timer_config_t config = {
293 .triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0),
294 .triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow,
295 .triggerSource = kFLEXIO_TimerTriggerSourceInternal,
296 .pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
297 .pinSelect = 0,
298 .pinPolarity = kFLEXIO_PinActiveHigh,
299 .timerMode = kFLEXIO_TimerModeDual8BitBaudBit,
300 .timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset,
301 .timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput,
302 .timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput,
303 .timerDisable = kFLEXIO_TimerDisableOnTimerCompare,
304 .timerEnable = kFLEXIO_TimerEnableOnTriggerHigh,
305 .timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable,
306 .timerStart = kFLEXIO_TimerStartBitEnabled
307 };
308 FLEXIO_SetTimerConfig(base, &config);
309 endcode
310 *
311 * param base FlexIO peripheral base address
312 * param index Timer index
313 * param timerConfig Pointer to the flexio_timer_config_t structure
314 */
FLEXIO_SetTimerConfig(FLEXIO_Type * base,uint8_t index,const flexio_timer_config_t * timerConfig)315 void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig)
316 {
317 base->TIMCFG[index] =
318 FLEXIO_TIMCFG_TIMOUT(timerConfig->timerOutput) | FLEXIO_TIMCFG_TIMDEC(timerConfig->timerDecrement) |
319 FLEXIO_TIMCFG_TIMRST(timerConfig->timerReset) | FLEXIO_TIMCFG_TIMDIS(timerConfig->timerDisable) |
320 FLEXIO_TIMCFG_TIMENA(timerConfig->timerEnable) | FLEXIO_TIMCFG_TSTOP(timerConfig->timerStop) |
321 FLEXIO_TIMCFG_TSTART(timerConfig->timerStart);
322
323 base->TIMCMP[index] = FLEXIO_TIMCMP_CMP(timerConfig->timerCompare);
324
325 base->TIMCTL[index] = FLEXIO_TIMCTL_TRGSEL(timerConfig->triggerSelect) |
326 FLEXIO_TIMCTL_TRGPOL(timerConfig->triggerPolarity) |
327 FLEXIO_TIMCTL_TRGSRC(timerConfig->triggerSource) |
328 FLEXIO_TIMCTL_PINCFG(timerConfig->pinConfig) | FLEXIO_TIMCTL_PINSEL(timerConfig->pinSelect) |
329 FLEXIO_TIMCTL_PINPOL(timerConfig->pinPolarity) | FLEXIO_TIMCTL_TIMOD(timerConfig->timerMode);
330 }
331
332 /*!
333 * brief Registers the handle and the interrupt handler for the FlexIO-simulated peripheral.
334 *
335 * param base Pointer to the FlexIO simulated peripheral type.
336 * param handle Pointer to the handler for FlexIO simulated peripheral.
337 * param isr FlexIO simulated peripheral interrupt handler.
338 * retval kStatus_Success Successfully create the handle.
339 * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
340 */
FLEXIO_RegisterHandleIRQ(void * base,void * handle,flexio_isr_t isr)341 status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr)
342 {
343 assert(base != NULL);
344 assert(handle != NULL);
345 assert(isr != NULL);
346
347 uint8_t index;
348
349 /* Find the an empty handle pointer to store the handle. */
350 for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++)
351 {
352 if (s_flexioHandle[index] == NULL)
353 {
354 /* Register FLEXIO simulated driver base, handle and isr. */
355 s_flexioType[index] = base;
356 s_flexioHandle[index] = handle;
357 s_flexioIsr[index] = isr;
358 break;
359 }
360 }
361
362 if (index == (uint8_t)FLEXIO_HANDLE_COUNT)
363 {
364 return kStatus_OutOfRange;
365 }
366 else
367 {
368 return kStatus_Success;
369 }
370 }
371
372 /*!
373 * brief Unregisters the handle and the interrupt handler for the FlexIO-simulated peripheral.
374 *
375 * param base Pointer to the FlexIO simulated peripheral type.
376 * retval kStatus_Success Successfully create the handle.
377 * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
378 */
FLEXIO_UnregisterHandleIRQ(void * base)379 status_t FLEXIO_UnregisterHandleIRQ(void *base)
380 {
381 assert(base != NULL);
382
383 uint8_t index;
384
385 /* Find the index from base address mappings. */
386 for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++)
387 {
388 if (s_flexioType[index] == base)
389 {
390 /* Unregister FLEXIO simulated driver handle and isr. */
391 s_flexioType[index] = NULL;
392 s_flexioHandle[index] = NULL;
393 s_flexioIsr[index] = NULL;
394 break;
395 }
396 }
397
398 if (index == (uint8_t)FLEXIO_HANDLE_COUNT)
399 {
400 return kStatus_OutOfRange;
401 }
402 else
403 {
404 return kStatus_Success;
405 }
406 }
407
FLEXIO_CommonIRQHandler(void)408 static void FLEXIO_CommonIRQHandler(void)
409 {
410 uint8_t index;
411
412 for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++)
413 {
414 if (s_flexioHandle[index] != NULL)
415 {
416 s_flexioIsr[index](s_flexioType[index], s_flexioHandle[index]);
417 }
418 }
419 SDK_ISR_EXIT_BARRIER;
420 }
421
422 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER
423 /*!
424 * brief Configure a FLEXIO pin used by the board.
425 *
426 * To Config the FLEXIO PIN, define a pin configuration, as either input or output, in the user file.
427 * Then, call the FLEXIO_SetPinConfig() function.
428 *
429 * This is an example to define an input pin or an output pin configuration.
430 * code
431 * Define a digital input pin configuration,
432 * flexio_gpio_config_t config =
433 * {
434 * kFLEXIO_DigitalInput,
435 * 0U,
436 * kFLEXIO_FlagRisingEdgeEnable | kFLEXIO_InputInterruptEnable,
437 * }
438 * Define a digital output pin configuration,
439 * flexio_gpio_config_t config =
440 * {
441 * kFLEXIO_DigitalOutput,
442 * 0U,
443 * 0U
444 * }
445 * endcode
446 * param base FlexIO peripheral base address
447 * param pin FLEXIO pin number.
448 * param config FLEXIO pin configuration pointer.
449 */
FLEXIO_SetPinConfig(FLEXIO_Type * base,uint32_t pin,flexio_gpio_config_t * config)450 void FLEXIO_SetPinConfig(FLEXIO_Type *base, uint32_t pin, flexio_gpio_config_t *config)
451 {
452 assert(NULL != config);
453 IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
454
455 if (config->pinDirection == kFLEXIO_DigitalInput)
456 {
457 base->PINOUTE &= ~(1UL << pin);
458 if (0U != (config->inputConfig & (uint8_t)kFLEXIO_InputInterruptEnable))
459 {
460 base->PINIEN = 1UL << pin;
461 /* Clear pending NVIC IRQ before enable NVIC IRQ. */
462 NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_GetInstance(base)]);
463 /* Enable interrupt in NVIC. */
464 (void)EnableIRQ(flexio_irqs[FLEXIO_GetInstance(base)]);
465 }
466
467 if (0U != (config->inputConfig & (uint8_t)kFLEXIO_FlagRisingEdgeEnable))
468 {
469 base->PINREN = 1UL << pin;
470 }
471
472 if (0U != (config->inputConfig & (uint8_t)kFLEXIO_FlagFallingEdgeEnable))
473 {
474 base->PINFEN = 1UL << pin;
475 }
476 }
477 else
478 {
479 FLEXIO_EnablePinOutput(base, pin);
480 FLEXIO_PinWrite(base, pin, config->outputLogic);
481 }
482 }
483 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER*/
484
485 void FLEXIO_DriverIRQHandler(void);
FLEXIO_DriverIRQHandler(void)486 void FLEXIO_DriverIRQHandler(void)
487 {
488 FLEXIO_CommonIRQHandler();
489 }
490
491 void FLEXIO0_DriverIRQHandler(void);
FLEXIO0_DriverIRQHandler(void)492 void FLEXIO0_DriverIRQHandler(void)
493 {
494 FLEXIO_CommonIRQHandler();
495 }
496
497 void FLEXIO1_DriverIRQHandler(void);
FLEXIO1_DriverIRQHandler(void)498 void FLEXIO1_DriverIRQHandler(void)
499 {
500 FLEXIO_CommonIRQHandler();
501 }
502
503 void UART2_FLEXIO_DriverIRQHandler(void);
UART2_FLEXIO_DriverIRQHandler(void)504 void UART2_FLEXIO_DriverIRQHandler(void)
505 {
506 FLEXIO_CommonIRQHandler();
507 }
508
509 void FLEXIO2_DriverIRQHandler(void);
FLEXIO2_DriverIRQHandler(void)510 void FLEXIO2_DriverIRQHandler(void)
511 {
512 FLEXIO_CommonIRQHandler();
513 }
514
515 void FLEXIO3_DriverIRQHandler(void);
FLEXIO3_DriverIRQHandler(void)516 void FLEXIO3_DriverIRQHandler(void)
517 {
518 FLEXIO_CommonIRQHandler();
519 }
520