diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-10-14 00:01:41 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-10-14 00:01:41 +0000 |
commit | 830531b7d463155018857ca9899e760d72208279 (patch) | |
tree | 59a5804735e7a28881f1525351d9c39a411dfe10 /firmware/target | |
parent | 0dc76136ca3fcf46b9a9993b75e7e7ed1e76816c (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/imx31/avic-imx31.c | 2 | ||||
-rw-r--r-- | firmware/target/arm/imx31/avic-imx31.h | 48 | ||||
-rw-r--r-- | firmware/target/arm/imx31/crt0.S | 35 | ||||
-rw-r--r-- | firmware/target/arm/imx31/dvfs_dptc-imx31.c | 4 |
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 */ |
108 | void __attribute__((naked)) fiq_handler(void) | 109 | void __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 | ||
119 | void INIT_ATTR avic_init(void) | 121 | void 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 | ||
352 | data_abort_handler: | 353 | data_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 |
361 | irq_stack: | 362 | irq_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 |
367 | fiq_stack: | 368 | svc_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) | |||
241 | static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) | 241 | static __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 */ |