1 /*
2 *********************************************************************************************************
3 * AR100 SYSTEM
4 * AR100 Software System Develop Kits
5 * interrupt manager
6 *
7 * (c) Copyright 2012-2016, Sunny China
8 * All Rights Reserved
9 *
10 * File : interrupt_manager.c
11 * By : Sunny
12 * Version : v1.0
13 * Date : 2012-5-3
14 * Descript: the manager of interrupt.
15 * Update : date auther ver notes
16 * 2012-5-3 10:45:15 Sunny 1.0 Create this file.
17 *********************************************************************************************************
18 */
19
20 #include <irqs.h>
21
22 #include "intc_i.h"
23 #include "platform-intc.h"
24
25 s32 interrupt_clear_pending(u32 intno);
26
27 struct int_isr_node isr_table[SUNXI_RINTC_IRQ_SOURCE_MAX];
28
29 /*
30 *********************************************************************************************************
31 * INIT INTERRUPT MANAGER
32 *
33 * Description: initialize interrupt manager.
34 *
35 * Arguments : none.
36 *
37 * Returns : OK if initialize interrupt manager succeeded, others if failed.
38 *********************************************************************************************************
39 */
interrupt_init(void)40 s32 interrupt_init(void)
41 {
42 s32 index;
43
44 /*initialize interrupt controller */
45 intc_init();
46
47 /*initialize ISR table */
48 for (index = 0; index < SUNXI_RINTC_IRQ_SOURCE_MAX; index++) {
49 isr_table[index].pisr = isr_default;
50 isr_table[index].parg = NULL;
51 }
52
53 /*interrupt manager initialize succeeded */
54 return OK;
55 }
56
57 /*
58 *********************************************************************************************************
59 * EXIT INTERRUPT MANAGER
60 *
61 * Description: exit interrupt manager.
62 *
63 * Arguments : none.
64 *
65 * Returns : OK if exit interrupt manager succeeded, others if failed.
66 *********************************************************************************************************
67 */
interrupt_exit(void)68 s32 interrupt_exit(void)
69 {
70 intc_exit();
71
72 return OK;
73 }
74
75 /*
76 *********************************************************************************************************
77 * ENABLE INTERRUPT
78 *
79 * Description: enable a specific interrupt.
80 *
81 * Arguments : intno : the number of interrupt which we want to enable.
82 *
83 * Returns : OK if enable interrupt succeeded, others if failed.
84 *********************************************************************************************************
85 */
interrupt_enable(u32 intno)86 s32 interrupt_enable(u32 intno)
87 {
88 return intc_enable_interrupt(intno);
89 }
90
91 /*
92 *********************************************************************************************************
93 * DISABLE INTERRUPT
94 *
95 * Description: disable a specific interrupt.
96 *
97 * Arguments : intno : the number of interrupt which we want to disable.
98 *
99 * Returns : OK if disable interrupt succeeded, others if failed.
100 *********************************************************************************************************
101 */
interrupt_disable(u32 intno)102 s32 interrupt_disable(u32 intno)
103 {
104 return intc_disable_interrupt(intno);
105 }
106
107 /*
108 *********************************************************************************************************
109 * SET NMI TRIGGER
110 *
111 * Description: set nmi trigger.
112 *
113 * Arguments : type : the trigger type.
114 *
115 * Returns : OK if set trigger type succeeded, others if failed.
116 *********************************************************************************************************
117 */
interrupt_set_nmi_trigger(u32 type)118 s32 interrupt_set_nmi_trigger(u32 type)
119 {
120 u32 value;
121
122 pintc_regs->control = type;
123
124 /*mask cpus nmi irq */
125 value = pintc_regs->mask;
126 value |= 0x1;
127 pintc_regs->mask = value;
128
129 return OK;
130 }
131
interrupt_set_mask(u32 intno,u32 mask)132 s32 interrupt_set_mask(u32 intno, u32 mask)
133 {
134 return intc_set_mask(intno, mask);
135 }
136
interrupt_set_group_config(u32 grp_irq_num,u32 mask)137 s32 interrupt_set_group_config(u32 grp_irq_num, u32 mask)
138 {
139 return intc_set_group_config(grp_irq_num, mask);
140 }
141
142 /*
143 *********************************************************************************************************
144 * INSTALL ISR
145 *
146 * Description: install ISR for a specific interrupt.
147 *
148 * Arguments : intno : the number of interrupt which we want to install ISR.
149 * pisr : the ISR which to been install.
150 * parg : the argument for the ISR.
151 *
152 * Returns : OK if install ISR succeeded, others if failed.
153 *
154 * Note : the ISR execute entironment : CPU disable interrupt response.
155 *********************************************************************************************************
156 */
install_isr(u32 intno,__pISR_hdle_t pisr,void * parg)157 s32 install_isr(u32 intno, __pISR_hdle_t pisr, void *parg)
158 {
159 /*intno can't beyond then IRQ_SOURCE_MAX */
160 /* ASSERT(intno < IRQ_SOUCE_MAX); */
161
162 /*default isr, install directly */
163 isr_table[intno].pisr = pisr;
164 isr_table[intno].parg = parg;
165
166 return OK;
167 }
168
169 /*
170 *********************************************************************************************************
171 * UNINSTALL ISR
172 *
173 * Description: uninstall ISR for a specific interrupt.
174 *
175 * Arguments : intno : the number of interrupt which we want to uninstall ISR.
176 * pisr : the ISR which to been uninstall.
177 *
178 * Returns : OK if uninstall ISR succeeded, others if failed.
179 *********************************************************************************************************
180 */
uninstall_isr(u32 intno,__pISR_hdle_t pisr)181 s32 uninstall_isr(u32 intno, __pISR_hdle_t pisr)
182 {
183 /*intno can't beyond then IRQ_SOURCE_MAX */
184 /* ASSERT(intno < IRQ_SOUCE_MAX); */
185
186 if (isr_table[intno].pisr == pisr) {
187 /*uninstall isr */
188 isr_table[intno].pisr = isr_default;
189 isr_table[intno].parg = NULL;
190 } else {
191 /*
192 * don't support shared interrupt now,
193 * by sunny at 2012-5-3 11:20:28.
194 */
195 return -1;
196 }
197
198 return OK;
199 }
200
201 /*
202 *********************************************************************************************************
203 * INTERRUPT ENTRY
204 *
205 * Description: the entry of CPU IRQ, mainly for CPU IRQ exception.
206 *
207 * Arguments : none.
208 *
209 * Returns : OK if process CPU IRQ succeeded, others if failed.
210 *********************************************************************************************************
211 */
interrupt_entry(void)212 s32 interrupt_entry(void)
213 {
214 u32 intno = intc_get_current_interrupt();
215
216 /*intno can't beyond then IRQ_SOURCE_MAX */
217 /* ASSERT(intno < IRQ_SOUCE_MAX); */
218
219 /*
220 * process interrupt by call isr,
221 * not support shared intterrupt.
222 */
223 (isr_table[intno].pisr) (0, isr_table[intno].parg);
224
225 return OK;
226 }
227
interrupt_query_pending(u32 intno)228 s32 interrupt_query_pending(u32 intno)
229 {
230 volatile u32 pending;
231
232 if (intno <= 31)
233 pending = pintc_regs->pending & (1 << intno);
234 else if (intno > 31 && intno <= 63)
235 pending = pintc_regs->pending1 & (1 << (intno - 32));
236 else
237 pending = pintc_regs->pending2 & (1 << (intno - 64));
238 return pending;
239 }
240
interrupt_clear_pending(u32 intno)241 s32 interrupt_clear_pending(u32 intno)
242 {
243 if (intno <= 31)
244 pintc_regs->pending = (1 << intno);
245 else if (intno > 31 && intno <= 63)
246 pintc_regs->pending = (1 << (intno - 32));
247 else
248 pintc_regs->pending = (1 << (intno - 64));
249 return OK;
250 }
251
isr_default(int dummy,void * arg)252 s32 isr_default(int dummy, void *arg)
253 {
254 return true;
255 }
256
interrupt_get_current_intno(void)257 u32 interrupt_get_current_intno(void)
258 {
259 return intc_get_current_interrupt();
260 }
261
262 /*the backup of enable and mask register*/
263 u32 intc_enable[3];
264 u32 intc_mask[3];
265
interrupt_standby_enter(void)266 s32 interrupt_standby_enter(void)
267 {
268 /*backup registers */
269 intc_enable[0] = pintc_regs->enable;
270 intc_enable[1] = pintc_regs->enable1;
271 intc_enable[2] = pintc_regs->enable2;
272 intc_mask[0] = pintc_regs->mask;
273 intc_mask[1] = pintc_regs->mask1;
274 intc_mask[2] = pintc_regs->mask2;
275
276 /*disable all interrupt */
277 pintc_regs->enable = 0;
278 pintc_regs->enable1 = 0;
279 pintc_regs->enable2 = 0;
280 pintc_regs->mask = 0;
281 pintc_regs->mask1 = 0;
282 pintc_regs->mask2 = 0;
283
284 return OK;
285 }
286
interrupt_standby_exit(void)287 s32 interrupt_standby_exit(void)
288 {
289 /*clear standby pendings */
290 pintc_regs->pending = 0xffffffff;
291 pintc_regs->pending1 = 0xffffffff;
292 pintc_regs->pending2 = 0xffffffff;
293
294 /*restore registers */
295 pintc_regs->enable = intc_enable[0];
296 pintc_regs->enable1 = intc_enable[1];
297 pintc_regs->enable2 = intc_enable[2];
298 pintc_regs->mask = intc_mask[0];
299 pintc_regs->mask1 = intc_mask[1];
300 pintc_regs->mask2 = intc_mask[2];
301
302 return OK;
303 }
304