2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
\r
3 * Copyright 2016-2019 NXP
\r
4 * All rights reserved.
\r
6 * SPDX-License-Identifier: BSD-3-Clause
\r
9 #include "fsl_common.h"
\r
10 #include "fsl_flexcomm.h"
\r
12 /*******************************************************************************
\r
14 ******************************************************************************/
\r
16 /* Component ID definition, used by tools. */
\r
17 #ifndef FSL_COMPONENT_ID
\r
18 #define FSL_COMPONENT_ID "platform.drivers.flexcomm"
\r
22 * @brief Used for conversion between `void*` and `uint32_t`.
\r
24 typedef union pvoid_to_u32
\r
30 /*******************************************************************************
\r
32 ******************************************************************************/
\r
33 /*! @brief Set the FLEXCOMM mode . */
\r
34 static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock);
\r
36 /*! @brief check whether flexcomm supports peripheral type */
\r
37 static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph);
\r
39 /*******************************************************************************
\r
41 ******************************************************************************/
\r
43 /*! @brief Pointers to real IRQ handlers installed by drivers for each instance. */
\r
44 static flexcomm_irq_handler_t s_flexcommIrqHandler[FSL_FEATURE_SOC_FLEXCOMM_COUNT];
\r
46 /*! @brief Pointers to handles for each instance to provide context to interrupt routines */
\r
47 static void *s_flexcommHandle[FSL_FEATURE_SOC_FLEXCOMM_COUNT];
\r
49 /*! @brief Array to map FLEXCOMM instance number to IRQ number. */
\r
50 IRQn_Type const kFlexcommIrqs[] = FLEXCOMM_IRQS;
\r
52 /*! @brief Array to map FLEXCOMM instance number to base address. */
\r
53 static const uint32_t s_flexcommBaseAddrs[FSL_FEATURE_SOC_FLEXCOMM_COUNT] = FLEXCOMM_BASE_ADDRS;
\r
55 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
\r
56 /*! @brief IDs of clock for each FLEXCOMM module */
\r
57 static const clock_ip_name_t s_flexcommClocks[] = FLEXCOMM_CLOCKS;
\r
58 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
\r
60 #if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
\r
61 /*! @brief Pointers to FLEXCOMM resets for each instance. */
\r
62 static const reset_ip_name_t s_flexcommResets[] = FLEXCOMM_RSTS;
\r
65 /*******************************************************************************
\r
67 ******************************************************************************/
\r
69 /* check whether flexcomm supports peripheral type */
\r
70 static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph)
\r
72 if (periph == FLEXCOMM_PERIPH_NONE)
\r
76 else if (periph <= FLEXCOMM_PERIPH_I2S_TX)
\r
78 return (base->PSELID & (1UL << ((uint32_t)periph + 3U))) > 0UL ? true : false;
\r
80 else if (periph == FLEXCOMM_PERIPH_I2S_RX)
\r
82 return (base->PSELID & (1U << 7U)) > (uint32_t)0U ? true : false;
\r
90 /* Get the index corresponding to the FLEXCOMM */
\r
91 /*! brief Returns instance number for FLEXCOMM module with given base address. */
\r
92 uint32_t FLEXCOMM_GetInstance(void *base)
\r
95 pvoid_to_u32_t BaseAddr;
\r
96 BaseAddr.pvoid = base;
\r
98 for (i = 0U; i < (uint32_t)FSL_FEATURE_SOC_FLEXCOMM_COUNT; i++)
\r
100 if (BaseAddr.u32 == s_flexcommBaseAddrs[i])
\r
106 assert(i < FSL_FEATURE_SOC_FLEXCOMM_COUNT);
\r
110 /* Changes FLEXCOMM mode */
\r
111 static status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock)
\r
113 /* Check whether peripheral type is present */
\r
114 if (!FLEXCOMM_PeripheralIsPresent(base, periph))
\r
116 return kStatus_OutOfRange;
\r
119 /* Flexcomm is locked to different peripheral type than expected */
\r
120 if (((base->PSELID & FLEXCOMM_PSELID_LOCK_MASK) != 0U) &&
\r
121 ((base->PSELID & FLEXCOMM_PSELID_PERSEL_MASK) != (uint32_t)periph))
\r
123 return kStatus_Fail;
\r
126 /* Check if we are asked to lock */
\r
129 base->PSELID = (uint32_t)periph | FLEXCOMM_PSELID_LOCK_MASK;
\r
133 base->PSELID = (uint32_t)periph;
\r
136 return kStatus_Success;
\r
139 /*! brief Initializes FLEXCOMM and selects peripheral mode according to the second parameter. */
\r
140 status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph)
\r
142 uint32_t idx = FLEXCOMM_GetInstance(base);
\r
144 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
\r
145 /* Enable the peripheral clock */
\r
146 CLOCK_EnableClock(s_flexcommClocks[idx]);
\r
147 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
\r
149 #if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
\r
150 /* Reset the FLEXCOMM module */
\r
151 RESET_PeripheralReset(s_flexcommResets[idx]);
\r
154 /* Set the FLEXCOMM to given peripheral */
\r
155 return FLEXCOMM_SetPeriph((FLEXCOMM_Type *)base, periph, 0);
\r
158 /*! brief Sets IRQ handler for given FLEXCOMM module. It is used by drivers register IRQ handler according to FLEXCOMM
\r
160 void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *handle)
\r
164 /* Look up instance number */
\r
165 instance = FLEXCOMM_GetInstance(base);
\r
167 /* Clear handler first to avoid execution of the handler with wrong handle */
\r
168 s_flexcommIrqHandler[instance] = NULL;
\r
169 s_flexcommHandle[instance] = handle;
\r
170 s_flexcommIrqHandler[instance] = handler;
\r
171 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
172 exception return operation might vector to incorrect interrupt */
\r
173 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
178 /* IRQ handler functions overloading weak symbols in the startup */
\r
179 #if defined(FLEXCOMM0)
\r
180 void FLEXCOMM0_DriverIRQHandler(void)
\r
182 assert(s_flexcommIrqHandler[0]);
\r
183 s_flexcommIrqHandler[0]((uint32_t *)s_flexcommBaseAddrs[0], s_flexcommHandle[0]);
\r
184 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
185 exception return operation might vector to incorrect interrupt */
\r
186 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
192 #if defined(FLEXCOMM1)
\r
193 void FLEXCOMM1_DriverIRQHandler(void)
\r
195 assert(s_flexcommIrqHandler[1]);
\r
196 s_flexcommIrqHandler[1]((uint32_t *)s_flexcommBaseAddrs[1], s_flexcommHandle[1]);
\r
197 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
198 exception return operation might vector to incorrect interrupt */
\r
199 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
205 #if defined(FLEXCOMM2)
\r
206 void FLEXCOMM2_DriverIRQHandler(void)
\r
208 assert(s_flexcommIrqHandler[2]);
\r
209 s_flexcommIrqHandler[2]((uint32_t *)s_flexcommBaseAddrs[2], s_flexcommHandle[2]);
\r
210 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
211 exception return operation might vector to incorrect interrupt */
\r
212 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
218 #if defined(FLEXCOMM3)
\r
219 void FLEXCOMM3_DriverIRQHandler(void)
\r
221 assert(s_flexcommIrqHandler[3]);
\r
222 s_flexcommIrqHandler[3]((uint32_t *)s_flexcommBaseAddrs[3], s_flexcommHandle[3]);
\r
223 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
224 exception return operation might vector to incorrect interrupt */
\r
225 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
231 #if defined(FLEXCOMM4)
\r
232 void FLEXCOMM4_DriverIRQHandler(void)
\r
234 assert(s_flexcommIrqHandler[4]);
\r
235 s_flexcommIrqHandler[4]((uint32_t *)s_flexcommBaseAddrs[4], s_flexcommHandle[4]);
\r
236 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
237 exception return operation might vector to incorrect interrupt */
\r
238 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
245 #if defined(FLEXCOMM5)
\r
246 void FLEXCOMM5_DriverIRQHandler(void)
\r
248 assert(s_flexcommIrqHandler[5]);
\r
249 s_flexcommIrqHandler[5]((uint32_t *)s_flexcommBaseAddrs[5], s_flexcommHandle[5]);
\r
250 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
251 exception return operation might vector to incorrect interrupt */
\r
252 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
258 #if defined(FLEXCOMM6)
\r
259 void FLEXCOMM6_DriverIRQHandler(void)
\r
261 assert(s_flexcommIrqHandler[6]);
\r
262 s_flexcommIrqHandler[6]((uint32_t *)s_flexcommBaseAddrs[6], s_flexcommHandle[6]);
\r
263 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
264 exception return operation might vector to incorrect interrupt */
\r
265 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
271 #if defined(FLEXCOMM7)
\r
272 void FLEXCOMM7_DriverIRQHandler(void)
\r
274 assert(s_flexcommIrqHandler[7]);
\r
275 s_flexcommIrqHandler[7]((uint32_t *)s_flexcommBaseAddrs[7], s_flexcommHandle[7]);
\r
276 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
277 exception return operation might vector to incorrect interrupt */
\r
278 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
284 #if defined(FLEXCOMM8)
\r
285 void FLEXCOMM8_DriverIRQHandler(void)
\r
287 assert(s_flexcommIrqHandler[8]);
\r
288 s_flexcommIrqHandler[8]((uint32_t *)s_flexcommBaseAddrs[8], s_flexcommHandle[8]);
\r
289 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
290 exception return operation might vector to incorrect interrupt */
\r
291 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
297 #if defined(FLEXCOMM9)
\r
298 void FLEXCOMM9_DriverIRQHandler(void)
\r
300 assert(s_flexcommIrqHandler[9]);
\r
301 s_flexcommIrqHandler[9]((uint32_t *)s_flexcommBaseAddrs[9], s_flexcommHandle[9]);
\r
302 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
303 exception return operation might vector to incorrect interrupt */
\r
304 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
310 #if defined(FLEXCOMM10)
\r
311 void FLEXCOMM10_DriverIRQHandler(void)
\r
313 assert(s_flexcommIrqHandler[10]);
\r
314 s_flexcommIrqHandler[10]((uint32_t *)s_flexcommBaseAddrs[10], s_flexcommHandle[10]);
\r
315 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
316 exception return operation might vector to incorrect interrupt */
\r
317 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
323 #if defined(FLEXCOMM11)
\r
324 void FLEXCOMM11_DriverIRQHandler(void)
\r
326 assert(s_flexcommIrqHandler[11]);
\r
327 s_flexcommIrqHandler[11]((uint32_t *)s_flexcommBaseAddrs[11], s_flexcommHandle[11]);
\r
328 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
329 exception return operation might vector to incorrect interrupt */
\r
330 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
336 #if defined(FLEXCOMM12)
\r
337 void FLEXCOMM12_DriverIRQHandler(void)
\r
339 assert(s_flexcommIrqHandler[12]);
\r
340 s_flexcommIrqHandler[12]((uint32_t *)s_flexcommBaseAddrs[12], s_flexcommHandle[12]);
\r
341 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
342 exception return operation might vector to incorrect interrupt */
\r
343 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
349 #if defined(FLEXCOMM13)
\r
350 void FLEXCOMM13_DriverIRQHandler(void)
\r
352 assert(s_flexcommIrqHandler[13]);
\r
353 s_flexcommIrqHandler[13]((uint32_t *)s_flexcommBaseAddrs[13], s_flexcommHandle[13]);
\r
354 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
355 exception return operation might vector to incorrect interrupt */
\r
356 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
362 #if defined(FLEXCOMM14)
\r
363 void FLEXCOMM14_DriverIRQHandler(void)
\r
367 /* Look up instance number */
\r
368 instance = FLEXCOMM_GetInstance(FLEXCOMM14);
\r
369 assert(s_flexcommIrqHandler[instance]);
\r
370 s_flexcommIrqHandler[instance]((void *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
\r
371 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
372 exception return operation might vector to incorrect interrupt */
\r
373 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
379 #if defined(FLEXCOMM15)
\r
380 void FLEXCOMM15_DriverIRQHandler(void)
\r
384 /* Look up instance number */
\r
385 instance = FLEXCOMM_GetInstance(FLEXCOMM15);
\r
386 assert(s_flexcommIrqHandler[instance]);
\r
387 s_flexcommIrqHandler[instance]((void *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
\r
388 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
389 exception return operation might vector to incorrect interrupt */
\r
390 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r
396 #if defined(FLEXCOMM16)
\r
397 void FLEXCOMM16_DriverIRQHandler(void)
\r
401 /* Look up instance number */
\r
402 instance = FLEXCOMM_GetInstance(FLEXCOMM16);
\r
403 assert(s_flexcommIrqHandler[instance]);
\r
404 s_flexcommIrqHandler[instance]((void *)s_flexcommBaseAddrs[instance], s_flexcommHandle[instance]);
\r
405 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
\r
406 exception return operation might vector to incorrect interrupt */
\r
407 #if defined __CORTEX_M && (__CORTEX_M == 4U)
\r