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