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