• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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