ARM: pm: convert samsung platforms to generic suspend/resume support
Tested-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
96c20015da
commit
2e2f3d3792
|
@ -32,25 +32,13 @@
|
|||
* code after resume.
|
||||
*
|
||||
* entry:
|
||||
* r0 = pointer to the save block
|
||||
* r1 = v:p offset
|
||||
*/
|
||||
|
||||
ENTRY(s3c_cpu_save)
|
||||
stmfd sp!, { r4 - r12, lr }
|
||||
|
||||
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
|
||||
mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
|
||||
mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
|
||||
mrc p15, 0, r9, c1, c0, 0 @ Control register
|
||||
mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
|
||||
mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
|
||||
|
||||
stmia r0, { r4 - r13 } @ Save CP registers and SP
|
||||
|
||||
@@ save our state to ram
|
||||
bl s3c_pm_cb_flushcache
|
||||
ldr r3, =resume_with_mmu
|
||||
bl cpu_suspend
|
||||
|
||||
@@ call final suspend code
|
||||
ldr r0, =pm_cpu_sleep
|
||||
|
@ -61,18 +49,6 @@ ENTRY(s3c_cpu_save)
|
|||
resume_with_mmu:
|
||||
ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
|
||||
|
||||
.data
|
||||
|
||||
/* the next bit is code, but it requires easy access to the
|
||||
* s3c_sleep_save_phys data before the MMU is switched on, so
|
||||
* we store the code that needs this variable in the .data where
|
||||
* the value can be written to (the .text segment is RO).
|
||||
*/
|
||||
|
||||
.global s3c_sleep_save_phys
|
||||
s3c_sleep_save_phys:
|
||||
.word 0
|
||||
|
||||
/* Sleep magic, the word before the resume entry point so that the
|
||||
* bootloader can check for a resumeable image. */
|
||||
|
||||
|
@ -110,35 +86,4 @@ ENTRY(s3c_cpu_resume)
|
|||
orr r0, r0, #1 << 15 @ GPN15
|
||||
str r0, [ r3, #S3C64XX_GPNDAT ]
|
||||
#endif
|
||||
|
||||
/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
|
||||
* are thoroughly cleaned just in case the bootloader didn't do it
|
||||
* for us. */
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
|
||||
mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||
@@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
|
||||
@@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches
|
||||
|
||||
ldr r0, s3c_sleep_save_phys
|
||||
ldmia r0, { r4 - r13 }
|
||||
|
||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
|
||||
mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
|
||||
mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
|
||||
mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
|
||||
|
||||
mov r0, #0 @ restore copro access controls
|
||||
mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
|
||||
mcr p15, 0, r0, c7, c5, 4
|
||||
|
||||
ldr r2, =resume_with_mmu
|
||||
mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
|
||||
nop
|
||||
mov pc, r2 /* jump back */
|
||||
|
||||
.end
|
||||
b cpu_resume
|
||||
|
|
|
@ -35,50 +35,24 @@
|
|||
/* s3c_cpu_save
|
||||
*
|
||||
* entry:
|
||||
* r0 = save address (virtual addr of s3c_sleep_save_phys)
|
||||
* r1 = v:p offset
|
||||
*/
|
||||
|
||||
ENTRY(s3c_cpu_save)
|
||||
|
||||
stmfd sp!, { r3 - r12, lr }
|
||||
|
||||
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
|
||||
mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
|
||||
mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
|
||||
mrc p15, 0, r9, c1, c0, 0 @ Control register
|
||||
mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
|
||||
mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
|
||||
mrc p15, 0, r12, c10, c2, 0 @ Read PRRR
|
||||
mrc p15, 0, r3, c10, c2, 1 @ READ NMRR
|
||||
|
||||
stmia r0, { r3 - r13 }
|
||||
|
||||
bl s3c_pm_cb_flushcache
|
||||
ldr r3, =resume_with_mmu
|
||||
bl cpu_suspend
|
||||
|
||||
ldr r0, =pm_cpu_sleep
|
||||
ldr r0, [ r0 ]
|
||||
mov pc, r0
|
||||
|
||||
resume_with_mmu:
|
||||
/*
|
||||
* After MMU is turned on, restore the previous MMU table.
|
||||
*/
|
||||
ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET)
|
||||
add r4, r4, r9
|
||||
str r12, [r4]
|
||||
|
||||
ldmfd sp!, { r3 - r12, pc }
|
||||
|
||||
.ltorg
|
||||
|
||||
.data
|
||||
|
||||
.global s3c_sleep_save_phys
|
||||
s3c_sleep_save_phys:
|
||||
.word 0
|
||||
|
||||
/* sleep magic, to allow the bootloader to check for an valid
|
||||
* image to resume to. Must be the first word before the
|
||||
* s3c_cpu_resume entry.
|
||||
|
@ -96,75 +70,4 @@ s3c_sleep_save_phys:
|
|||
*/
|
||||
|
||||
ENTRY(s3c_cpu_resume)
|
||||
mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
|
||||
msr cpsr_c, r0
|
||||
|
||||
mov r1, #0
|
||||
mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs
|
||||
mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache
|
||||
|
||||
ldr r0, s3c_sleep_save_phys @ address of restore block
|
||||
ldmia r0, { r3 - r13 }
|
||||
|
||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
|
||||
mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
|
||||
mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
|
||||
mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
|
||||
|
||||
mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB
|
||||
|
||||
mov r0, #0 @ restore copro access
|
||||
mcr p15, 0, r11, c1, c0, 2 @ Co-processor access
|
||||
mcr p15, 0, r0, c7, c5, 4
|
||||
|
||||
mcr p15, 0, r12, c10, c2, 0 @ write PRRR
|
||||
mcr p15, 0, r3, c10, c2, 1 @ write NMRR
|
||||
|
||||
/*
|
||||
* In Cortex-A8, when MMU is turned on, the pipeline is flushed.
|
||||
* And there are no valid entries in the MMU table at this point.
|
||||
* So before turning on the MMU, the MMU entry for the DRAM address
|
||||
* range is added. After the MMU is turned on, the other entries
|
||||
* in the MMU table will be restored.
|
||||
*/
|
||||
|
||||
/* r6 = Translation Table BASE0 */
|
||||
mov r4, r6
|
||||
mov r4, r4, LSR #14
|
||||
mov r4, r4, LSL #14
|
||||
|
||||
/* Load address for adding to MMU table list */
|
||||
ldr r11, =0xE010F000 @ INFORM0 reg.
|
||||
ldr r10, [r11, #0]
|
||||
mov r10, r10, LSR #18
|
||||
bic r10, r10, #0x3
|
||||
orr r4, r4, r10
|
||||
|
||||
/* Calculate MMU table entry */
|
||||
mov r10, r10, LSL #18
|
||||
ldr r5, =0x40E
|
||||
orr r10, r10, r5
|
||||
|
||||
/* Back up originally data */
|
||||
ldr r12, [r4]
|
||||
|
||||
/* Add calculated MMU table entry into MMU table list */
|
||||
str r10, [r4]
|
||||
|
||||
ldr r2, =resume_with_mmu
|
||||
mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop @ second-to-last before mmu
|
||||
|
||||
mov pc, r2 @ go back to virtual address
|
||||
|
||||
.ltorg
|
||||
b cpu_resume
|
||||
|
|
|
@ -44,23 +44,13 @@
|
|||
/* s3c_cpu_save
|
||||
*
|
||||
* entry:
|
||||
* r0 = save address (virtual addr of s3c_sleep_save_phys)
|
||||
* r1 = v:p offset
|
||||
*/
|
||||
|
||||
ENTRY(s3c_cpu_save)
|
||||
stmfd sp!, { r4 - r12, lr }
|
||||
|
||||
@@ store co-processor registers
|
||||
|
||||
mrc p15, 0, r4, c13, c0, 0 @ PID
|
||||
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
mrc p15, 0, r6, c2, c0, 0 @ translation table base address
|
||||
mrc p15, 0, r7, c1, c0, 0 @ control register
|
||||
|
||||
stmia r0, { r4 - r13 }
|
||||
|
||||
@@ write our state back to RAM
|
||||
bl s3c_pm_cb_flushcache
|
||||
ldr r3, =resume_with_mmu
|
||||
bl cpu_suspend
|
||||
|
||||
@@ jump to final code to send system to sleep
|
||||
ldr r0, =pm_cpu_sleep
|
||||
|
@ -76,20 +66,6 @@ resume_with_mmu:
|
|||
|
||||
.ltorg
|
||||
|
||||
@@ the next bits sit in the .data segment, even though they
|
||||
@@ happen to be code... the s3c_sleep_save_phys needs to be
|
||||
@@ accessed by the resume code before it can restore the MMU.
|
||||
@@ This means that the variable has to be close enough for the
|
||||
@@ code to read it... since the .text segment needs to be RO,
|
||||
@@ the data segment can be the only place to put this code.
|
||||
|
||||
.data
|
||||
|
||||
.global s3c_sleep_save_phys
|
||||
s3c_sleep_save_phys:
|
||||
.word 0
|
||||
|
||||
|
||||
/* sleep magic, to allow the bootloader to check for an valid
|
||||
* image to resume to. Must be the first word before the
|
||||
* s3c_cpu_resume entry.
|
||||
|
@ -100,10 +76,6 @@ s3c_sleep_save_phys:
|
|||
/* s3c_cpu_resume
|
||||
*
|
||||
* resume code entry for bootloader to call
|
||||
*
|
||||
* we must put this code here in the data segment as we have no
|
||||
* other way of restoring the stack pointer after sleep, and we
|
||||
* must not write to the code segment (code is read-only)
|
||||
*/
|
||||
|
||||
ENTRY(s3c_cpu_resume)
|
||||
|
@ -134,25 +106,4 @@ ENTRY(s3c_cpu_resume)
|
|||
beq 1001b
|
||||
#endif /* CONFIG_DEBUG_RESUME */
|
||||
|
||||
mov r1, #0
|
||||
mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
|
||||
mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
|
||||
|
||||
ldr r0, s3c_sleep_save_phys @ address of restore block
|
||||
ldmia r0, { r4 - r13 }
|
||||
|
||||
mcr p15, 0, r4, c13, c0, 0 @ PID
|
||||
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||
mcr p15, 0, r6, c2, c0, 0 @ translation table base
|
||||
|
||||
#ifdef CONFIG_DEBUG_RESUME
|
||||
mov r3, #'R'
|
||||
strb r3, [ r2, #S3C2410_UTXH ]
|
||||
#endif
|
||||
|
||||
ldr r2, =resume_with_mmu
|
||||
mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, etc
|
||||
nop @ second-to-last before mmu
|
||||
mov pc, r2 @ go back to virtual address
|
||||
|
||||
.ltorg
|
||||
b cpu_resume
|
||||
|
|
|
@ -50,13 +50,11 @@ extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
|
|||
|
||||
/* from sleep.S */
|
||||
|
||||
extern int s3c_cpu_save(unsigned long *saveblk);
|
||||
extern int s3c_cpu_save(unsigned long *saveblk, long);
|
||||
extern void s3c_cpu_resume(void);
|
||||
|
||||
extern void s3c2410_cpu_suspend(void);
|
||||
|
||||
extern unsigned long s3c_sleep_save_phys;
|
||||
|
||||
/* sleep save info */
|
||||
|
||||
/**
|
||||
|
@ -179,13 +177,5 @@ extern void s3c_pm_restore_gpios(void);
|
|||
*/
|
||||
extern void s3c_pm_save_gpios(void);
|
||||
|
||||
/**
|
||||
* s3c_pm_cb_flushcache - callback for assembly code
|
||||
*
|
||||
* Callback to issue flush_cache_all() as this call is
|
||||
* not a directly callable object.
|
||||
*/
|
||||
extern void s3c_pm_cb_flushcache(void);
|
||||
|
||||
extern void s3c_pm_save_core(void);
|
||||
extern void s3c_pm_restore_core(void);
|
||||
|
|
|
@ -241,8 +241,6 @@ void (*pm_cpu_sleep)(void);
|
|||
|
||||
static int s3c_pm_enter(suspend_state_t state)
|
||||
{
|
||||
static unsigned long regs_save[16];
|
||||
|
||||
/* ensure the debug is initialised (if enabled) */
|
||||
|
||||
s3c_pm_debug_init();
|
||||
|
@ -266,12 +264,6 @@ static int s3c_pm_enter(suspend_state_t state)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* store the physical address of the register recovery block */
|
||||
|
||||
s3c_sleep_save_phys = virt_to_phys(regs_save);
|
||||
|
||||
S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
|
||||
|
||||
/* save all necessary core registers not covered by the drivers */
|
||||
|
||||
s3c_pm_save_gpios();
|
||||
|
@ -305,7 +297,7 @@ static int s3c_pm_enter(suspend_state_t state)
|
|||
* we resume as it saves its own register state and restores it
|
||||
* during the resume. */
|
||||
|
||||
s3c_cpu_save(regs_save);
|
||||
s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
|
||||
|
||||
/* restore the cpu state using the kernel's cpu init code. */
|
||||
|
||||
|
@ -336,12 +328,6 @@ static int s3c_pm_enter(suspend_state_t state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* callback from assembly code */
|
||||
void s3c_pm_cb_flushcache(void)
|
||||
{
|
||||
flush_cache_all();
|
||||
}
|
||||
|
||||
static int s3c_pm_prepare(void)
|
||||
{
|
||||
/* prepare check area if configured */
|
||||
|
|
Loading…
Reference in New Issue