1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: Interrupt DRIVER
15 *
16 * Create: 2021-07-01
17 */
18 #include "chip_io.h"
19 #include "arch_encoding.h"
20 #include "vectors.h"
21 #include "arch_barrier.h"
22 #include "interrupt_handler.h"
23
24 /*lint -e40 -e571 -e718 -e737 -e746*/
int_set_irq_func(int32_t irq_id,isr_function func)25 uint32_t int_set_irq_func(int32_t irq_id, isr_function func)
26 {
27 ((isr_function *)(isr_get_ramexceptiontable_addr()))[irq_id] = func;
28
29 return 0;
30 }
31
int_set_priority_grouping(uint32_t priority_group)32 void int_set_priority_grouping(uint32_t priority_group)
33 {
34 UNUSED(priority_group);
35 }
36
int_get_priority_grouping(void)37 uint32_t int_get_priority_grouping(void)
38 {
39 return 0;
40 }
41
int_enable_irq(int32_t irq_id)42 void int_enable_irq(int32_t irq_id)
43 {
44 uint32_t irqorder;
45 uint32_t locien_offset;
46
47 // enable local interrupt 26 -31 by irq_id
48 if ((irq_id < RISCV_LOCAL_IRQ_VECTOR_CNT) && (irq_id >= RISCV_SYS_VECTOR_CNT)) {
49 irqorder = (uint32_t)irq_id;
50 set_csr(mie, ((uint32_t)1 << irqorder));
51 } else {
52 irqorder = (uint32_t)((irq_id - RISCV_LOCAL_IRQ_VECTOR_CNT) % LOCIEN_IRQ_NUM);
53 locien_offset = (uint32_t)((irq_id - RISCV_LOCAL_IRQ_VECTOR_CNT) / LOCIEN_IRQ_NUM);
54 switch (locien_offset) {
55 case EXTERNAL_INTERRUPT_GROUP0:
56 set_custom_csr(LOCIEN0, (uint32_t)((uint32_t)1 << irqorder));
57 break;
58 case EXTERNAL_INTERRUPT_GROUP1:
59 set_custom_csr(LOCIEN1, (uint32_t)((uint32_t)1 << irqorder));
60 break;
61 case EXTERNAL_INTERRUPT_GROUP2:
62 set_custom_csr(LOCIEN2, (uint32_t)((uint32_t)1 << irqorder));
63 break;
64 default:
65 break;
66 }
67 }
68 }
69
int_disable_irq(int32_t irq_id)70 void int_disable_irq(int32_t irq_id)
71 {
72 uint32_t irqorder;
73 uint32_t locien_offset;
74
75 // Disable local interrupt 26 -31 by irq_id
76 if ((irq_id < RISCV_LOCAL_IRQ_VECTOR_CNT) && (irq_id >= RISCV_SYS_VECTOR_CNT)) {
77 irqorder = (uint32_t)irq_id;
78 clear_csr(mie, ((uint32_t)1 << irqorder));
79 } else {
80 irqorder = (uint32_t)((irq_id - RISCV_LOCAL_IRQ_VECTOR_CNT) % LOCIEN_IRQ_NUM);
81 locien_offset = (uint32_t)((irq_id - RISCV_LOCAL_IRQ_VECTOR_CNT) / LOCIEN_IRQ_NUM);
82 switch (locien_offset) {
83 case EXTERNAL_INTERRUPT_GROUP0:
84 clear_custom_csr(LOCIEN0, ((uint32_t)1 << irqorder));
85 break;
86 case EXTERNAL_INTERRUPT_GROUP1:
87 clear_custom_csr(LOCIEN1, ((uint32_t)1 << irqorder));
88 break;
89 case EXTERNAL_INTERRUPT_GROUP2:
90 clear_custom_csr(LOCIEN2, ((uint32_t)1 << irqorder));
91 break;
92 default:
93 break;
94 }
95 }
96 int_clear_pending_irq(irq_id);
97 }
98
int_get_enable_irq(int32_t irq_id)99 uint32_t int_get_enable_irq(int32_t irq_id)
100 {
101 uint32_t irqorder;
102 uint32_t locien_offset;
103 uint32_t enable = 0;
104
105 if ((irq_id < RISCV_LOCAL_IRQ_VECTOR_CNT) && (irq_id >= RISCV_SYS_VECTOR_CNT)) {
106 irqorder = (uint32_t)irq_id;
107 enable = read_csr(mie) & (((uint32_t)1 << irqorder));
108 } else {
109 irqorder = (uint32_t)((irq_id - RISCV_LOCAL_IRQ_VECTOR_CNT) % LOCIEN_IRQ_NUM);
110 locien_offset = (uint32_t)((irq_id - RISCV_LOCAL_IRQ_VECTOR_CNT) / LOCIEN_IRQ_NUM);
111 switch (locien_offset) {
112 case EXTERNAL_INTERRUPT_GROUP0:
113 enable = read_custom_csr(LOCIEN0) & (((uint32_t)1 << irqorder));
114 break;
115 case EXTERNAL_INTERRUPT_GROUP1:
116 enable = read_custom_csr(LOCIEN1) & (((uint32_t)1 << irqorder));
117 break;
118 case EXTERNAL_INTERRUPT_GROUP2:
119 enable = read_custom_csr(LOCIEN2) & (((uint32_t)1 << irqorder));
120 break;
121 default:
122 break;
123 }
124 }
125 return enable;
126 }
127
int_get_pending_irq(int32_t irq_id)128 uint32_t int_get_pending_irq(int32_t irq_id)
129 {
130 UNUSED(irq_id);
131 return 0;
132 }
133
int_clear_pending_irq(int32_t irq_id)134 void int_clear_pending_irq(int32_t irq_id)
135 {
136 dsb();
137 write_custom_csr_val(LOCIPCLR, irq_id);
138 dsb();
139 }
140
int_set_pendind_irq(int32_t irq_id)141 void int_set_pendind_irq(int32_t irq_id)
142 {
143 UNUSED(irq_id);
144 }
145
int_get_active(int32_t irq_id)146 uint32_t int_get_active(int32_t irq_id)
147 {
148 UNUSED(irq_id);
149 return 0;
150 }
151
int_set_priority(int32_t irq_id,uint32_t priority)152 void int_set_priority(int32_t irq_id, uint32_t priority)
153 {
154 uint32_t irqorder;
155 uint32_t locipri_offset;
156
157 if (priority < INTERRUPT_PRIO_LOWEST || priority > INTERRUPT_PRIO_HIGHEST) {
158 return;
159 }
160
161 // set the priority of non-standard local interrupt
162 if (irq_id >= RISCV_SYS_VECTOR_CNT && irq_id < RISCV_VECTOR_CNT) {
163 irqorder = (uint32_t)((irq_id - RISCV_SYS_VECTOR_CNT) % LOCIPRI_IRQ_NUM);
164 locipri_offset = (uint32_t)((irq_id - RISCV_SYS_VECTOR_CNT) / LOCIPRI_IRQ_NUM);
165 switch (locipri_offset) {
166 case EXTERNAL_INTERRUPT_GROUP0:
167 set_custom_csr(LOCIPRI0, (uint32_t)(priority << (irqorder * LOCIPRI_IRQ_BITS)));
168 break;
169 case EXTERNAL_INTERRUPT_GROUP1:
170 set_custom_csr(LOCIPRI1, priority << (irqorder * LOCIPRI_IRQ_BITS));
171 break;
172 case EXTERNAL_INTERRUPT_GROUP2:
173 set_custom_csr(LOCIPRI2, priority << (irqorder * LOCIPRI_IRQ_BITS));
174 break;
175 case EXTERNAL_INTERRUPT_GROUP3:
176 set_custom_csr(LOCIPRI3, priority << (irqorder * LOCIPRI_IRQ_BITS));
177 break;
178 case EXTERNAL_INTERRUPT_GROUP4:
179 set_custom_csr(LOCIPRI4, priority << (irqorder * LOCIPRI_IRQ_BITS));
180 break;
181 case EXTERNAL_INTERRUPT_GROUP5:
182 set_custom_csr(LOCIPRI5, priority << (irqorder * LOCIPRI_IRQ_BITS));
183 break;
184 case EXTERNAL_INTERRUPT_GROUP6:
185 set_custom_csr(LOCIPRI6, priority << (irqorder * LOCIPRI_IRQ_BITS));
186 break;
187 case EXTERNAL_INTERRUPT_GROUP7:
188 set_custom_csr(LOCIPRI7, priority << (irqorder * LOCIPRI_IRQ_BITS));
189 break;
190 default:
191 break;
192 }
193 }
194 }
195
int_get_priority(int32_t irq_id)196 uint32_t int_get_priority(int32_t irq_id)
197 {
198 unsigned int irqorder;
199 uint32_t locipri_offset;
200 uint32_t priority = 0;
201
202 // get the priority of non-standard local interrupt
203 if (irq_id >= RISCV_SYS_VECTOR_CNT && irq_id < RISCV_VECTOR_CNT) {
204 irqorder = (uint32_t)((irq_id - RISCV_SYS_VECTOR_CNT) % LOCIPRI_IRQ_NUM);
205 locipri_offset = (uint32_t)((irq_id - RISCV_SYS_VECTOR_CNT) / LOCIPRI_IRQ_NUM);
206 switch (locipri_offset) {
207 case EXTERNAL_INTERRUPT_GROUP0:
208 priority = read_custom_csr(LOCIPRI0) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
209 break;
210 case EXTERNAL_INTERRUPT_GROUP1:
211 priority = read_custom_csr(LOCIPRI1) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
212 break;
213 case EXTERNAL_INTERRUPT_GROUP2:
214 priority = read_custom_csr(LOCIPRI2) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
215 break;
216 case EXTERNAL_INTERRUPT_GROUP3:
217 priority = read_custom_csr(LOCIPRI3) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
218 break;
219 case EXTERNAL_INTERRUPT_GROUP4:
220 priority = read_custom_csr(LOCIPRI4) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
221 break;
222 case EXTERNAL_INTERRUPT_GROUP5:
223 priority = read_custom_csr(LOCIPRI5) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
224 break;
225 case EXTERNAL_INTERRUPT_GROUP6:
226 priority = read_custom_csr(LOCIPRI6) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
227 break;
228 case EXTERNAL_INTERRUPT_GROUP7:
229 priority = read_custom_csr(LOCIPRI7) & ((uint32_t)0x3 << (irqorder * LOCIPRI_IRQ_BITS));
230 break;
231 default:
232 break;
233 }
234 }
235
236 return priority;
237 }
238
int_system_reset(void)239 void int_system_reset(void)
240 {
241 }
242
int_set_default_priority(void)243 static void int_set_default_priority(void)
244 {
245 write_custom_csr_val(LOCIPRI0, LOCIPRI_DEFAULT_VAL);
246 write_custom_csr_val(LOCIPRI1, LOCIPRI_DEFAULT_VAL);
247 write_custom_csr_val(LOCIPRI2, LOCIPRI_DEFAULT_VAL);
248 write_custom_csr_val(LOCIPRI3, LOCIPRI_DEFAULT_VAL);
249 write_custom_csr_val(LOCIPRI4, LOCIPRI_DEFAULT_VAL);
250 write_custom_csr_val(LOCIPRI5, LOCIPRI_DEFAULT_VAL);
251 write_custom_csr_val(LOCIPRI6, LOCIPRI_DEFAULT_VAL);
252 write_custom_csr_val(LOCIPRI7, LOCIPRI_DEFAULT_VAL);
253 write_custom_csr_val(LOCIPRI8, LOCIPRI_DEFAULT_VAL);
254 write_custom_csr_val(LOCIPRI9, LOCIPRI_DEFAULT_VAL);
255 write_custom_csr_val(LOCIPRI10, LOCIPRI_DEFAULT_VAL);
256 write_custom_csr_val(LOCIPRI11, LOCIPRI_DEFAULT_VAL);
257 write_custom_csr_val(LOCIPRI12, LOCIPRI_DEFAULT_VAL);
258 write_custom_csr_val(LOCIPRI13, LOCIPRI_DEFAULT_VAL);
259 write_custom_csr_val(LOCIPRI14, LOCIPRI_DEFAULT_VAL);
260 write_custom_csr_val(LOCIPRI15, LOCIPRI_DEFAULT_VAL);
261 }
262
int_setup(void)263 void int_setup(void)
264 {
265 set_csr(mstatus, MSTATUS_MIE);
266 int_set_default_priority();
267 }
268
int_is_interrupt_context(void)269 bool int_is_interrupt_context(void)
270 {
271 return (interrupt_number_get() > 0);
272 }
273
int_get_current_irqn(void)274 int32_t int_get_current_irqn(void)
275 {
276 return (int32_t)(interrupt_number_get());
277 }
278
int_get_current_priority(void)279 int32_t int_get_current_priority(void)
280 {
281 return (int32_t)(int_get_priority(int_get_current_irqn()));
282 }
283