From 60efd38bbea318292502c398d41ba3c1044bbb0c Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Thu, 5 Jul 2007 07:14:24 +0000 Subject: Gigabeat: Use vectored IRQ mode interrupts and add a trap for unhandled ones. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13792 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/s3c2440.h | 83 +++++++++++++++ firmware/kernel.c | 10 +- firmware/target/arm/crt0.S | 8 -- .../target/arm/s3c2440/gigabeat-fx/system-meg-fx.c | 115 +++++++++++++++------ 4 files changed, 174 insertions(+), 42 deletions(-) (limited to 'firmware') diff --git a/firmware/export/s3c2440.h b/firmware/export/s3c2440.h index 4a799da3e2..72c33e227c 100644 --- a/firmware/export/s3c2440.h +++ b/firmware/export/s3c2440.h @@ -16,6 +16,8 @@ * KIND, either express or implied. * ****************************************************************************/ +#ifndef __S3C2440_H__ +#define __S3C2440_H__ /* Memory Controllers */ @@ -74,6 +76,86 @@ #define SUBSRCPND (*(volatile int *)0x4A000018) /* Sub source pending */ #define INTSUBMSK (*(volatile int *)0x4A00001C) /* Interrupt sub mask */ +/* Interrupt indexes - INTOFFSET - IRQ mode only */ +/* Arbiter 5 => Arbiter 6 Req 5 */ +#define ADC_OFFSET 31 /* REQ4 */ +#define RTC_OFFSET 30 /* REQ3 */ +#define SPI1_OFFSET 29 /* REQ2 */ +#define UART0_OFFSET 28 /* REQ1 */ +/* Arbiter 4 => Arbiter 6 Req 4 */ +#define IIC_OFFSET 27 /* REQ5 */ +#define USBH_OFFSET 26 /* REQ4 */ +#define USBD_OFFSET 25 /* REQ3 */ +#define NFCON_OFFSET 24 /* REQ2 */ +#define UART1_OFFSET 23 /* REQ1 */ +#define SPI0_OFFSET 22 /* REQ0 */ +/* Arbiter 3 => Arbiter 6 Req 3 */ +#define SDI_OFFSET 21 /* REQ5 */ +#define DMA3_OFFSET 20 /* REQ4 */ +#define DMA2_OFFSET 19 /* REQ3 */ +#define DMA1_OFFSET 18 /* REQ2 */ +#define DMA0_OFFSET 17 /* REQ1 */ +#define LCD_OFFSET 16 /* REQ0 */ +/* Arbiter 2 => Arbiter 6 Req 2 */ +#define UART2_OFFSET 15 /* REQ5 */ +#define TIMER4_OFFSET 14 /* REQ4 */ +#define TIMER3_OFFSET 13 /* REQ3 */ +#define TIMER2_OFFSET 12 /* REQ2 */ +#define TIMER1_OFFSET 11 /* REQ1 */ +#define TIMER0_OFFSET 10 /* REQ0 */ +/* Arbiter 1 => Arbiter 6 Req 1 */ +#define WDT_AC97_OFFSET 9 /* REQ5 */ +#define TICK_OFFSET 8 /* REQ4 */ +#define nBATT_FLT_OFFSET 7 /* REQ3 */ +#define CAM_OFFSET 6 /* REQ2 */ +#define EINT8_23_OFFSET 5 /* REQ1 */ +#define EINT4_7_OFFSET 4 /* REQ0 */ +/* Arbiter 0 => Arbiter 6 Req 0 */ +#define EINT3_OFFSET 3 /* REQ4 */ +#define EINT2_OFFSET 2 /* REQ3 */ +#define EINT1_OFFSET 1 /* REQ2 */ +#define EINT0_OFFSET 0 /* REQ1 */ + +/* Interrupt bitmasks - SRCPND, INTMOD, INTMSK, INTPND */ +/* Arbiter 5 => Arbiter 6 Req 5 */ +#define ADC_MASK (1 << 31) /* REQ4 */ +#define RTC_MASK (1 << 30) /* REQ3 */ +#define SPI1_MASK (1 << 29) /* REQ2 */ +#define UART0_MASK (1 << 28) /* REQ1 */ +/* Arbiter 4 => Arbiter 6 Req 4 */ +#define IIC_MASK (1 << 27) /* REQ5 */ +#define USBH_MASK (1 << 26) /* REQ4 */ +#define USBD_MASK (1 << 25) /* REQ3 */ +#define NFCON_MASK (1 << 24) /* REQ2 */ +#define UART1_MASK (1 << 23) /* REQ1 */ +#define SPI0_MASK (1 << 22) /* REQ0 */ +/* Arbiter 3 => Arbiter 6 Req 3 */ +#define SDI_MASK (1 << 21) /* REQ5 */ +#define DMA3_MASK (1 << 20) /* REQ4 */ +#define DMA2_MASK (1 << 19) /* REQ3 */ +#define DMA1_MASK (1 << 18) /* REQ2 */ +#define DMA0_MASK (1 << 17) /* REQ1 */ +#define LCD_MASK (1 << 16) /* REQ0 */ +/* Arbiter 2 => Arbiter 6 Req 2 */ +#define UART2_MASK (1 << 15) /* REQ5 */ +#define TIMER4_MASK (1 << 14) /* REQ4 */ +#define TIMER3_MASK (1 << 13) /* REQ3 */ +#define TIMER2_MASK (1 << 12) /* REQ2 */ +#define TIMER1_MASK (1 << 11) /* REQ1 */ +#define TIMER0_MASK (1 << 10) /* REQ0 */ +/* Arbiter 1 => Arbiter 6 Req 1 */ +#define WDT_AC97_MASK (1 << 9) /* REQ5 */ +#define TICK_MASK (1 << 8) /* REQ4 */ +#define nBATT_FLT_MASK (1 << 7) /* REQ3 */ +#define CAM_MASK (1 << 6) /* REQ2 */ +#define EINT8_23_MASK (1 << 5) /* REQ1 */ +#define EINT4_7_MASK (1 << 4) /* REQ0 */ +/* Arbiter 0 => Arbiter 6 Req 0 */ +#define EINT3_MASK (1 << 3) /* REQ4 */ +#define EINT2_MASK (1 << 2) /* REQ3 */ +#define EINT1_MASK (1 << 1) /* REQ2 */ +#define EINT0_MASK (1 << 0) /* REQ1 */ + /* DMA */ #define DISRC0 (*(volatile int *)0x4B000000) /* DMA 0 initial source */ @@ -465,3 +547,4 @@ #define DRAM1 0x31000000 #define BOOTRAM 0x40000000 +#endif /* __S3C2440_H__ */ diff --git a/firmware/kernel.c b/firmware/kernel.c index fcee53f331..2d4ccde267 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -724,8 +724,13 @@ void tick_start(unsigned int interval_in_ms) INTMSK &= ~(1 << 14); // timer 4 unmask interrupts } -void timer4(void) { +void TIMER4(void) +{ int i; + + SRCPND = TIMER4_MASK; + INTPND = TIMER4_MASK; + /* Run through the list of tick tasks */ for(i = 0; i < MAX_NUM_TICK_TASKS; i++) { @@ -736,9 +741,6 @@ void timer4(void) { } current_tick++; - - /* following needs to be fixed. */ - /*wake_up_thread();*/ } #endif diff --git a/firmware/target/arm/crt0.S b/firmware/target/arm/crt0.S index c513bd7ce7..e7a0a38f36 100644 --- a/firmware/target/arm/crt0.S +++ b/firmware/target/arm/crt0.S @@ -198,14 +198,6 @@ data_abort_handler: mov r1, #2 b UIE -irq_handler: -#ifndef STUB - stmfd sp!, {r0-r11, r12, lr} - bl irq - ldmfd sp!, {r0-r11, r12, lr} -#endif - subs pc, lr, #4 - #ifdef STUB UIE: b UIE diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c index aa011dc56b..f626438de4 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c @@ -3,44 +3,83 @@ #include "panic.h" #include "mmu-meg-fx.h" -#include "lcd.h" +#define default_interrupt(name) \ + extern __attribute__((weak,alias("UIRQ"))) void name (void) + +default_interrupt(EINT0); +default_interrupt(EINT1); +default_interrupt(EINT2); +default_interrupt(EINT3); +default_interrupt(EINT4_7); +default_interrupt(EINT8_23); +default_interrupt(CAM); +default_interrupt(nBATT_FLT); +default_interrupt(TICK); +default_interrupt(WDT_AC97); +default_interrupt(TIMER0); +default_interrupt(TIMER1); +default_interrupt(TIMER2); +default_interrupt(TIMER3); +default_interrupt(TIMER4); +default_interrupt(UART2); +default_interrupt(LCD); +default_interrupt(DMA0); +default_interrupt(DMA1); +default_interrupt(DMA2); +default_interrupt(DMA3); +default_interrupt(SDI); +default_interrupt(SPI0); +default_interrupt(UART1); +default_interrupt(NFCON); +default_interrupt(USBD); +default_interrupt(USBH); +default_interrupt(IIC); +default_interrupt(UART0); +default_interrupt(SPI1); +default_interrupt(RTC); +default_interrupt(ADC); + +static void (* const irqvector[32])(void) = +{ + EINT0, EINT1, EINT2, EINT3, + EINT4_7, EINT8_23, CAM, nBATT_FLT, TICK, WDT_AC97, + TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, UART2, + LCD, DMA0, DMA1, DMA2, DMA3, SDI, + SPI0, UART1, NFCON, USBD, IIC, + UART0, SPI1, RTC, ADC, +}; -enum +static const char * const irqname[32] = { - TIMER4_MASK = (1 << 14), - LCD_MASK = (1 << 16), - DMA0_MASK = (1 << 17), - DMA1_MASK = (1 << 18), - DMA2_MASK = (1 << 19), - DMA3_MASK = (1 << 20), - ALARM_MASK = (1 << 30), + "EINT0", "EINT1", "EINT2", "EINT3", + "EINT4_7", "EINT8_23", "CAM", "nBATT_FLT", "TICK", "WDT_AC97", + "TIMER0", "TIMER1", "TIMER2", "TIMER3", "TIMER4", "UART2", + "LCD", "DMA0", "DMA1", "DMA2", "DMA3", "SDI", + "SPI0", "UART1", "NFCON", "USBD", "USBH", "IIC", + "UART0", "SPI1", "RTC", "ADC" }; -int system_memory_guard(int newmode) +static void UIRQ(void) { - (void)newmode; - return 0; + unsigned int offset = INTOFFSET; + panicf("Unhandled IRQ %02X: %s", offset, irqname[offset]); } -extern void timer4(void); -extern void dma0(void); /* free */ -extern void dma1(void); -extern void dma3(void); - -void irq(void) +void irq_handler(void) __attribute__((interrupt ("IRQ"), naked)); +void irq_handler(void) { - int intpending = INTPND; - - SRCPND = intpending; /* Clear this interrupt. */ - INTPND = intpending; /* Clear this interrupt. */ - - /* Timer 4 */ - if ((intpending & TIMER4_MASK) != 0) - timer4(); - else - { - /* unexpected interrupt */ - } + asm volatile ( + "sub lr, lr, #4 \r\n" + "stmfd sp!, {r0-r3, ip, lr} \r\n" + "mov r0, #0x4a000000 \r\n" /* INTOFFSET = 0x4a000014 */ + "add r0, r0, #0x00000014 \r\n" + "ldr r0, [r0] \r\n" + "ldr r1, =irqvector \r\n" + "ldr r1, [r1, r0, lsl #2] \r\n" + "mov lr, pc \r\n" + "bx r1 \r\n" + "ldmfd sp!, {r0-r3, ip, pc}^ \r\n" + ); } void system_reboot(void) @@ -54,6 +93,17 @@ void system_reboot(void) void system_init(void) { + /* Disable interrupts and set all to IRQ mode */ + INTMSK = -1; + INTMOD = 0; + SRCPND = -1; + INTPND = -1; + INTSUBMSK = -1; + SUBSRCPND = -1; + + /* TODO: do something with PRIORITY */ + + /* Turn off currently-not or never-needed devices */ CLKCON &= ~( @@ -90,6 +140,11 @@ void system_init(void) CLKSLOW |= (1 << 7); } +int system_memory_guard(int newmode) +{ + (void)newmode; + return 0; +} #ifdef HAVE_ADJUSTABLE_CPU_FREQ -- cgit v1.2.3