summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-02-02 04:24:40 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2014-02-10 23:14:24 +0100
commitf7efa925fd570f87e3fb04a7f776a9130953f366 (patch)
tree3ccc371ae0996b034fae761ad38872c291e82c19
parentcefaabfe9d284e3eaa049819be0c06ac6c37a29b (diff)
downloadrockbox-f7efa925fd570f87e3fb04a7f776a9130953f366.tar.gz
rockbox-f7efa925fd570f87e3fb04a7f776a9130953f366.zip
imx233: add support for nested IRQ
Rewrite IRQ handling to allow nested IRQs: on each IRQ entry, we save the parameters on the (IRQ) stack and then switch to SVC mode (with its own stack) and renable interrupts. Make sure interrupt is properly acknowledged by using the read side-effect (RSE) mode and handle priority levels as well. Change-Id: I3fd68289b430c56bdd256868939238ff268e42b4
-rw-r--r--firmware/target/arm/imx233/crt0.S11
-rw-r--r--firmware/target/arm/imx233/icoll-imx233.c39
2 files changed, 39 insertions, 11 deletions
diff --git a/firmware/target/arm/imx233/crt0.S b/firmware/target/arm/imx233/crt0.S
index ffc58d56fc..0a71da5d08 100644
--- a/firmware/target/arm/imx233/crt0.S
+++ b/firmware/target/arm/imx233/crt0.S
@@ -132,11 +132,12 @@ remap:
132 132
133 /* Set up stack for FIQ mode */ 133 /* Set up stack for FIQ mode */
134 msr cpsr_c, #0xd1 134 msr cpsr_c, #0xd1
135 ldr sp, =fiq_stack 135 ldr sp, =irq_stack
136 136
137 /* Let svc, abort and undefined modes use irq stack */ 137 /* Let abort and undefined modes use irq stack, svc uses its own stack
138 * for interrupt processing */
138 msr cpsr_c, #0xd3 139 msr cpsr_c, #0xd3
139 ldr sp, =irq_stack 140 ldr sp, =svc_stack
140 msr cpsr_c, #0xd7 141 msr cpsr_c, #0xd7
141 ldr sp, =irq_stack 142 ldr sp, =irq_stack
142 msr cpsr_c, #0xdb 143 msr cpsr_c, #0xdb
@@ -161,11 +162,13 @@ remap:
1611: 1621:
162 b 1b 163 b 1b
163 164
165/* Cache-align interrupt stacks */
166 .balign 32
164/* 256 words of IRQ stack */ 167/* 256 words of IRQ stack */
165 .space 256*4 168 .space 256*4
166irq_stack: 169irq_stack:
167 170
168/* 256 words of FIQ stack */ 171/* 256 words of FIQ stack */
169 .space 256*4 172 .space 256*4
170fiq_stack: 173svc_stack:
171end: 174end:
diff --git a/firmware/target/arm/imx233/icoll-imx233.c b/firmware/target/arm/imx233/icoll-imx233.c
index 1c8774ad80..e42e0f3291 100644
--- a/firmware/target/arm/imx233/icoll-imx233.c
+++ b/firmware/target/arm/imx233/icoll-imx233.c
@@ -29,7 +29,7 @@
29 extern __attribute__((weak, alias("UIRQ"))) void name(void) 29 extern __attribute__((weak, alias("UIRQ"))) void name(void)
30 30
31static void UIRQ (void) __attribute__((interrupt ("IRQ"))); 31static void UIRQ (void) __attribute__((interrupt ("IRQ")));
32void irq_handler(void) __attribute__((interrupt("IRQ"))); 32void irq_handler(void) __attribute__((naked));
33void fiq_handler(void) __attribute__((interrupt("FIQ"))); 33void fiq_handler(void) __attribute__((interrupt("FIQ")));
34 34
35default_interrupt(INT_USB_CTRL); 35default_interrupt(INT_USB_CTRL);
@@ -161,17 +161,40 @@ static void UIRQ(void)
161 (unsigned int)(HW_ICOLL_VECTOR - (uint32_t)isr_table) / 4); 161 (unsigned int)(HW_ICOLL_VECTOR - (uint32_t)isr_table) / 4);
162} 162}
163 163
164void irq_handler(void) 164/* return the priority level */
165int _irq_handler(uint32_t vec)
165{ 166{
166 HW_ICOLL_VECTOR = HW_ICOLL_VECTOR; /* notify icoll that we entered ISR */ 167 int irq_nr = (vec - HW_ICOLL_VBASE) / 4;
167 int irq_nr = (HW_ICOLL_VECTOR - HW_ICOLL_VBASE) / 4;
168 if(irq_count[irq_nr]++ > IRQ_STORM_THRESHOLD) 168 if(irq_count[irq_nr]++ > IRQ_STORM_THRESHOLD)
169 panicf("IRQ %d: storm detected", irq_nr); 169 panicf("IRQ %d: storm detected", irq_nr);
170 if(irq_nr == INT_SRC_TIMER(TIMER_TICK)) 170 if(irq_nr == INT_SRC_TIMER(TIMER_TICK))
171 do_irq_stat(); 171 do_irq_stat();
172 (*(isr_t *)HW_ICOLL_VECTOR)(); 172 (*(isr_t *)vec)();
173 /* acknowledge completion of IRQ (all use the same priority 0) */ 173 /* acknowledge completion of IRQ */
174 HW_ICOLL_LEVELACK = BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0; 174 return imx233_icoll_get_irq_info(irq_nr).priority;
175}
176
177void irq_handler(void)
178{
179 /* save stuff */
180 asm volatile(
181 "sub lr, lr, #4 \n" /* Create return address */
182 "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */
183 "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */
184 "ldr r0, [r4] \n" /* and notify as side-effect */
185 "mrs lr, spsr \n" /* Save SPSR_irq */
186 "stmfd sp!, { lr } \n" /* Push it on the IRQ stack */
187 "msr cpsr_c, #0x13 \n" /* Switch to SVC mode, enable IRQ */
188 "stmfd sp!, { lr } \n" /* Save lr_SVC */
189 "blx _irq_handler \n" /* Process IRQ, returns ack level */
190 "ldmfd sp!, { lr } \n" /* Restore lr_SVC */
191 "msr cpsr_c, #0x92 \n" /* Mask IRQ, return to IRQ mode */
192 "ldmfd sp!, { lr } \n" /* Pop back SPSR */
193 "msr spsr_cxsf, lr \n" /* Restore SPSR_irq */
194 "mov r3, #1 \n" /* Compute ack level value */
195 "lsl r0, r3, r0 \n" /* (1 << ack_lvl) */
196 "str r0, [r4, #0x10] \n" /* and write it to HW_ICOLL_LEVELACK */
197 "ldmfd sp!, { r0-r5, r12, pc }^ \n" /* Restore regs, and RFE */);
175} 198}
176 199
177void fiq_handler(void) 200void fiq_handler(void)
@@ -220,6 +243,8 @@ void imx233_icoll_set_priority(int src, unsigned prio)
220void imx233_icoll_init(void) 243void imx233_icoll_init(void)
221{ 244{
222 imx233_reset_block(&HW_ICOLL_CTRL); 245 imx233_reset_block(&HW_ICOLL_CTRL);
246 /* enable read side-effect mode for nested interrupts */
247 BF_SET(ICOLL_CTRL, ARM_RSE_MODE);
223 /* disable all interrupts */ 248 /* disable all interrupts */
224 /* priority = 0, disable, disable fiq */ 249 /* priority = 0, disable, disable fiq */
225#if IMX233_SUBTARGET >= 3780 250#if IMX233_SUBTARGET >= 3780