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