1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_common.h"
10 #include "fsl_flexcomm.h"
11
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15
16 /* Component ID definition, used by tools. */
17 #ifndef FSL_COMPONENT_ID
18 #define FSL_COMPONENT_ID "platform.drivers.flexcomm"
19 #endif
20
21 /*!
22 * @brief Used for conversion between `void*` and `uint32_t`.
23 */
24 typedef union pvoid_to_u32
25 {
26 void *pvoid;
27 uint32_t u32;
28 } pvoid_to_u32_t;
29
30 /*******************************************************************************
31 * Prototypes
32 ******************************************************************************/
33 /*! @brief Set the FLEXCOMM mode . */
34 static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock);
35
36 /*! @brief check whether flexcomm supports peripheral type */
37 static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph);
38
39 /*******************************************************************************
40 * Variables
41 ******************************************************************************/
42
43 /*! @brief Array to map FLEXCOMM instance number to base address. */
44 static const uint32_t s_flexcommBaseAddrs[] = FLEXCOMM_BASE_ADDRS;
45
46 /*! @brief Pointers to real IRQ handlers installed by drivers for each instance. */
47 static flexcomm_irq_handler_t s_flexcommIrqHandler[ARRAY_SIZE(s_flexcommBaseAddrs)];
48
49 /*! @brief Pointers to handles for each instance to provide context to interrupt routines */
50 static void *s_flexcommHandle[ARRAY_SIZE(s_flexcommBaseAddrs)];
51
52 /*! @brief Array to map FLEXCOMM instance number to IRQ number. */
53 IRQn_Type const kFlexcommIrqs[] = FLEXCOMM_IRQS;
54
55 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
56 /*! @brief IDs of clock for each FLEXCOMM module */
57 static const clock_ip_name_t s_flexcommClocks[] = FLEXCOMM_CLOCKS;
58 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
59
60 #if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
61 /*! @brief Pointers to FLEXCOMM resets for each instance. */
62 static const reset_ip_name_t s_flexcommResets[] = FLEXCOMM_RSTS;
63 #endif
64
65 /*******************************************************************************
66 * Code
67 ******************************************************************************/
68
69 /* check whether flexcomm supports peripheral type */
FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type * base,FLEXCOMM_PERIPH_T periph)70 static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph)
71 {
72 if (periph == FLEXCOMM_PERIPH_NONE)
73 {
74 return true;
75 }
76 else if (periph <= FLEXCOMM_PERIPH_I2S_TX)
77 {
78 return (base->PSELID & (1UL << ((uint32_t)periph + 3U))) > 0UL ? true : false;
79 }
80 else if (periph == FLEXCOMM_PERIPH_I2S_RX)
81 {
82 return (base->PSELID & (1U << 7U)) > (uint32_t)0U ? true : false;
83 }
84 else
85 {
86 return false;
87 }
88 }
89
90 /* Get the index corresponding to the FLEXCOMM */
91 /*! brief Returns instance number for FLEXCOMM module with given base address. */
FLEXCOMM_GetInstance(void * base)92 uint32_t FLEXCOMM_GetInstance(void *base)
93 {
94 uint32_t i;
95 pvoid_to_u32_t BaseAddr;
96 BaseAddr.pvoid = base;
97
98 for (i = 0U; i < (uint32_t)FSL_FEATURE_SOC_FLEXCOMM_COUNT; i++)
99 {
100 if (BaseAddr.u32 == s_flexcommBaseAddrs[i])
101 {
102 break;
103 }
104 }
105
106 assert(i < (uint32_t)FSL_FEATURE_SOC_FLEXCOMM_COUNT);
107 return i;
108 }
109
110 /* Changes FLEXCOMM mode */
FLEXCOMM_SetPeriph(FLEXCOMM_Type * base,FLEXCOMM_PERIPH_T periph,int lock)111 static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock)
112 {
113 /* Check whether peripheral type is present */
114 if (!FLEXCOMM_PeripheralIsPresent(base, periph))
115 {
116 return kStatus_OutOfRange;
117 }
118
119 /* Flexcomm is locked to different peripheral type than expected */
120 if (((base->PSELID & FLEXCOMM_PSELID_LOCK_MASK) != 0U) &&
121 ((base->PSELID & FLEXCOMM_PSELID_PERSEL_MASK) != (uint32_t)periph))
122 {
123 return kStatus_Fail;
124 }
125
126 /* Check if we are asked to lock */
127 if (lock != 0)
128 {
129 base->PSELID = (uint32_t)periph | FLEXCOMM_PSELID_LOCK_MASK;
130 }
131 else
132 {
133 base->PSELID = (uint32_t)periph;
134 }
135
136 return kStatus_Success;
137 }
138
139 /*! brief Initializes FLEXCOMM and selects peripheral mode according to the second parameter. */
FLEXCOMM_Init(void * base,FLEXCOMM_PERIPH_T periph)140 status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph)
141 {
142 uint32_t idx = FLEXCOMM_GetInstance(base);
143
144 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
145 /* Enable the peripheral clock */
146 CLOCK_EnableClock(s_flexcommClocks[idx]);
147 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
148
149 #if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
150 /* Reset the FLEXCOMM module */
151 RESET_PeripheralReset(s_flexcommResets[idx]);
152 #endif
153
154 /* Set the FLEXCOMM to given peripheral */
155 return FLEXCOMM_SetPeriph((FLEXCOMM_Type *)base, periph, 0);
156 }
157
158 /*! brief Sets IRQ handler for given FLEXCOMM module. It is used by drivers register IRQ handler according to FLEXCOMM
159 * mode */
FLEXCOMM_SetIRQHandler(void * base,flexcomm_irq_handler_t handler,void * flexcommHandle)160 void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *flexcommHandle)
161 {
162 uint32_t instance;
163
164 /* Look up instance number */
165 instance = FLEXCOMM_GetInstance(base);
166
167 /* Clear handler first to avoid execution of the handler with wrong handle */
168 s_flexcommIrqHandler[instance] = NULL;
169 s_flexcommHandle[instance] = flexcommHandle;
170 s_flexcommIrqHandler[instance] = handler;
171 SDK_ISR_EXIT_BARRIER;
172 }
173
174 /* IRQ handler functions overloading weak symbols in the startup */
175 #if defined(FLEXCOMM0)
176 void FLEXCOMM0_DriverIRQHandler(void);
FLEXCOMM0_DriverIRQHandler(void)177 void FLEXCOMM0_DriverIRQHandler(void)
178 {
179 uint32_t instance;
180
181 /* Look up instance number */
182 instance = FLEXCOMM_GetInstance(FLEXCOMM0);
183 assert(s_flexcommIrqHandler[instance] != NULL);
184 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
185 SDK_ISR_EXIT_BARRIER;
186 }
187 #endif
188
189 #if defined(FLEXCOMM1)
190 void FLEXCOMM1_DriverIRQHandler(void);
FLEXCOMM1_DriverIRQHandler(void)191 void FLEXCOMM1_DriverIRQHandler(void)
192 {
193 uint32_t instance;
194
195 /* Look up instance number */
196 instance = FLEXCOMM_GetInstance(FLEXCOMM1);
197 assert(s_flexcommIrqHandler[instance] != NULL);
198 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
199 SDK_ISR_EXIT_BARRIER;
200 }
201 #endif
202
203 #if defined(FLEXCOMM2)
204 void FLEXCOMM2_DriverIRQHandler(void);
FLEXCOMM2_DriverIRQHandler(void)205 void FLEXCOMM2_DriverIRQHandler(void)
206 {
207 uint32_t instance;
208
209 /* Look up instance number */
210 instance = FLEXCOMM_GetInstance(FLEXCOMM2);
211 assert(s_flexcommIrqHandler[instance] != NULL);
212 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
213 SDK_ISR_EXIT_BARRIER;
214 }
215 #endif
216
217 #if defined(FLEXCOMM3)
218 void FLEXCOMM3_DriverIRQHandler(void);
FLEXCOMM3_DriverIRQHandler(void)219 void FLEXCOMM3_DriverIRQHandler(void)
220 {
221 uint32_t instance;
222
223 /* Look up instance number */
224 instance = FLEXCOMM_GetInstance(FLEXCOMM3);
225 assert(s_flexcommIrqHandler[instance] != NULL);
226 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
227 SDK_ISR_EXIT_BARRIER;
228 }
229 #endif
230
231 #if defined(FLEXCOMM4)
232 void FLEXCOMM4_DriverIRQHandler(void);
FLEXCOMM4_DriverIRQHandler(void)233 void FLEXCOMM4_DriverIRQHandler(void)
234 {
235 uint32_t instance;
236
237 /* Look up instance number */
238 instance = FLEXCOMM_GetInstance(FLEXCOMM4);
239 assert(s_flexcommIrqHandler[instance] != NULL);
240 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
241 SDK_ISR_EXIT_BARRIER;
242 }
243
244 #endif
245
246 #if defined(FLEXCOMM5)
247 void FLEXCOMM5_DriverIRQHandler(void);
FLEXCOMM5_DriverIRQHandler(void)248 void FLEXCOMM5_DriverIRQHandler(void)
249 {
250 uint32_t instance;
251
252 /* Look up instance number */
253 instance = FLEXCOMM_GetInstance(FLEXCOMM5);
254 assert(s_flexcommIrqHandler[instance] != NULL);
255 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
256 SDK_ISR_EXIT_BARRIER;
257 }
258 #endif
259
260 #if defined(FLEXCOMM6)
261 void FLEXCOMM6_DriverIRQHandler(void);
FLEXCOMM6_DriverIRQHandler(void)262 void FLEXCOMM6_DriverIRQHandler(void)
263 {
264 uint32_t instance;
265
266 /* Look up instance number */
267 instance = FLEXCOMM_GetInstance(FLEXCOMM6);
268 assert(s_flexcommIrqHandler[instance] != NULL);
269 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
270 SDK_ISR_EXIT_BARRIER;
271 }
272 #endif
273
274 #if defined(FLEXCOMM7)
275 void FLEXCOMM7_DriverIRQHandler(void);
FLEXCOMM7_DriverIRQHandler(void)276 void FLEXCOMM7_DriverIRQHandler(void)
277 {
278 uint32_t instance;
279
280 /* Look up instance number */
281 instance = FLEXCOMM_GetInstance(FLEXCOMM7);
282 assert(s_flexcommIrqHandler[instance] != NULL);
283 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
284 SDK_ISR_EXIT_BARRIER;
285 }
286 #endif
287
288 #if defined(FLEXCOMM8)
289 void FLEXCOMM8_DriverIRQHandler(void);
FLEXCOMM8_DriverIRQHandler(void)290 void FLEXCOMM8_DriverIRQHandler(void)
291 {
292 uint32_t instance;
293
294 /* Look up instance number */
295 instance = FLEXCOMM_GetInstance(FLEXCOMM8);
296 assert(s_flexcommIrqHandler[instance] != NULL);
297 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
298 SDK_ISR_EXIT_BARRIER;
299 }
300 #endif
301
302 #if defined(FLEXCOMM9)
303 void FLEXCOMM9_DriverIRQHandler(void);
FLEXCOMM9_DriverIRQHandler(void)304 void FLEXCOMM9_DriverIRQHandler(void)
305 {
306 uint32_t instance;
307
308 /* Look up instance number */
309 instance = FLEXCOMM_GetInstance(FLEXCOMM9);
310 assert(s_flexcommIrqHandler[instance] != NULL);
311 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
312 SDK_ISR_EXIT_BARRIER;
313 }
314 #endif
315
316 #if defined(FLEXCOMM10)
317 void FLEXCOMM10_DriverIRQHandler(void);
FLEXCOMM10_DriverIRQHandler(void)318 void FLEXCOMM10_DriverIRQHandler(void)
319 {
320 uint32_t instance;
321
322 /* Look up instance number */
323 instance = FLEXCOMM_GetInstance(FLEXCOMM10);
324 assert(s_flexcommIrqHandler[instance] != NULL);
325 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
326 SDK_ISR_EXIT_BARRIER;
327 }
328 #endif
329
330 #if defined(FLEXCOMM11)
331 void FLEXCOMM11_DriverIRQHandler(void);
FLEXCOMM11_DriverIRQHandler(void)332 void FLEXCOMM11_DriverIRQHandler(void)
333 {
334 uint32_t instance;
335
336 /* Look up instance number */
337 instance = FLEXCOMM_GetInstance(FLEXCOMM11);
338 assert(s_flexcommIrqHandler[instance] != NULL);
339 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
340 SDK_ISR_EXIT_BARRIER;
341 }
342 #endif
343
344 #if defined(FLEXCOMM12)
345 void FLEXCOMM12_DriverIRQHandler(void);
FLEXCOMM12_DriverIRQHandler(void)346 void FLEXCOMM12_DriverIRQHandler(void)
347 {
348 uint32_t instance;
349
350 /* Look up instance number */
351 instance = FLEXCOMM_GetInstance(FLEXCOMM12);
352 assert(s_flexcommIrqHandler[instance] != NULL);
353 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
354 SDK_ISR_EXIT_BARRIER;
355 }
356 #endif
357
358 #if defined(FLEXCOMM13)
359 void FLEXCOMM13_DriverIRQHandler(void);
FLEXCOMM13_DriverIRQHandler(void)360 void FLEXCOMM13_DriverIRQHandler(void)
361 {
362 uint32_t instance;
363
364 /* Look up instance number */
365 instance = FLEXCOMM_GetInstance(FLEXCOMM13);
366 assert(s_flexcommIrqHandler[instance] != NULL);
367 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
368 SDK_ISR_EXIT_BARRIER;
369 }
370 #endif
371
372 #if defined(FLEXCOMM14)
373 void FLEXCOMM14_DriverIRQHandler(void);
FLEXCOMM14_DriverIRQHandler(void)374 void FLEXCOMM14_DriverIRQHandler(void)
375 {
376 uint32_t instance;
377
378 /* Look up instance number */
379 instance = FLEXCOMM_GetInstance(FLEXCOMM14);
380 assert(s_flexcommIrqHandler[instance] != NULL);
381 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
382 SDK_ISR_EXIT_BARRIER;
383 }
384 #endif
385
386 #if defined(FLEXCOMM15)
387 void FLEXCOMM15_DriverIRQHandler(void);
FLEXCOMM15_DriverIRQHandler(void)388 void FLEXCOMM15_DriverIRQHandler(void)
389 {
390 uint32_t instance;
391
392 /* Look up instance number */
393 instance = FLEXCOMM_GetInstance(FLEXCOMM15);
394 assert(s_flexcommIrqHandler[instance] != NULL);
395 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
396 SDK_ISR_EXIT_BARRIER;
397 }
398 #endif
399
400 #if defined(FLEXCOMM16)
401 void FLEXCOMM16_DriverIRQHandler(void);
FLEXCOMM16_DriverIRQHandler(void)402 void FLEXCOMM16_DriverIRQHandler(void)
403 {
404 uint32_t instance;
405
406 /* Look up instance number */
407 instance = FLEXCOMM_GetInstance(FLEXCOMM16);
408 assert(s_flexcommIrqHandler[instance] != NULL);
409 s_flexcommIrqHandler[instance]((uint32_t *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
410 SDK_ISR_EXIT_BARRIER;
411 }
412 #endif
413