1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <stdint.h>
20 #include <soc.h>
21 #include <csi_core.h>
22 #include <csi_config.h>
23 #include <drv/common.h>
24 #if CONFIG_AOS_OSAL
25 #include <aos/kernel.h>
26 #endif
27
28 extern void Default_Handler(void);
29 extern uint32_t soc_irq_get_irq_num(void);
30 extern void soc_irq_end(uint32_t irq_num);
31
32 #if CONFIG_AOS_OSAL
33 #define CSI_INTRPT_ENTER() aos_kernel_intrpt_enter()
34 #define CSI_INTRPT_EXIT() aos_kernel_intrpt_exit()
35 #else
36 #ifdef CONFIG_KERNEL_FREERTOS
37 extern int freertos_intrpt_enter(void);
38 extern int freertos_intrpt_exit(void);
39 #define CSI_INTRPT_ENTER() freertos_intrpt_enter()
40 #define CSI_INTRPT_EXIT() freertos_intrpt_exit()
41 #elif defined(CONFIG_KERNEL_RTTHREAD)
42 extern void rt_interrupt_enter(void);
43 extern void rt_interrupt_leave(void);
44 #define CSI_INTRPT_ENTER() rt_interrupt_enter()
45 #define CSI_INTRPT_EXIT() rt_interrupt_leave()
46 #else
47 #define CSI_INTRPT_ENTER()
48 #define CSI_INTRPT_EXIT()
49 #endif
50 #endif /* end CONFIG_AOS_OSAL */
51
52 #if defined(CONFIG_SMP) && CONFIG_SMP
53 volatile uint32_t g_irq_nested_level[CONFIG_NR_CPUS];
54 #else
55 volatile uint32_t g_irq_nested_level;
56 #endif
57 csi_dev_t *g_irq_table[CONFIG_IRQ_NUM];
58
59 /**
60 \brief register irq handler(deprecated).
61 \param[in] irq_num Number of IRQ.
62 \return None.
63 */
csi_irq_attach(uint32_t irq_num,void * irq_handler,csi_dev_t * dev)64 void csi_irq_attach(uint32_t irq_num, void *irq_handler, csi_dev_t *dev)
65 {
66 dev->irq_handler = irq_handler;
67 g_irq_table[irq_num] = dev;
68 }
69
70 /**
71 \brief Attach irq handler2 for compatible(Recommended).
72 \param[in] irq_num Number of IRQ.
73 \param[in] irq_handler2 IRQ Handler.
74 \param[in] dev The dev to operate
75 \param[in] arg user data of irq_handler2
76 \return None.
77 */
csi_irq_attach2(uint32_t irq_num,void * irq_handler2,csi_dev_t * dev,void * arg)78 void csi_irq_attach2(uint32_t irq_num, void *irq_handler2, csi_dev_t *dev, void *arg)
79 {
80 dev->arg = arg;
81 dev->irq_handler2 = irq_handler2;
82 g_irq_table[irq_num] = dev;
83 }
84
85 /**
86 \brief unregister irq handler.
87 \param[in] irq_num Number of IRQ.
88 \param[in] irq_handler IRQ Handler.
89 \return None.
90 */
csi_irq_detach(uint32_t irq_num)91 void csi_irq_detach(uint32_t irq_num)
92 {
93 g_irq_table[irq_num] = NULL;
94 }
95
96 /**
97 \brief gets whether in irq context
98 \return true or false.
99 */
csi_irq_context(void)100 bool csi_irq_context(void)
101 {
102 #if defined(CONFIG_SMP) && CONFIG_SMP
103 return ((g_irq_nested_level[csi_get_cpu_id()] > 0U) ? true : false);
104 #else
105 return ((g_irq_nested_level > 0U) ? true : false);
106 #endif
107 }
108
109 #if CONFIG_CPU_XUANTIE_E9XX
110 static volatile int g_nmi_cnt;
handle_nmi_exception(void)111 __attribute__((weak)) void handle_nmi_exception(void)
112 {
113 g_nmi_cnt++;
114 #if CONFIG_SUPPORT_NMI_DEMO
115 extern void timer_clear_irq();
116 timer_clear_irq();
117 #endif
118 }
119 #else
120 //FIXME:
121 extern void tick_irq_handler(void *arg);
CORET_IRQHandler(void)122 void CORET_IRQHandler(void)
123 {
124 #if defined(CONFIG_SMP) && CONFIG_SMP
125 g_irq_nested_level[csi_get_cpu_id()]++;
126 #else
127 g_irq_nested_level++;
128 #endif
129 CSI_INTRPT_ENTER();
130 tick_irq_handler(NULL);
131 CSI_INTRPT_EXIT();
132 #if defined(CONFIG_SMP) && CONFIG_SMP
133 g_irq_nested_level[csi_get_cpu_id()]--;
134 #else
135 g_irq_nested_level--;
136 #endif
137 }
138 #endif /* CONFIG_CPU_XUANTIE_E9XX */
139
140 #if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_L2_ENABLE
141 static struct {
142 int err_cnt_l1;
143 int err_cnt_l2;
144 } g_ecc_stat;
145
ecc_l1_irqhandler(void * arg)146 void __attribute__((weak)) ecc_l1_irqhandler(void *arg)
147 {
148 g_ecc_stat.err_cnt_l1++;
149
150 if (!(__get_MCER() >> 31) || (__get_MCER() & (0x1 << 30))) {
151 /* may be ecc fatal error happens */
152 while (1);
153 } else {
154 /* clear MCER EE_VLD */
155 #if __riscv_xlen == 32
156 __set_MCER(0);
157 __set_MCERH(0);
158 #else
159 __set_MCER(0);
160 #endif
161 }
162 }
163
ecc_l2_irqhandler(void * arg)164 void __attribute__((weak)) ecc_l2_irqhandler(void *arg)
165 {
166 g_ecc_stat.err_cnt_l2++;
167
168 #if __riscv_xlen == 32
169 if((__get_MCER2H() >> 30) == 0x2) {
170 /* clear MCER EE_VLD */
171 __set_MCER2(0);
172 __set_MCER2H(0);
173 } else {
174 /* may be ecc fatal error happens */
175 while (1);
176 }
177 #else
178 if((__get_MCER2() >> 62) == 0x2) {
179 /* clear MCER EE_VLD */
180 __set_MCER2(0);
181 } else {
182 /* may be ecc fatal error happens */
183 while (1);
184 }
185 #endif
186 }
187
ECC_L1_IRQHandler(void)188 void ECC_L1_IRQHandler(void)
189 {
190 #if defined(CONFIG_SMP) && CONFIG_SMP
191 g_irq_nested_level[csi_get_cpu_id()]++;
192 #else
193 g_irq_nested_level++;
194 #endif
195 CSI_INTRPT_ENTER();
196 ecc_l1_irqhandler(NULL);
197 CSI_INTRPT_EXIT();
198 #if defined(CONFIG_SMP) && CONFIG_SMP
199 g_irq_nested_level[csi_get_cpu_id()]--;
200 #else
201 g_irq_nested_level--;
202 #endif
203 }
204
205 #endif
206 /**
207 \brief dispatching irq handlers(only handle external irq)
208 \return None.
209 */
do_irq(void)210 void do_irq(void)
211 {
212 uint32_t irqn;
213
214 #if defined(CONFIG_SMP) && CONFIG_SMP
215 g_irq_nested_level[csi_get_cpu_id()]++;
216 #else
217 g_irq_nested_level++;
218 #endif
219 CSI_INTRPT_ENTER();
220 irqn = soc_irq_get_irq_num();
221 if (g_irq_table[irqn]) {
222 if (g_irq_table[irqn]->irq_handler)
223 /* for compatibility */
224 g_irq_table[irqn]->irq_handler(g_irq_table[irqn]);
225 else if (g_irq_table[irqn]->irq_handler2)
226 g_irq_table[irqn]->irq_handler2(irqn, g_irq_table[irqn]->arg);
227 else
228 Default_Handler();
229 } else {
230 Default_Handler();
231 }
232 /* clear irq for cxx */
233 soc_irq_end(irqn);
234 CSI_INTRPT_EXIT();
235 #if defined(CONFIG_SMP) && CONFIG_SMP
236 g_irq_nested_level[csi_get_cpu_id()]--;
237 #else
238 g_irq_nested_level--;
239 #endif
240 }
241