diff options
Diffstat (limited to 'firmware/target/arm/imx233')
-rw-r--r-- | firmware/target/arm/imx233/crt0.S | 11 | ||||
-rw-r--r-- | firmware/target/arm/imx233/icoll-imx233.c | 39 |
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: | |||
161 | 1: | 162 | 1: |
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 |
166 | irq_stack: | 169 | irq_stack: |
167 | 170 | ||
168 | /* 256 words of FIQ stack */ | 171 | /* 256 words of FIQ stack */ |
169 | .space 256*4 | 172 | .space 256*4 |
170 | fiq_stack: | 173 | svc_stack: |
171 | end: | 174 | end: |
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 | ||
31 | static void UIRQ (void) __attribute__((interrupt ("IRQ"))); | 31 | static void UIRQ (void) __attribute__((interrupt ("IRQ"))); |
32 | void irq_handler(void) __attribute__((interrupt("IRQ"))); | 32 | void irq_handler(void) __attribute__((naked)); |
33 | void fiq_handler(void) __attribute__((interrupt("FIQ"))); | 33 | void fiq_handler(void) __attribute__((interrupt("FIQ"))); |
34 | 34 | ||
35 | default_interrupt(INT_USB_CTRL); | 35 | default_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 | ||
164 | void irq_handler(void) | 164 | /* return the priority level */ |
165 | int _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 | |||
177 | void 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 | ||
177 | void fiq_handler(void) | 200 | void fiq_handler(void) |
@@ -220,6 +243,8 @@ void imx233_icoll_set_priority(int src, unsigned prio) | |||
220 | void imx233_icoll_init(void) | 243 | void 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 |