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_intmux.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.intmux"
18 #endif
19 
20 /*******************************************************************************
21  * Prototypes
22  ******************************************************************************/
23 
24 /*!
25  * @brief Get instance number for INTMUX.
26  *
27  * @param base INTMUX peripheral base address.
28  */
29 static uint32_t INTMUX_GetInstance(INTMUX_Type *base);
30 
31 #if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
32 /*!
33  * @brief Handle INTMUX all channels IRQ.
34  *
35  * The handler reads the INTMUX channel's active vector register. This returns the offset
36  * from the start of the vector table to the vector for the INTMUX channel's highest priority
37  * pending source interrupt. After a check for spurious interrupts (an offset of 0), the
38  * function address at the vector offset is read and jumped to.
39  *
40  * @param base INTMUX peripheral base address.
41  * @param channel INTMUX channel number.
42  */
43 static void INTMUX_CommonIRQHandler(INTMUX_Type *intmuxBase, uint32_t channel);
44 #endif
45 
46 /*******************************************************************************
47  * Variables
48  ******************************************************************************/
49 
50 /*! @brief Array to map INTMUX instance number to base pointer. */
51 static INTMUX_Type *const s_intmuxBases[] = INTMUX_BASE_PTRS;
52 
53 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
54 /*! @brief Array to map INTMUX instance number to clock name. */
55 static const clock_ip_name_t s_intmuxClockName[] = INTMUX_CLOCKS;
56 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
57 
58 #if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
59 /*! @brief Array to map INTMUX instance number to IRQ number. */
60 static const IRQn_Type s_intmuxIRQNumber[][FSL_FEATURE_INTMUX_CHANNEL_COUNT] = INTMUX_IRQS;
61 #endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
62 
63 /*******************************************************************************
64  * Code
65  ******************************************************************************/
66 
INTMUX_GetInstance(INTMUX_Type * base)67 static uint32_t INTMUX_GetInstance(INTMUX_Type *base)
68 {
69     uint32_t instance;
70 
71     /* Find the instance index from base address mappings. */
72     for (instance = 0; instance < ARRAY_SIZE(s_intmuxBases); instance++)
73     {
74         if (s_intmuxBases[instance] == base)
75         {
76             break;
77         }
78     }
79 
80     assert(instance < ARRAY_SIZE(s_intmuxBases));
81 
82     return instance;
83 }
84 
85 #if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
INTMUX_CommonIRQHandler(INTMUX_Type * intmuxBase,uint32_t channel)86 static void INTMUX_CommonIRQHandler(INTMUX_Type *intmuxBase, uint32_t channel)
87 {
88     uint32_t pendingIrqOffset;
89 
90     pendingIrqOffset = intmuxBase->CHANNEL[channel].CHn_VEC;
91     if (pendingIrqOffset != 0x00U)
92     {
93         uint32_t isr = *(uint32_t *)(SCB->VTOR + pendingIrqOffset);
94         ((void (*)(void))isr)();
95     }
96     SDK_ISR_EXIT_BARRIER;
97 }
98 #endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
99 
100 /*!
101  * brief Initializes the INTMUX module.
102  *
103  * This function enables the clock gate for the specified INTMUX. It then resets all channels, so that no
104  * interrupt sources are routed and the logic mode is set to default of #kINTMUX_ChannelLogicOR.
105  * Finally, the NVIC vectors for all the INTMUX output channels are enabled.
106  *
107  * param base INTMUX peripheral base address.
108  */
INTMUX_Init(INTMUX_Type * base)109 void INTMUX_Init(INTMUX_Type *base)
110 {
111     uint32_t channel;
112     uint32_t instance = INTMUX_GetInstance(base);
113 
114 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
115     /* Enable clock gate. */
116     (void)CLOCK_EnableClock(s_intmuxClockName[instance]);
117 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
118     /* Reset all channels and enable NVIC vectors for all INTMUX channels. */
119     for (channel = 0; channel < (uint32_t)FSL_FEATURE_INTMUX_CHANNEL_COUNT; channel++)
120     {
121         INTMUX_ResetChannel(base, channel);
122 #if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
123         NVIC_EnableIRQ(s_intmuxIRQNumber[instance][channel]);
124 #endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
125     }
126 }
127 
128 /*!
129  * brief Deinitializes an INTMUX instance for operation.
130  *
131  * The clock gate for the specified INTMUX is disabled and the NVIC vectors for all channels are disabled.
132  *
133  * param base INTMUX peripheral base address.
134  */
INTMUX_Deinit(INTMUX_Type * base)135 void INTMUX_Deinit(INTMUX_Type *base)
136 {
137     uint32_t channel;
138     uint32_t instance = INTMUX_GetInstance(base);
139 
140 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
141     /* Disable clock gate. */
142     (void)CLOCK_DisableClock(s_intmuxClockName[instance]);
143 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
144     /* Disable NVIC vectors for all of the INTMUX channels. */
145     for (channel = 0; channel < (uint32_t)FSL_FEATURE_INTMUX_CHANNEL_COUNT; channel++)
146     {
147 #if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
148         NVIC_DisableIRQ(s_intmuxIRQNumber[instance][channel]);
149 #endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
150     }
151 }
152 
153 #if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
154 #if defined(INTMUX0)
155 void INTMUX0_0_DriverIRQHandler(void);
INTMUX0_0_DriverIRQHandler(void)156 void INTMUX0_0_DriverIRQHandler(void)
157 {
158     INTMUX_CommonIRQHandler(INTMUX0, 0);
159 }
160 
161 void INTMUX0_1_DriverIRQHandler(void);
INTMUX0_1_DriverIRQHandler(void)162 void INTMUX0_1_DriverIRQHandler(void)
163 {
164     INTMUX_CommonIRQHandler(INTMUX0, 1);
165 }
166 
167 void INTMUX0_2_DriverIRQHandler(void);
INTMUX0_2_DriverIRQHandler(void)168 void INTMUX0_2_DriverIRQHandler(void)
169 {
170     INTMUX_CommonIRQHandler(INTMUX0, 2);
171 }
172 
173 void INTMUX0_3_DriverIRQHandler(void);
INTMUX0_3_DriverIRQHandler(void)174 void INTMUX0_3_DriverIRQHandler(void)
175 {
176     INTMUX_CommonIRQHandler(INTMUX0, 3);
177 }
178 
179 #if defined(FSL_FEATURE_INTMUX_CHANNEL_COUNT) && (FSL_FEATURE_INTMUX_CHANNEL_COUNT > 4U)
180 void INTMUX0_4_DriverIRQHandler(void);
INTMUX0_4_DriverIRQHandler(void)181 void INTMUX0_4_DriverIRQHandler(void)
182 {
183     INTMUX_CommonIRQHandler(INTMUX0, 4);
184 }
185 
186 void INTMUX0_5_DriverIRQHandler(void);
INTMUX0_5_DriverIRQHandler(void)187 void INTMUX0_5_DriverIRQHandler(void)
188 {
189     INTMUX_CommonIRQHandler(INTMUX0, 5);
190 }
191 
192 void INTMUX0_6_DriverIRQHandler(void);
INTMUX0_6_DriverIRQHandler(void)193 void INTMUX0_6_DriverIRQHandler(void)
194 {
195     INTMUX_CommonIRQHandler(INTMUX0, 6);
196 }
197 
198 void INTMUX0_7_DriverIRQHandler(void);
INTMUX0_7_DriverIRQHandler(void)199 void INTMUX0_7_DriverIRQHandler(void)
200 {
201     INTMUX_CommonIRQHandler(INTMUX0, 7);
202 }
203 #endif /* FSL_FEATURE_INTMUX_CHANNEL_COUNT */
204 
205 #endif
206 
207 #if defined(INTMUX1)
208 void INTMUX1_0_DriverIRQHandler(void);
INTMUX1_0_DriverIRQHandler(void)209 void INTMUX1_0_DriverIRQHandler(void)
210 {
211     INTMUX_CommonIRQHandler(INTMUX1, 0);
212 }
213 
214 void INTMUX1_1_DriverIRQHandler(void);
INTMUX1_1_DriverIRQHandler(void)215 void INTMUX1_1_DriverIRQHandler(void)
216 {
217     INTMUX_CommonIRQHandler(INTMUX1, 1);
218 }
219 
220 void INTMUX1_2_DriverIRQHandler(void);
INTMUX1_2_DriverIRQHandler(void)221 void INTMUX1_2_DriverIRQHandler(void)
222 {
223     INTMUX_CommonIRQHandler(INTMUX1, 2);
224 }
225 
226 void INTMUX1_3_DriverIRQHandler(void);
INTMUX1_3_DriverIRQHandler(void)227 void INTMUX1_3_DriverIRQHandler(void)
228 {
229     INTMUX_CommonIRQHandler(INTMUX1, 3);
230 }
231 
232 #if defined(FSL_FEATURE_INTMUX_CHANNEL_COUNT) && (FSL_FEATURE_INTMUX_CHANNEL_COUNT > 4U)
233 void INTMUX1_4_DriverIRQHandler(void);
INTMUX1_4_DriverIRQHandler(void)234 void INTMUX1_4_DriverIRQHandler(void)
235 {
236     INTMUX_CommonIRQHandler(INTMUX1, 4);
237 }
238 
239 void INTMUX1_5_DriverIRQHandler(void);
INTMUX1_5_DriverIRQHandler(void)240 void INTMUX1_5_DriverIRQHandler(void)
241 {
242     INTMUX_CommonIRQHandler(INTMUX1, 5);
243 }
244 
245 void INTMUX1_6_DriverIRQHandler(void);
INTMUX1_6_DriverIRQHandler(void)246 void INTMUX1_6_DriverIRQHandler(void)
247 {
248     INTMUX_CommonIRQHandler(INTMUX1, 6);
249 }
250 
251 void INTMUX1_7_DriverIRQHandler(void);
INTMUX1_7_DriverIRQHandler(void)252 void INTMUX1_7_DriverIRQHandler(void)
253 {
254     INTMUX_CommonIRQHandler(INTMUX1, 7);
255 }
256 #endif /* FSL_FEATURE_INTMUX_CHANNEL_COUNT */
257 #endif /* INTMUX1 */
258 #endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
259