summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-11-27 01:20:26 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-11-27 01:20:26 +0000
commita8b388fb86096b265780ac682adddcec22005f79 (patch)
treed200d0ef25dcca41eecf5f0565970cc481fedb03
parent0ade09bd6b14f4c27d28d055306ccd63569f5c49 (diff)
downloadrockbox-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
-rw-r--r--firmware/app.lds16
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/export/pp5002.h18
-rw-r--r--firmware/target/arm/crt0-pp-bl.S113
-rw-r--r--firmware/target/arm/crt0-pp.S84
-rw-r--r--firmware/target/arm/system-pp5002.c71
-rw-r--r--firmware/target/arm/system-target.h18
-rw-r--r--firmware/thread.c170
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]
1081:
109 ldr r1, [r2]
110 tst r1, #0x8000
111 bne 1b
1122:
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
1211: 1181:
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]
1611:
162 ldr r1, [r2]
163 tst r1, #0x8000
164 bne 1b
1652:
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
180cache_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]
1921:
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
2011:
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
1171: 1241:
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
1751: 1831:
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
2761: 2841:
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
62void flush_icache(void) ICODE_ATTR;
63void 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
73void invalidate_icache(void) ICODE_ATTR;
74void 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
64static void ipod_init_cache(void) 91static 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 */
78static inline unsigned int processor_id(void) 78static 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);
115void flush_icache(void); 121void 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 */
251struct 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
259static 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 */
394static 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 */
410static 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)
421static 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 480static 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 */
469void 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 */
547void 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)
552void 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 */
602void 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 {