1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes   <System Includes> , "Project Includes"
9  **********************************************************************************************************************/
10 #include "bsp_api.h"
11 
12 /** ELC event definitions. */
13 
14 /***********************************************************************************************************************
15  * Macro definitions
16  **********************************************************************************************************************/
17 #define BSP_IRQ_UINT32_MAX                       (0xFFFFFFFFU)
18 
19 #define BSP_PRV_CLEAR_REG_MAX                    (13U)
20 #define BSP_PRV_ALL_BIT_CLEAR                    (0xFFFFFFFFU)
21 
22 #define BSP_PRV_ID_MASK                          (0x000003FFU)
23 #define BSP_PRV_INTERRUPTABLE_NUM                (32U)
24 
25 #define BSP_PRV_ICFGR_EVENT_TYPE_SETTING_MASK    (0x3U)
26 #define BSP_PRV_ICFGR_EDGE_DETECTION_TYPE        (0x2U)
27 #define BSP_PRV_ICFGR_REG_FIELD_NUM              (16U)
28 #define BSP_PRV_ICFGR_FIELD_WIDTH_BITS           (2U)
29 
30 #define BSP_PRV_CR52_INTSEL_INIT                 (0x03FF03FFUL)
31 
32 /***********************************************************************************************************************
33  * Typedef definitions
34  **********************************************************************************************************************/
35 
36 /***********************************************************************************************************************
37  * Exported global variables (to be accessed by other files)
38  **********************************************************************************************************************/
39 #if VECTOR_DATA_IRQ_COUNT > 0
40 extern fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES];
41 #endif
42 extern fsp_vector_t g_sgi_ppi_vector_table[BSP_CORTEX_VECTOR_TABLE_ENTRIES];
43 
44 #if (0 == BSP_FEATURE_BSP_IRQ_CR52_SEL_SUPPORTED)
45 extern const uint32_t BSP_GICD_ICFGR_INIT[BSP_NON_SELECTABLE_ICFGR_MAX];
46 
47 #elif (1 == BSP_FEATURE_BSP_IRQ_CR52_SEL_SUPPORTED)
48 extern const uint32_t BSP_GICD_ICFGR_INIT[BSP_EVENT_ARRAY_NUM];
49 
50 #endif
51 
52 /* This table is used to store the context in the ISR. */
53 void * gp_renesas_isr_context[BSP_ICU_VECTOR_MAX_ENTRIES + BSP_CORTEX_VECTOR_TABLE_ENTRIES];
54 
55 /* GIC current interrupt ID and variable. */
56 IRQn_Type g_current_interrupt_num[BSP_PRV_INTERRUPTABLE_NUM];
57 uint8_t   g_current_interrupt_pointer = 0;
58 
59 const bsp_interrupt_event_t g_interrupt_event_link_select[BSP_ICU_VECTOR_MAX_ENTRIES] BSP_WEAK_REFERENCE =
60 {
61     (bsp_interrupt_event_t) 0
62 };
63 
64 /***********************************************************************************************************************
65  * Private global variables and functions
66  **********************************************************************************************************************/
67 #if (1 == BSP_FEATURE_BSP_IRQ_CR52_SEL_SUPPORTED)
68 
69 /*******************************************************************************************************************//**
70  * Set the events to CR52_SEL. Events can be set through the configurator.
71  *
72  **********************************************************************************************************************/
bsp_prv_cr52_sel_cfg(void)73 static void bsp_prv_cr52_sel_cfg (void)
74 {
75     for (uint32_t intsel_reg_num = 0;
76          intsel_reg_num < BSP_FEATURE_BSP_SELECTABLE_INTERRUPT_EVENT_NUM / 2U;
77          intsel_reg_num++)
78     {
79         /* Get interrupt number of SELECT0_IRQn */
80         uint32_t select0_irqx = (2U * intsel_reg_num) + BSP_FEATURE_BSP_SELECTABLE_INTERRUPT_START;
81         uint32_t select0_irqy = (2U * intsel_reg_num + 1U) + BSP_FEATURE_BSP_SELECTABLE_INTERRUPT_START;
82 
83         /* Get user-setting event number from vector_data.c */
84         uint32_t intselx = g_interrupt_event_link_select[select0_irqx];
85         uint32_t intsely = g_interrupt_event_link_select[select0_irqy];
86 
87         uint32_t intseln = BSP_PRV_CR52_INTSEL_INIT;
88 
89         /* 0 in g_interrupt_event_link_select indicates that either INTCPU0 event is registered
90          * or no event is registered. INTCPU0 is not a target of selected interrupt
91          * and does not appear as a value after 384 in the array.
92          * Therefore, 0 means that user registered no event in SELECT0_IRQn with FSP configurator. */
93         if (intselx != 0U)             // Set INTSELX of CR520_INTSELn register
94         {
95             intseln &= (intselx << R_ICU_NS_CR520_INTSEL_INTSELX_Pos) | R_ICU_NS_CR520_INTSEL_INTSELY_Msk;
96         }
97 
98         if (intsely != 0U)             // Set INTSELY of CR520_INTSELn register
99         {
100             intseln &= (intsely << R_ICU_NS_CR520_INTSEL_INTSELY_Pos) | R_ICU_NS_CR520_INTSEL_INTSELX_Msk;
101         }
102 
103  #if (0 == BSP_CFG_CORE_CR52)
104         R_ICU_NS->CR520_INTSEL[intsel_reg_num] = intseln;
105  #elif (1 == BSP_CFG_CORE_CR52)
106         R_ICU_NS->CR521_INTSEL[intsel_reg_num] = intseln;
107  #endif
108     }
109 }
110 
111 #endif
112 
113 #if (1 == BSP_FEATURE_BSP_IRQ_CR52_SEL_SUPPORTED)
114 
115 /*******************************************************************************************************************//**
116  * Identifies the event interrupt type of selected interrupts to be set in GICD_ICFGR.
117  *
118  * @param[in]  gicd_reg_num    Register number of GICD_ICFGR.
119  **********************************************************************************************************************/
bsp_prv_gicd_icfgr_set(uint32_t gicd_reg_num)120 static uint32_t bsp_prv_gicd_icfgr_set (uint32_t gicd_reg_num)
121 {
122     uint32_t gicd_reg_icfgr = 0;
123 
124     /* GICD_ICFGR sets 16 events per register */
125     for (uint32_t field_num = 0; field_num < BSP_PRV_ICFGR_REG_FIELD_NUM; field_num++)
126     {
127         bsp_interrupt_event_t event =
128             g_interrupt_event_link_select[gicd_reg_num * BSP_PRV_ICFGR_REG_FIELD_NUM + field_num];
129 
130         /* Identify the location in BSP_GICD_ICFGR_INIT where type of the event is stored */
131         uint32_t event_type_array_num   = event / BSP_PRV_ICFGR_REG_FIELD_NUM;
132         uint32_t event_type_array_shift = (event % BSP_PRV_ICFGR_REG_FIELD_NUM) * BSP_PRV_ICFGR_FIELD_WIDTH_BITS;
133 
134         /* 0 in g_interrupt_event_link_select indicates that either INTCPU0 event is registered
135          * or no event is registered. INTCPU0 is not a target of selected interrupt
136          * and does not appear as a value after 384 in the array.
137          * Therefore, 0 means that user registered no event in SELECT0_IRQn with FSP configurator. */
138         if (event != 0)
139         {
140             gicd_reg_icfgr |=
141                 ((BSP_GICD_ICFGR_INIT[event_type_array_num] >> event_type_array_shift) &
142                  BSP_PRV_ICFGR_EVENT_TYPE_SETTING_MASK) <<
143                     field_num * BSP_PRV_ICFGR_FIELD_WIDTH_BITS;
144         }
145         else
146         {
147             /* SELECT0_IRQn is level/edge type. Therefore, interrupt type is initialized by edge. */
148             gicd_reg_icfgr |= (BSP_PRV_ICFGR_EDGE_DETECTION_TYPE & BSP_PRV_ICFGR_EVENT_TYPE_SETTING_MASK) <<
149                               field_num * BSP_PRV_ICFGR_FIELD_WIDTH_BITS;
150         }
151     }
152 
153     return gicd_reg_icfgr;
154 }
155 
156 #endif
157 
158 /*******************************************************************************************************************//**
159  *        Using the vector table information section that has been built by the linker and placed into ROM in the
160  * .vector_info. section, this function will initialize the ICU so that configured ELC events will trigger interrupts
161  * in the NVIC.
162  *
163  **********************************************************************************************************************/
bsp_irq_core_cfg(void)164 void bsp_irq_core_cfg (void)
165 {
166     uint32_t                   gicd_reg_num;
167     GICD_Type                * GICD;
168     GICR_CONTROL_TARGET_Type * GICR_TARGET0_IFREG;
169 
170     GICD               = BSP_PRV_GICD_ADDRESS;
171     GICR_TARGET0_IFREG = BSP_PRV_GICR_TARGET0_IFREG_ADDRESS;
172 
173 #if (1 == BSP_FEATURE_BSP_IRQ_CR52_SEL_SUPPORTED)
174 
175     /* Set events to CR520_INTSELn */
176     bsp_prv_cr52_sel_cfg();
177 #endif
178 
179     /* Enable Group1 interrupts from the GIC Distributor to the GIC CPU interface. */
180     GICD->GICD_CTLR |= 0x00000002UL;
181 
182     /* Release Processor Sleep state of the target. */
183     GICR_TARGET0_IFREG->GICR_WAKER = 0x00000000UL;
184 
185     /* Initialize GICD_ICFGR register for the edge-triggered interrupt. */
186     for (gicd_reg_num = 0; gicd_reg_num < BSP_NON_SELECTABLE_ICFGR_MAX; gicd_reg_num++)
187     {
188         GICD->GICD_ICFGR[gicd_reg_num] = BSP_GICD_ICFGR_INIT[gicd_reg_num];
189     }
190 
191 #if (1 == BSP_FEATURE_BSP_IRQ_CR52_SEL_SUPPORTED)
192 
193     /* Initialize GICD_ICFGR register of SELECT0_IRQn interrupt. */
194     for (gicd_reg_num = BSP_NON_SELECTABLE_ICFGR_MAX; gicd_reg_num < BSP_ICFGR_MAX; gicd_reg_num++)
195     {
196         GICD->GICD_ICFGR[gicd_reg_num] = bsp_prv_gicd_icfgr_set(gicd_reg_num);
197     }
198 #endif
199 
200     /* Clear the Pending and Active bit for the all interrupts. */
201     for (gicd_reg_num = 0; gicd_reg_num < BSP_PRV_CLEAR_REG_MAX; gicd_reg_num++)
202     {
203         GICD->GICD_ICPENDR[gicd_reg_num]   = BSP_PRV_ALL_BIT_CLEAR;
204         GICD->GICD_ICACTIVER[gicd_reg_num] = BSP_PRV_ALL_BIT_CLEAR;
205     }
206 
207     __asm volatile ("cpsie i    \n"    /* Enable IRQ Interrupts */
208                     "cpsie f    \n"    /* Enable FIQ Interrupts */
209                     "cpsie a    \n"    /* Enable SError Interrupts */
210                     "isb");            /* Ensuring Context-changing */
211 }
212 
213 /*******************************************************************************************************************//**
214  * This function is called first when an interrupt is generated and branches to each interrupt isr function.
215  *
216  * @param[in]  id    GIC INTID used to identify the interrupt.
217  **********************************************************************************************************************/
bsp_common_interrupt_handler(uint32_t id)218 void bsp_common_interrupt_handler (uint32_t id)
219 {
220     uint16_t  gic_intid;
221     IRQn_Type irq;
222 
223     /* Get interrupt ID (GIC INTID). */
224     gic_intid = (uint16_t) (id & BSP_PRV_ID_MASK);
225 
226     irq = (IRQn_Type) (gic_intid - BSP_CORTEX_VECTOR_TABLE_ENTRIES);
227 
228     /* Remain the interrupt number */
229     g_current_interrupt_num[g_current_interrupt_pointer++] = irq;
230     __asm volatile ("dmb");
231 
232     BSP_CFG_TFU_SAVE_ENABLE;
233     BSP_CFG_MULTIPLEX_INTERRUPT_ENABLE;
234 
235 #if VECTOR_DATA_IRQ_COUNT > 0
236     if (BSP_CORTEX_VECTOR_TABLE_ENTRIES <= gic_intid)
237     {
238         /* Branch to an interrupt handler. */
239         g_vector_table[irq]();
240     }
241     else
242 #endif
243     {
244         /* Branch to an interrupt handler. */
245         g_sgi_ppi_vector_table[gic_intid]();
246     }
247 
248     g_current_interrupt_pointer--;
249 
250     BSP_CFG_MULTIPLEX_INTERRUPT_DISABLE;
251     BSP_CFG_TFU_RESTORE_ENABLE;
252 }
253