diff options
Diffstat (limited to 'firmware/target/arm/imx31/avic-imx31.h')
-rw-r--r-- | firmware/target/arm/imx31/avic-imx31.h | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/firmware/target/arm/imx31/avic-imx31.h b/firmware/target/arm/imx31/avic-imx31.h index 43fd726db3..ba9e50652d 100644 --- a/firmware/target/arm/imx31/avic-imx31.h +++ b/firmware/target/arm/imx31/avic-imx31.h | |||
@@ -214,14 +214,16 @@ void avic_set_int_priority(enum IMX31_INT_LIST ints, | |||
214 | void avic_disable_int(enum IMX31_INT_LIST ints); | 214 | void avic_disable_int(enum IMX31_INT_LIST ints); |
215 | void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype); | 215 | void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype); |
216 | 216 | ||
217 | #define AVIC_NIL_DISABLE 0xf | 217 | #define AVIC_NIL_DISABLE 15 |
218 | #define AVIC_NIL_ENABLE 0x1f | 218 | #define AVIC_NIL_ENABLE (-1) |
219 | void avic_set_ni_level(unsigned int level); | 219 | void avic_set_ni_level(int level); |
220 | 220 | ||
221 | 221 | ||
222 | /* Call a service routine while allowing preemption by interrupts of higher | 222 | /* Call a service routine while allowing preemption by interrupts of higher |
223 | * priority. r4-r7 must be preserved for epilogue code to restore context. */ | 223 | * priority. Avoid using any app or other SVC stack by doing it with a mini |
224 | #define AVIC_NESTED_NI_CALL_PROLOGUE(prio) \ | 224 | * "stack on irq stack". Avoid actually enabling IRQ until the routine |
225 | * decides to do so; epilogue code will always disable them again. */ | ||
226 | #define AVIC_NESTED_NI_CALL_PROLOGUE(prio, stacksize) \ | ||
225 | ({ asm volatile ( \ | 227 | ({ asm volatile ( \ |
226 | "sub lr, lr, #4 \n" /* prepare return address */ \ | 228 | "sub lr, lr, #4 \n" /* prepare return address */ \ |
227 | "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \ | 229 | "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \ |
@@ -230,18 +232,25 @@ void avic_set_ni_level(unsigned int level); | |||
230 | "mov r1, %0 \n" /* load interrupt level */ \ | 232 | "mov r1, %0 \n" /* load interrupt level */ \ |
231 | "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \ | 233 | "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \ |
232 | "str r1, [r0, #0x04] \n" /* set interrupt level */ \ | 234 | "str r1, [r0, #0x04] \n" /* set interrupt level */ \ |
233 | "cpsie i, #0x13 \n" /* change to SVC mode, unmask IRQ */ \ | 235 | "mov r0, sp \n" /* grab IRQ stack */ \ |
234 | "stmfd sp!, { r2, lr } \n" /* push NIMASK and LR on SVC stack */ \ | 236 | "sub sp, sp, %1 \n" /* allocate space for routine to SP_irq */ \ |
235 | : : "i"(prio)); }) | 237 | "cps #0x13 \n" /* change to SVC mode */ \ |
238 | "mov r1, sp \n" /* save SP_svc */ \ | ||
239 | "mov sp, r0 \n" /* switch to SP_irq *copy* */ \ | ||
240 | "stmfd sp!, { r1, r2, lr } \n" /* push SP_svc, NIMASK and LR_svc */ \ | ||
241 | : : "i"(prio), "i"(stacksize)); }) | ||
236 | 242 | ||
237 | #define AVIC_NESTED_NI_CALL_EPILOGUE() \ | 243 | #define AVIC_NESTED_NI_CALL_EPILOGUE(stacksize) \ |
238 | ({ asm volatile ( \ | 244 | ({ asm volatile ( \ |
239 | "ldmfd sp!, { r2, lr } \n" /* pop original LR and NIMASK */ \ | 245 | "cpsid i \n" /* disable IRQ */ \ |
240 | "cpsid i, #0x12 \n" /* return to IRQ mode, mask IRQ */ \ | 246 | "ldmfd sp!, { r1, r2, lr } \n" /* pop SP_svc, NIMASK and LR_svc */ \ |
247 | "mov sp, r1 \n" /* restore SP_svc */ \ | ||
248 | "cps #0x12 \n" /* return to IRQ mode */ \ | ||
249 | "add sp, sp, %0 \n" /* deallocate routine space */ \ | ||
241 | "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \ | 250 | "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \ |
242 | "str r2, [r0, #0x04] \n" /* restore NIMASK */ \ | 251 | "str r2, [r0, #0x04] \n" /* restore NIMASK */ \ |
243 | "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \ | 252 | "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \ |
244 | "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \ | 253 | "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \ |
245 | ); }) | 254 | : : "i"(stacksize)); }) |
246 | 255 | ||
247 | #endif /* AVIC_IMX31_H */ | 256 | #endif /* AVIC_IMX31_H */ |