forked from len0rd/rockbox
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
This commit is contained in:
parent
0ade09bd6b
commit
a8b388fb86
8 changed files with 362 additions and 146 deletions
|
|
@ -369,14 +369,6 @@ SECTIONS
|
||||||
} > IRAM
|
} > IRAM
|
||||||
|
|
||||||
#if defined(CPU_COLDFIRE) || defined(CPU_ARM)
|
#if defined(CPU_COLDFIRE) || defined(CPU_ARM)
|
||||||
.stack :
|
|
||||||
{
|
|
||||||
*(.stack)
|
|
||||||
stackbegin = .;
|
|
||||||
. += 0x2000;
|
|
||||||
stackend = .;
|
|
||||||
} > IRAM
|
|
||||||
|
|
||||||
#ifdef CPU_PP
|
#ifdef CPU_PP
|
||||||
.idle_stacks :
|
.idle_stacks :
|
||||||
{
|
{
|
||||||
|
|
@ -392,6 +384,14 @@ SECTIONS
|
||||||
} > IRAM
|
} > IRAM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
.stack :
|
||||||
|
{
|
||||||
|
*(.stack)
|
||||||
|
stackbegin = .;
|
||||||
|
. += 0x2000;
|
||||||
|
stackend = .;
|
||||||
|
} > IRAM
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* TRICK ALERT! We want 0x2000 bytes of stack, but we set the section
|
/* TRICK ALERT! We want 0x2000 bytes of stack, but we set the section
|
||||||
size smaller, and allow the stack to grow into the .iram copy */
|
size smaller, and allow the stack to grow into the .iram copy */
|
||||||
|
|
|
||||||
|
|
@ -423,7 +423,7 @@
|
||||||
#define IDLE_STACK_SIZE 0x80
|
#define IDLE_STACK_SIZE 0x80
|
||||||
#define IDLE_STACK_WORDS 0x20
|
#define IDLE_STACK_WORDS 0x20
|
||||||
|
|
||||||
#if !defined(FORCE_SINGLE_CORE) && CONFIG_CPU != PP5002
|
#if !defined(FORCE_SINGLE_CORE)
|
||||||
|
|
||||||
#define NUM_CORES 2
|
#define NUM_CORES 2
|
||||||
#define CURRENT_CORE current_core()
|
#define CURRENT_CORE current_core()
|
||||||
|
|
@ -436,7 +436,7 @@
|
||||||
#define IF_COP_VOID(...) __VA_ARGS__
|
#define IF_COP_VOID(...) __VA_ARGS__
|
||||||
#define IF_COP_CORE(core) core
|
#define IF_COP_CORE(core) core
|
||||||
|
|
||||||
#if CONFIG_CPU == PP5020
|
#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
|
||||||
#define CONFIG_CORELOCK SW_CORELOCK /* SWP(B) is broken */
|
#define CONFIG_CORELOCK SW_CORELOCK /* SWP(B) is broken */
|
||||||
#else
|
#else
|
||||||
#define CONFIG_CORELOCK CORELOCK_SWAP
|
#define CONFIG_CORELOCK CORELOCK_SWAP
|
||||||
|
|
|
||||||
|
|
@ -141,14 +141,32 @@
|
||||||
#define PP_VER3 (*(volatile unsigned long *)(0xcf004038))
|
#define PP_VER3 (*(volatile unsigned long *)(0xcf004038))
|
||||||
#define PP_VER4 (*(volatile unsigned long *)(0xcf00403c))
|
#define PP_VER4 (*(volatile unsigned long *)(0xcf00403c))
|
||||||
|
|
||||||
|
/* Processors Control */
|
||||||
|
#define PROC_STAT (*(volatile unsigned long *)(0xcf004050))
|
||||||
#define CPU_CTL (*(volatile unsigned char *)(0xcf004054))
|
#define CPU_CTL (*(volatile unsigned char *)(0xcf004054))
|
||||||
#define COP_CTL (*(volatile unsigned char *)(0xcf004058))
|
#define COP_CTL (*(volatile unsigned char *)(0xcf004058))
|
||||||
|
|
||||||
|
#define CPU_SLEEPING 0x8000
|
||||||
|
#define COP_SLEEPING 0x4000
|
||||||
|
#define PROC_SLEEPING(core) (0x8000 >> (core))
|
||||||
|
|
||||||
#define PROC_CTL(core) ((&CPU_CTL)[(core)*4])
|
#define PROC_CTL(core) ((&CPU_CTL)[(core)*4])
|
||||||
|
|
||||||
#define PROC_SLEEP 0xca
|
#define PROC_SLEEP 0xca
|
||||||
#define PROC_WAKE 0xce
|
#define PROC_WAKE 0xce
|
||||||
|
|
||||||
|
/* Cache Control */
|
||||||
|
#define CACHE_CTL (*(volatile unsigned long *)(0xcf004024))
|
||||||
|
#define CACHE_RUN 0x1
|
||||||
|
#define CACHE_INIT 0x2
|
||||||
|
|
||||||
|
#define CACHE_MASK (*(volatile unsigned long *)(0xf000f020))
|
||||||
|
#define CACHE_OPERATION (*(volatile unsigned long *)(0xf000f024))
|
||||||
|
#define CACHE_FLUSH_BASE (*(volatile unsigned long *)(0xf000c000))
|
||||||
|
#define CACHE_INVALIDATE_BASE (*(volatile unsigned long *)(0xf0004000))
|
||||||
|
#define CACHE_SIZE 0x2000 /* PP5002 has 8KB cache */
|
||||||
|
|
||||||
|
#define CACHE_OP_UNKNOWN1 (1<<11) /* 0x800 */
|
||||||
|
|
||||||
#define DEV_EN (*(volatile unsigned long *)(0xcf005000))
|
#define DEV_EN (*(volatile unsigned long *)(0xcf005000))
|
||||||
#define DEV_RS (*(volatile unsigned long *)(0xcf005030))
|
#define DEV_RS (*(volatile unsigned long *)(0xcf005030))
|
||||||
|
|
|
||||||
|
|
@ -33,20 +33,28 @@ start:
|
||||||
*/
|
*/
|
||||||
#if CONFIG_CPU == PP5002
|
#if CONFIG_CPU == PP5002
|
||||||
.equ PROC_ID, 0xc4000000
|
.equ PROC_ID, 0xc4000000
|
||||||
|
.equ CPU_CTRL, 0xcf004054
|
||||||
|
.equ CPU_STATUS, 0xcf004050
|
||||||
.equ COP_CTRL, 0xcf004058
|
.equ COP_CTRL, 0xcf004058
|
||||||
.equ COP_STATUS, 0xcf004050
|
.equ COP_STATUS, 0xcf004050
|
||||||
.equ IIS_CONFIG, 0xc0002500
|
.equ IIS_CONFIG, 0xc0002500
|
||||||
.equ SLEEP, 0xca
|
.equ SLEEP, 0xca
|
||||||
.equ WAKE, 0xce
|
.equ WAKE, 0xce
|
||||||
.equ SLEEPING, 0x4000
|
.equ CPUSLEEPING, 0x8000
|
||||||
|
.equ COPSLEEPING, 0x4000
|
||||||
|
.equ CACHE_CTRL, 0xcf004024
|
||||||
|
.equ CACHE_ENAB, 0x2 /* Actually the CACHE_INIT flag */
|
||||||
#else
|
#else
|
||||||
.equ PROC_ID, 0x60000000
|
.equ PROC_ID, 0x60000000
|
||||||
|
.equ CPU_CTRL, 0x60007000
|
||||||
|
.equ CPU_STATUS, 0x60007000
|
||||||
.equ COP_CTRL, 0x60007004
|
.equ COP_CTRL, 0x60007004
|
||||||
.equ COP_STATUS, 0x60007004
|
.equ COP_STATUS, 0x60007004
|
||||||
.equ IIS_CONFIG, 0x70002800
|
.equ IIS_CONFIG, 0x70002800
|
||||||
.equ SLEEP, 0x80000000
|
.equ SLEEP, 0x80000000
|
||||||
.equ WAKE, 0x0
|
.equ WAKE, 0x0
|
||||||
.equ SLEEPING, 0x80000000
|
.equ CPUSLEEPING, 0x80000000
|
||||||
|
.equ COPSLEEPING, 0x80000000
|
||||||
.equ CACHE_CTRL, 0x6000c000
|
.equ CACHE_CTRL, 0x6000c000
|
||||||
.equ CACHE_ENAB, 0x1
|
.equ CACHE_ENAB, 0x1
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -94,23 +102,12 @@ cop:
|
||||||
ldr r0, =COP_CTRL
|
ldr r0, =COP_CTRL
|
||||||
mov r1, #SLEEP
|
mov r1, #SLEEP
|
||||||
str r1, [r0]
|
str r1, [r0]
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
#ifdef CPU_PP502x
|
/* Invalidate cache */
|
||||||
/* COP: Invalidate cache if enabled */
|
mov r0, #1
|
||||||
ldr r2, =CACHE_CTRL
|
bl cache_op
|
||||||
ldr r1, [r2]
|
|
||||||
tst r1, #CACHE_ENAB
|
|
||||||
beq 2f
|
|
||||||
ldr r0, =0xf000f044
|
|
||||||
ldr r1, [r0]
|
|
||||||
orr r1, r1, #0x6
|
|
||||||
str r1, [r0]
|
|
||||||
1:
|
|
||||||
ldr r1, [r2]
|
|
||||||
tst r1, #0x8000
|
|
||||||
bne 1b
|
|
||||||
2:
|
|
||||||
#endif /* CPU_PP502x */
|
|
||||||
|
|
||||||
ldr r0, =startup_loc
|
ldr r0, =startup_loc
|
||||||
ldr pc, [r0]
|
ldr pc, [r0]
|
||||||
|
|
@ -120,7 +117,7 @@ cpu:
|
||||||
ldr r0, =COP_STATUS
|
ldr r0, =COP_STATUS
|
||||||
1:
|
1:
|
||||||
ldr r1, [r0]
|
ldr r1, [r0]
|
||||||
tst r1, #SLEEPING
|
tst r1, #COPSLEEPING
|
||||||
beq 1b
|
beq 1b
|
||||||
|
|
||||||
/* Initialise bss section to zero */
|
/* Initialise bss section to zero */
|
||||||
|
|
@ -148,22 +145,9 @@ cpu:
|
||||||
ldr r1, =startup_loc
|
ldr r1, =startup_loc
|
||||||
str r0, [r1]
|
str r0, [r1]
|
||||||
|
|
||||||
#ifdef CPU_PP502x
|
/* flush cache */
|
||||||
/* Flush cache if enabled */
|
mov r0, #0
|
||||||
ldr r2, =CACHE_CTRL
|
bl cache_op
|
||||||
ldr r1, [r2]
|
|
||||||
tst r1, #CACHE_ENAB
|
|
||||||
beq 2f
|
|
||||||
ldr r0, =0xf000f044
|
|
||||||
ldr r1, [r0]
|
|
||||||
orr r1, r1, #0x2
|
|
||||||
str r1, [r0]
|
|
||||||
1:
|
|
||||||
ldr r1, [r2]
|
|
||||||
tst r1, #0x8000
|
|
||||||
bne 1b
|
|
||||||
2:
|
|
||||||
#endif /* CPU_PP502x */
|
|
||||||
|
|
||||||
/* Wake up the coprocessor before executing the firmware */
|
/* Wake up the coprocessor before executing the firmware */
|
||||||
ldr r0, =COP_CTRL
|
ldr r0, =COP_CTRL
|
||||||
|
|
@ -192,3 +176,32 @@ boot_table:
|
||||||
code+data must stay <= 256 bytes */
|
code+data must stay <= 256 bytes */
|
||||||
.space 400
|
.space 400
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
cache_op:
|
||||||
|
ldr r2, =CACHE_CTRL
|
||||||
|
ldr r1, [r2]
|
||||||
|
tst r1, #CACHE_ENAB
|
||||||
|
bxeq lr
|
||||||
|
cmp r0, #0
|
||||||
|
#ifdef CPU_PP502x
|
||||||
|
ldr r0, =0xf000f044
|
||||||
|
ldr r1, [r0]
|
||||||
|
orrne r1, r1, #0x6
|
||||||
|
orreq r1, r1, #0x2
|
||||||
|
str r1, [r0]
|
||||||
|
1:
|
||||||
|
ldr r1, [r2]
|
||||||
|
tst r1, #0x8000
|
||||||
|
bne 1b
|
||||||
|
#elif CONFIG_CPU == PP5002
|
||||||
|
ldrne r0, =0xf0004000
|
||||||
|
ldreq r0, =0xf000c000
|
||||||
|
add r1, r0, #0x2000
|
||||||
|
mov r2, #0
|
||||||
|
1:
|
||||||
|
cmp r1, r0
|
||||||
|
strhi r2, [r0], #16
|
||||||
|
bhi 1b
|
||||||
|
#endif /* CPU type */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,17 +37,20 @@ start:
|
||||||
.equ CPU_CTRL, 0xcf004054
|
.equ CPU_CTRL, 0xcf004054
|
||||||
.equ COP_ICLR, 0xcf001038
|
.equ COP_ICLR, 0xcf001038
|
||||||
.equ COP_CTRL, 0xcf004058
|
.equ COP_CTRL, 0xcf004058
|
||||||
|
.equ CPU_STATUS, 0xcf004050
|
||||||
.equ COP_STATUS, 0xcf004050
|
.equ COP_STATUS, 0xcf004050
|
||||||
.equ IIS_CONFIG, 0xc0002500
|
.equ IIS_CONFIG, 0xc0002500
|
||||||
.equ SLEEP, 0x000000ca
|
.equ SLEEP, 0x000000ca
|
||||||
.equ WAKE, 0x000000ce
|
.equ WAKE, 0x000000ce
|
||||||
.equ SLEEPING, 0x00004000
|
.equ CPUSLEEPING, 0x00008000
|
||||||
.equ MMAP_LOG, 0xf000f010 /* MMAP2 */
|
.equ COPSLEEPING, 0x00004000
|
||||||
.equ MMAP_PHYS, 0xf000f014
|
.equ CACHE_CTRL, 0xcf004024
|
||||||
|
.equ MMAP_LOG, 0xf000f000 /* MMAP0 */
|
||||||
|
.equ MMAP_PHYS, 0xf000f004
|
||||||
#if MEM > 32
|
#if MEM > 32
|
||||||
.equ MMAP_MASK, 0x00007400
|
.equ MMAP_MASK, 0x00003c00
|
||||||
#else
|
#else
|
||||||
.equ MMAP_MASK, 0x00003a00
|
.equ MMAP_MASK, 0x00003e00
|
||||||
#endif
|
#endif
|
||||||
.equ MMAP_FLAGS, 0x00003f84
|
.equ MMAP_FLAGS, 0x00003f84
|
||||||
#else
|
#else
|
||||||
|
|
@ -61,7 +64,8 @@ start:
|
||||||
.equ IIS_CONFIG, 0x70002800
|
.equ IIS_CONFIG, 0x70002800
|
||||||
.equ SLEEP, 0x80000000
|
.equ SLEEP, 0x80000000
|
||||||
.equ WAKE, 0x00000000
|
.equ WAKE, 0x00000000
|
||||||
.equ SLEEPING, 0x80000000
|
.equ CPUSLEEPING, 0x80000000
|
||||||
|
.equ COPSLEEPING, 0x80000000
|
||||||
.equ CACHE_CTRL, 0x6000c000
|
.equ CACHE_CTRL, 0x6000c000
|
||||||
.equ MMAP_LOG, 0xf000f000 /* MMAP0 */
|
.equ MMAP_LOG, 0xf000f000 /* MMAP0 */
|
||||||
.equ MMAP_PHYS, 0xf000f004
|
.equ MMAP_PHYS, 0xf000f004
|
||||||
|
|
@ -111,21 +115,22 @@ pad_skip:
|
||||||
ldrne r2, =COP_CTRL
|
ldrne r2, =COP_CTRL
|
||||||
movne r1, #SLEEP
|
movne r1, #SLEEP
|
||||||
strne r1, [r2]
|
strne r1, [r2]
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
/* wait for co-processor to sleep then CPU can begin its remapping */
|
/* wait for co-processor to sleep then CPU can begin its remapping */
|
||||||
ldreq r2, =COP_STATUS
|
ldreq r2, =COP_STATUS
|
||||||
1:
|
1:
|
||||||
ldreq r1, [r2]
|
ldreq r1, [r2]
|
||||||
tsteq r1, #SLEEPING
|
tsteq r1, #COPSLEEPING
|
||||||
beq 1b
|
beq 1b
|
||||||
|
|
||||||
#ifdef CPU_PP502x
|
|
||||||
/* disable cache and local interrupt vectors - it is really not desireable
|
/* disable cache and local interrupt vectors - it is really not desireable
|
||||||
to have them enabled here */
|
to have them enabled here */
|
||||||
ldr r2, =CACHE_CTRL
|
ldr r2, =CACHE_CTRL
|
||||||
mov r1, #0
|
mov r1, #0
|
||||||
str r1, [r2]
|
str r1, [r2]
|
||||||
#endif
|
|
||||||
|
|
||||||
mov r2, #0x40000000
|
mov r2, #0x40000000
|
||||||
ldr r3, =remap_start
|
ldr r3, =remap_start
|
||||||
|
|
@ -165,6 +170,9 @@ remap_end:
|
||||||
/* Sleep us (co-processor) and wait for CPU to do kernel initialization */
|
/* Sleep us (co-processor) and wait for CPU to do kernel initialization */
|
||||||
movne r3, #SLEEP
|
movne r3, #SLEEP
|
||||||
str r3, [r4]
|
str r3, [r4]
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
/* Jump to co-processor init */
|
/* Jump to co-processor init */
|
||||||
ldrne pc, =cop_init
|
ldrne pc, =cop_init
|
||||||
|
|
@ -174,7 +182,7 @@ cpu_init:
|
||||||
ldr r4, =COP_STATUS
|
ldr r4, =COP_STATUS
|
||||||
1:
|
1:
|
||||||
ldr r3, [r4]
|
ldr r3, [r4]
|
||||||
tst r3, #SLEEPING
|
tst r3, #COPSLEEPING
|
||||||
beq 1b
|
beq 1b
|
||||||
|
|
||||||
/* Copy exception handler code to address 0 */
|
/* Copy exception handler code to address 0 */
|
||||||
|
|
@ -275,7 +283,7 @@ cop_init:
|
||||||
ldr r4, =CPU_STATUS
|
ldr r4, =CPU_STATUS
|
||||||
1:
|
1:
|
||||||
ldr r3, [r4]
|
ldr r3, [r4]
|
||||||
tst r3, #SLEEPING
|
tst r3, #CPUSLEEPING
|
||||||
beq 1b
|
beq 1b
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -377,7 +385,7 @@ UIE:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Align stacks to cache line boundary */
|
/* Align stacks to cache line boundary */
|
||||||
.balign 16
|
.balign 32
|
||||||
|
|
||||||
/* 256 words of IRQ stack */
|
/* 256 words of IRQ stack */
|
||||||
.space 256*4
|
.space 256*4
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,7 @@ void irq(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (COP_INT_STAT & TIMER1_MASK)
|
if (COP_INT_STAT & TIMER2_MASK)
|
||||||
TIMER1();
|
|
||||||
else if (COP_INT_STAT & TIMER2_MASK)
|
|
||||||
TIMER2();
|
TIMER2();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,24 +59,60 @@ void irq(void)
|
||||||
some other CPU frequency scaling. */
|
some other CPU frequency scaling. */
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
static void ipod_init_cache(void)
|
void flush_icache(void) ICODE_ATTR;
|
||||||
|
void flush_icache(void)
|
||||||
{
|
{
|
||||||
int i =0;
|
intptr_t b, e;
|
||||||
/* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
|
|
||||||
outl(inl(0xcf004050) & ~0x700, 0xcf004050);
|
|
||||||
outl(0x4000, 0xcf004020);
|
|
||||||
|
|
||||||
outl(0x2, 0xcf004024);
|
for (b = (intptr_t)&CACHE_FLUSH_BASE, e = b + CACHE_SIZE;
|
||||||
|
b < e; b += 16) {
|
||||||
/* PP5002 has 8KB cache */
|
outl(0x0, b);
|
||||||
for (i = 0xf0004000; i < (int)(0xf0006000); i += 16) {
|
}
|
||||||
outl(0x0, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outl(0x0, 0xf000f020);
|
void invalidate_icache(void) ICODE_ATTR;
|
||||||
outl(0x3fc0, 0xf000f024);
|
void invalidate_icache(void)
|
||||||
|
{
|
||||||
|
intptr_t b, e;
|
||||||
|
|
||||||
outl(0x3, 0xcf004024);
|
/* Flush */
|
||||||
|
for (b = (intptr_t)&CACHE_FLUSH_BASE, e = b + CACHE_SIZE;
|
||||||
|
b < e; b += 16) {
|
||||||
|
outl(0x0, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalidate */
|
||||||
|
for (b = (intptr_t)&CACHE_INVALIDATE_BASE, e = b + CACHE_SIZE;
|
||||||
|
b < e; b += 16) {
|
||||||
|
outl(0x0, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ipod_init_cache(void)
|
||||||
|
{
|
||||||
|
intptr_t b, e;
|
||||||
|
|
||||||
|
/* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
|
||||||
|
PROC_STAT &= ~0x700;
|
||||||
|
outl(0x4000, 0xcf004020);
|
||||||
|
|
||||||
|
CACHE_CTL = CACHE_INIT;
|
||||||
|
|
||||||
|
for (b = (intptr_t)&CACHE_INVALIDATE_BASE, e = b + CACHE_SIZE;
|
||||||
|
b < e; b += 16) {
|
||||||
|
outl(0x0, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cache if (addr & mask) >> 16 == (mask & match) >> 16:
|
||||||
|
* yes: 0x00000000 - 0x03ffffff
|
||||||
|
* no: 0x04000000 - 0x1fffffff
|
||||||
|
* yes: 0x20000000 - 0x23ffffff
|
||||||
|
* no: 0x24000000 - 0x3fffffff <= range containing uncached alias
|
||||||
|
*/
|
||||||
|
CACHE_MASK = 0x00001c00;
|
||||||
|
CACHE_OPERATION = 0x3fc0;
|
||||||
|
|
||||||
|
CACHE_CTL = CACHE_INIT | CACHE_RUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
|
@ -132,9 +166,10 @@ void system_init(void)
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
if (CURRENT_CORE == CPU)
|
if (CURRENT_CORE == CPU)
|
||||||
{
|
{
|
||||||
/* Remap the flash ROM from 0x00000000 to 0x20000000. */
|
/* Remap the flash ROM on CPU, keep hidden from COP:
|
||||||
MMAP3_LOGICAL = 0x20000000 | 0x3a00;
|
* 0x00000000-0x03ffffff = 0x20000000-0x23ffffff */
|
||||||
MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
|
MMAP1_LOGICAL = 0x20003c00;
|
||||||
|
MMAP1_PHYSICAL = 0x00003f84;
|
||||||
|
|
||||||
#if defined(IPOD_1G2G) || defined(IPOD_3G)
|
#if defined(IPOD_1G2G) || defined(IPOD_3G)
|
||||||
DEV_EN = 0x0b9f; /* don't clock unused PP5002 hardware components */
|
DEV_EN = 0x0b9f; /* don't clock unused PP5002 hardware components */
|
||||||
|
|
@ -150,7 +185,11 @@ void system_init(void)
|
||||||
GPIOC_INT_EN = 0;
|
GPIOC_INT_EN = 0;
|
||||||
GPIOD_INT_EN = 0;
|
GPIOD_INT_EN = 0;
|
||||||
|
|
||||||
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
#if NUM_CORES > 1
|
||||||
|
cpu_boost_init();
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
pp_set_cpu_frequency(CPUFREQ_MAX);
|
pp_set_cpu_frequency(CPUFREQ_MAX);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ static inline unsigned int current_core(void)
|
||||||
/* Return the actual ID instead of core index */
|
/* Return the actual ID instead of core index */
|
||||||
static inline unsigned int processor_id(void)
|
static inline unsigned int processor_id(void)
|
||||||
{
|
{
|
||||||
unsigned char id;
|
unsigned int id;
|
||||||
|
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"ldrb %0, [%1] \n"
|
"ldrb %0, [%1] \n"
|
||||||
|
|
@ -92,12 +92,18 @@ static inline unsigned int processor_id(void)
|
||||||
/* All addresses within rockbox are in IRAM in the bootloader so
|
/* All addresses within rockbox are in IRAM in the bootloader so
|
||||||
are therefore uncached */
|
are therefore uncached */
|
||||||
#define UNCACHED_ADDR(a) (a)
|
#define UNCACHED_ADDR(a) (a)
|
||||||
#else
|
|
||||||
#define UNCACHED_ADDR(a) \
|
#else /* !BOOTLOADER */
|
||||||
((typeof (a))((uintptr_t)(a) | 0x10000000))
|
|
||||||
|
#if CONFIG_CPU == PP5002
|
||||||
|
#define UNCACHED_BASE_ADDR 0x28000000
|
||||||
|
#else /* PP502x */
|
||||||
|
#define UNCACHED_BASE_ADDR 0x10000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CPU_PP502x
|
#define UNCACHED_ADDR(a) \
|
||||||
|
((typeof (a))((uintptr_t)(a) | UNCACHED_BASE_ADDR))
|
||||||
|
#endif /* BOOTLOADER */
|
||||||
|
|
||||||
/* Certain data needs to be out of the way of cache line interference
|
/* Certain data needs to be out of the way of cache line interference
|
||||||
* such as data for COP use or for use with UNCACHED_ADDR */
|
* such as data for COP use or for use with UNCACHED_ADDR */
|
||||||
|
|
@ -115,8 +121,6 @@ void invalidate_icache(void);
|
||||||
void flush_icache(void);
|
void flush_icache(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CPU_PP502x */
|
|
||||||
|
|
||||||
#endif /* CPU_PP */
|
#endif /* CPU_PP */
|
||||||
|
|
||||||
#endif /* SYSTEM_TARGET_H */
|
#endif /* SYSTEM_TARGET_H */
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,20 @@ static int * const idle_stacks[NUM_CORES] NOCACHEDATA_ATTR =
|
||||||
[CPU] = cpu_idlestackbegin,
|
[CPU] = cpu_idlestackbegin,
|
||||||
[COP] = cop_idlestackbegin
|
[COP] = cop_idlestackbegin
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_CPU == PP5002
|
||||||
|
/* Bytes to emulate the PP502x mailbox bits */
|
||||||
|
struct core_semaphores
|
||||||
|
{
|
||||||
|
volatile uint8_t intend_wake; /* 00h */
|
||||||
|
volatile uint8_t stay_awake; /* 01h */
|
||||||
|
volatile uint8_t intend_sleep; /* 02h */
|
||||||
|
volatile uint8_t unused; /* 03h */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct core_semaphores core_semaphores[NUM_CORES] NOCACHEBSS_ATTR;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* NUM_CORES */
|
#endif /* NUM_CORES */
|
||||||
|
|
||||||
#if CONFIG_CORELOCK == SW_CORELOCK
|
#if CONFIG_CORELOCK == SW_CORELOCK
|
||||||
|
|
@ -391,10 +405,22 @@ void corelock_unlock(struct corelock *cl)
|
||||||
* no other core requested a wakeup for it to perform a task.
|
* no other core requested a wakeup for it to perform a task.
|
||||||
*---------------------------------------------------------------------------
|
*---------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
static inline void core_sleep(IF_COP(unsigned int core,) struct thread_entry **waking)
|
#if NUM_CORES == 1
|
||||||
|
/* Shared single-core build debugging version */
|
||||||
|
static inline void core_sleep(struct thread_entry **waking)
|
||||||
|
{
|
||||||
|
set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
|
||||||
|
if (*waking == NULL)
|
||||||
|
{
|
||||||
|
PROC_CTL(CURRENT_CORE) = PROC_SLEEP;
|
||||||
|
nop; nop; nop;
|
||||||
|
}
|
||||||
|
set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS);
|
||||||
|
}
|
||||||
|
#elif defined (CPU_PP502x)
|
||||||
|
static inline void core_sleep(unsigned int core,
|
||||||
|
struct thread_entry **waking)
|
||||||
{
|
{
|
||||||
#if NUM_CORES > 1
|
|
||||||
#ifdef CPU_PP502x
|
|
||||||
#if 1
|
#if 1
|
||||||
/* Disabling IRQ and FIQ is important to making the fixed-time sequence
|
/* Disabling IRQ and FIQ is important to making the fixed-time sequence
|
||||||
* non-interruptable */
|
* non-interruptable */
|
||||||
|
|
@ -448,29 +474,83 @@ static inline void core_sleep(IF_COP(unsigned int core,) struct thread_entry **w
|
||||||
/* Enable IRQ, FIQ */
|
/* Enable IRQ, FIQ */
|
||||||
set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS);
|
set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS);
|
||||||
#endif /* ASM/C selection */
|
#endif /* ASM/C selection */
|
||||||
#else
|
}
|
||||||
/* TODO: PP5002 */
|
#elif CONFIG_CPU == PP5002
|
||||||
#endif /* CONFIG_CPU == */
|
/* PP5002 has no mailboxes - emulate using bytes */
|
||||||
#else
|
static inline void core_sleep(unsigned int core,
|
||||||
set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
|
struct thread_entry **waking)
|
||||||
if (*waking == NULL)
|
|
||||||
{
|
{
|
||||||
PROC_CTL(IF_COP_CORE(core)) = PROC_SLEEP;
|
#if 1
|
||||||
|
asm volatile (
|
||||||
|
"mrs r1, cpsr \n" /* Disable IRQ, FIQ */
|
||||||
|
"orr r1, r1, #0xc0 \n"
|
||||||
|
"msr cpsr_c, r1 \n"
|
||||||
|
"mov r0, #1 \n" /* Signal intent to sleep */
|
||||||
|
"strb r0, [%[sem], #2] \n"
|
||||||
|
"ldr r0, [%[waking]] \n" /* *waking == NULL? */
|
||||||
|
"cmp r0, #0 \n"
|
||||||
|
"ldreqb r0, [%[sem], #1] \n" /* && stay_awake == 0? */
|
||||||
|
"cmpeq r0, #0 \n"
|
||||||
|
"moveq r0, #0xca \n" /* Then sleep */
|
||||||
|
"streqb r0, [%[ctl], %[c], lsl #2] \n"
|
||||||
|
"nop \n" /* nop's needed because of pipeline */
|
||||||
|
"nop \n"
|
||||||
|
"nop \n"
|
||||||
|
"mov r0, #0 \n" /* Clear stay_awake and sleep intent */
|
||||||
|
"strb r0, [%[sem], #1] \n"
|
||||||
|
"strb r0, [%[sem], #2] \n"
|
||||||
|
"1: \n" /* Wait for wake procedure to finish */
|
||||||
|
"ldrb r0, [%[sem], #0] \n"
|
||||||
|
"cmp r0, #0 \n"
|
||||||
|
"bne 1b \n"
|
||||||
|
"bic r1, r1, #0xc0 \n" /* Enable interrupts */
|
||||||
|
"msr cpsr_c, r1 \n"
|
||||||
|
:
|
||||||
|
: [sem]"r"(&core_semaphores[core]), [c]"r"(core),
|
||||||
|
[waking]"r"(waking), [ctl]"r"(&PROC_CTL(CPU))
|
||||||
|
: "r0", "r1"
|
||||||
|
);
|
||||||
|
#else /* C version for reference */
|
||||||
|
/* Disable IRQ, FIQ */
|
||||||
|
set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
|
||||||
|
|
||||||
|
/* Signal intent to sleep */
|
||||||
|
core_semaphores[core].intend_sleep = 1;
|
||||||
|
|
||||||
|
/* Something waking or other processor intends to wake us? */
|
||||||
|
if (*waking == NULL && core_semaphores[core].stay_awake == 0)
|
||||||
|
{
|
||||||
|
PROC_CTL(core) = PROC_SLEEP; /* Snooze */
|
||||||
|
nop; nop; nop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Signal wake - clear wake flag */
|
||||||
|
core_semaphores[core].stay_awake = 0;
|
||||||
|
core_semaphores[core].intend_sleep = 0;
|
||||||
|
|
||||||
|
/* Wait for other processor to finish wake procedure */
|
||||||
|
while (core_semaphores[core].intend_wake != 0);
|
||||||
|
|
||||||
|
/* Enable IRQ, FIQ */
|
||||||
set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS);
|
set_interrupt_status(IRQ_FIQ_ENABLED, IRQ_FIQ_STATUS);
|
||||||
#endif /* NUM_CORES */
|
#endif /* ASM/C selection */
|
||||||
}
|
}
|
||||||
|
#endif /* CPU type */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
* Wake another processor core that is sleeping or prevent it from doing so
|
* Wake another processor core that is sleeping or prevent it from doing so
|
||||||
* if it was already destined. FIQ, IRQ should be disabled before calling.
|
* if it was already destined. FIQ, IRQ should be disabled before calling.
|
||||||
*---------------------------------------------------------------------------
|
*---------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void core_wake(IF_COP_VOID(unsigned int othercore))
|
|
||||||
{
|
|
||||||
#if NUM_CORES == 1
|
#if NUM_CORES == 1
|
||||||
|
/* Shared single-core build debugging version */
|
||||||
|
void core_wake(void)
|
||||||
|
{
|
||||||
/* No wakey - core already wakey */
|
/* No wakey - core already wakey */
|
||||||
|
}
|
||||||
#elif defined (CPU_PP502x)
|
#elif defined (CPU_PP502x)
|
||||||
|
void core_wake(unsigned int othercore)
|
||||||
|
{
|
||||||
#if 1
|
#if 1
|
||||||
/* avoid r0 since that contains othercore */
|
/* avoid r0 since that contains othercore */
|
||||||
asm volatile (
|
asm volatile (
|
||||||
|
|
@ -494,7 +574,8 @@ void core_wake(IF_COP_VOID(unsigned int othercore))
|
||||||
"str r1, [%[mbx], #8] \n" /* Done with wake procedure */
|
"str r1, [%[mbx], #8] \n" /* Done with wake procedure */
|
||||||
"msr cpsr_c, r3 \n" /* Restore int status */
|
"msr cpsr_c, r3 \n" /* Restore int status */
|
||||||
:
|
:
|
||||||
: [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), [oc]"r" (othercore)
|
: [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE),
|
||||||
|
[oc]"r"(othercore)
|
||||||
: "r1", "r2", "r3");
|
: "r1", "r2", "r3");
|
||||||
#else /* C version for reference */
|
#else /* C version for reference */
|
||||||
/* Disable interrupts - avoid reentrancy from the tick */
|
/* Disable interrupts - avoid reentrancy from the tick */
|
||||||
|
|
@ -509,18 +590,68 @@ void core_wake(IF_COP_VOID(unsigned int othercore))
|
||||||
|
|
||||||
/* If sleeping, wake it up */
|
/* If sleeping, wake it up */
|
||||||
if (PROC_CTL(othercore) & PROC_SLEEP)
|
if (PROC_CTL(othercore) & PROC_SLEEP)
|
||||||
{
|
|
||||||
PROC_CTL(othercore) = 0;
|
PROC_CTL(othercore) = 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* Done with wake procedure */
|
/* Done with wake procedure */
|
||||||
MBX_MSG_CLR = 0x1 << othercore;
|
MBX_MSG_CLR = 0x1 << othercore;
|
||||||
set_irq_level(oldlevel);
|
set_irq_level(oldlevel);
|
||||||
#endif /* ASM/C selection */
|
#endif /* ASM/C selection */
|
||||||
#else
|
|
||||||
PROC_CTL(othercore) = PROC_WAKE;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_CPU == PP5002
|
||||||
|
/* PP5002 has no mailboxes - emulate using bytes */
|
||||||
|
void core_wake(unsigned int othercore)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
/* avoid r0 since that contains othercore */
|
||||||
|
asm volatile (
|
||||||
|
"mrs r3, cpsr \n" /* Disable IRQ */
|
||||||
|
"orr r1, r3, #0x80 \n"
|
||||||
|
"msr cpsr_c, r1 \n"
|
||||||
|
"mov r1, #1 \n" /* Signal intent to wake other core */
|
||||||
|
"orr r1, r1, r1, lsl #8 \n" /* and set stay_awake */
|
||||||
|
"strh r1, [%[sem], #0] \n"
|
||||||
|
"mov r2, #0x8000 \n"
|
||||||
|
"1: \n" /* If it intends to sleep, let it first */
|
||||||
|
"ldrb r1, [%[sem], #2] \n" /* intend_sleep != 0 ? */
|
||||||
|
"cmp r1, #1 \n"
|
||||||
|
"ldr r1, [%[st]] \n" /* && not sleeping ? */
|
||||||
|
"tsteq r1, r2, lsr %[oc] \n"
|
||||||
|
"beq 1b \n" /* Wait for sleep or wake */
|
||||||
|
"tst r1, r2, lsr %[oc] \n"
|
||||||
|
"ldrne r2, =0xcf004054 \n" /* If sleeping, wake it */
|
||||||
|
"movne r1, #0xce \n"
|
||||||
|
"strneb r1, [r2, %[oc], lsl #2] \n"
|
||||||
|
"mov r1, #0 \n" /* Done with wake procedure */
|
||||||
|
"strb r1, [%[sem], #0] \n"
|
||||||
|
"msr cpsr_c, r3 \n" /* Restore int status */
|
||||||
|
:
|
||||||
|
: [sem]"r"(&core_semaphores[othercore]),
|
||||||
|
[st]"r"(&PROC_STAT),
|
||||||
|
[oc]"r"(othercore)
|
||||||
|
: "r1", "r2", "r3"
|
||||||
|
);
|
||||||
|
#else /* C version for reference */
|
||||||
|
/* Disable interrupts - avoid reentrancy from the tick */
|
||||||
|
int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
|
||||||
|
|
||||||
|
/* Signal intent to wake other processor - set stay awake */
|
||||||
|
core_semaphores[othercore].intend_wake = 1;
|
||||||
|
core_semaphores[othercore].stay_awake = 1;
|
||||||
|
|
||||||
|
/* If it intends to sleep, wait until it does or aborts */
|
||||||
|
while (core_semaphores[othercore].intend_sleep != 0 &&
|
||||||
|
(PROC_STAT & PROC_SLEEPING(othercore)) == 0);
|
||||||
|
|
||||||
|
/* If sleeping, wake it up */
|
||||||
|
if (PROC_STAT & PROC_SLEEPING(othercore))
|
||||||
|
PROC_CTL(othercore) = PROC_WAKE;
|
||||||
|
|
||||||
|
/* Done with wake procedure */
|
||||||
|
core_semaphores[othercore].intend_wake = 0;
|
||||||
|
set_irq_level(oldlevel);
|
||||||
|
#endif /* ASM/C selection */
|
||||||
|
}
|
||||||
|
#endif /* CPU type */
|
||||||
|
|
||||||
#if NUM_CORES > 1
|
#if NUM_CORES > 1
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
|
|
@ -2539,10 +2670,13 @@ void init_threads(void)
|
||||||
#if NUM_CORES > 1 /* This code path will not be run on single core targets */
|
#if NUM_CORES > 1 /* This code path will not be run on single core targets */
|
||||||
/* TODO: HAL interface for this */
|
/* TODO: HAL interface for this */
|
||||||
/* Wake up coprocessor and let it initialize kernel and threads */
|
/* Wake up coprocessor and let it initialize kernel and threads */
|
||||||
|
#ifdef CPU_PP502x
|
||||||
MBX_MSG_CLR = 0x3f;
|
MBX_MSG_CLR = 0x3f;
|
||||||
|
#endif
|
||||||
COP_CTL = PROC_WAKE;
|
COP_CTL = PROC_WAKE;
|
||||||
/* Sleep until finished */
|
/* Sleep until finished */
|
||||||
CPU_CTL = PROC_SLEEP;
|
CPU_CTL = PROC_SLEEP;
|
||||||
|
nop; nop; nop; nop;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue