1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017, 2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_irqsteer.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.irqsteer"
18 #endif
19
20 /*******************************************************************************
21 * Prototypes
22 ******************************************************************************/
23
24 /*!
25 * @brief Get instance number for IRQSTEER.
26 *
27 * @param base IRQSTEER peripheral base address.
28 */
29 static uint32_t IRQSTEER_GetInstance(IRQSTEER_Type *base);
30
31 /*******************************************************************************
32 * Variables
33 ******************************************************************************/
34
35 /*! @brief Array to map IRQSTEER instance number to base pointer. */
36 static IRQSTEER_Type *const s_irqsteerBases[] = IRQSTEER_BASE_PTRS;
37
38 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
39 /*! @brief Array to map IRQSTEER instance number to clock name. */
40 static const clock_ip_name_t s_irqsteerClockName[] = IRQSTEER_CLOCKS;
41 #endif
42
43 /*! @brief Array to map IRQSTEER instance number to IRQ number. */
44 static const IRQn_Type s_irqsteerIRQNumber[] = IRQSTEER_IRQS;
45
46 /*******************************************************************************
47 * Code
48 ******************************************************************************/
49
IRQSTEER_GetInstance(IRQSTEER_Type * base)50 static uint32_t IRQSTEER_GetInstance(IRQSTEER_Type *base)
51 {
52 uint32_t instance;
53
54 /* Find the instance index from base address mappings. */
55 for (instance = 0; instance < ARRAY_SIZE(s_irqsteerBases); instance++)
56 {
57 if (s_irqsteerBases[instance] == base)
58 {
59 break;
60 }
61 }
62
63 assert(instance < ARRAY_SIZE(s_irqsteerBases));
64
65 return instance;
66 }
67
68 /*!
69 * brief Initializes the IRQSTEER module.
70 *
71 * This function enables the clock gate for the specified IRQSTEER.
72 *
73 * param base IRQSTEER peripheral base address.
74 */
IRQSTEER_Init(IRQSTEER_Type * base)75 void IRQSTEER_Init(IRQSTEER_Type *base)
76 {
77 uint32_t i;
78 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
79 /* Enable clock. */
80 (void)CLOCK_EnableClock(s_irqsteerClockName[IRQSTEER_GetInstance(base)]);
81 #endif
82 /* Mask all interrupts. */
83 for (i = 0; i < (uint32_t)FSL_FEATURE_IRQSTEER_CHn_MASK_COUNT; i++)
84 {
85 base->CHn_MASK[i] &= ~IRQSTEER_CHn_MASK_MASKFLD_MASK;
86 }
87 /* Enable NVIC vectors for all IRQSTEER master. */
88 for (i = 0; i < (uint32_t)FSL_FEATURE_IRQSTEER_MASTER_COUNT; i++)
89 {
90 (void)EnableIRQ(s_irqsteerIRQNumber[i]);
91 }
92 }
93
94 /*!
95 * brief Deinitializes an IRQSTEER instance for operation.
96 *
97 * The clock gate for the specified IRQSTEER is disabled.
98 *
99 * param base IRQSTEER peripheral base address.
100 */
IRQSTEER_Deinit(IRQSTEER_Type * base)101 void IRQSTEER_Deinit(IRQSTEER_Type *base)
102 {
103 uint32_t master;
104 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
105 /* Disable clock. */
106 (void)CLOCK_DisableClock(s_irqsteerClockName[IRQSTEER_GetInstance(base)]);
107 #endif
108 /* Disable NVIC vectors for all IRQSTEER master. */
109 for (master = 0; master < (uint32_t)FSL_FEATURE_IRQSTEER_MASTER_COUNT; master++)
110 {
111 (void)DisableIRQ(s_irqsteerIRQNumber[master]);
112 }
113 }
114
115 /*!
116 * brief Gets the next interrupt source (currently set) of one specific master.
117 *
118 * param base IRQSTEER peripheral base address.
119 * param intMasterIndex Master index of interrupt sources. ref "irqsteer_int_master_t".
120 * return The current set next interrupt source number of one specific master.
121 * Return IRQSTEER_INT_Invalid if no interrupt set.
122 */
IRQSTEER_GetMasterNextInterrupt(IRQSTEER_Type * base,irqsteer_int_master_t intMasterIndex)123 IRQn_Type IRQSTEER_GetMasterNextInterrupt(IRQSTEER_Type *base, irqsteer_int_master_t intMasterIndex)
124 {
125 uint32_t regIndex = (uint32_t)FSL_FEATURE_IRQSTEER_CHn_MASK_COUNT - 1U - ((uint32_t)intMasterIndex) * 2U;
126 uint32_t bitOffset;
127 uint32_t irqNum;
128
129 bitOffset = __CLZ(__RBIT(base->CHn_STATUS[regIndex]));
130 /* When no result found, continue the loop to parse the next CHn_STATUS register. */
131 if (IRQSTEER_INT_SRC_REG_WIDTH == bitOffset)
132 {
133 regIndex--;
134 bitOffset = __CLZ(__RBIT(base->CHn_STATUS[regIndex]));
135 }
136
137 if (IRQSTEER_INT_SRC_REG_WIDTH == bitOffset)
138 {
139 return NotAvail_IRQn;
140 }
141 else
142 {
143 irqNum = (uint32_t)IRQSTEER_INT_SRC_NUM(regIndex, bitOffset) + (uint32_t)FSL_FEATURE_IRQSTEER_IRQ_START_INDEX;
144 return (IRQn_Type)irqNum;
145 }
146 }
147
IRQSTEER_CommonIRQHandler(IRQSTEER_Type * base,irqsteer_int_master_t intMasterIndex)148 static void IRQSTEER_CommonIRQHandler(IRQSTEER_Type *base, irqsteer_int_master_t intMasterIndex)
149 {
150 IRQn_Type intSource;
151 uint32_t isr;
152
153 intSource = IRQSTEER_GetMasterNextInterrupt(base, intMasterIndex);
154 if (NotAvail_IRQn != intSource)
155 {
156 isr = *(uint32_t *)(SCB->VTOR + (((uint32_t)intSource + 16UL) << 2U));
157
158 ((void (*)(void))isr)();
159 }
160 #if defined(FSL_FEATURE_EDMA_IRQSTEER_INTERRUPT_PATCH)
161 /*This is used for ESAI Interrupt IRQSTEER triggering*/
162 else
163 {
164 if ((intMasterIndex == 6) && ((base->CHn_MASK[2]) & 0x10))
165 {
166 isr = *(uint32_t *)(SCB->VTOR + (((uint32_t)ADMA_ESAI0_INT_IRQn + 16UL) << 2U));
167 ((void (*)(void))isr)();
168 }
169 }
170 #endif
171 SDK_ISR_EXIT_BARRIER;
172 }
173
174 void IRQSTEER_0_DriverIRQHandler(void);
IRQSTEER_0_DriverIRQHandler(void)175 void IRQSTEER_0_DriverIRQHandler(void)
176 {
177 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster0);
178 }
179
180 void IRQSTEER_1_DriverIRQHandler(void);
IRQSTEER_1_DriverIRQHandler(void)181 void IRQSTEER_1_DriverIRQHandler(void)
182 {
183 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster1);
184 }
185
186 void IRQSTEER_2_DriverIRQHandler(void);
IRQSTEER_2_DriverIRQHandler(void)187 void IRQSTEER_2_DriverIRQHandler(void)
188 {
189 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster2);
190 }
191
192 void IRQSTEER_3_DriverIRQHandler(void);
IRQSTEER_3_DriverIRQHandler(void)193 void IRQSTEER_3_DriverIRQHandler(void)
194 {
195 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster3);
196 }
197
198 void IRQSTEER_4_DriverIRQHandler(void);
IRQSTEER_4_DriverIRQHandler(void)199 void IRQSTEER_4_DriverIRQHandler(void)
200 {
201 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster4);
202 }
203
204 void IRQSTEER_5_DriverIRQHandler(void);
IRQSTEER_5_DriverIRQHandler(void)205 void IRQSTEER_5_DriverIRQHandler(void)
206 {
207 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster5);
208 }
209
210 void IRQSTEER_6_DriverIRQHandler(void);
IRQSTEER_6_DriverIRQHandler(void)211 void IRQSTEER_6_DriverIRQHandler(void)
212 {
213 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster6);
214 }
215
216 void IRQSTEER_7_DriverIRQHandler(void);
IRQSTEER_7_DriverIRQHandler(void)217 void IRQSTEER_7_DriverIRQHandler(void)
218 {
219 IRQSTEER_CommonIRQHandler(IRQSTEER, kIRQSTEER_InterruptMaster7);
220 }
221