88 lines
2.5 KiB
C
88 lines
2.5 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "omap35x_intc.h"
|
|
#include "cortexa8.h"
|
|
|
|
static volatile uint32_t *const intc_sysconfig = (uint32_t*)0x48200010;
|
|
static volatile uint32_t *const intc_idle = (uint32_t*)0x48200050;
|
|
static volatile uint32_t *const intc_mir_clear0 = (uint32_t*)0x48200088;
|
|
static volatile uint32_t *const intc_mir_clear1 = (uint32_t*)0x482000a8;
|
|
static volatile uint32_t *const intc_mir_clear2 = (uint32_t*)0x482000c8;
|
|
static volatile uint32_t *const intc_mir_set0 = (uint32_t*)0x4820008c;
|
|
static volatile uint32_t *const intc_mir_set1 = (uint32_t*)0x482000ac;
|
|
static volatile uint32_t *const intc_mir_set2 = (uint32_t*)0x482000cc;
|
|
static volatile uint32_t *const intc_sir_irq = (uint32_t*)0x48200040;
|
|
static volatile uint32_t *const intc_control = (uint32_t*)0x48200048;
|
|
static volatile uint32_t *const intc_ilr = (uint32_t*)0x48200100; // 96 words
|
|
|
|
static omap35x_intc_hfunc handler_tbl[96];
|
|
static void* handler_data[96];
|
|
|
|
void omap35x_intc_init() {
|
|
// Interrupts should (still) be disabled from boot
|
|
assert(!cortexa8_get_int());
|
|
|
|
memset(handler_tbl, 0, sizeof(omap35x_intc_hfunc)*96);
|
|
|
|
*intc_sysconfig = 0x1; // Autoidle = 1
|
|
*intc_idle = 0x2; // Turbo = 1, Funcidle = 0
|
|
|
|
// Disable all ints
|
|
*intc_mir_set0 = 0xffffffff;
|
|
*intc_mir_set1 = 0xffffffff;
|
|
*intc_mir_set2 = 0xffffffff;
|
|
}
|
|
|
|
void omap35x_intc_register(int irq, omap35x_intc_hfunc handler, void *data, int prio) {
|
|
assert(irq >= 0 && irq <= 95);
|
|
assert(prio >= 0 && prio <= 63);
|
|
|
|
handler_tbl[irq] = handler;
|
|
handler_data[irq] = data;
|
|
intc_ilr[irq] = prio<<2;
|
|
}
|
|
|
|
void omap35x_intc_ena(int irq) {
|
|
assert(irq >= 0 && irq <= 95);
|
|
assert(handler_tbl[irq] != NULL);
|
|
int i = irq/32, j = irq%32;
|
|
if(i == 0)
|
|
*intc_mir_clear0 = (1<<j);
|
|
else if(i == 1)
|
|
*intc_mir_clear1 = (1<<j);
|
|
else //if(i == 2)
|
|
*intc_mir_clear2 = (1<<j);
|
|
}
|
|
|
|
void omap35x_intc_dis(int irq) {
|
|
assert(irq >= 0 && irq <= 95);
|
|
int i = irq/32, j = irq%32;
|
|
if(i == 0)
|
|
*intc_mir_set0 = (1<<j);
|
|
else if(i == 1)
|
|
*intc_mir_set1 = (1<<j);
|
|
else //if(i == 2)
|
|
*intc_mir_set2 = (1<<j);
|
|
}
|
|
|
|
void omap35x_intc_handler() __attribute__((interrupt ("IRQ")));
|
|
void omap35x_intc_handler() {
|
|
uint32_t sir = *intc_sir_irq;
|
|
int irq = sir&0x7f;
|
|
|
|
if(sir&0xffffff80) {
|
|
printf("WARNING: Spurious interrupt (%.8lx)\n", sir);
|
|
return;
|
|
}
|
|
|
|
assert(irq >= 0 && irq <= 95);
|
|
assert(handler_tbl[irq] != NULL);
|
|
|
|
handler_tbl[irq](handler_data[irq]);
|
|
|
|
*intc_control = 0x1;
|
|
__asm__ __volatile__ ("dsb");
|
|
}
|