diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2008-12-05 17:10:11 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2008-12-05 17:10:11 +0000 |
commit | ab64424598e34fe47b25141e47ac340ae1fabc5a (patch) | |
tree | d7903955f54ca1fd8b23b25be4e14e1dd330fad7 /firmware/target/arm/as3525 | |
parent | f07aa65117a196ecfd5ef097dc432d6f5d49c743 (diff) | |
download | rockbox-ab64424598e34fe47b25141e47ac340ae1fabc5a.tar.gz rockbox-ab64424598e34fe47b25141e47ac340ae1fabc5a.zip |
Sansa AMS: use vectored interrupts
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19351 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r-- | firmware/target/arm/as3525/system-as3525.c | 72 |
1 files changed, 44 insertions, 28 deletions
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index 649ba77527..c2a2e4f47d 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c | |||
@@ -66,18 +66,6 @@ default_interrupt(INT_GPIOA); | |||
66 | default_interrupt(INT_GPIOB); | 66 | default_interrupt(INT_GPIOB); |
67 | default_interrupt(INT_GPIOC); | 67 | default_interrupt(INT_GPIOC); |
68 | 68 | ||
69 | |||
70 | |||
71 | static void (* const irqvector[])(void) = | ||
72 | { | ||
73 | INT_WATCHDOG, INT_TIMER1, INT_TIMER2, INT_USB, INT_DMAC, INT_NAND, INT_IDE, INT_MCI0, | ||
74 | INT_MCI1, INT_AUDIO, INT_SSP, INT_I2C_MS, INT_I2C_AUDIO, INT_I2SIN, INT_I2SOUT, | ||
75 | INT_UART, INT_GPIOD, RESERVED1 /* 17 */ ,INT_CGU, INT_MEMORY_STICK, INT_DBOP, | ||
76 | RESERVED2 /* 21 */, RESERVED3 /* 22 */, RESERVED4 /* 23 */, RESERVED5 /* 24 */, | ||
77 | RESERVED6 /* 25 */, RESERVED7 /* 26 */, RESERVED8 /* 27 */, RESERVED9 /* 28 */, | ||
78 | INT_GPIOA, INT_GPIOB, INT_GPIOC | ||
79 | }; | ||
80 | |||
81 | static const char * const irqname[] = | 69 | static const char * const irqname[] = |
82 | { | 70 | { |
83 | "INT_WATCHDOG", "INT_TIMER1", "INT_TIMER2", "INT_USB", "INT_DMAC", "INT_NAND", | 71 | "INT_WATCHDOG", "INT_TIMER1", "INT_TIMER2", "INT_USB", "INT_DMAC", "INT_NAND", |
@@ -98,23 +86,54 @@ static void UIRQ(void) | |||
98 | panicf("Unhandled IRQ %02X: %s", irq_no, irqname[irq_no]); | 86 | panicf("Unhandled IRQ %02X: %s", irq_no, irqname[irq_no]); |
99 | } | 87 | } |
100 | 88 | ||
101 | void irq_handler(void) | 89 | struct vec_int_src |
102 | { | 90 | { |
103 | /* | 91 | int source; |
104 | * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c | 92 | void (*isr) (void); |
105 | */ | 93 | }; |
106 | 94 | ||
107 | asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" );/* Store context */ | 95 | /* Vectored interrupts (16 available) */ |
96 | struct vec_int_src vec_int_srcs[] = | ||
97 | { | ||
98 | { INT_SRC_TIMER1, INT_TIMER1 }, | ||
99 | { INT_SRC_TIMER2, INT_TIMER2 }, | ||
100 | { INT_SRC_DMAC, INT_DMAC }, | ||
101 | { INT_SRC_NAND, INT_NAND }, | ||
102 | { INT_SRC_MCI0, INT_MCI0 }, | ||
103 | { INT_SRC_GPIOA, INT_GPIOA, }, | ||
104 | { INT_SRC_GPIOB, INT_GPIOB, }, | ||
105 | }; | ||
108 | 106 | ||
109 | unsigned int irq_no = 0; | 107 | static void setup_vic(void) |
110 | int status = VIC_IRQ_STATUS; | 108 | { |
111 | while((status >>= 1)) | 109 | volatile unsigned long *vic_vect_addrs = VIC_VECT_ADDRS; |
112 | irq_no++; | 110 | volatile unsigned long *vic_vect_cntls = VIC_VECT_CNTLS; |
111 | const unsigned int n = sizeof(vec_int_srcs)/sizeof(vec_int_srcs[0]); | ||
112 | unsigned int i; | ||
113 | |||
114 | CGU_PERI |= CGU_VIC_CLOCK_ENABLE; /* enable VIC */ | ||
115 | VIC_INT_EN_CLEAR = 0xffffffff; /* disable all interrupt lines */ | ||
116 | VIC_INT_SELECT = 0; /* only IRQ, no FIQ */ | ||
113 | 117 | ||
114 | irqvector[irq_no](); | 118 | VIC_DEF_VECT_ADDR = (unsigned long)UIRQ; |
115 | 119 | ||
116 | asm volatile( "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */ | 120 | for(i = 0; i < n; i++) |
117 | "subs pc, lr, #4 \n"); /* Return from IRQ */ | 121 | { |
122 | vic_vect_addrs[i] = (unsigned long)vec_int_srcs[i].isr; | ||
123 | vic_vect_cntls[i] = (1<<5) | vec_int_srcs[i].source; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | void irq_handler(void) | ||
128 | { | ||
129 | asm volatile( "stmfd sp!, {r0-r5,ip,lr} \n" /* Store context */ | ||
130 | "ldr r5, =0xC6010030 \n" /* VIC_VECT_ADDR */ | ||
131 | "mov lr, pc \n" /* Return from ISR */ | ||
132 | "ldr pc, [r5] \n" /* execute ISR */ | ||
133 | "str r0, [r5] \n" /* Ack interrupt */ | ||
134 | "ldmfd sp!, {r0-r5,ip,lr} \n" /* Restore context */ | ||
135 | "subs pc, lr, #4 \n" /* Return from IRQ */ | ||
136 | ); | ||
118 | } | 137 | } |
119 | 138 | ||
120 | void fiq_handler(void) | 139 | void fiq_handler(void) |
@@ -235,10 +254,7 @@ void system_init(void) | |||
235 | /* enable timer interface for TIMER1 & TIMER2 */ | 254 | /* enable timer interface for TIMER1 & TIMER2 */ |
236 | CGU_PERI |= CGU_TIMERIF_CLOCK_ENABLE; | 255 | CGU_PERI |= CGU_TIMERIF_CLOCK_ENABLE; |
237 | 256 | ||
238 | /* enable VIC */ | 257 | setup_vic(); |
239 | VIC_INT_EN_CLEAR = 0xffffffff; /* disable all interrupt lines */ | ||
240 | CGU_PERI |= CGU_VIC_CLOCK_ENABLE; | ||
241 | VIC_INT_SELECT = 0; /* only IRQ, no FIQ */ | ||
242 | 258 | ||
243 | dma_init(); | 259 | dma_init(); |
244 | 260 | ||