summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233')
-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