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 */
FLEXIO_GetInstance(FLEXIO_Type * base)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 */
FLEXIO_Init(FLEXIO_Type * base,const flexio_config_t * userConfig)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 */
FLEXIO_Deinit(FLEXIO_Type * base)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 */
FLEXIO_GetDefaultConfig(flexio_config_t * userConfig)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 */
FLEXIO_Reset(FLEXIO_Type * base)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 */
FLEXIO_GetShifterBufferAddress(FLEXIO_Type * base,flexio_shifter_buffer_type_t type,uint8_t index)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 */
FLEXIO_SetShifterConfig(FLEXIO_Type * base,uint8_t index,const flexio_shifter_config_t * shifterConfig)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 */
FLEXIO_SetTimerConfig(FLEXIO_Type * base,uint8_t index,const flexio_timer_config_t * timerConfig)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 */
FLEXIO_RegisterHandleIRQ(void * base,void * handle,flexio_isr_t isr)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 */
FLEXIO_UnregisterHandleIRQ(void * base)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
FLEXIO_CommonIRQHandler(void)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 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER
400 /*!
401 * brief Configure a FLEXIO pin used by the board.
402 *
403 * To Config the FLEXIO PIN, define a pin configuration, as either input or output, in the user file.
404 * Then, call the FLEXIO_SetPinConfig() function.
405 *
406 * This is an example to define an input pin or an output pin configuration.
407 * code
408 * Define a digital input pin configuration,
409 * flexio_gpio_config_t config =
410 * {
411 * kFLEXIO_DigitalInput,
412 * 0U,
413 * kFLEXIO_FlagRisingEdgeEnable | kFLEXIO_InputInterruptEnable,
414 * }
415 * Define a digital output pin configuration,
416 * flexio_gpio_config_t config =
417 * {
418 * kFLEXIO_DigitalOutput,
419 * 0U,
420 * 0U
421 * }
422 * endcode
423 * param base FlexIO peripheral base address
424 * param pin FLEXIO pin number.
425 * param config FLEXIO pin configuration pointer.
426 */
FLEXIO_SetPinConfig(FLEXIO_Type * base,uint32_t pin,flexio_gpio_config_t * config)427 void FLEXIO_SetPinConfig(FLEXIO_Type *base, uint32_t pin, flexio_gpio_config_t *config)
428 {
429 assert(NULL != config);
430 IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
431
432 if (config->pinDirection == kFLEXIO_DigitalInput)
433 {
434 base->PINOUTE &= ~(1UL << pin);
435 if (0U != (config->inputConfig & (uint8_t)kFLEXIO_InputInterruptEnable))
436 {
437 base->PINIEN = 1UL << pin;
438 /* Clear pending NVIC IRQ before enable NVIC IRQ. */
439 NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_GetInstance(base)]);
440 /* Enable interrupt in NVIC. */
441 (void)EnableIRQ(flexio_irqs[FLEXIO_GetInstance(base)]);
442 }
443
444 if (0U != (config->inputConfig & (uint8_t)kFLEXIO_FlagRisingEdgeEnable))
445 {
446 base->PINREN = 1UL << pin;
447 }
448
449 if (0U != (config->inputConfig & (uint8_t)kFLEXIO_FlagFallingEdgeEnable))
450 {
451 base->PINFEN = 1UL << pin;
452 }
453 }
454 else
455 {
456 FLEXIO_EnablePinOutput(base, pin);
457 FLEXIO_PinWrite(base, pin, config->outputLogic);
458 }
459 }
460 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER*/
461
462 void FLEXIO_DriverIRQHandler(void);
FLEXIO_DriverIRQHandler(void)463 void FLEXIO_DriverIRQHandler(void)
464 {
465 FLEXIO_CommonIRQHandler();
466 }
467
468 void FLEXIO0_DriverIRQHandler(void);
FLEXIO0_DriverIRQHandler(void)469 void FLEXIO0_DriverIRQHandler(void)
470 {
471 FLEXIO_CommonIRQHandler();
472 }
473
474 void FLEXIO1_DriverIRQHandler(void);
FLEXIO1_DriverIRQHandler(void)475 void FLEXIO1_DriverIRQHandler(void)
476 {
477 FLEXIO_CommonIRQHandler();
478 }
479
480 void UART2_FLEXIO_DriverIRQHandler(void);
UART2_FLEXIO_DriverIRQHandler(void)481 void UART2_FLEXIO_DriverIRQHandler(void)
482 {
483 FLEXIO_CommonIRQHandler();
484 }
485
486 void FLEXIO2_DriverIRQHandler(void);
FLEXIO2_DriverIRQHandler(void)487 void FLEXIO2_DriverIRQHandler(void)
488 {
489 FLEXIO_CommonIRQHandler();
490 }
491
492 void FLEXIO3_DriverIRQHandler(void);
FLEXIO3_DriverIRQHandler(void)493 void FLEXIO3_DriverIRQHandler(void)
494 {
495 FLEXIO_CommonIRQHandler();
496 }
497