timer interrupts hopefully work now (pwm and isr not yet working!)
[my-code/arm.git] / betty / interrupts.c
1 /*
2  * interrupts.c - arm exception handling
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 #include "interrupts.h"
9 #include "functions.h"
10
11 // 'module global' interrupt variable
12 static t_interrupt interrupt;
13
14 /*
15  * functions
16  */
17
18 // generaal interrupt handling
19
20 void interrupt_init(void) {
21
22         interrupt.default_soft_callback=0;
23         VICSoftIntClr=0xffffffff;
24         VICIntEnClr=0xffffffff;
25         VICDefVectAddr=0;
26 }
27
28 void interrupt_set_default_callback(u32 callback_addr) {
29
30         VICDefVectAddr=callback_addr;
31 }
32
33 void interrupt_set_soft_callback(void (*callback)(void)) {
34
35         interrupt.default_soft_callback=callback;
36 }
37
38 void interrupt_set_fiq_callback(void (*callback)(void)) {
39
40         interrupt.fiq_callback=callback;
41 }
42
43 void interrupt_soft_clear(u8 src_number) {
44
45         VICSoftIntClr=(1<<src_number);
46 }
47 void interrupt_clear(u8 src_number) {
48
49         int cnt;
50         u32 *addr;
51         u32 *cntl;
52
53         VICIntEnClr=(1<<src_number);
54         VICIntSelect&=~(1<<src_number);
55
56         addr=(u32 *)&VICVectAddr0;
57         cntl=(u32 *)&VICVectCntl0;
58
59         for(cnt=0;cnt<INTERRUPT_MAX_VIC;cnt++) {
60                 if((cntl[cnt]&0x1f)==src_number) {
61                         *((volatile u32 *)(addr+cnt))=0;
62                         *((volatile u32 *)(cntl+cnt))=0;
63                 }
64         }
65 }
66
67 void interrupt_soft_enable(u8 src_number) {
68         
69         VICSoftInt=(1<<src_number);
70 }
71
72 int interrupt_enable(u8 src_number,u8 mode,u8 prio,u32 callback_addr) {
73
74         u32 *addr;
75         u32 *cntl;
76
77         addr=(u32 *)&VICVectAddr0;
78         cntl=(u32 *)&VICVectCntl0;
79
80         /* check whether this ir source is allready assigned */
81         if(VICIntEnable&(1<<src_number))
82                 return INTERRUPT_USED;
83
84         /* prepare depending on mode */
85         switch(mode) {
86                 case INTERRUPT_MODE_FIQ:
87                         VICIntSelect|=(1<<src_number);
88                         break;
89                 case INTERRUPT_MODE_VIRQ:
90                         if(addr[prio]&0x3f)
91                                 return INTERRUPT_PRIORITY_USED;
92                         *((volatile u32 *)(addr+prio))=callback_addr;
93                         *((volatile u32 *)(cntl+prio))=(src_number&0x1f)+0x20;
94                 case INTERRUPT_MODE_IRQ:
95                 default:
96                         break;
97         }
98
99         /* force interrupt */
100         VICIntEnable=(1<<src_number);
101
102         return INTERRUPT_SET;
103 }
104
105 int interrupt_change_callback(u8 src_number,u32 callback) {
106
107         int i;
108         u32 *addr,*cntl;
109
110         cntl=(u32 *)&VICVectCntl0;
111         addr=(u32 *)&VICVectAddr0;
112
113         i=0;
114         while(i<INTERRUPT_MAX_VIC) {
115                 if((*cntl&0x1f)==src_number) {
116                         *(addr+i)=callback;
117                         return INTERRUPT_CALLBACK_CHANGED;
118                 }
119                 i++;
120         }
121
122         return INTERRUPT_SRC_NOT_USED;
123 }
124
125 void interrupt_ack(void) {
126
127         VICVectAddr=0;
128 }
129
130 // specific interrupt handling
131
132 // external interrupts
133 void interrupt_ext_ir_config(u8 eint,u8 wakeup,u8 mode,u8 polarity) {
134
135         if(eint>3)
136                 return;
137
138         if(wakeup)
139                 EXTWAKE=(EXTWAKE&0xf)|(1<<eint);
140
141         EXTMODE=(EXTMODE&0xf)|(mode<<eint);
142         EXTPOLAR=(EXTPOLAR&0xf)|(polarity<<eint);
143 }
144
145 void interrupt_ext_ir_set(u8 eint) {
146
147         if(eint>3)
148                 return;
149
150         EXTINT=(1<<eint);
151 }
152
153 // timer counter interrupts
154 void interrupt_tc_config(u8 tcnum,u8 mode,u8 cap,u32 psv) {
155
156         if(tcnum>1)
157                 return;
158
159         if(tcnum==0) {
160                 T0TCR=0x03;
161                 T0TC=0;
162                 T0CTCR=mode|(cap<<2);
163                 T0PR=psv;
164         }
165         else {
166                 T1TCR=0x03;
167                 T1TC=0;
168                 T1CTCR=mode|(cap<<2);
169                 T1PR=psv;
170         }
171 }
172
173 void interrupt_tc_match_config(u8 tcnum,u8 mnum,u32 val,u8 mode) {
174
175         u32 *mraddr;
176
177         if(tcnum>1)
178                 return;
179
180         if(mnum>3)
181                 return;
182
183         if(tcnum==0) {
184                 T0MCR=(T0MCR&0x0fff)|(mode<<(3*mnum));
185                 mraddr=(u32 *)&T0MR0;
186         }
187         else {
188                 T1MCR=(T1MCR&0x0fff)|(mode<<(3*mnum));
189                 mraddr=(u32 *)&T1MR0;
190         }
191
192         *((volatile u32 *)(mraddr+mnum))=val;
193 }
194
195 void interrupt_tc_capt_config(u8 tcnum,u8 cnum,u8 mode) {
196
197         if(tcnum>1)
198                 return;
199
200         if(cnum>3)
201                 return;
202
203         if(tcnum==0)
204                 T0CCR=(T0CCR&0x0fff)|(mode<<(3*cnum));
205         else
206                 T1CCR=(T1CCR&0x0fff)|(mode<<(3*cnum));
207 }
208
209 void interrupt_tc_ir_set(u8 tcnum,u8 tcmc) {
210
211         if(tcnum>1)
212                 return;
213
214         if(tcnum==0) {
215                 T0IR=tcmc;
216                 T0TCR=0x01;
217         }
218         else {
219                 T1IR=tcmc;
220                 T1TCR=0x01;
221         }
222 }
223
224 // pwm interrupts
225 void interrupt_pwm_ir_set(u8 pwm_channel) {
226
227         PWMIR=(pwm_channel&0x0f)|((pwm_channel&0x70)<<4);
228 }
229
230 /*
231  * the actual exception handlers (as defined in startup.s)
232  */
233
234 // reset
235 void interrupt_handler_reset(void) {
236 }
237
238 // undefined instruction
239 void interrupt_handler_undef_instruction(void) {
240 }
241
242 // software interrupt
243 void interrupt_handler_soft_ir(void) {
244         
245         if(interrupt.default_soft_callback)
246                 interrupt.default_soft_callback();
247 }
248
249 // prefetch abort
250 void interrupt_handler_prefetch_abort(void) {
251 }
252
253 // data abort
254 void interrupt_handler_data_abort(void) {
255 }
256
257 // fiq
258 void interrupt_handler_fiq(void) {
259
260         if(interrupt.fiq_callback)
261                 interrupt.fiq_callback();
262 }
263