added timer/counter interrupt support
[my-code/arm.git] / betty / interrupts.c
index e344f05..0e0baa3 100644 (file)
@@ -15,6 +15,8 @@ static t_interrupt interrupt;
  * functions
  */
 
+// generaal interrupt handling
+
 void interrupt_init(void) {
 
        interrupt.default_soft_callback=0;
@@ -33,6 +35,11 @@ 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);
@@ -62,7 +69,7 @@ void interrupt_soft_enable(u8 src_number) {
        VICSoftInt=(1<<src_number);
 }
 
-int interrupt_enable(u8 src_number,u8 mode,u8 priority,u32 callback_addr) {
+int interrupt_enable(u8 src_number,u8 mode,u8 prio,u32 callback_addr) {
 
        u32 *addr;
        u32 *cntl;
@@ -80,10 +87,10 @@ int interrupt_enable(u8 src_number,u8 mode,u8 priority,u32 callback_addr) {
                        VICIntSelect|=(1<<src_number);
                        break;
                case INTERRUPT_MODE_VIRQ:
-                       if(addr[priority]&0x3f)
+                       if(addr[prio]&0x3f)
                                return INTERRUPT_PRIORITY_USED;
-                       *((volatile u32 *)(addr+priority))=callback_addr;
-                       *((volatile u32 *)(cntl+priority))=(src_number&0x1f)+0x20;
+                       *((volatile u32 *)(addr+prio))=callback_addr;
+                       *((volatile u32 *)(cntl+prio))=(src_number&0x1f)+0x20;
                case INTERRUPT_MODE_IRQ:
                default:
                        break;
@@ -115,6 +122,14 @@ int interrupt_change_callback(u8 src_number,u32 callback) {
        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)
@@ -135,9 +150,69 @@ void interrupt_ext_ir_set(u8 eint) {
        EXTINT=(1<<eint);
 }
 
-void interrupt_ack(void) {
+// timer counter interrupts
+void interrupt_tc_config(u8 tcnum,u8 mode,u8 cap,u32 psc) {
 
-       VICVectAddr=0;
+       if(tcnum>1)
+               return;
+
+       if(tcnum==0) {
+               T0TCR=0x03;
+               T0CTCR=mode|(cap<<2);
+               T0PR=psc;
+       }
+       else {
+               T1TCR=0x03;
+               T1CTCR=mode|(cap<<2);
+               T1PR=psc;
+       }
+}
+
+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=mode<<(3*mnum);
+               mrddr=&T0MR0
+       }
+       else {
+               T1MCR=mode<<(3*mnum);
+               mrddr=&T1MR0
+       }
+
+       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=mode<<(3*cnum);
+       else
+               T1CCR=mode<<(3*cnum);
+}
+
+void interrupt_tc_ir_set(u8 tcnum,u8 tcmc) {
+
+       if(tcnum>1)
+               return;
+
+       if(tcnum==0)
+               T0IR=tcmc;
+       else
+               T1IR=tcmc;
 }
 
 /*
@@ -169,5 +244,8 @@ void interrupt_handler_data_abort(void) {
 
 // fiq
 void interrupt_handler_fiq(void) {
+
+       if(interrupt.fiq_callback)
+               interrupt.fiq_callback();
 }