#include "interrupt.h"

#define VICBASE	0xFFFFF000

#define IRQStatus	0x00
#define FIQStatus	0x04
#define RawIntr		0x08
#define IntSelect	0x0c
#define IntEnable	0x10
#define IntEnClr	0x14
#define SoftInt		0x18
#define SoftIntClear	0x1c
#define Protection	0x20
#define VectAddr	0x30
#define DefVectAddr	0x34
#define VectAddr0	0x100
#define VectAddr1	0x104
#define VectAddr2	0x108
#define VectAddr3	0x10c
#define VectAddr4	0x110
#define VectAddr5	0x114
#define VectAddr6	0x118
#define VectAddr7	0x11c
#define VectAddr8	0x120
#define VectAddr9	0x124
#define VectAddr10	0x128
#define VectAddr11	0x12c
#define VectAddr12	0x130
#define VectAddr13	0x134
#define VectAddr14	0x138
#define VectAddr15	0x13c
#define VectCntl0	0x200
#define VectCntl1	0x204
#define VectCntl2	0x208
#define VectCntl3	0x20c
#define VectCntl4	0x210
#define VectCntl5	0x214
#define VectCntl6	0x218
#define VectCntl7	0x21c
#define VectCntl8	0x220
#define VectCntl9	0x224
#define VectCntl10	0x228
#define VectCntl11	0x22c
#define VectCntl12	0x230
#define VectCntl13	0x234
#define VectCntl14	0x238
#define VectCntl15	0x23c

#define VWREG(x) (((volatile unsigned int *)VICBASE)[(x)/sizeof(unsigned int)])
#define VADDRREG(x) VWREG(VectAddr0 + (x) * 4)
#define VCNTLREG(x) VWREG(VectCntl0 + (x) * 4)

#define IRQslot_en (1<<5)


void __attribute__((interrupt("IRQ"))) interrupt_default_handler(void);


void init_interrupt(void)
{
	VWREG(IntSelect) = 0;
	VWREG(IntEnable) = 0;
	VWREG(DefVectAddr) = (unsigned int) &interrupt_default_handler;
}

void __attribute__((interrupt("IRQ"))) interrupt_default_handler(void)
{
	/* Do nothing. Assume that if there is a genuine interrupt
	 * request that it will be asserted again soon.
	 */
	interrupt_clear();
}


/* Call as interrupt_register(SOURCE, fn) */

void interrupt_register_code(unsigned int source, unsigned int priority,
			     void(*handler)(void))
{
	VADDRREG(priority) = (unsigned int) handler;
	VCNTLREG(priority) = source | IRQslot_en;
	VWREG(IntEnable) |= (1<<source);
}

