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