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