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