*/
#include "interrupts.h"
+#include "functions.h"
+
+// 'module global' interrupt variable
+static t_interrupt interrupt;
/*
* functions
*/
-void interrupt_set_default_callback(void *callback) {
+// generaal interrupt handling
- VICDefVectAddr=(u32)callback;
-
+void interrupt_init(void) {
+
+ interrupt.default_soft_callback=0;
+ VICSoftIntClr=0xffffffff;
+ VICIntEnClr=0xffffffff;
+ VICDefVectAddr=0;
+}
+
+void interrupt_set_default_callback(u32 callback_addr) {
+
+ VICDefVectAddr=callback_addr;
+}
+
+void interrupt_set_soft_callback(void (*callback)(void)) {
+
+ interrupt.default_soft_callback=callback;
+}
+
+void interrupt_set_fiq_callback(void (*callback)(void)) {
+
+ interrupt.fiq_callback=callback;
}
+void interrupt_soft_clear(u8 src_number) {
+
+ VICSoftIntClr=(1<<src_number);
+}
void interrupt_clear(u8 src_number) {
+ int cnt;
+ u32 *addr;
+ u32 *cntl;
+
+ VICIntEnClr=(1<<src_number);
+ VICIntSelect&=~(1<<src_number);
+
+ addr=(u32 *)&VICVectAddr0;
+ cntl=(u32 *)&VICVectCntl0;
+
+ for(cnt=0;cnt<INTERRUPT_MAX_VIC;cnt++) {
+ if((cntl[cnt]&0x1f)==src_number) {
+ *((volatile u32 *)(addr+cnt))=0;
+ *((volatile u32 *)(cntl+cnt))=0;
+ }
+ }
+}
+
+void interrupt_soft_enable(u8 src_number) {
+
+ VICSoftInt=(1<<src_number);
}
-int interrupt_set(u8 src_number,u8 mode,u8 priority,void *callback) {
+int interrupt_enable(u8 src_number,u8 mode,u8 prio,u32 callback_addr) {
+
+ u32 *addr;
+ u32 *cntl;
+
+ addr=(u32 *)&VICVectAddr0;
+ cntl=(u32 *)&VICVectCntl0;
/* check whether this ir source is allready assigned */
- if(VICSoftInt&(1<<src_number))
- return INTERRUPT_EINUSE;
-
- /* force interrupt */
- VICSoftInt|=(1<<src_number);
- VICIntEnable|=(1<<src_number);
+ if(VICIntEnable&(1<<src_number))
+ return INTERRUPT_USED;
+ /* prepare depending on mode */
switch(mode) {
- case INTERRUPT_FIQ:
+ case INTERRUPT_MODE_FIQ:
VICIntSelect|=(1<<src_number);
break;
- case INTERRUPT_VIRQ:
- case INTERRUPT_IRQ:
- case default:
+ case INTERRUPT_MODE_VIRQ:
+ if(addr[prio]&0x3f)
+ return INTERRUPT_PRIORITY_USED;
+ *((volatile u32 *)(addr+prio))=callback_addr;
+ *((volatile u32 *)(cntl+prio))=(src_number&0x1f)+0x20;
+ case INTERRUPT_MODE_IRQ:
+ default:
+ break;
}
+ /* force interrupt */
+ VICIntEnable=(1<<src_number);
+
return INTERRUPT_SET;
}
+int interrupt_change_callback(u8 src_number,u32 callback) {
+
+ int i;
+ u32 *addr,*cntl;
+
+ cntl=(u32 *)&VICVectCntl0;
+ addr=(u32 *)&VICVectAddr0;
+
+ i=0;
+ while(i<INTERRUPT_MAX_VIC) {
+ if((*cntl&0x1f)==src_number) {
+ *(addr+i)=callback;
+ return INTERRUPT_CALLBACK_CHANGED;
+ }
+ i++;
+ }
+
+ return INTERRUPT_SRC_NOT_USED;
+}
+
+void interrupt_ack(void) {
+
+ VICVectAddr=0;
+}
+
+// specific interrupt handling
+
+// external interrupts
+void interrupt_ext_ir_config(u8 eint,u8 wakeup,u8 mode,u8 polarity) {
+
+ if(eint>3)
+ return;
+
+ if(wakeup)
+ EXTWAKE=(EXTWAKE&0xf)|(1<<eint);
+
+ EXTMODE=(EXTMODE&0xf)|(mode<<eint);
+ EXTPOLAR=(EXTPOLAR&0xf)|(polarity<<eint);
+}
+
+void interrupt_ext_ir_set(u8 eint) {
+
+ if(eint>3)
+ return;
+
+ EXTINT=(1<<eint);
+}
+
+// timer counter interrupts
+void interrupt_tc_config(u8 tcnum,u8 mode,u8 cap,u32 psv) {
+
+ if(tcnum>1)
+ return;
+
+ if(tcnum==0) {
+ T0TCR=0x03;
+ T0CTCR=mode|(cap<<2);
+ T0PR=psv;
+ }
+ else {
+ T1TCR=0x03;
+ T1CTCR=mode|(cap<<2);
+ T1PR=psv;
+ }
+}
+
+void interrupt_tc_match_config(u8 tcnum,u8 mnum,u32 val,u8 mode) {
+
+ u32 *mraddr;
+
+ if(tcnum>1)
+ return;
+
+ if(mnum>3)
+ return;
+
+ if(tcnum==0) {
+ T0MCR=(T0MCR&0x0fff)|(mode<<(3*mnum));
+ mraddr=(u32 *)&T0MR0;
+ }
+ else {
+ T1MCR=(T1MCR&0x0fff)|(mode<<(3*mnum));
+ mraddr=(u32 *)&T1MR0;
+ }
+
+ *((volatile u32 *)(mraddr+mnum))=val;
+}
+
+void interrupt_tc_capt_config(u8 tcnum,u8 cnum,u8 mode) {
+
+ if(tcnum>1)
+ return;
+
+ if(cnum>3)
+ return;
+
+ if(tcnum==0)
+ T0CCR=(T0CCR&0x0fff)|(mode<<(3*cnum));
+ else
+ T1CCR=(T1CCR&0x0fff)|(mode<<(3*cnum));
+}
+
+void interrupt_tc_ir_set(u8 tcnum,u8 tcmc) {
+
+ if(tcnum>1)
+ return;
+
+ if(tcnum==0) {
+ T0IR=tcmc;
+ T0TCR=0x01;
+ }
+ else {
+ T1IR=tcmc;
+ T1TCR=0x01;
+ }
+}
+
+// pwm interrupts
+void interrupt_pwm_ir_set(u8 pwm_channel) {
+
+ PWMIR=(pwm_channel&0x0f)|((pwm_channel&0x70)<<4);
+}
+
/*
* the actual exception handlers (as defined in startup.s)
*/
// software interrupt
void interrupt_handler_soft_ir(void) {
+
+ if(interrupt.default_soft_callback)
+ interrupt.default_soft_callback();
}
// prefetch abort
// fiq
void interrupt_handler_fiq(void) {
+
+ if(interrupt.fiq_callback)
+ interrupt.fiq_callback();
}