summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-10-14 00:01:41 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-10-14 00:01:41 +0000
commit830531b7d463155018857ca9899e760d72208279 (patch)
tree59a5804735e7a28881f1525351d9c39a411dfe10
parent0dc76136ca3fcf46b9a9993b75e7e7ed1e76816c (diff)
downloadrockbox-830531b7d463155018857ca9899e760d72208279.tar.gz
rockbox-830531b7d463155018857ca9899e760d72208279.zip
i.MX31: Simplify nested interrupt handling. Give SVC mode its own stack by grabbing the FIQ stack that's just been taking up space. Just get rid of all FIQ setup since it isn't used anyway.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30747 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/imx31/avic-imx31.c2
-rw-r--r--firmware/target/arm/imx31/avic-imx31.h48
-rw-r--r--firmware/target/arm/imx31/crt0.S35
-rw-r--r--firmware/target/arm/imx31/dvfs_dptc-imx31.c4
4 files changed, 40 insertions, 49 deletions
diff --git a/firmware/target/arm/imx31/avic-imx31.c b/firmware/target/arm/imx31/avic-imx31.c
index b2b62755e1..5b0aad434c 100644
--- a/firmware/target/arm/imx31/avic-imx31.c
+++ b/firmware/target/arm/imx31/avic-imx31.c
@@ -103,6 +103,7 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void)
103} 103}
104#endif /* 0 */ 104#endif /* 0 */
105 105
106#if 0
106/* Accoring to section 9.3.5 of the UM, the AVIC doesn't accelerate 107/* Accoring to section 9.3.5 of the UM, the AVIC doesn't accelerate
107 * fast interrupts and they must be dispatched */ 108 * fast interrupts and they must be dispatched */
108void __attribute__((naked)) fiq_handler(void) 109void __attribute__((naked)) fiq_handler(void)
@@ -115,6 +116,7 @@ void __attribute__((naked)) fiq_handler(void)
115 "bx r8 \n" /* jump to FIQ service routine */ 116 "bx r8 \n" /* jump to FIQ service routine */
116 ); 117 );
117} 118}
119#endif /* 0 */
118 120
119void INIT_ATTR avic_init(void) 121void INIT_ATTR avic_init(void)
120{ 122{
diff --git a/firmware/target/arm/imx31/avic-imx31.h b/firmware/target/arm/imx31/avic-imx31.h
index ca48f85ba5..a01a6cd795 100644
--- a/firmware/target/arm/imx31/avic-imx31.h
+++ b/firmware/target/arm/imx31/avic-imx31.h
@@ -77,34 +77,24 @@ static inline void avic_unmask_int(enum IMX31_INT_LIST ints)
77 * priority. Avoid using any app or other SVC stack by doing it with a mini 77 * priority. Avoid using any app or other SVC stack by doing it with a mini
78 * "stack on irq stack". Avoid actually enabling IRQ until the routine 78 * "stack on irq stack". Avoid actually enabling IRQ until the routine
79 * decides to do so; epilogue code will always disable them again. */ 79 * decides to do so; epilogue code will always disable them again. */
80#define AVIC_NESTED_NI_CALL_PROLOGUE(prio, stacksize) \ 80#define AVIC_NESTED_NI_CALL(fn, prio) \
81({ asm volatile ( \ 81({ asm volatile ( \
82 "sub lr, lr, #4 \n" /* prepare return address */ \ 82 "sub lr, lr, #4 \n" /* prepare return address */ \
83 "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \ 83 "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \
84 "stmfd sp!, { r0-r3, r12 } \n" /* preserve context */ \ 84 "stmfd sp!, { r0-r3, r12 } \n" /* preserve context */ \
85 "mov r0, #0x68000000 \n" /* AVIC_BASE_ADDR */ \ 85 "mov r0, #0x68000000 \n" /* AVIC_BASE_ADDR */ \
86 "mov r1, %0 \n" /* load interrupt level */ \ 86 "mov r1, %0 \n" /* load interrupt level */ \
87 "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \ 87 "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \
88 "str r1, [r0, #0x04] \n" /* set interrupt level */ \ 88 "str r1, [r0, #0x04] \n" /* set interrupt level */ \
89 "mov r0, sp \n" /* grab IRQ stack */ \ 89 "cps #0x13 \n" /* change to SVC mode */ \
90 "sub sp, sp, %1 \n" /* allocate space for routine to SP_irq */ \ 90 "stmfd sp!, { r2, lr } \n" /* push NIMASK and LR_svc */ \
91 "cps #0x13 \n" /* change to SVC mode */ \ 91 "bl " #fn " \n" /* Call SVC routine */ \
92 "mov r1, sp \n" /* save SP_svc */ \ 92 "cpsid i \n" /* disable IRQ */ \
93 "mov sp, r0 \n" /* switch to SP_irq *copy* */ \ 93 "ldmfd sp!, { r1, lr } \n" /* pop NIMASK and LR_svc */ \
94 "stmfd sp!, { r1, r2, lr } \n" /* push SP_svc, NIMASK and LR_svc */ \ 94 "cps #0x12 \n" /* return to IRQ mode */ \
95 : : "i"(prio), "i"(stacksize)); }) 95 "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \
96 96 "str r1, [r0, #0x04] \n" /* restore NIMASK */ \
97#define AVIC_NESTED_NI_CALL_EPILOGUE(stacksize) \ 97 "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \
98({ asm volatile ( \ 98 "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \
99 "cpsid i \n" /* disable IRQ */ \ 99 : : "i"(prio)); })
100 "ldmfd sp!, { r1, r2, lr } \n" /* pop SP_svc, NIMASK and LR_svc */ \
101 "mov sp, r1 \n" /* restore SP_svc */ \
102 "cps #0x12 \n" /* return to IRQ mode */ \
103 "add sp, sp, %0 \n" /* deallocate routine space */ \
104 "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \
105 "str r2, [r0, #0x04] \n" /* restore NIMASK */ \
106 "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \
107 "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \
108 : : "i"(stacksize)); })
109
110#endif /* AVIC_IMX31_H */ 100#endif /* AVIC_IMX31_H */
diff --git a/firmware/target/arm/imx31/crt0.S b/firmware/target/arm/imx31/crt0.S
index 69577e4d3d..b6a49266ef 100644
--- a/firmware/target/arm/imx31/crt0.S
+++ b/firmware/target/arm/imx31/crt0.S
@@ -32,8 +32,9 @@ start:
32 b prefetch_abort_handler 32 b prefetch_abort_handler
33 b data_abort_handler 33 b data_abort_handler
34 b reserved_handler 34 b reserved_handler
35 /* These vectors are unused */
35 subs pc, lr, #4 @ b irq_handler 36 subs pc, lr, #4 @ b irq_handler
36 b fiq_handler 37 subs pc, lr, #4 @ b fiq_handler
37 .balign 0x40, 0x6B 38 .balign 0x40, 0x6B
38 39
39/* Arm bootloader and startup code based on startup.s from the iPodLinux loader 40/* Arm bootloader and startup code based on startup.s from the iPodLinux loader
@@ -80,7 +81,7 @@ remap_start:
80 mcrne p15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */ 81 mcrne p15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */
81 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ 82 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */
82 mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffer */ 83 mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffer */
83 84
84 mcr p15, 0, r0, c13, c0, 0 85 mcr p15, 0, r0, c13, c0, 0
85 mcr p15, 0, r0, c13, c0, 1 86 mcr p15, 0, r0, c13, c0, 1
86 87
@@ -100,7 +101,7 @@ remap_start:
100 bic r3, r3, #((1 << 2) | /* L1 D-cache disabled */ \ 101 bic r3, r3, #((1 << 2) | /* L1 D-cache disabled */ \
101 (1 << 0)) /* MMU disabled */ 102 (1 << 0)) /* MMU disabled */
102 mcr p15, 0, r3, c1, c0, 0 103 mcr p15, 0, r3, c1, c0, 0
103 104
104 /* 105 /*
105 * Configure L2 Cache: 106 * Configure L2 Cache:
106 * - 128k size(16k way) 107 * - 128k size(16k way)
@@ -175,7 +176,7 @@ remap_start:
175 mov r0, #0 176 mov r0, #0
176 mcr p15, 0, r0, c8, c7, 0 /* Invalidate TLB */ 177 mcr p15, 0, r0, c8, c7, 0 /* Invalidate TLB */
177 mcr p15, 0, r0, c7, c7, 0 /* Invalidate icache and dcache */ 178 mcr p15, 0, r0, c7, c7, 0 /* Invalidate icache and dcache */
178 179
179 /* Auxilliary control register */ 180 /* Auxilliary control register */
180 mrc p15, 0, r0, c1, c0, 1 181 mrc p15, 0, r0, c1, c0, 1
181 bic r0, r0, #((1 << 6) | /* Restrict cache size OFF */ \ 182 bic r0, r0, #((1 << 6) | /* Restrict cache size OFF */ \
@@ -252,18 +253,18 @@ remap_end:
252 cmp r3, r2 253 cmp r3, r2
253 strhi r4, [r2], #4 254 strhi r4, [r2], #4
254 bhi 1b 255 bhi 1b
255 256
256 /* Set up stack for IRQ mode */ 257 /* Set up stack for IRQ mode */
257 msr cpsr_c, #0xd2 258 msr cpsr_c, #0xd2
258 ldr sp, =irq_stack 259 ldr sp, =irq_stack
259 260
260 /* Set up stack for FIQ mode */ 261 /* FIQ mode is unused, thus sp_FIQ is irrelevant for it */
261 msr cpsr_c, #0xd1
262 ldr sp, =fiq_stack
263 262
264 /* Let svc, abort and undefined modes use irq stack */ 263 /* Set up stack for SVC mode */
265 msr cpsr_c, #0xd3 264 msr cpsr_c, #0xd3
266 ldr sp, =irq_stack 265 ldr sp, =svc_stack
266
267 /* Let abort and undefined modes use irq stack */
267 msr cpsr_c, #0xd7 268 msr cpsr_c, #0xd7
268 ldr sp, =irq_stack 269 ldr sp, =irq_stack
269 msr cpsr_c, #0xdb 270 msr cpsr_c, #0xdb
@@ -286,7 +287,7 @@ remap_end:
286 mrc p15, 0, r3, c1, c0, 2 287 mrc p15, 0, r3, c1, c0, 2
287 orr r3, r3, #0xf00000 288 orr r3, r3, #0xf00000
288 mcr p15, 0, r3, c1, c0, 2 289 mcr p15, 0, r3, c1, c0, 2
289 290
290 /* Enable VFP */ 291 /* Enable VFP */
291 mrc p10, 7, r3, c8, c0, 0 292 mrc p10, 7, r3, c8, c0, 0
292 orr r3, r3, #1<<30 293 orr r3, r3, #1<<30
@@ -314,7 +315,7 @@ remap_end:
314 ldr pc, [pc, #24] 315 ldr pc, [pc, #24]
315 ldr pc, [pc, #24] 316 ldr pc, [pc, #24]
316 subs pc, lr, #4 @ ldr pc, [pc, #24] 317 subs pc, lr, #4 @ ldr pc, [pc, #24]
317 ldr pc, [pc, #24] 318 subs pc, lr, #4 @ ldr pc, [pc, #24]
318 .word newstart 319 .word newstart
319 .word undef_instr_handler 320 .word undef_instr_handler
320 .word software_int_handler 321 .word software_int_handler
@@ -322,7 +323,7 @@ remap_end:
322 .word data_abort_handler 323 .word data_abort_handler
323 .word reserved_handler 324 .word reserved_handler
324 .word 0 @ irq_handler 325 .word 0 @ irq_handler
325 .word fiq_handler 326 .word 0 @ fiq_handler
326#endif /* BOOTLOADER */ 327#endif /* BOOTLOADER */
327 328
328 .text 329 .text
@@ -350,7 +351,7 @@ prefetch_abort_handler:
350 b UIE 351 b UIE
351 352
352data_abort_handler: 353data_abort_handler:
353 sub r0, lr, #8 354 sub r0, lr, #8
354 mov r1, #2 355 mov r1, #2
355 b UIE 356 b UIE
356 357
@@ -360,8 +361,8 @@ data_abort_handler:
360 .space 256*4 361 .space 256*4
361irq_stack: 362irq_stack:
362 363
363/* 256 words of FIQ stack */ 364/* 256 words of SVC stack */
364 .section .bss 365 .section .bss
365 .balign 32 366 .balign 32
366 .space 256*4 367 .space 256*4
367fiq_stack: 368svc_stack:
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.c b/firmware/target/arm/imx31/dvfs_dptc-imx31.c
index 1c5ad863ce..e8dee17416 100644
--- a/firmware/target/arm/imx31/dvfs_dptc-imx31.c
+++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.c
@@ -241,9 +241,7 @@ static void __attribute__((used)) dvfs_int(void)
241static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) 241static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void)
242{ 242{
243 /* Audio can glitch with the long udelay if nested IRQ isn't allowed. */ 243 /* Audio can glitch with the long udelay if nested IRQ isn't allowed. */
244 AVIC_NESTED_NI_CALL_PROLOGUE(INT_PRIO_DVFS, 32*4); 244 AVIC_NESTED_NI_CALL(dvfs_int, INT_PRIO_DVFS);
245 asm volatile ("bl dvfs_int");
246 AVIC_NESTED_NI_CALL_EPILOGUE(32*4);
247} 245}
248 246
249/* Initialize the DVFS hardware */ 247/* Initialize the DVFS hardware */