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