[PATCH 5/6] ARM: pm: convert samsung platforms to generic suspend/resume support
Kukjin Kim
kgene.kim at samsung.com
Thu Feb 17 07:09:02 EST 2011
Russell King - ARM Linux wrote:
>
> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> ---
> arch/arm/mach-s3c64xx/sleep.S | 63 +-----------------
> arch/arm/mach-s5pv210/sleep.S | 104
+----------------------------
> --
> arch/arm/plat-s3c24xx/sleep.S | 57 +----------------
> arch/arm/plat-samsung/include/plat/pm.h | 12 +---
> arch/arm/plat-samsung/pm.c | 16 +-----
> 5 files changed, 13 insertions(+), 239 deletions(-)
>
> diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S
> index b2ef443..afe5a76 100644
> --- a/arch/arm/mach-s3c64xx/sleep.S
> +++ b/arch/arm/mach-s3c64xx/sleep.S
> @@ -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
> diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
> index d4d222b..ef4bd2a 100644
> --- a/arch/arm/mach-s5pv210/sleep.S
> +++ b/arch/arm/mach-s5pv210/sleep.S
> @@ -35,50 +35,23 @@
> /* 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
> + 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 +69,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
> diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
> index e73e3b6..fd7032f 100644
> --- a/arch/arm/plat-s3c24xx/sleep.S
> +++ b/arch/arm/plat-s3c24xx/sleep.S
> @@ -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
> diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-
> samsung/include/plat/pm.h
> index d9025e3..4aa697d 100644
> --- a/arch/arm/plat-samsung/include/plat/pm.h
> +++ b/arch/arm/plat-samsung/include/plat/pm.h
> @@ -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);
> diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
> index 02d531f..d5b58d3 100644
> --- a/arch/arm/plat-samsung/pm.c
> +++ b/arch/arm/plat-samsung/pm.c
> @@ -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 */
> --
> 1.6.2.5
Hi Russell,
I tested on SMDKV210(S5PV210) and SMDKC110(S5PC110).
Firstly, looks like suspend working is fine.
But had some problem during resume :( unfortunately, didn't find fundamental
reason of it.
Shortly, the problem is that r14 has always unexpected value, 0x4 on #113
line, "cpy pc, r14" of v7_flush_cache_all.
So happened abort. I will debugging tomorrow then let you know.
As a note, I tested it based on your devel-stable branch.
If missed some stuff, please let me know :)
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim at samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
More information about the linux-arm-kernel
mailing list