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