summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/avic-imx31.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/avic-imx31.h')
-rw-r--r--firmware/target/arm/imx31/avic-imx31.h33
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,
214void avic_disable_int(enum IMX31_INT_LIST ints); 214void avic_disable_int(enum IMX31_INT_LIST ints);
215void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype); 215void 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)
219void avic_set_ni_level(unsigned int level); 219void 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 */