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