Skip to content

Commit

Permalink
ARM: pm: convert samsung platforms to generic suspend/resume support
Browse files Browse the repository at this point in the history
Tested-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Russell King committed Feb 22, 2011
1 parent 96c2001 commit 2e2f3d3
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 239 deletions.
63 changes: 4 additions & 59 deletions arch/arm/mach-s3c64xx/sleep.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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. */

Expand Down Expand Up @@ -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
105 changes: 4 additions & 101 deletions arch/arm/mach-s5pv210/sleep.S
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
57 changes: 4 additions & 53 deletions arch/arm/plat-s3c24xx/sleep.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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)
Expand Down Expand Up @@ -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
12 changes: 1 addition & 11 deletions arch/arm/plat-samsung/include/plat/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

/**
Expand Down Expand Up @@ -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);
16 changes: 1 addition & 15 deletions arch/arm/plat-samsung/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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. */

Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 2e2f3d3

Please sign in to comment.