Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e2f3d37 authored by Russell King's avatar Russell King
Browse files

ARM: pm: convert samsung platforms to generic suspend/resume support

parent 96c20015
Loading
Loading
Loading
Loading
+4 −59
Original line number Diff line number Diff line
@@ -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
+4 −101
Original line number Diff line number Diff line
@@ -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
+4 −53
Original line number Diff line number Diff line
@@ -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
+1 −11
Original line number Diff line number Diff line
@@ -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);
+1 −15
Original line number Diff line number Diff line
@@ -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 */