diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-11-27 01:20:26 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-11-27 01:20:26 +0000 |
commit | a8b388fb86096b265780ac682adddcec22005f79 (patch) | |
tree | d200d0ef25dcca41eecf5f0565970cc481fedb03 /firmware | |
parent | 0ade09bd6b14f4c27d28d055306ccd63569f5c49 (diff) | |
download | rockbox-a8b388fb86096b265780ac682adddcec22005f79.tar.gz rockbox-a8b388fb86096b265780ac682adddcec22005f79.zip |
Enable dualcore for the pp5002 processor by adding the needed cache handling and sleep/wakeup sync to the kernel. Refine some handling of fw/bl startup for all.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15827 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/app.lds | 16 | ||||
-rw-r--r-- | firmware/export/config.h | 4 | ||||
-rw-r--r-- | firmware/export/pp5002.h | 18 | ||||
-rw-r--r-- | firmware/target/arm/crt0-pp-bl.S | 113 | ||||
-rw-r--r-- | firmware/target/arm/crt0-pp.S | 84 | ||||
-rw-r--r-- | firmware/target/arm/system-pp5002.c | 71 | ||||
-rw-r--r-- | firmware/target/arm/system-target.h | 18 | ||||
-rw-r--r-- | firmware/thread.c | 170 |
8 files changed, 355 insertions, 139 deletions
diff --git a/firmware/app.lds b/firmware/app.lds index e3f6ef2e50..d88ce9fd60 100644 --- a/firmware/app.lds +++ b/firmware/app.lds | |||
@@ -369,14 +369,6 @@ SECTIONS | |||
369 | } > IRAM | 369 | } > IRAM |
370 | 370 | ||
371 | #if defined(CPU_COLDFIRE) || defined(CPU_ARM) | 371 | #if defined(CPU_COLDFIRE) || defined(CPU_ARM) |
372 | .stack : | ||
373 | { | ||
374 | *(.stack) | ||
375 | stackbegin = .; | ||
376 | . += 0x2000; | ||
377 | stackend = .; | ||
378 | } > IRAM | ||
379 | |||
380 | #ifdef CPU_PP | 372 | #ifdef CPU_PP |
381 | .idle_stacks : | 373 | .idle_stacks : |
382 | { | 374 | { |
@@ -392,6 +384,14 @@ SECTIONS | |||
392 | } > IRAM | 384 | } > IRAM |
393 | #endif | 385 | #endif |
394 | 386 | ||
387 | .stack : | ||
388 | { | ||
389 | *(.stack) | ||
390 | stackbegin = .; | ||
391 | . += 0x2000; | ||
392 | stackend = .; | ||
393 | } > IRAM | ||
394 | |||
395 | #else | 395 | #else |
396 | /* TRICK ALERT! We want 0x2000 bytes of stack, but we set the section | 396 | /* TRICK ALERT! We want 0x2000 bytes of stack, but we set the section |
397 | size smaller, and allow the stack to grow into the .iram copy */ | 397 | size smaller, and allow the stack to grow into the .iram copy */ |
diff --git a/firmware/export/config.h b/firmware/export/config.h index 6a2c02cffd..f377697b70 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -423,7 +423,7 @@ | |||
423 | #define IDLE_STACK_SIZE 0x80 | 423 | #define IDLE_STACK_SIZE 0x80 |
424 | #define IDLE_STACK_WORDS 0x20 | 424 | #define IDLE_STACK_WORDS 0x20 |
425 | 425 | ||
426 | #if !defined(FORCE_SINGLE_CORE) && CONFIG_CPU != PP5002 | 426 | #if !defined(FORCE_SINGLE_CORE) |
427 | 427 | ||
428 | #define NUM_CORES 2 | 428 | #define NUM_CORES 2 |
429 | #define CURRENT_CORE current_core() | 429 | #define CURRENT_CORE current_core() |
@@ -436,7 +436,7 @@ | |||
436 | #define IF_COP_VOID(...) __VA_ARGS__ | 436 | #define IF_COP_VOID(...) __VA_ARGS__ |
437 | #define IF_COP_CORE(core) core | 437 | #define IF_COP_CORE(core) core |
438 | 438 | ||
439 | #if CONFIG_CPU == PP5020 | 439 | #if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 |
440 | #define CONFIG_CORELOCK SW_CORELOCK /* SWP(B) is broken */ | 440 | #define CONFIG_CORELOCK SW_CORELOCK /* SWP(B) is broken */ |
441 | #else | 441 | #else |
442 | #define CONFIG_CORELOCK CORELOCK_SWAP | 442 | #define CONFIG_CORELOCK CORELOCK_SWAP |
diff --git a/firmware/export/pp5002.h b/firmware/export/pp5002.h index 6076703f1a..8882f296c3 100644 --- a/firmware/export/pp5002.h +++ b/firmware/export/pp5002.h | |||
@@ -141,14 +141,32 @@ | |||
141 | #define PP_VER3 (*(volatile unsigned long *)(0xcf004038)) | 141 | #define PP_VER3 (*(volatile unsigned long *)(0xcf004038)) |
142 | #define PP_VER4 (*(volatile unsigned long *)(0xcf00403c)) | 142 | #define PP_VER4 (*(volatile unsigned long *)(0xcf00403c)) |
143 | 143 | ||
144 | /* Processors Control */ | ||
145 | #define PROC_STAT (*(volatile unsigned long *)(0xcf004050)) | ||
144 | #define CPU_CTL (*(volatile unsigned char *)(0xcf004054)) | 146 | #define CPU_CTL (*(volatile unsigned char *)(0xcf004054)) |
145 | #define COP_CTL (*(volatile unsigned char *)(0xcf004058)) | 147 | #define COP_CTL (*(volatile unsigned char *)(0xcf004058)) |
146 | 148 | ||
149 | #define CPU_SLEEPING 0x8000 | ||
150 | #define COP_SLEEPING 0x4000 | ||
151 | #define PROC_SLEEPING(core) (0x8000 >> (core)) | ||
152 | |||
147 | #define PROC_CTL(core) ((&CPU_CTL)[(core)*4]) | 153 | #define PROC_CTL(core) ((&CPU_CTL)[(core)*4]) |
148 | 154 | ||
149 | #define PROC_SLEEP 0xca | 155 | #define PROC_SLEEP 0xca |
150 | #define PROC_WAKE 0xce | 156 | #define PROC_WAKE 0xce |
151 | 157 | ||
158 | /* Cache Control */ | ||
159 | #define CACHE_CTL (*(volatile unsigned long *)(0xcf004024)) | ||
160 | #define CACHE_RUN 0x1 | ||
161 | #define CACHE_INIT 0x2 | ||
162 | |||
163 | #define CACHE_MASK (*(volatile unsigned long *)(0xf000f020)) | ||
164 | #define CACHE_OPERATION (*(volatile unsigned long *)(0xf000f024)) | ||
165 | #define CACHE_FLUSH_BASE (*(volatile unsigned long *)(0xf000c000)) | ||
166 | #define CACHE_INVALIDATE_BASE (*(volatile unsigned long *)(0xf0004000)) | ||
167 | #define CACHE_SIZE 0x2000 /* PP5002 has 8KB cache */ | ||
168 | |||
169 | #define CACHE_OP_UNKNOWN1 (1<<11) /* 0x800 */ | ||
152 | 170 | ||
153 | #define DEV_EN (*(volatile unsigned long *)(0xcf005000)) | 171 | #define DEV_EN (*(volatile unsigned long *)(0xcf005000)) |
154 | #define DEV_RS (*(volatile unsigned long *)(0xcf005030)) | 172 | #define DEV_RS (*(volatile unsigned long *)(0xcf005030)) |
diff --git a/firmware/target/arm/crt0-pp-bl.S b/firmware/target/arm/crt0-pp-bl.S index 9ab33a78d3..7aabd2b06a 100644 --- a/firmware/target/arm/crt0-pp-bl.S +++ b/firmware/target/arm/crt0-pp-bl.S | |||
@@ -32,23 +32,31 @@ start: | |||
32 | * | 32 | * |
33 | */ | 33 | */ |
34 | #if CONFIG_CPU == PP5002 | 34 | #if CONFIG_CPU == PP5002 |
35 | .equ PROC_ID, 0xc4000000 | 35 | .equ PROC_ID, 0xc4000000 |
36 | .equ COP_CTRL, 0xcf004058 | 36 | .equ CPU_CTRL, 0xcf004054 |
37 | .equ COP_STATUS, 0xcf004050 | 37 | .equ CPU_STATUS, 0xcf004050 |
38 | .equ IIS_CONFIG, 0xc0002500 | 38 | .equ COP_CTRL, 0xcf004058 |
39 | .equ SLEEP, 0xca | 39 | .equ COP_STATUS, 0xcf004050 |
40 | .equ WAKE, 0xce | 40 | .equ IIS_CONFIG, 0xc0002500 |
41 | .equ SLEEPING, 0x4000 | 41 | .equ SLEEP, 0xca |
42 | .equ WAKE, 0xce | ||
43 | .equ CPUSLEEPING, 0x8000 | ||
44 | .equ COPSLEEPING, 0x4000 | ||
45 | .equ CACHE_CTRL, 0xcf004024 | ||
46 | .equ CACHE_ENAB, 0x2 /* Actually the CACHE_INIT flag */ | ||
42 | #else | 47 | #else |
43 | .equ PROC_ID, 0x60000000 | 48 | .equ PROC_ID, 0x60000000 |
44 | .equ COP_CTRL, 0x60007004 | 49 | .equ CPU_CTRL, 0x60007000 |
45 | .equ COP_STATUS, 0x60007004 | 50 | .equ CPU_STATUS, 0x60007000 |
46 | .equ IIS_CONFIG, 0x70002800 | 51 | .equ COP_CTRL, 0x60007004 |
47 | .equ SLEEP, 0x80000000 | 52 | .equ COP_STATUS, 0x60007004 |
48 | .equ WAKE, 0x0 | 53 | .equ IIS_CONFIG, 0x70002800 |
49 | .equ SLEEPING, 0x80000000 | 54 | .equ SLEEP, 0x80000000 |
50 | .equ CACHE_CTRL, 0x6000c000 | 55 | .equ WAKE, 0x0 |
51 | .equ CACHE_ENAB, 0x1 | 56 | .equ CPUSLEEPING, 0x80000000 |
57 | .equ COPSLEEPING, 0x80000000 | ||
58 | .equ CACHE_CTRL, 0x6000c000 | ||
59 | .equ CACHE_ENAB, 0x1 | ||
52 | #endif | 60 | #endif |
53 | 61 | ||
54 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ */ | 62 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ */ |
@@ -94,23 +102,12 @@ cop: | |||
94 | ldr r0, =COP_CTRL | 102 | ldr r0, =COP_CTRL |
95 | mov r1, #SLEEP | 103 | mov r1, #SLEEP |
96 | str r1, [r0] | 104 | str r1, [r0] |
97 | 105 | nop | |
98 | #ifdef CPU_PP502x | 106 | nop |
99 | /* COP: Invalidate cache if enabled */ | 107 | |
100 | ldr r2, =CACHE_CTRL | 108 | /* Invalidate cache */ |
101 | ldr r1, [r2] | 109 | mov r0, #1 |
102 | tst r1, #CACHE_ENAB | 110 | bl cache_op |
103 | beq 2f | ||
104 | ldr r0, =0xf000f044 | ||
105 | ldr r1, [r0] | ||
106 | orr r1, r1, #0x6 | ||
107 | str r1, [r0] | ||
108 | 1: | ||
109 | ldr r1, [r2] | ||
110 | tst r1, #0x8000 | ||
111 | bne 1b | ||
112 | 2: | ||
113 | #endif /* CPU_PP502x */ | ||
114 | 111 | ||
115 | ldr r0, =startup_loc | 112 | ldr r0, =startup_loc |
116 | ldr pc, [r0] | 113 | ldr pc, [r0] |
@@ -120,7 +117,7 @@ cpu: | |||
120 | ldr r0, =COP_STATUS | 117 | ldr r0, =COP_STATUS |
121 | 1: | 118 | 1: |
122 | ldr r1, [r0] | 119 | ldr r1, [r0] |
123 | tst r1, #SLEEPING | 120 | tst r1, #COPSLEEPING |
124 | beq 1b | 121 | beq 1b |
125 | 122 | ||
126 | /* Initialise bss section to zero */ | 123 | /* Initialise bss section to zero */ |
@@ -148,22 +145,9 @@ cpu: | |||
148 | ldr r1, =startup_loc | 145 | ldr r1, =startup_loc |
149 | str r0, [r1] | 146 | str r0, [r1] |
150 | 147 | ||
151 | #ifdef CPU_PP502x | 148 | /* flush cache */ |
152 | /* Flush cache if enabled */ | 149 | mov r0, #0 |
153 | ldr r2, =CACHE_CTRL | 150 | bl cache_op |
154 | ldr r1, [r2] | ||
155 | tst r1, #CACHE_ENAB | ||
156 | beq 2f | ||
157 | ldr r0, =0xf000f044 | ||
158 | ldr r1, [r0] | ||
159 | orr r1, r1, #0x2 | ||
160 | str r1, [r0] | ||
161 | 1: | ||
162 | ldr r1, [r2] | ||
163 | tst r1, #0x8000 | ||
164 | bne 1b | ||
165 | 2: | ||
166 | #endif /* CPU_PP502x */ | ||
167 | 151 | ||
168 | /* Wake up the coprocessor before executing the firmware */ | 152 | /* Wake up the coprocessor before executing the firmware */ |
169 | ldr r0, =COP_CTRL | 153 | ldr r0, =COP_CTRL |
@@ -192,3 +176,32 @@ boot_table: | |||
192 | code+data must stay <= 256 bytes */ | 176 | code+data must stay <= 256 bytes */ |
193 | .space 400 | 177 | .space 400 |
194 | #endif | 178 | #endif |
179 | |||
180 | cache_op: | ||
181 | ldr r2, =CACHE_CTRL | ||
182 | ldr r1, [r2] | ||
183 | tst r1, #CACHE_ENAB | ||
184 | bxeq lr | ||
185 | cmp r0, #0 | ||
186 | #ifdef CPU_PP502x | ||
187 | ldr r0, =0xf000f044 | ||
188 | ldr r1, [r0] | ||
189 | orrne r1, r1, #0x6 | ||
190 | orreq r1, r1, #0x2 | ||
191 | str r1, [r0] | ||
192 | 1: | ||
193 | ldr r1, [r2] | ||
194 | tst r1, #0x8000 | ||
195 | bne 1b | ||
196 | #elif CONFIG_CPU == PP5002 | ||
197 | ldrne r0, =0xf0004000 | ||
198 | ldreq r0, =0xf000c000 | ||
199 | add r1, r0, #0x2000 | ||
200 | mov r2, #0 | ||
201 | 1: | ||
202 | cmp r1, r0 | ||
203 | strhi r2, [r0], #16 | ||
204 | bhi 1b | ||
205 | #endif /* CPU type */ | ||
206 | bx lr | ||
207 | |||
diff --git a/firmware/target/arm/crt0-pp.S b/firmware/target/arm/crt0-pp.S index 8fd1e31f09..dac666ca1c 100644 --- a/firmware/target/arm/crt0-pp.S +++ b/firmware/target/arm/crt0-pp.S | |||
@@ -32,45 +32,49 @@ start: | |||
32 | * | 32 | * |
33 | */ | 33 | */ |
34 | #if CONFIG_CPU == PP5002 | 34 | #if CONFIG_CPU == PP5002 |
35 | .equ PROC_ID, 0xc4000000 | 35 | .equ PROC_ID, 0xc4000000 |
36 | .equ CPU_ICLR, 0xcf001028 | 36 | .equ CPU_ICLR, 0xcf001028 |
37 | .equ CPU_CTRL, 0xcf004054 | 37 | .equ CPU_CTRL, 0xcf004054 |
38 | .equ COP_ICLR, 0xcf001038 | 38 | .equ COP_ICLR, 0xcf001038 |
39 | .equ COP_CTRL, 0xcf004058 | 39 | .equ COP_CTRL, 0xcf004058 |
40 | .equ COP_STATUS, 0xcf004050 | 40 | .equ CPU_STATUS, 0xcf004050 |
41 | .equ IIS_CONFIG, 0xc0002500 | 41 | .equ COP_STATUS, 0xcf004050 |
42 | .equ SLEEP, 0x000000ca | 42 | .equ IIS_CONFIG, 0xc0002500 |
43 | .equ WAKE, 0x000000ce | 43 | .equ SLEEP, 0x000000ca |
44 | .equ SLEEPING, 0x00004000 | 44 | .equ WAKE, 0x000000ce |
45 | .equ MMAP_LOG, 0xf000f010 /* MMAP2 */ | 45 | .equ CPUSLEEPING, 0x00008000 |
46 | .equ MMAP_PHYS, 0xf000f014 | 46 | .equ COPSLEEPING, 0x00004000 |
47 | .equ CACHE_CTRL, 0xcf004024 | ||
48 | .equ MMAP_LOG, 0xf000f000 /* MMAP0 */ | ||
49 | .equ MMAP_PHYS, 0xf000f004 | ||
47 | #if MEM > 32 | 50 | #if MEM > 32 |
48 | .equ MMAP_MASK, 0x00007400 | 51 | .equ MMAP_MASK, 0x00003c00 |
49 | #else | 52 | #else |
50 | .equ MMAP_MASK, 0x00003a00 | 53 | .equ MMAP_MASK, 0x00003e00 |
51 | #endif | 54 | #endif |
52 | .equ MMAP_FLAGS, 0x00003f84 | 55 | .equ MMAP_FLAGS, 0x00003f84 |
53 | #else | 56 | #else |
54 | .equ PROC_ID, 0x60000000 | 57 | .equ PROC_ID, 0x60000000 |
55 | .equ CPU_ICLR, 0x60004028 | 58 | .equ CPU_ICLR, 0x60004028 |
56 | .equ CPU_CTRL, 0x60007000 | 59 | .equ CPU_CTRL, 0x60007000 |
57 | .equ CPU_STATUS, 0x60007000 | 60 | .equ CPU_STATUS, 0x60007000 |
58 | .equ COP_ICLR, 0x60004038 | 61 | .equ COP_ICLR, 0x60004038 |
59 | .equ COP_CTRL, 0x60007004 | 62 | .equ COP_CTRL, 0x60007004 |
60 | .equ COP_STATUS, 0x60007004 | 63 | .equ COP_STATUS, 0x60007004 |
61 | .equ IIS_CONFIG, 0x70002800 | 64 | .equ IIS_CONFIG, 0x70002800 |
62 | .equ SLEEP, 0x80000000 | 65 | .equ SLEEP, 0x80000000 |
63 | .equ WAKE, 0x00000000 | 66 | .equ WAKE, 0x00000000 |
64 | .equ SLEEPING, 0x80000000 | 67 | .equ CPUSLEEPING, 0x80000000 |
65 | .equ CACHE_CTRL, 0x6000c000 | 68 | .equ COPSLEEPING, 0x80000000 |
66 | .equ MMAP_LOG, 0xf000f000 /* MMAP0 */ | 69 | .equ CACHE_CTRL, 0x6000c000 |
67 | .equ MMAP_PHYS, 0xf000f004 | 70 | .equ MMAP_LOG, 0xf000f000 /* MMAP0 */ |
71 | .equ MMAP_PHYS, 0xf000f004 | ||
68 | #if MEM > 32 | 72 | #if MEM > 32 |
69 | .equ MMAP_MASK, 0x00003c00 | 73 | .equ MMAP_MASK, 0x00003c00 |
70 | #else | 74 | #else |
71 | .equ MMAP_MASK, 0x00003e00 | 75 | .equ MMAP_MASK, 0x00003e00 |
72 | #endif | 76 | #endif |
73 | .equ MMAP_FLAGS, 0x00000f84 | 77 | .equ MMAP_FLAGS, 0x00000f84 |
74 | #endif | 78 | #endif |
75 | 79 | ||
76 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ | 80 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ |
@@ -111,21 +115,22 @@ pad_skip: | |||
111 | ldrne r2, =COP_CTRL | 115 | ldrne r2, =COP_CTRL |
112 | movne r1, #SLEEP | 116 | movne r1, #SLEEP |
113 | strne r1, [r2] | 117 | strne r1, [r2] |
118 | nop | ||
119 | nop | ||
120 | nop | ||
114 | 121 | ||
115 | /* wait for co-processor to sleep then CPU can begin its remapping */ | 122 | /* wait for co-processor to sleep then CPU can begin its remapping */ |
116 | ldreq r2, =COP_STATUS | 123 | ldreq r2, =COP_STATUS |
117 | 1: | 124 | 1: |
118 | ldreq r1, [r2] | 125 | ldreq r1, [r2] |
119 | tsteq r1, #SLEEPING | 126 | tsteq r1, #COPSLEEPING |
120 | beq 1b | 127 | beq 1b |
121 | 128 | ||
122 | #ifdef CPU_PP502x | ||
123 | /* disable cache and local interrupt vectors - it is really not desireable | 129 | /* disable cache and local interrupt vectors - it is really not desireable |
124 | to have them enabled here */ | 130 | to have them enabled here */ |
125 | ldr r2, =CACHE_CTRL | 131 | ldr r2, =CACHE_CTRL |
126 | mov r1, #0 | 132 | mov r1, #0 |
127 | str r1, [r2] | 133 | str r1, [r2] |
128 | #endif | ||
129 | 134 | ||
130 | mov r2, #0x40000000 | 135 | mov r2, #0x40000000 |
131 | ldr r3, =remap_start | 136 | ldr r3, =remap_start |
@@ -165,6 +170,9 @@ remap_end: | |||
165 | /* Sleep us (co-processor) and wait for CPU to do kernel initialization */ | 170 | /* Sleep us (co-processor) and wait for CPU to do kernel initialization */ |
166 | movne r3, #SLEEP | 171 | movne r3, #SLEEP |
167 | str r3, [r4] | 172 | str r3, [r4] |
173 | nop | ||
174 | nop | ||
175 | nop | ||
168 | 176 | ||
169 | /* Jump to co-processor init */ | 177 | /* Jump to co-processor init */ |
170 | ldrne pc, =cop_init | 178 | ldrne pc, =cop_init |
@@ -174,7 +182,7 @@ cpu_init: | |||
174 | ldr r4, =COP_STATUS | 182 | ldr r4, =COP_STATUS |
175 | 1: | 183 | 1: |
176 | ldr r3, [r4] | 184 | ldr r3, [r4] |
177 | tst r3, #SLEEPING | 185 | tst r3, #COPSLEEPING |
178 | beq 1b | 186 | beq 1b |
179 | 187 | ||
180 | /* Copy exception handler code to address 0 */ | 188 | /* Copy exception handler code to address 0 */ |
@@ -275,7 +283,7 @@ cop_init: | |||
275 | ldr r4, =CPU_STATUS | 283 | ldr r4, =CPU_STATUS |
276 | 1: | 284 | 1: |
277 | ldr r3, [r4] | 285 | ldr r3, [r4] |
278 | tst r3, #SLEEPING | 286 | tst r3, #CPUSLEEPING |
279 | beq 1b | 287 | beq 1b |
280 | #endif | 288 | #endif |
281 | 289 | ||
@@ -377,7 +385,7 @@ UIE: | |||
377 | #endif | 385 | #endif |
378 | 386 | ||
379 | /* Align stacks to cache line boundary */ | 387 | /* Align stacks to cache line boundary */ |
380 | .balign 16 | 388 | .balign 32 |
381 | 389 | ||
382 | /* 256 words of IRQ stack */ | 390 | /* 256 words of IRQ stack */ |
383 | .space 256*4 | 391 | .space 256*4 |
diff --git a/firmware/target/arm/system-pp5002.c b/firmware/target/arm/system-pp5002.c index 08783280be..164913f0f6 100644 --- a/firmware/target/arm/system-pp5002.c +++ b/firmware/target/arm/system-pp5002.c | |||
@@ -44,9 +44,7 @@ void irq(void) | |||
44 | } | 44 | } |
45 | else | 45 | else |
46 | { | 46 | { |
47 | if (COP_INT_STAT & TIMER1_MASK) | 47 | if (COP_INT_STAT & TIMER2_MASK) |
48 | TIMER1(); | ||
49 | else if (COP_INT_STAT & TIMER2_MASK) | ||
50 | TIMER2(); | 48 | TIMER2(); |
51 | } | 49 | } |
52 | } | 50 | } |
@@ -61,24 +59,60 @@ void irq(void) | |||
61 | some other CPU frequency scaling. */ | 59 | some other CPU frequency scaling. */ |
62 | 60 | ||
63 | #ifndef BOOTLOADER | 61 | #ifndef BOOTLOADER |
62 | void flush_icache(void) ICODE_ATTR; | ||
63 | void flush_icache(void) | ||
64 | { | ||
65 | intptr_t b, e; | ||
66 | |||
67 | for (b = (intptr_t)&CACHE_FLUSH_BASE, e = b + CACHE_SIZE; | ||
68 | b < e; b += 16) { | ||
69 | outl(0x0, b); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | void invalidate_icache(void) ICODE_ATTR; | ||
74 | void invalidate_icache(void) | ||
75 | { | ||
76 | intptr_t b, e; | ||
77 | |||
78 | /* Flush */ | ||
79 | for (b = (intptr_t)&CACHE_FLUSH_BASE, e = b + CACHE_SIZE; | ||
80 | b < e; b += 16) { | ||
81 | outl(0x0, b); | ||
82 | } | ||
83 | |||
84 | /* Invalidate */ | ||
85 | for (b = (intptr_t)&CACHE_INVALIDATE_BASE, e = b + CACHE_SIZE; | ||
86 | b < e; b += 16) { | ||
87 | outl(0x0, b); | ||
88 | } | ||
89 | } | ||
90 | |||
64 | static void ipod_init_cache(void) | 91 | static void ipod_init_cache(void) |
65 | { | 92 | { |
66 | int i =0; | 93 | intptr_t b, e; |
94 | |||
67 | /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */ | 95 | /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */ |
68 | outl(inl(0xcf004050) & ~0x700, 0xcf004050); | 96 | PROC_STAT &= ~0x700; |
69 | outl(0x4000, 0xcf004020); | 97 | outl(0x4000, 0xcf004020); |
70 | 98 | ||
71 | outl(0x2, 0xcf004024); | 99 | CACHE_CTL = CACHE_INIT; |
72 | 100 | ||
73 | /* PP5002 has 8KB cache */ | 101 | for (b = (intptr_t)&CACHE_INVALIDATE_BASE, e = b + CACHE_SIZE; |
74 | for (i = 0xf0004000; i < (int)(0xf0006000); i += 16) { | 102 | b < e; b += 16) { |
75 | outl(0x0, i); | 103 | outl(0x0, b); |
76 | } | 104 | } |
77 | 105 | ||
78 | outl(0x0, 0xf000f020); | 106 | /* Cache if (addr & mask) >> 16 == (mask & match) >> 16: |
79 | outl(0x3fc0, 0xf000f024); | 107 | * yes: 0x00000000 - 0x03ffffff |
108 | * no: 0x04000000 - 0x1fffffff | ||
109 | * yes: 0x20000000 - 0x23ffffff | ||
110 | * no: 0x24000000 - 0x3fffffff <= range containing uncached alias | ||
111 | */ | ||
112 | CACHE_MASK = 0x00001c00; | ||
113 | CACHE_OPERATION = 0x3fc0; | ||
80 | 114 | ||
81 | outl(0x3, 0xcf004024); | 115 | CACHE_CTL = CACHE_INIT | CACHE_RUN; |
82 | } | 116 | } |
83 | 117 | ||
84 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 118 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
@@ -132,9 +166,10 @@ void system_init(void) | |||
132 | #ifndef BOOTLOADER | 166 | #ifndef BOOTLOADER |
133 | if (CURRENT_CORE == CPU) | 167 | if (CURRENT_CORE == CPU) |
134 | { | 168 | { |
135 | /* Remap the flash ROM from 0x00000000 to 0x20000000. */ | 169 | /* Remap the flash ROM on CPU, keep hidden from COP: |
136 | MMAP3_LOGICAL = 0x20000000 | 0x3a00; | 170 | * 0x00000000-0x03ffffff = 0x20000000-0x23ffffff */ |
137 | MMAP3_PHYSICAL = 0x00000000 | 0x3f84; | 171 | MMAP1_LOGICAL = 0x20003c00; |
172 | MMAP1_PHYSICAL = 0x00003f84; | ||
138 | 173 | ||
139 | #if defined(IPOD_1G2G) || defined(IPOD_3G) | 174 | #if defined(IPOD_1G2G) || defined(IPOD_3G) |
140 | DEV_EN = 0x0b9f; /* don't clock unused PP5002 hardware components */ | 175 | DEV_EN = 0x0b9f; /* don't clock unused PP5002 hardware components */ |
@@ -150,7 +185,11 @@ void system_init(void) | |||
150 | GPIOC_INT_EN = 0; | 185 | GPIOC_INT_EN = 0; |
151 | GPIOD_INT_EN = 0; | 186 | GPIOD_INT_EN = 0; |
152 | 187 | ||
153 | #ifndef HAVE_ADJUSTABLE_CPU_FREQ | 188 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
189 | #if NUM_CORES > 1 | ||
190 | cpu_boost_init(); | ||
191 | #endif | ||
192 | #else | ||
154 | pp_set_cpu_frequency(CPUFREQ_MAX); | 193 | pp_set_cpu_frequency(CPUFREQ_MAX); |
155 | #endif | 194 | #endif |
156 | } | 195 | } |
diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h index e9419b3f86..8dcbf0f9da 100644 --- a/firmware/target/arm/system-target.h +++ b/firmware/target/arm/system-target.h | |||
@@ -77,7 +77,7 @@ static inline unsigned int current_core(void) | |||
77 | /* Return the actual ID instead of core index */ | 77 | /* Return the actual ID instead of core index */ |
78 | static inline unsigned int processor_id(void) | 78 | static inline unsigned int processor_id(void) |
79 | { | 79 | { |
80 | unsigned char id; | 80 | unsigned int id; |
81 | 81 | ||
82 | asm volatile ( | 82 | asm volatile ( |
83 | "ldrb %0, [%1] \n" | 83 | "ldrb %0, [%1] \n" |
@@ -92,12 +92,18 @@ static inline unsigned int processor_id(void) | |||
92 | /* All addresses within rockbox are in IRAM in the bootloader so | 92 | /* All addresses within rockbox are in IRAM in the bootloader so |
93 | are therefore uncached */ | 93 | are therefore uncached */ |
94 | #define UNCACHED_ADDR(a) (a) | 94 | #define UNCACHED_ADDR(a) (a) |
95 | #else | 95 | |
96 | #define UNCACHED_ADDR(a) \ | 96 | #else /* !BOOTLOADER */ |
97 | ((typeof (a))((uintptr_t)(a) | 0x10000000)) | 97 | |
98 | #if CONFIG_CPU == PP5002 | ||
99 | #define UNCACHED_BASE_ADDR 0x28000000 | ||
100 | #else /* PP502x */ | ||
101 | #define UNCACHED_BASE_ADDR 0x10000000 | ||
98 | #endif | 102 | #endif |
99 | 103 | ||
100 | #ifdef CPU_PP502x | 104 | #define UNCACHED_ADDR(a) \ |
105 | ((typeof (a))((uintptr_t)(a) | UNCACHED_BASE_ADDR)) | ||
106 | #endif /* BOOTLOADER */ | ||
101 | 107 | ||
102 | /* Certain data needs to be out of the way of cache line interference | 108 | /* Certain data needs to be out of the way of cache line interference |
103 | * such as data for COP use or for use with UNCACHED_ADDR */ | 109 | * such as data for COP use or for use with UNCACHED_ADDR */ |
@@ -115,8 +121,6 @@ void invalidate_icache(void); | |||
115 | void flush_icache(void); | 121 | void flush_icache(void); |
116 | #endif | 122 | #endif |
117 | 123 | ||
118 | #endif /* CPU_PP502x */ | ||
119 | |||
120 | #endif /* CPU_PP */ | 124 | #endif /* CPU_PP */ |
121 | 125 | ||
122 | #endif /* SYSTEM_TARGET_H */ | 126 | #endif /* SYSTEM_TARGET_H */ |
diff --git a/firmware/thread.c b/firmware/thread.c index 126cc41c0f..37157be245 100644 --- a/firmware/thread.c +++ b/firmware/thread.c | |||
@@ -245,6 +245,20 @@ static int * const idle_stacks[NUM_CORES] NOCACHEDATA_ATTR = | |||
245 | [CPU] = cpu_idlestackbegin, | 245 | [CPU] = cpu_idlestackbegin, |
246 | [COP] = cop_idlestackbegin | 246 | [COP] = cop_idlestackbegin |
247 | }; | 247 | }; |
248 | |||
249 | #if CONFIG_CPU == PP5002 | ||
250 | /* Bytes to emulate the PP502x mailbox bits */ | ||
251 | struct core_semaphores | ||
252 | { | ||
253 | volatile uint8_t intend_wake; /* 00h */ | ||
254 | volatile uint8_t stay_awake; /* 01h */ | ||
255 | volatile uint8_t intend_sleep; /* 02h */ | ||
256 | volatile uint8_t unused; /* 03h */ | ||
257 | }; | ||
258 | |||
259 | static struct core_semaphores core_semaphores[NUM_CORES] NOCACHEBSS_ATTR; | ||
260 | #endif | ||
261 | |||
248 | #endif /* NUM_CORES */ | 262 | #endif /* NUM_CORES */ |
249 | 263 | ||
250 | #if CONFIG_CORELOCK == SW_CORELOCK | 264 | #if CONFIG_CORELOCK == SW_CORELOCK |
@@ -391,10 +405,22 @@ void corelock_unlock(struct corelock *cl) | |||
391 | * no other core requested a wakeup for it to perform a task. | 405 | * no other core requested a wakeup for it to perform a task. |
392 | *--------------------------------------------------------------------------- | 406 | *--------------------------------------------------------------------------- |
393 | */ | 407 | */ |
394 | static inline void core_sleep(IF_COP(unsigned int core,) struct thread_entry **waking) | 408 | #if NUM_CORES == 1 |
409 | /* Shared single-core build debugging version */ | ||
410 | static inline void core_sleep(struct thread_entry **waking) | ||
411 | { | ||
412 | set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); | ||
413 | if (*waking == NULL) | ||
414 | { | ||
415 | PROC_CTL(CURRENT_CORE) = PROC_SLEEP; | ||
416 | nop; nop; nop; | ||
417 | } | ||
418 | set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS); | ||
419 | } | ||
420 | #elif defined (CPU_PP502x) | ||
421 | static inline void core_sleep(unsigned int core, | ||
422 | struct thread_entry **waking) | ||
395 | { | 423 | { |
396 | #if NUM_CORES > 1 | ||
397 | #ifdef CPU_PP502x | ||
398 | #if 1 | 424 | #if 1 |
399 | /* Disabling IRQ and FIQ is important to making the fixed-time sequence | 425 | /* Disabling IRQ and FIQ is important to making the fixed-time sequence |
400 | * non-interruptable */ | 426 | * non-interruptable */ |
@@ -448,29 +474,83 @@ static inline void core_sleep(IF_COP(unsigned int core,) struct thread_entry **w | |||
448 | /* Enable IRQ, FIQ */ | 474 | /* Enable IRQ, FIQ */ |
449 | set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS); | 475 | set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS); |
450 | #endif /* ASM/C selection */ | 476 | #endif /* ASM/C selection */ |
451 | #else | 477 | } |
452 | /* TODO: PP5002 */ | 478 | #elif CONFIG_CPU == PP5002 |
453 | #endif /* CONFIG_CPU == */ | 479 | /* PP5002 has no mailboxes - emulate using bytes */ |
454 | #else | 480 | static inline void core_sleep(unsigned int core, |
481 | struct thread_entry **waking) | ||
482 | { | ||
483 | #if 1 | ||
484 | asm volatile ( | ||
485 | "mrs r1, cpsr \n" /* Disable IRQ, FIQ */ | ||
486 | "orr r1, r1, #0xc0 \n" | ||
487 | "msr cpsr_c, r1 \n" | ||
488 | "mov r0, #1 \n" /* Signal intent to sleep */ | ||
489 | "strb r0, [%[sem], #2] \n" | ||
490 | "ldr r0, [%[waking]] \n" /* *waking == NULL? */ | ||
491 | "cmp r0, #0 \n" | ||
492 | "ldreqb r0, [%[sem], #1] \n" /* && stay_awake == 0? */ | ||
493 | "cmpeq r0, #0 \n" | ||
494 | "moveq r0, #0xca \n" /* Then sleep */ | ||
495 | "streqb r0, [%[ctl], %[c], lsl #2] \n" | ||
496 | "nop \n" /* nop's needed because of pipeline */ | ||
497 | "nop \n" | ||
498 | "nop \n" | ||
499 | "mov r0, #0 \n" /* Clear stay_awake and sleep intent */ | ||
500 | "strb r0, [%[sem], #1] \n" | ||
501 | "strb r0, [%[sem], #2] \n" | ||
502 | "1: \n" /* Wait for wake procedure to finish */ | ||
503 | "ldrb r0, [%[sem], #0] \n" | ||
504 | "cmp r0, #0 \n" | ||
505 | "bne 1b \n" | ||
506 | "bic r1, r1, #0xc0 \n" /* Enable interrupts */ | ||
507 | "msr cpsr_c, r1 \n" | ||
508 | : | ||
509 | : [sem]"r"(&core_semaphores[core]), [c]"r"(core), | ||
510 | [waking]"r"(waking), [ctl]"r"(&PROC_CTL(CPU)) | ||
511 | : "r0", "r1" | ||
512 | ); | ||
513 | #else /* C version for reference */ | ||
514 | /* Disable IRQ, FIQ */ | ||
455 | set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); | 515 | set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); |
456 | if (*waking == NULL) | 516 | |
517 | /* Signal intent to sleep */ | ||
518 | core_semaphores[core].intend_sleep = 1; | ||
519 | |||
520 | /* Something waking or other processor intends to wake us? */ | ||
521 | if (*waking == NULL && core_semaphores[core].stay_awake == 0) | ||
457 | { | 522 | { |
458 | PROC_CTL(IF_COP_CORE(core)) = PROC_SLEEP; | 523 | PROC_CTL(core) = PROC_SLEEP; /* Snooze */ |
524 | nop; nop; nop; | ||
459 | } | 525 | } |
526 | |||
527 | /* Signal wake - clear wake flag */ | ||
528 | core_semaphores[core].stay_awake = 0; | ||
529 | core_semaphores[core].intend_sleep = 0; | ||
530 | |||
531 | /* Wait for other processor to finish wake procedure */ | ||
532 | while (core_semaphores[core].intend_wake != 0); | ||
533 | |||
534 | /* Enable IRQ, FIQ */ | ||
460 | set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS); | 535 | set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS); |
461 | #endif /* NUM_CORES */ | 536 | #endif /* ASM/C selection */ |
462 | } | 537 | } |
538 | #endif /* CPU type */ | ||
463 | 539 | ||
464 | /*--------------------------------------------------------------------------- | 540 | /*--------------------------------------------------------------------------- |
465 | * Wake another processor core that is sleeping or prevent it from doing so | 541 | * Wake another processor core that is sleeping or prevent it from doing so |
466 | * if it was already destined. FIQ, IRQ should be disabled before calling. | 542 | * if it was already destined. FIQ, IRQ should be disabled before calling. |
467 | *--------------------------------------------------------------------------- | 543 | *--------------------------------------------------------------------------- |
468 | */ | 544 | */ |
469 | void core_wake(IF_COP_VOID(unsigned int othercore)) | ||
470 | { | ||
471 | #if NUM_CORES == 1 | 545 | #if NUM_CORES == 1 |
546 | /* Shared single-core build debugging version */ | ||
547 | void core_wake(void) | ||
548 | { | ||
472 | /* No wakey - core already wakey */ | 549 | /* No wakey - core already wakey */ |
550 | } | ||
473 | #elif defined (CPU_PP502x) | 551 | #elif defined (CPU_PP502x) |
552 | void core_wake(unsigned int othercore) | ||
553 | { | ||
474 | #if 1 | 554 | #if 1 |
475 | /* avoid r0 since that contains othercore */ | 555 | /* avoid r0 since that contains othercore */ |
476 | asm volatile ( | 556 | asm volatile ( |
@@ -494,7 +574,8 @@ void core_wake(IF_COP_VOID(unsigned int othercore)) | |||
494 | "str r1, [%[mbx], #8] \n" /* Done with wake procedure */ | 574 | "str r1, [%[mbx], #8] \n" /* Done with wake procedure */ |
495 | "msr cpsr_c, r3 \n" /* Restore int status */ | 575 | "msr cpsr_c, r3 \n" /* Restore int status */ |
496 | : | 576 | : |
497 | : [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), [oc]"r" (othercore) | 577 | : [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), |
578 | [oc]"r"(othercore) | ||
498 | : "r1", "r2", "r3"); | 579 | : "r1", "r2", "r3"); |
499 | #else /* C version for reference */ | 580 | #else /* C version for reference */ |
500 | /* Disable interrupts - avoid reentrancy from the tick */ | 581 | /* Disable interrupts - avoid reentrancy from the tick */ |
@@ -509,18 +590,68 @@ void core_wake(IF_COP_VOID(unsigned int othercore)) | |||
509 | 590 | ||
510 | /* If sleeping, wake it up */ | 591 | /* If sleeping, wake it up */ |
511 | if (PROC_CTL(othercore) & PROC_SLEEP) | 592 | if (PROC_CTL(othercore) & PROC_SLEEP) |
512 | { | ||
513 | PROC_CTL(othercore) = 0; | 593 | PROC_CTL(othercore) = 0; |
514 | } | ||
515 | 594 | ||
516 | /* Done with wake procedure */ | 595 | /* Done with wake procedure */ |
517 | MBX_MSG_CLR = 0x1 << othercore; | 596 | MBX_MSG_CLR = 0x1 << othercore; |
518 | set_irq_level(oldlevel); | 597 | set_irq_level(oldlevel); |
519 | #endif /* ASM/C selection */ | 598 | #endif /* ASM/C selection */ |
520 | #else | ||
521 | PROC_CTL(othercore) = PROC_WAKE; | ||
522 | #endif | ||
523 | } | 599 | } |
600 | #elif CONFIG_CPU == PP5002 | ||
601 | /* PP5002 has no mailboxes - emulate using bytes */ | ||
602 | void core_wake(unsigned int othercore) | ||
603 | { | ||
604 | #if 1 | ||
605 | /* avoid r0 since that contains othercore */ | ||
606 | asm volatile ( | ||
607 | "mrs r3, cpsr \n" /* Disable IRQ */ | ||
608 | "orr r1, r3, #0x80 \n" | ||
609 | "msr cpsr_c, r1 \n" | ||
610 | "mov r1, #1 \n" /* Signal intent to wake other core */ | ||
611 | "orr r1, r1, r1, lsl #8 \n" /* and set stay_awake */ | ||
612 | "strh r1, [%[sem], #0] \n" | ||
613 | "mov r2, #0x8000 \n" | ||
614 | "1: \n" /* If it intends to sleep, let it first */ | ||
615 | "ldrb r1, [%[sem], #2] \n" /* intend_sleep != 0 ? */ | ||
616 | "cmp r1, #1 \n" | ||
617 | "ldr r1, [%[st]] \n" /* && not sleeping ? */ | ||
618 | "tsteq r1, r2, lsr %[oc] \n" | ||
619 | "beq 1b \n" /* Wait for sleep or wake */ | ||
620 | "tst r1, r2, lsr %[oc] \n" | ||
621 | "ldrne r2, =0xcf004054 \n" /* If sleeping, wake it */ | ||
622 | "movne r1, #0xce \n" | ||
623 | "strneb r1, [r2, %[oc], lsl #2] \n" | ||
624 | "mov r1, #0 \n" /* Done with wake procedure */ | ||
625 | "strb r1, [%[sem], #0] \n" | ||
626 | "msr cpsr_c, r3 \n" /* Restore int status */ | ||
627 | : | ||
628 | : [sem]"r"(&core_semaphores[othercore]), | ||
629 | [st]"r"(&PROC_STAT), | ||
630 | [oc]"r"(othercore) | ||
631 | : "r1", "r2", "r3" | ||
632 | ); | ||
633 | #else /* C version for reference */ | ||
634 | /* Disable interrupts - avoid reentrancy from the tick */ | ||
635 | int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
636 | |||
637 | /* Signal intent to wake other processor - set stay awake */ | ||
638 | core_semaphores[othercore].intend_wake = 1; | ||
639 | core_semaphores[othercore].stay_awake = 1; | ||
640 | |||
641 | /* If it intends to sleep, wait until it does or aborts */ | ||
642 | while (core_semaphores[othercore].intend_sleep != 0 && | ||
643 | (PROC_STAT & PROC_SLEEPING(othercore)) == 0); | ||
644 | |||
645 | /* If sleeping, wake it up */ | ||
646 | if (PROC_STAT & PROC_SLEEPING(othercore)) | ||
647 | PROC_CTL(othercore) = PROC_WAKE; | ||
648 | |||
649 | /* Done with wake procedure */ | ||
650 | core_semaphores[othercore].intend_wake = 0; | ||
651 | set_irq_level(oldlevel); | ||
652 | #endif /* ASM/C selection */ | ||
653 | } | ||
654 | #endif /* CPU type */ | ||
524 | 655 | ||
525 | #if NUM_CORES > 1 | 656 | #if NUM_CORES > 1 |
526 | /*--------------------------------------------------------------------------- | 657 | /*--------------------------------------------------------------------------- |
@@ -2539,10 +2670,13 @@ void init_threads(void) | |||
2539 | #if NUM_CORES > 1 /* This code path will not be run on single core targets */ | 2670 | #if NUM_CORES > 1 /* This code path will not be run on single core targets */ |
2540 | /* TODO: HAL interface for this */ | 2671 | /* TODO: HAL interface for this */ |
2541 | /* Wake up coprocessor and let it initialize kernel and threads */ | 2672 | /* Wake up coprocessor and let it initialize kernel and threads */ |
2673 | #ifdef CPU_PP502x | ||
2542 | MBX_MSG_CLR = 0x3f; | 2674 | MBX_MSG_CLR = 0x3f; |
2675 | #endif | ||
2543 | COP_CTL = PROC_WAKE; | 2676 | COP_CTL = PROC_WAKE; |
2544 | /* Sleep until finished */ | 2677 | /* Sleep until finished */ |
2545 | CPU_CTL = PROC_SLEEP; | 2678 | CPU_CTL = PROC_SLEEP; |
2679 | nop; nop; nop; nop; | ||
2546 | } | 2680 | } |
2547 | else | 2681 | else |
2548 | { | 2682 | { |