Skip to contentSkip to conversation

Re-jig cpu_suspend for a saner calling convention

PATCH New Russell King - ARM Linux 4 participants 32 messages Jun 23, 2011 – Jun 24, 2011

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover Re-jig cpu_suspend for a saner calling convention

Version 3.

Currently cpu_suspend is not like a normal C function - when it's called it returns normally to a bunch of code which is not expected to return. The return path is via code pointed to by 'r3'.

It also corrupts a bunch of registers in ways which make it non-compliant with a C API.

If we do make this compliant as a normal C-like function, it eliminates this register saving, and also allows us to make greater savings. We also swap 'lr' and 'r3', so cpu_suspend effectively only returns to following code on resume - and r3 points to the suspend code.

I've also changed cpu_suspend() to have a saner visible prototype for calling from platforms, hiding the needed v:p offset parameter in the inline function.

So, this becomes:
static void soc_suspend(void)
{
[soc specific preparation]

cpu_suspend(soc_suspend_arg, soc_finish_suspend);

[soc specific cleanup ]
}

where soc_suspend_fn can be either assembly or C code - but must never return. (See separate patch posted on 13th June to allow it to return.)

This patch series also merges the call to cpu_init() into cpu_suspend(), and makes cpu_init() call the per-CPU initialization function to ensure that various registers are setup (eg, clock switching on StrongARM, read-buffer enabled for userspace, etc.) This allows some more custom platform suspend code to be removed.

I've been able to convert OMAP3 suspend support and test it in both retention and off modes.

The only platform not converted to cpu_suspend() is the shmobile stuff, which I've requested their assistance with.

This patch set also eliminates 300 LOC from platform code.

Tested on Assabet (SA1100) and 3430LDP only.

 arch/arm/include/asm/suspend.h          |   21 ++++
 arch/arm/kernel/setup.c                 |   99 ++++++++++----------
 arch/arm/kernel/sleep.S                 |   73 ++++++---------
 arch/arm/mach-exynos4/pm.c              |    2 +-
 arch/arm/mach-exynos4/sleep.S           |   22 ----
 arch/arm/mach-omap2/pm34xx.c            |   48 ++-------
 arch/arm/mach-omap2/sleep34xx.S         |  160 ++-----------------------------
 arch/arm/mach-pxa/include/mach/pm.h     |    4 +-
 arch/arm/mach-pxa/palmz72.c             |    1 +
 arch/arm/mach-pxa/pm.c                  |    1 -
 arch/arm/mach-pxa/pxa25x.c              |    3 +-
 arch/arm/mach-pxa/pxa27x.c              |   11 ++-
 arch/arm/mach-pxa/pxa3xx.c              |   14 +++-
 arch/arm/mach-pxa/sleep.S               |   55 ++---------
 arch/arm/mach-pxa/zeus.c                |    3 +-
 arch/arm/mach-s3c2412/pm.c              |    4 +-
 arch/arm/mach-s3c2416/pm.c              |    4 +-
 arch/arm/mach-s3c64xx/pm.c              |    2 +-
 arch/arm/mach-s3c64xx/sleep.S           |   23 -----
 arch/arm/mach-s5pv210/pm.c              |    2 +-
 arch/arm/mach-s5pv210/sleep.S           |   21 ----
 arch/arm/mach-sa1100/pm.c               |    7 +-
 arch/arm/mach-sa1100/sleep.S            |   19 +----
 arch/arm/mm/proc-sa1100.S               |    4 +-
 arch/arm/mm/proc-v7.S                   |   10 ++-
 arch/arm/plat-s3c24xx/sleep.S           |   25 -----
 arch/arm/plat-samsung/include/plat/pm.h |    5 +-
 arch/arm/plat-samsung/pm.c              |   11 +--
 28 files changed, 180 insertions(+), 474 deletions(-)
#1 lore raw

PATCH 1/25 ARM: pm: ensure ARMv7 CPUs save and restore the TLS register

Ensure that the TLS register is saved and restored over a suspend cycle, so that userspace programs don't see a corrupted TLS value.

---
 arch/arm/mm/proc-v7.S |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)
arch/arm/mm/proc-v7.S +7 -3
index b3b566e..426c946 100644
@@ -208,19 +208,21 @@ cpu_v7_name:
 
 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
 .globl	cpu_v7_suspend_size
-.equ	cpu_v7_suspend_size, 4 * 8
+.equ	cpu_v7_suspend_size, 4 * 9
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v7_do_suspend)
 	stmfd	sp!, {r4 - r11, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
+	stmia	r0!, {r4 - r6}
 	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
 	mrc	p15, 0, r7, c2, c0, 0	@ TTB 0
 	mrc	p15, 0, r8, c2, c0, 1	@ TTB 1
 	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 control
-	stmia	r0, {r4 - r11}
+	stmia	r0, {r6 - r11}
 	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_v7_do_suspend)
 
@@ -228,9 +230,11 @@ ENTRY(cpu_v7_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate TLBs
 	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
-	ldmia	r0, {r4 - r11}
+	ldmia	r0!, {r4 - r6}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
+	ldmia	r0, {r6 - r11}
 	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
 	mcr	p15, 0, r7, c2, c0, 0	@ TTB 0
 	mcr	p15, 0, r8, c2, c0, 1	@ TTB 1
Signature · 1 line
1.7.4.4
#2 lore raw

PATCH 2/25 ARM: pm: arrange for cpu_proc_init() to be called on resume

In reply to Russell King - ARM Linux

cpu_proc_init() does processor specific initialization, which we do at boot time. We have been omitting to do this on resume, which causes some of this initialization to be skipped. We've also been skipping this on SMP initialization too.

Ensure that cpu_proc_init() is always called appropriately by moving it into cpu_init(), and move cpu_init() to a more appropriate point in the boot initialization.

---
 arch/arm/kernel/setup.c   |   99 +++++++++++++++++++++++----------------------
 arch/arm/mm/proc-sa1100.S |    4 +-
 2 files changed, 51 insertions(+), 52 deletions(-)
arch/arm/kernel/setup.c +50 -49
index ed11fb0..edcab02 100644
@@ -342,54 +342,6 @@ static void __init feat_v6_fixup(void)
 		elf_hwcap &= ~HWCAP_TLS;
 }
 
-static void __init setup_processor(void)
-{
-	struct proc_info_list *list;
-
-	/*
-	 * locate processor in the list of supported processor
-	 * types.  The linker builds this table for us from the
-	 * entries in arch/arm/mm/proc-*.S
-	 */
-	list = lookup_processor_type(read_cpuid_id());
-	if (!list) {
-		printk("CPU configuration botched (ID %08x), unable "
-		       "to continue.\n", read_cpuid_id());
-		while (1);
-	}
-
-	cpu_name = list->cpu_name;
-
-#ifdef MULTI_CPU
-	processor = *list->proc;
-#endif
-#ifdef MULTI_TLB
-	cpu_tlb = *list->tlb;
-#endif
-#ifdef MULTI_USER
-	cpu_user = *list->user;
-#endif
-#ifdef MULTI_CACHE
-	cpu_cache = *list->cache;
-#endif
-
-	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
-	       proc_arch[cpu_architecture()], cr_alignment);
-
-	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
-	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
-	elf_hwcap = list->elf_hwcap;
-#ifndef CONFIG_ARM_THUMB
-	elf_hwcap &= ~HWCAP_THUMB;
-#endif
-
-	feat_v6_fixup();
-
-	cacheid_init();
-	cpu_proc_init();
-}
-
 /*
  * cpu_init - initialise one CPU.
  *
@@ -405,6 +357,8 @@ void cpu_init(void)
 		BUG();
 	}
 
+	cpu_proc_init();
+
 	/*
 	 * Define the placement constraint for the inline asm directive below.
 	 * In Thumb-2, msr with an immediate value is not allowed.
@@ -441,6 +395,54 @@ void cpu_init(void)
 	    : "r14");
 }
 
+static void __init setup_processor(void)
+{
+	struct proc_info_list *list;
+
+	/*
+	 * locate processor in the list of supported processor
+	 * types.  The linker builds this table for us from the
+	 * entries in arch/arm/mm/proc-*.S
+	 */
+	list = lookup_processor_type(read_cpuid_id());
+	if (!list) {
+		printk("CPU configuration botched (ID %08x), unable "
+		       "to continue.\n", read_cpuid_id());
+		while (1);
+	}
+
+	cpu_name = list->cpu_name;
+
+#ifdef MULTI_CPU
+	processor = *list->proc;
+#endif
+#ifdef MULTI_TLB
+	cpu_tlb = *list->tlb;
+#endif
+#ifdef MULTI_USER
+	cpu_user = *list->user;
+#endif
+#ifdef MULTI_CACHE
+	cpu_cache = *list->cache;
+#endif
+
+	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
+	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+	       proc_arch[cpu_architecture()], cr_alignment);
+
+	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
+	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+	elf_hwcap = list->elf_hwcap;
+#ifndef CONFIG_ARM_THUMB
+	elf_hwcap &= ~HWCAP_THUMB;
+#endif
+
+	feat_v6_fixup();
+
+	cacheid_init();
+	cpu_init();
+}
+
 void __init dump_machine_table(void)
 {
 	struct machine_desc *p;
@@ -913,7 +915,6 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	reserve_crashkernel();
 
-	cpu_init();
 	tcm_init();
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
arch/arm/mm/proc-sa1100.S +1 -3
index 184a9c9..e9c4727 100644
@@ -34,7 +34,7 @@
  */
 #define DCACHELINESIZE	32
 
-	__INIT
+	.section .text
 
 /*
  * cpu_sa1100_proc_init()
@@ -45,8 +45,6 @@ ENTRY(cpu_sa1100_proc_init)
 	mcr	p15, 0, r0, c9, c0, 5		@ Allow read-buffer operations from userland
 	mov	pc, lr
 
-	.section .text
-
 /*
  * cpu_sa1100_proc_fin()
  *
Signature · 1 line
1.7.4.4
#3 lore raw

PATCH 3/25 ARM: pm: sa1100: no need to re-enable clock switching

In reply to Russell King - ARM Linux

This is now taken care of by calling cpu_proc_init() in the resume path, so eliminate this unnecessary call.

---
 arch/arm/mach-sa1100/sleep.S |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-sa1100/sleep.S +0 -1
index 04f2a61..122ab3c 100644
@@ -147,5 +147,4 @@ sa1110_sdram_controller_fix:
  */
 	.align 5
 sa1100_cpu_resume:
-	mcr	p15, 0, r1, c15, c1, 2		@ enable clock switching
 	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
Signature · 1 line
1.7.4.4
#4 lore raw

PATCH 4/25 ARM: pm: make MULTI_CPU and !MULTI_CPU resume paths the same

In reply to Russell King - ARM Linux

Eliminate the differences between MULTI_CPU and non-MULTI_CPU resume paths, making the saved structure identical irrespective of the way the kernel was configured.

---
 arch/arm/kernel/sleep.S |   12 +++---------
 1 files changed, 3 insertions(+), 9 deletions(-)
arch/arm/kernel/sleep.S +3 -9
index 6398ead..97a6577 100644
@@ -40,9 +40,11 @@ ENTRY(cpu_suspend)
 #else
 	mov	r2, sp			@ current virtual SP
 	ldr	r0, =cpu_suspend_size
+	ldr	ip, =cpu_do_resume
 	sub	sp, sp, r0		@ allocate CPU state on stack
 	mov	r0, sp			@ save pointer
-	stmfd	sp!, {r1, r2, r3}	@ save v:p, virt SP, return fn
+	add	ip, ip, r1		@ convert resume fn to phys
+	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
 	ldr	r3, =sleep_save_sp
 	add	r2, sp, r1		@ convert SP to phys
 #ifdef CONFIG_SMP
@@ -120,20 +122,12 @@ ENTRY(cpu_resume)
 	ldr	r0, sleep_save_sp	@ stack phys addr
 #endif
 	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
-#ifdef MULTI_CPU
 	@ load v:p, stack, return fn, resume fn
   ARM(	ldmia	r0!, {r1, sp, lr, pc}	)
 THUMB(	ldmia	r0!, {r1, r2, r3, r4}	)
 THUMB(	mov	sp, r2			)
 THUMB(	mov	lr, r3			)
 THUMB(	bx	r4			)
-#else
-	@ load v:p, stack, return fn
-  ARM(	ldmia	r0!, {r1, sp, lr}	)
-THUMB(	ldmia	r0!, {r1, r2, lr}	)
-THUMB(	mov	sp, r2			)
-	b	cpu_do_resume
-#endif
 ENDPROC(cpu_resume)
 
 sleep_save_sp:
Signature · 1 line
1.7.4.4
#5 lore raw

PATCH 5/25 ARM: pm: move return address (for cpu_resume) to top of stack

In reply to Russell King - ARM Linux

Move the return address for cpu_resume to the top of stack so that cpu_resume looks more like a normal function.

---
 arch/arm/kernel/sleep.S |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)
arch/arm/kernel/sleep.S +8 -8
index 97a6577..f8e9251 100644
@@ -15,6 +15,7 @@
  * r0-r3,r9,r10,lr corrupted
  */
 ENTRY(cpu_suspend)
+	stmfd	sp!, {r3}
 	mov	r9, lr
 #ifdef MULTI_CPU
 	ldr	r10, =processor
@@ -24,7 +25,7 @@ ENTRY(cpu_suspend)
 	sub	sp, sp, r0		@ allocate CPU state on stack
 	mov	r0, sp			@ save pointer
 	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	stmfd	sp!, {r1, r2, ip}	@ save v:p, virt SP, phys resume fn
 	ldr	r3, =sleep_save_sp
 	add	r2, sp, r1		@ convert SP to phys
 #ifdef CONFIG_SMP
@@ -44,7 +45,7 @@ ENTRY(cpu_suspend)
 	sub	sp, sp, r0		@ allocate CPU state on stack
 	mov	r0, sp			@ save pointer
 	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	stmfd	sp!, {r1, r2, ip}	@ save v:p, virt SP, phys resume fn
 	ldr	r3, =sleep_save_sp
 	add	r2, sp, r1		@ convert SP to phys
 #ifdef CONFIG_SMP
@@ -99,7 +100,7 @@ ENDPROC(cpu_resume_turn_mmu_on)
 cpu_resume_after_mmu:
 	str	r5, [r2, r4, lsl #2]	@ restore old mapping
 	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
-	mov	pc, lr
+	ldmfd	sp!, {pc}
 ENDPROC(cpu_resume_after_mmu)
 
 /*
@@ -122,12 +123,11 @@ ENTRY(cpu_resume)
 	ldr	r0, sleep_save_sp	@ stack phys addr
 #endif
 	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
-	@ load v:p, stack, return fn, resume fn
-  ARM(	ldmia	r0!, {r1, sp, lr, pc}	)
-THUMB(	ldmia	r0!, {r1, r2, r3, r4}	)
+	@ load v:p, stack, resume fn
+  ARM(	ldmia	r0!, {r1, sp, pc}	)
+THUMB(	ldmia	r0!, {r1, r2, r3}	)
 THUMB(	mov	sp, r2			)
-THUMB(	mov	lr, r3			)
-THUMB(	bx	r4			)
+THUMB(	bx	r3			)
 ENDPROC(cpu_resume)
 
 sleep_save_sp:
Signature · 1 line
1.7.4.4
#6 lore raw

PATCH 6/25 ARM: pm: extract common code from MULTI_CPU/!MULTI_CPU paths

In reply to Russell King - ARM Linux

Very little code is different between these two paths now, so extract the common code.

---
 arch/arm/kernel/sleep.S |   24 ++++++------------------
 1 files changed, 6 insertions(+), 18 deletions(-)
arch/arm/kernel/sleep.S +6 -18
index f8e9251..0a778c3 100644
@@ -19,29 +19,13 @@ ENTRY(cpu_suspend)
 	mov	r9, lr
 #ifdef MULTI_CPU
 	ldr	r10, =processor
-	mov	r2, sp			@ current virtual SP
 	ldr	r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
 	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
-	sub	sp, sp, r0		@ allocate CPU state on stack
-	mov	r0, sp			@ save pointer
-	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r2, ip}	@ save v:p, virt SP, phys resume fn
-	ldr	r3, =sleep_save_sp
-	add	r2, sp, r1		@ convert SP to phys
-#ifdef CONFIG_SMP
-	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
-	ALT_UP(mov lr, #0)
-	and	lr, lr, #15
-	str	r2, [r3, lr, lsl #2]	@ save phys SP
 #else
-	str	r2, [r3]		@ save phys SP
-#endif
-	mov	lr, pc
-	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
-#else
-	mov	r2, sp			@ current virtual SP
 	ldr	r0, =cpu_suspend_size
 	ldr	ip, =cpu_do_resume
+#endif
+	mov	r2, sp			@ current virtual SP
 	sub	sp, sp, r0		@ allocate CPU state on stack
 	mov	r0, sp			@ save pointer
 	add	ip, ip, r1		@ convert resume fn to phys
@@ -56,6 +40,10 @@ ENTRY(cpu_suspend)
 #else
 	str	r2, [r3]		@ save phys SP
 #endif
+#ifdef MULTI_CPU
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
+#else
 	bl	cpu_do_suspend
 #endif
 
Signature · 1 line
1.7.4.4
#7 lore raw

PATCH 7/25 ARM: pm: preserve r4 - r11 across a suspend

In reply to Russell King - ARM Linux

Make cpu_suspend()..return function preserve r4 to r11 across a suspend cycle. This is in preparation of relieving platform support code from this task.

---
 arch/arm/kernel/sleep.S |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/kernel/sleep.S +3 -2
index 0a778c3..8dbca93 100644
@@ -12,10 +12,11 @@
  *  r1 = v:p offset
  *  r3 = virtual return function
  * Note: sp is decremented to allocate space for CPU state on stack
- * r0-r3,r9,r10,lr corrupted
+ * r0-r3,ip,lr corrupted
  */
 ENTRY(cpu_suspend)
 	stmfd	sp!, {r3}
+	stmfd	sp!, {r4 - r11}
 	mov	r9, lr
 #ifdef MULTI_CPU
 	ldr	r10, =processor
@@ -88,7 +89,7 @@ ENDPROC(cpu_resume_turn_mmu_on)
 cpu_resume_after_mmu:
 	str	r5, [r2, r4, lsl #2]	@ restore old mapping
 	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
-	ldmfd	sp!, {pc}
+	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_resume_after_mmu)
 
 /*
Signature · 1 line
1.7.4.4
#8 lore raw

PATCH 8/25 ARM: pm: reallocate registers to avoid r2, r3

In reply to Russell King - ARM Linux

Avoid using r2 and r3 in the suspend code, allowing these to be passed further into the function as arguments.

---
 arch/arm/kernel/sleep.S |   18 +++++++++---------
 1 files changed, 9 insertions(+), 9 deletions(-)
arch/arm/kernel/sleep.S +9 -9
index 8dbca93..358be13 100644
@@ -20,26 +20,26 @@ ENTRY(cpu_suspend)
 	mov	r9, lr
 #ifdef MULTI_CPU
 	ldr	r10, =processor
-	ldr	r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
+	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
 	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
 #else
-	ldr	r0, =cpu_suspend_size
+	ldr	r5, =cpu_suspend_size
 	ldr	ip, =cpu_do_resume
 #endif
-	mov	r2, sp			@ current virtual SP
-	sub	sp, sp, r0		@ allocate CPU state on stack
+	mov	r6, sp			@ current virtual SP
+	sub	sp, sp, r5		@ allocate CPU state on stack
 	mov	r0, sp			@ save pointer
 	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r2, ip}	@ save v:p, virt SP, phys resume fn
-	ldr	r3, =sleep_save_sp
-	add	r2, sp, r1		@ convert SP to phys
+	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn
+	ldr	r5, =sleep_save_sp
+	add	r6, sp, r1		@ convert SP to phys
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
 	and	lr, lr, #15
-	str	r2, [r3, lr, lsl #2]	@ save phys SP
+	str	r6, [r5, lr, lsl #2]	@ save phys SP
 #else
-	str	r2, [r3]		@ save phys SP
+	str	r6, [r5]		@ save phys SP
 #endif
 #ifdef MULTI_CPU
 	mov	lr, pc
Signature · 1 line
1.7.4.4
#9 lore raw

PATCH 9/25 ARM: pm: rejig suspend follow-on function calling convention

In reply to Russell King - ARM Linux

Save the suspend function pointer onto the stack for use when returning. Allocate r2 to pass an argument to the suspend function.

---
 arch/arm/kernel/sleep.S |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)
arch/arm/kernel/sleep.S +5 -4
index 358be13..b924bcc 100644
@@ -10,6 +10,7 @@
 /*
  * Save CPU state for a suspend
  *  r1 = v:p offset
+ *  r2 = suspend function arg0
  *  r3 = virtual return function
  * Note: sp is decremented to allocate space for CPU state on stack
  * r0-r3,ip,lr corrupted
@@ -17,7 +18,6 @@
 ENTRY(cpu_suspend)
 	stmfd	sp!, {r3}
 	stmfd	sp!, {r4 - r11}
-	mov	r9, lr
 #ifdef MULTI_CPU
 	ldr	r10, =processor
 	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
@@ -33,6 +33,7 @@ ENTRY(cpu_suspend)
 	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn
 	ldr	r5, =sleep_save_sp
 	add	r6, sp, r1		@ convert SP to phys
+	stmfd	sp!, {r2, lr}		@ save suspend func arg and pointer
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
@@ -51,12 +52,12 @@ ENTRY(cpu_suspend)
 	@ flush data cache
 #ifdef MULTI_CACHE
 	ldr	r10, =cpu_cache
-	mov	lr, r9
+	mov	lr, pc
 	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
 #else
-	mov	lr, r9
-	b	__cpuc_flush_kern_all
+	bl	__cpuc_flush_kern_all
 #endif
+	ldmfd	sp!, {r0, pc}		@ call suspend fn
 ENDPROC(cpu_suspend)
 	.ltorg
 
Signature · 1 line
1.7.4.4
#10 lore raw

PATCH 10/25 ARM: pm: move sa1100 to use proper suspend func arg0

In reply to Russell King - ARM Linux

In the previous commit, we introduced an official way to supply an argument to the suspend function. Convert the sa1100 suspend code to use this method.

---
 arch/arm/mach-pxa/sleep.S |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
arch/arm/mach-pxa/sleep.S +4 -4
index 6f53688..613ddfa 100644
@@ -59,7 +59,7 @@ ENTRY(pxa27x_cpu_suspend)
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-	mov	r4, r0				@ save sleep mode
+	mov	r2, r0				@ save sleep mode
 	ldr	r3, =pxa_cpu_resume		@ resume function
 	bl	cpu_suspend
 
@@ -67,7 +67,7 @@ ENTRY(pxa27x_cpu_suspend)
 	@ (also workaround for sighting 28071)
 
 	@ prepare value for sleep mode
-	mov	r1, r4				@ sleep mode
+	mov	r1, r0				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -109,11 +109,11 @@ ENTRY(pxa27x_cpu_suspend)
 
 ENTRY(pxa25x_cpu_suspend)
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-	mov	r4, r0				@ save sleep mode
+	mov	r2, r0				@ save sleep mode
 	ldr	r3, =pxa_cpu_resume		@ resume function
 	bl	cpu_suspend
 	@ prepare value for sleep mode
-	mov	r1, r4				@ sleep mode
+	mov	r1, r0				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
Signature · 1 line
1.7.4.4
#11 lore raw

PATCH 11/25 ARM: pm: convert cpu_suspend() to a normal function

In reply to Russell King - ARM Linux

cpu_suspend() has a weird calling method which makes it only possible to call from assembly code: it returns with a modified stack pointer to finish the suspend, but on resume, it 'returns' via a provided pointer.

We can make cpu_suspend() appear to be a normal function merely by swapping the resume pointer argument and the link register.

Do so, and update all callers to take account of this more traditional behaviour.

---
 arch/arm/include/asm/system.h |    2 ++
 arch/arm/kernel/sleep.S       |   10 ++++------
 arch/arm/mach-exynos4/sleep.S |    7 +++----
 arch/arm/mach-pxa/sleep.S     |   13 ++++++++++---
 arch/arm/mach-s3c64xx/sleep.S |    9 +++------
 arch/arm/mach-s5pv210/sleep.S |    7 +++----
 arch/arm/mach-sa1100/sleep.S  |   13 +++----------
 arch/arm/plat-s3c24xx/sleep.S |   10 +++-------
 8 files changed, 31 insertions(+), 40 deletions(-)
arch/arm/include/asm/system.h +2 -0
index 832888d..50be605 100644
@@ -106,6 +106,8 @@ extern void __show_regs(struct pt_regs *);
 
 extern int cpu_architecture(void);
 extern void cpu_init(void);
+extern void cpu_suspend(int, long, unsigned long, void (*)(unsigned long));
+extern void cpu_resume(void);
 
 void arm_machine_restart(char mode, const char *cmd);
 extern void (*arm_pm_restart)(char str, const char *cmd);
arch/arm/kernel/sleep.S +4 -6
index b924bcc..e062677 100644
@@ -11,13 +11,11 @@
  * Save CPU state for a suspend
  *  r1 = v:p offset
  *  r2 = suspend function arg0
- *  r3 = virtual return function
- * Note: sp is decremented to allocate space for CPU state on stack
- * r0-r3,ip,lr corrupted
+ *  r3 = suspend function
+ * Note: does not return until system resumes
  */
 ENTRY(cpu_suspend)
-	stmfd	sp!, {r3}
-	stmfd	sp!, {r4 - r11}
+	stmfd	sp!, {r4 - r11, lr}
 #ifdef MULTI_CPU
 	ldr	r10, =processor
 	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
@@ -33,7 +31,7 @@ ENTRY(cpu_suspend)
 	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn
 	ldr	r5, =sleep_save_sp
 	add	r6, sp, r1		@ convert SP to phys
-	stmfd	sp!, {r2, lr}		@ save suspend func arg and pointer
+	stmfd	sp!, {r2, r3}		@ save suspend func arg and pointer
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
arch/arm/mach-exynos4/sleep.S +3 -4
index 6b62425..d9a2287 100644
@@ -42,16 +42,15 @@
 ENTRY(s3c_cpu_save)
 
 	stmfd	sp!, { r3 - r12, lr }
-	ldr	r3, =resume_with_mmu
+	adr	r3, BSYM(exynos4_finish_suspend)
 	bl	cpu_suspend
+	ldmfd	sp!, { r3 - r12, pc }
 
+exynos4_finish_suspend:
 	ldr	r0, =pm_cpu_sleep
 	ldr	r0, [ r0 ]
 	mov	pc, r0
 
-resume_with_mmu:
-	ldmfd	sp!, { r3 - r12, pc }
-
 	.ltorg
 
 	/*
arch/arm/mach-pxa/sleep.S +10 -3
index 613ddfa..3a67887 100644
@@ -35,9 +35,11 @@ ENTRY(pxa3xx_cpu_suspend)
 #endif
 	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
 	mov	r1, r0
-	ldr	r3, =pxa_cpu_resume	@ resume function
+	adr	r3, BSYM(pxa3xx_finish_suspend)
 	bl	cpu_suspend
+	b	pxa_cpu_resume
 
+pxa3xx_finish_suspend:
 	mov	r0, #0x06		@ S2D3C4 mode
 	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
 
@@ -60,9 +62,11 @@ ENTRY(pxa27x_cpu_suspend)
 #endif
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
 	mov	r2, r0				@ save sleep mode
-	ldr	r3, =pxa_cpu_resume		@ resume function
+	adr	r3, BSYM(pxa27x_finish_suspend)
 	bl	cpu_suspend
+	b	pxa_cpu_resume
 
+pxa27x_finish_suspend:
 	@ Put the processor to sleep
 	@ (also workaround for sighting 28071)
 
@@ -110,8 +114,11 @@ ENTRY(pxa27x_cpu_suspend)
 ENTRY(pxa25x_cpu_suspend)
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
 	mov	r2, r0				@ save sleep mode
-	ldr	r3, =pxa_cpu_resume		@ resume function
+	adr	r3, BSYM(pxa25x_finish_suspend)
 	bl	cpu_suspend
+	b	pxa_cpu_resume
+
+pxa25x_finish_suspend:
 	@ prepare value for sleep mode
 	mov	r1, r0				@ sleep mode
 
arch/arm/mach-s3c64xx/sleep.S +3 -6
index 1f87732..dc4f582 100644
@@ -36,18 +36,15 @@
 
 ENTRY(s3c_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
-	ldr	r3, =resume_with_mmu
+	adr	r3, BSYM(s3c64xx_finish_suspend)
 	bl	cpu_suspend
+	ldmfd	sp!, { r4 - r12, pc }
 
+s3c64xx_finish_suspend:
 	@@ call final suspend code
 	ldr	r0, =pm_cpu_sleep
 	ldr	pc, [r0]
 	
-	@@ return to the caller, after the MMU is turned on.
-	@@ restore the last bits of the stack and return.
-resume_with_mmu:
-	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save
-
 	/* Sleep magic, the word before the resume entry point so that the
 	 * bootloader can check for a resumeable image. */
 
arch/arm/mach-s5pv210/sleep.S +3 -4
index a3d6494..1182fc8 100644
@@ -41,16 +41,15 @@
 ENTRY(s3c_cpu_save)
 
 	stmfd	sp!, { r3 - r12, lr }
-	ldr	r3, =resume_with_mmu
+	adr	r3, BSYM(s5pv210_finish_suspend)
 	bl	cpu_suspend
+	ldmfd	sp!, { r3 - r12, pc }
 
+s5pv210_finish_suspend:
 	ldr	r0, =pm_cpu_sleep
 	ldr	r0, [ r0 ]
 	mov	pc, r0
 
-resume_with_mmu:
-	ldmfd	sp!, { r3 - r12, pc }
-
 	.ltorg
 
 	/* sleep magic, to allow the bootloader to check for an valid
arch/arm/mach-sa1100/sleep.S +3 -10
index 122ab3c..f3fe397 100644
@@ -31,9 +31,11 @@
 ENTRY(sa1100_cpu_suspend)
 	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack
 	mov	r1, r0
-	ldr	r3, =sa1100_cpu_resume		@ return function
+	adr	r3, BSYM(sa1100_finish_suspend)
 	bl	cpu_suspend
+	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
 
+sa1100_finish_suspend:
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
 
@@ -139,12 +141,3 @@ sa1110_sdram_controller_fix:
 	str	r13, [r12]
 
 20:	b	20b			@ loop waiting for sleep
-
-/*
- * cpu_sa1100_resume()
- *
- * entry point from bootloader into kernel during resume
- */
-	.align 5
-sa1100_cpu_resume:
-	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
arch/arm/plat-s3c24xx/sleep.S +3 -7
index fd7032f..f822e62 100644
@@ -49,21 +49,17 @@
 
 ENTRY(s3c_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
-	ldr	r3, =resume_with_mmu
+	adr	r3, BSYM(s3c24xx_finish_suspend)
 	bl	cpu_suspend
+	ldmfd	sp!, { r4 - r12, pc }
 
+s3c24xx_finish_suspend:
 	@@ jump to final code to send system to sleep
 	ldr	r0, =pm_cpu_sleep
 	@@ldr	pc, [ r0 ]
 	ldr	r0, [ r0 ]
 	mov	pc, r0
 	
-	@@ return to the caller, after having the MMU
-	@@ turned on, this restores the last bits from the
-	@@ stack
-resume_with_mmu:
-	ldmfd	sp!, { r4 - r12, pc }
-
 	.ltorg
 
 	/* sleep magic, to allow the bootloader to check for an valid
Signature · 1 line
1.7.4.4
#12 lore raw

PATCH 12/25 ARM: pm: move cpu_init() call into core code

In reply to Russell King - ARM Linux

As we have core code dealing with CPU suspend/resume, we can re-initialize the CPUs exception banked registers via that code rather than having platforms deal with that level of detail. So, move the call to cpu_init() out of platform code into core code.

---
 arch/arm/kernel/sleep.S    |    1 +
 arch/arm/mach-pxa/pm.c     |    1 -
 arch/arm/mach-sa1100/pm.c  |    2 --
 arch/arm/plat-samsung/pm.c |    4 ----
 4 files changed, 1 insertions(+), 7 deletions(-)
arch/arm/kernel/sleep.S +1 -0
index e062677..5392274 100644
@@ -88,6 +88,7 @@ ENDPROC(cpu_resume_turn_mmu_on)
 cpu_resume_after_mmu:
 	str	r5, [r2, r4, lsl #2]	@ restore old mapping
 	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
+	bl	cpu_init		@ restore the und/abt/irq banked regs
 	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_resume_after_mmu)
 
arch/arm/mach-pxa/pm.c +0 -1
index 51e1583..37178a8 100644
@@ -42,7 +42,6 @@ int pxa_pm_enter(suspend_state_t state)
 
 	/* *** go zzz *** */
 	pxa_cpu_pm_fns->enter(state);
-	cpu_init();
 
 	if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) {
 		/* after sleeping, validate the checksum */
arch/arm/mach-sa1100/pm.c +0 -2
index c4661aa..d35885c 100644
@@ -77,8 +77,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	/* go zzz */
 	sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
-	cpu_init();
-
 	/*
 	 * Ensure not to come back here if it wasn't intended
 	 */
arch/arm/plat-samsung/pm.c +0 -4
index 5c0a440..3828191 100644
@@ -300,10 +300,6 @@ static int s3c_pm_enter(suspend_state_t state)
 
 	s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
-	/* restore the cpu state using the kernel's cpu init code. */
-
-	cpu_init();
-
 	/* restore the system state */
 
 	s3c_pm_restore_core();
Signature · 1 line
1.7.4.4
#13 lore raw

PATCH 13/25 ARM: pm: sa1100: move cpu_suspend into C code

In reply to Russell King - ARM Linux

We don't need a veneer for cpu_suspend, it can be called directly from C code now. Move it into sa11x0_pm_enter() along with the re-enabling of clock switching.

---
 arch/arm/mach-sa1100/pm.c    |    4 ++--
 arch/arm/mach-sa1100/sleep.S |   11 ++---------
 2 files changed, 4 insertions(+), 11 deletions(-)
arch/arm/mach-sa1100/pm.c +2 -2
index d35885c..259ed3b 100644
@@ -32,7 +32,7 @@
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
-extern void sa1100_cpu_suspend(long);
+extern void sa1100_finish_suspend(unsigned long);
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
@@ -75,7 +75,7 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	PSPR = virt_to_phys(cpu_resume);
 
 	/* go zzz */
-	sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, 0, sa1100_finish_suspend);
 
 	/*
 	 * Ensure not to come back here if it wasn't intended
arch/arm/mach-sa1100/sleep.S +2 -9
index f3fe397..e822331 100644
@@ -22,20 +22,13 @@
 
 		.text
 /*
- * sa1100_cpu_suspend()
+ * sa1100_finish_suspend()
  *
  * Causes sa11x0 to enter sleep state
  *
  */
 
-ENTRY(sa1100_cpu_suspend)
-	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack
-	mov	r1, r0
-	adr	r3, BSYM(sa1100_finish_suspend)
-	bl	cpu_suspend
-	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
-
-sa1100_finish_suspend:
+ENTRY(sa1100_finish_suspend)
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
 
Signature · 1 line
1.7.4.4
#14 lore raw

PATCH 14/25 ARM: pm: plat-s3c24xx: cleanup s3c_cpu_save

In reply to Russell King - ARM Linux

s3c_cpu_save does not need to save any registers with the new cpu_suspend calling convention. Remove these redundant instructions.

---
 arch/arm/plat-s3c24xx/sleep.S |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)
arch/arm/plat-s3c24xx/sleep.S +1 -3
index f822e62..6ada459 100644
@@ -48,10 +48,8 @@
 	*/
 
 ENTRY(s3c_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
 	adr	r3, BSYM(s3c24xx_finish_suspend)
-	bl	cpu_suspend
-	ldmfd	sp!, { r4 - r12, pc }
+	b	cpu_suspend
 
 s3c24xx_finish_suspend:
 	@@ jump to final code to send system to sleep
Signature · 1 line
1.7.4.4
#15 lore raw

PATCH 14/25 ARM: pm: plat-s3c24xx: cleanup s3c_cpu_save

Quoted 5 lines · Russell King - ARM Linux

s3c_cpu_save does not need to save any registers with the new cpu_suspend calling convention. Remove these redundant instructions.

It works fine on Samsung stuff with this whole series.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

Quoted 22 lines
---
 arch/arm/plat-s3c24xx/sleep.S |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)
arch/arm/plat-s3c24xx/sleep.S +1 -4
index f822e62..6ada459 100644
@@ -48,10 +48,8 @@
 	*/
 
 ENTRY(s3c_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
 	adr	r3, BSYM(s3c24xx_finish_suspend)
-	bl	cpu_suspend
-	ldmfd	sp!, { r4 - r12, pc }
+	b	cpu_suspend
 
 s3c24xx_finish_suspend:
 	@@ jump to final code to send system to sleep
--

1.7.4.4

#16 lore raw

PATCH 15/25 ARM: pm: mach-s5pv210: cleanup s3c_cpu_save

In reply to Russell King - ARM Linux

s3c_cpu_save does not need to save any registers with the new cpu_suspend calling convention. Remove these redundant instructions.

---
 arch/arm/mach-s5pv210/sleep.S |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
arch/arm/mach-s5pv210/sleep.S +1 -4
index 1182fc8..28dfeff 100644
@@ -39,11 +39,8 @@
 	*/
 
 ENTRY(s3c_cpu_save)
-
-	stmfd	sp!, { r3 - r12, lr }
 	adr	r3, BSYM(s5pv210_finish_suspend)
-	bl	cpu_suspend
-	ldmfd	sp!, { r3 - r12, pc }
+	b	cpu_suspend
 
 s5pv210_finish_suspend:
 	ldr	r0, =pm_cpu_sleep
Signature · 1 line
1.7.4.4
#17 lore raw

PATCH 16/25 ARM: pm: mach-exynos4: cleanup s3c_cpu_save

In reply to Russell King - ARM Linux

s3c_cpu_save does not need to save any registers with the new cpu_suspend calling convention. Remove these redundant instructions.

---
 arch/arm/mach-exynos4/sleep.S |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
arch/arm/mach-exynos4/sleep.S +1 -4
index d9a2287..b56a491 100644
@@ -40,11 +40,8 @@
 	 */
 
 ENTRY(s3c_cpu_save)
-
-	stmfd	sp!, { r3 - r12, lr }
 	adr	r3, BSYM(exynos4_finish_suspend)
-	bl	cpu_suspend
-	ldmfd	sp!, { r3 - r12, pc }
+	b	cpu_suspend
 
 exynos4_finish_suspend:
 	ldr	r0, =pm_cpu_sleep
Signature · 1 line
1.7.4.4
#18 lore raw

PATCH 17/25 ARM: pm: mach-s3c64xx: cleanup s3c_cpu_save

In reply to Russell King - ARM Linux

s3c_cpu_save does not need to save any registers with the new cpu_suspend calling convention. Remove these redundant instructions.

---
 arch/arm/mach-s3c64xx/sleep.S |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)
arch/arm/mach-s3c64xx/sleep.S +1 -3
index dc4f582..2fd3433 100644
@@ -35,10 +35,8 @@
 	*/
 
 ENTRY(s3c_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
 	adr	r3, BSYM(s3c64xx_finish_suspend)
-	bl	cpu_suspend
-	ldmfd	sp!, { r4 - r12, pc }
+	b	cpu_suspend
 
 s3c64xx_finish_suspend:
 	@@ call final suspend code
Signature · 1 line
1.7.4.4
#19 lore raw

PATCH 18/25 ARM: pm: samsung: move cpu_suspend into C code

In reply to Russell King - ARM Linux

Move the call to cpu_suspend into C code, and noticing that all the s3c_cpu_save implementations are now identical, we can move this into the common samsung code.

---
 arch/arm/mach-exynos4/pm.c              |    2 +-
 arch/arm/mach-exynos4/sleep.S           |   18 ------------------
 arch/arm/mach-s3c2412/pm.c              |    2 +-
 arch/arm/mach-s3c2416/pm.c              |    2 +-
 arch/arm/mach-s3c64xx/pm.c              |    2 +-
 arch/arm/mach-s3c64xx/sleep.S           |   18 ------------------
 arch/arm/mach-s5pv210/pm.c              |    2 +-
 arch/arm/mach-s5pv210/sleep.S           |   17 -----------------
 arch/arm/plat-s3c24xx/sleep.S           |   19 -------------------
 arch/arm/plat-samsung/include/plat/pm.h |    5 ++---
 arch/arm/plat-samsung/pm.c              |    6 +++---
 11 files changed, 10 insertions(+), 83 deletions(-)
arch/arm/mach-exynos4/pm.c +1 -1
index 8755ca8..5c01c60 100644
@@ -280,7 +280,7 @@ static struct sleep_save exynos4_l2cc_save[] = {
 	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
 };
 
-void exynos4_cpu_suspend(void)
+void exynos4_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 	unsigned long mask = 0xFFFFFFFF;
arch/arm/mach-exynos4/sleep.S +0 -18
index b56a491..0984078 100644
@@ -33,24 +33,6 @@
 	.text
 
 	/*
-	 * s3c_cpu_save
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	 */
-
-ENTRY(s3c_cpu_save)
-	adr	r3, BSYM(exynos4_finish_suspend)
-	b	cpu_suspend
-
-exynos4_finish_suspend:
-	ldr	r0, =pm_cpu_sleep
-	ldr	r0, [ r0 ]
-	mov	pc, r0
-
-	.ltorg
-
-	/*
 	 * 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.
arch/arm/mach-s3c2412/pm.c +1 -1
index 752b13a..fecd854 100644
@@ -37,7 +37,7 @@
 
 extern void s3c2412_sleep_enter(void);
 
-static void s3c2412_cpu_suspend(void)
+static void s3c2412_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
arch/arm/mach-s3c2416/pm.c +1 -1
index 41db2b2..268fda7 100644
@@ -24,7 +24,7 @@
 
 extern void s3c2412_sleep_enter(void);
 
-static void s3c2416_cpu_suspend(void)
+static void s3c2416_cpu_suspend(unsigned long arg)
 {
 	flush_cache_all();
 
arch/arm/mach-s3c64xx/pm.c +1 -1
index bc1c470..7cc1879 100644
@@ -112,7 +112,7 @@ void s3c_pm_save_core(void)
  * this.
  */
 
-static void s3c64xx_cpu_suspend(void)
+static void s3c64xx_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
arch/arm/mach-s3c64xx/sleep.S +0 -18
index 2fd3433..34313f9 100644
@@ -25,24 +25,6 @@
 
 	.text
 
-	/* s3c_cpu_save
-	 *
-	 * Save enough processor state to allow the restart of the pm.c
-	 * code after resume.
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	*/
-
-ENTRY(s3c_cpu_save)
-	adr	r3, BSYM(s3c64xx_finish_suspend)
-	b	cpu_suspend
-
-s3c64xx_finish_suspend:
-	@@ call final suspend code
-	ldr	r0, =pm_cpu_sleep
-	ldr	pc, [r0]
-	
 	/* Sleep magic, the word before the resume entry point so that the
 	 * bootloader can check for a resumeable image. */
 
arch/arm/mach-s5pv210/pm.c +1 -1
index 24febae..309e388 100644
@@ -88,7 +88,7 @@ static struct sleep_save s5pv210_core_save[] = {
 	SAVE_ITEM(S3C2410_TCNTO(0)),
 };
 
-void s5pv210_cpu_suspend(void)
+void s5pv210_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
arch/arm/mach-s5pv210/sleep.S +0 -17
index 28dfeff..e3452cc 100644
@@ -32,23 +32,6 @@
 
 	.text
 
-	/* s3c_cpu_save
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	*/
-
-ENTRY(s3c_cpu_save)
-	adr	r3, BSYM(s5pv210_finish_suspend)
-	b	cpu_suspend
-
-s5pv210_finish_suspend:
-	ldr	r0, =pm_cpu_sleep
-	ldr	r0, [ r0 ]
-	mov	pc, r0
-
-	.ltorg
-
 	/* 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.
arch/arm/plat-s3c24xx/sleep.S +0 -19
index 6ada459..c566125 100644
@@ -41,25 +41,6 @@
 
 	.text
 
-	/* s3c_cpu_save
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	*/
-
-ENTRY(s3c_cpu_save)
-	adr	r3, BSYM(s3c24xx_finish_suspend)
-	b	cpu_suspend
-
-s3c24xx_finish_suspend:
-	@@ jump to final code to send system to sleep
-	ldr	r0, =pm_cpu_sleep
-	@@ldr	pc, [ r0 ]
-	ldr	r0, [ r0 ]
-	mov	pc, r0
-	
-	.ltorg
-
 	/* 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.
arch/arm/plat-samsung/include/plat/pm.h +2 -3
index 7fb6f6b..0a5b7fa 100644
@@ -42,7 +42,7 @@ extern unsigned long s3c_irqwake_eintallow;
 /* per-cpu sleep functions */
 
 extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
+extern void (*pm_cpu_sleep)(unsigned long);
 
 /* Flags for PM Control */
 
@@ -52,10 +52,9 @@ extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
 
 /* from sleep.S */
 
-extern int  s3c_cpu_save(unsigned long *saveblk, long);
 extern void s3c_cpu_resume(void);
 
-extern void s3c2410_cpu_suspend(void);
+extern void s3c2410_cpu_suspend(unsigned long);
 
 /* sleep save info */
 
arch/arm/plat-samsung/pm.c +3 -3
index 3828191..3a6d076 100644
@@ -231,7 +231,7 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start,
 
 
 void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
+void (*pm_cpu_sleep)(unsigned long);
 
 #define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
 
@@ -294,11 +294,11 @@ static int s3c_pm_enter(suspend_state_t state)
 
 	s3c_pm_arch_stop_clocks();
 
-	/* s3c_cpu_save will also act as our return point from when
+	/* this will also act as our return point from when
 	 * we resume as it saves its own register state and restores it
 	 * during the resume.  */
 
-	s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, 0, pm_cpu_sleep);
 
 	/* restore the system state */
 
Signature · 1 line
1.7.4.4
#20 lore raw

PATCH 19/25 ARM: pm: samsung: no need to call flush_cache_all()

In reply to Russell King - ARM Linux

The core suspend code calls flush_cache_all() immediately prior to calling the suspend finisher function, so remove these needless calls from the finisher functions.

---
 arch/arm/mach-s3c2412/pm.c |    2 --
 arch/arm/mach-s3c2416/pm.c |    2 --
 2 files changed, 0 insertions(+), 4 deletions(-)
arch/arm/mach-s3c2412/pm.c +0 -2
index fecd854..9a1fb89 100644
@@ -41,8 +41,6 @@ static void s3c2412_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
-	flush_cache_all();
-
 	/* set our standby method to sleep */
 
 	tmp = __raw_readl(S3C2412_PWRCFG);
arch/arm/mach-s3c2416/pm.c +0 -2
index 268fda7..9e67a2a 100644
@@ -26,8 +26,6 @@ extern void s3c2412_sleep_enter(void);
 
 static void s3c2416_cpu_suspend(unsigned long arg)
 {
-	flush_cache_all();
-
 	/* enable wakeup sources regardless of battery state */
 	__raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG);
 
Signature · 1 line
1.7.4.4
#21 lore raw

PATCH 20/25 ARM: pm: pxa: move cpu_suspend into C code

In reply to Russell King - ARM Linux

We don't need a veneer for cpu_suspend, it can be called directly from C code now. Move it into the PXA CPU suspend functions, along with the accumulator register saving/restoring.

---
 arch/arm/mach-pxa/include/mach/pm.h |    4 +-
 arch/arm/mach-pxa/pxa25x.c          |    3 +-
 arch/arm/mach-pxa/pxa27x.c          |   11 ++++++-
 arch/arm/mach-pxa/pxa3xx.c          |   13 ++++++-
 arch/arm/mach-pxa/sleep.S           |   58 +++-------------------------------
 arch/arm/mach-pxa/zeus.c            |    3 +-
 6 files changed, 33 insertions(+), 59 deletions(-)
arch/arm/mach-pxa/include/mach/pm.h +2 -2
index f15afe0..a566720 100644
@@ -22,8 +22,8 @@ struct pxa_cpu_pm_fns {
 extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
 
 /* sleep.S */
-extern void pxa25x_cpu_suspend(unsigned int, long);
-extern void pxa27x_cpu_suspend(unsigned int, long);
+extern void pxa25x_finish_suspend(unsigned long);
+extern void pxa27x_finish_suspend(unsigned long);
 
 extern int pxa_pm_enter(suspend_state_t state);
 extern int pxa_pm_prepare(void);
arch/arm/mach-pxa/pxa25x.c +2 -1
index fed363c..fd7725c 100644
@@ -244,7 +244,8 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
-		pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+		cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, PWRMODE_SLEEP,
+			    pxa25x_finish_suspend);
 		break;
 	}
 }
arch/arm/mach-pxa/pxa27x.c +10 -1
index 2fecbec..824379d 100644
@@ -284,6 +284,11 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
 void pxa27x_cpu_pm_enter(suspend_state_t state)
 {
 	extern void pxa_cpu_standby(void);
+#ifndef CONFIG_IWMMXT
+	u64 acc0;
+
+	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
+#endif
 
 	/* ensure voltage-change sequencer not initiated, which hangs */
 	PCFR &= ~PCFR_FVC;
@@ -299,7 +304,11 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+		cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, pwrmode,
+			    pxa27x_finish_suspend);
+#ifndef CONFIG_IWMMXT
+		asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
+#endif
 		break;
 	}
 }
arch/arm/mach-pxa/pxa3xx.c +11 -2
index 8521d7d..220fd8c 100644
@@ -141,8 +141,13 @@ static void pxa3xx_cpu_pm_suspend(void)
 {
 	volatile unsigned long *p = (volatile void *)0xc0000000;
 	unsigned long saved_data = *p;
+#ifndef CONFIG_IWMMXT
+	u64 acc0;
 
-	extern void pxa3xx_cpu_suspend(long);
+	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
+#endif
+
+	extern void pxa3xx_finish_suspend(unsigned long);
 
 	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
 	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
@@ -162,11 +167,15 @@ static void pxa3xx_cpu_pm_suspend(void)
 	/* overwrite with the resume address */
 	*p = virt_to_phys(cpu_resume);
 
-	pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, 0, pxa3xx_finish_suspend);
 
 	*p = saved_data;
 
 	AD3ER = 0;
+
+#ifndef CONFIG_IWMMXT
+	asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
+#endif
 }
 
 static void pxa3xx_cpu_pm_enter(suspend_state_t state)
arch/arm/mach-pxa/sleep.S +6 -52

91 lines not on this page · raw message

arch/arm/mach-pxa/zeus.c +2 -1
index 00363c7..28eb410 100644
@@ -676,7 +676,8 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
 static void zeus_power_off(void)
 {
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, PWRMODE_DEEPSLEEP,
+		    pxa27x_finish_suspend);
 }
 #else
 #define zeus_power_off   NULL
Signature · 1 line
1.7.4.4
#22 lore raw

PATCH 21/25 ARM: pm: omap34xx: no need to save all registers in sleep34xx.S

In reply to Russell King - ARM Linux

The ABI allows called functions to corrupt r0-r3 and ip (r12). So its pointless saving these registers in the suspend code - the calling function will expect them to be corrupted and so won't rely on their contents after resume.

---
 arch/arm/mach-omap2/sleep34xx.S |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)
arch/arm/mach-omap2/sleep34xx.S +5 -5
index 63f1066..9551c7d 100644
@@ -133,7 +133,7 @@ ENDPROC(enable_omap3630_toggle_l2_on_restore)
 /* Function to call rom code to save secure ram context */
 	.align	3
 ENTRY(save_secure_ram_context)
-	stmfd	sp!, {r1-r12, lr}	@ save registers on stack
+	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
 	adr	r3, api_params		@ r3 points to parameters
 	str	r0, [r3,#0x4]		@ r0 has sdram address
 	ldr	r12, high_mask
@@ -152,7 +152,7 @@ ENTRY(save_secure_ram_context)
 	nop
 	nop
 	nop
-	ldmfd	sp!, {r1-r12, pc}
+	ldmfd	sp!, {r4 - r11, pc}
 	.align
 sram_phy_addr_mask:
 	.word	SRAM_BASE_P
@@ -187,7 +187,7 @@ ENTRY(save_secure_ram_context_sz)
  */
 	.align	3
 ENTRY(omap34xx_cpu_suspend)
-	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
+	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
 
 	/*
 	 * r0 contains CPU context save/restore pointer in sdram
@@ -329,7 +329,7 @@ omap3_do_wfi:
  * == Exit point from non-OFF modes ==
  * ===================================
  */
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
 
 
 /*
@@ -572,7 +572,7 @@ usettbr0:
  * ==============================
  */
 restoremmu_on:
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
 
 
 /*
Signature · 1 line
1.7.4.4
#23 lore raw

PATCH 22/25 ARM: pm: omap34xx: remove misleading comment and use of r9

In reply to Russell King - ARM Linux

The code alludes to r9 being used to indicate what was lost over the suspend/resume transition. However, although r9 is set, it is never actually used.

Also, the comments before the code (which refer to the value of r9) and the comments against the assignment of r9 contradict each other, so just remove them to avoid confusion.

---
 arch/arm/mach-omap2/sleep34xx.S |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/sleep34xx.S +2 -7
index 9551c7d..12e9da2 100644
@@ -381,18 +381,13 @@ restore_3630:
 
 restore:
 	/*
-	 * Check what was the reason for mpu reset and store the reason in r9:
-	 *  0 - No context lost
-	 *  1 - Only L1 and logic lost
-	 *  2 - Only L2 lost - In this case, we wont be here
-	 *  3 - Both L1 and L2 lost
+	 * Read the pwstctrl register to check the reason for mpu reset.
+	 * This tells us what was lost.
 	 */
 	ldr	r1, pm_pwstctrl_mpu
 	ldr	r2, [r1]
 	and	r2, r2, #0x3
 	cmp	r2, #0x0	@ Check if target power state was OFF or RET
-	moveq	r9, #0x3	@ MPU OFF => L1 and L2 lost
-	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation
 	bne	logic_l1_restore
 
 	ldr	r0, l2dis_3630
Signature · 1 line
1.7.4.4
#24 lore raw

PATCH 23/25 ARM: pm: omap34xx: convert to generic suspend/resume support

In reply to Russell King - ARM Linux

Convert sa11x0 to use the generic CPU suspend/resume support, rather than implementing its own version. Tested on 3430 LDP.

---
 arch/arm/mach-omap2/pm34xx.c    |   47 +++----------
 arch/arm/mach-omap2/sleep34xx.S |  143 +--------------------------------------
 2 files changed, 13 insertions(+), 177 deletions(-)
arch/arm/mach-omap2/pm34xx.c +10 -37
index c155c9d..ae40177 100644
@@ -40,8 +40,6 @@
 #include <plat/gpmc.h>
 #include <plat/dma.h>
 
-#include <asm/tlbflush.h>
-
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
@@ -64,11 +62,6 @@ static inline bool is_suspending(void)
 }
 #endif
 
-/* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET	   0xc4
-#define OMAP343X_TABLE_VALUE_OFFSET	   0xc0
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
-
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
 
@@ -312,28 +305,9 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-/* Function to restore the table entry that was modified for enabling MMU */
-static void restore_table_entry(void)
+static void omap34xx_do_sram_idle(unsigned long save_state)
 {
-	void __iomem *scratchpad_address;
-	u32 previous_value, control_reg_value;
-	u32 *address;
-
-	scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
-
-	/* Get address of entry that was modified */
-	address = (u32 *)__raw_readl(scratchpad_address +
-				     OMAP343X_TABLE_ADDRESS_OFFSET);
-	/* Get the previous value which needs to be restored */
-	previous_value = __raw_readl(scratchpad_address +
-				     OMAP343X_TABLE_VALUE_OFFSET);
-	address = __va(address);
-	*address = previous_value;
-	flush_tlb_all();
-	control_reg_value = __raw_readl(scratchpad_address
-					+ OMAP343X_CONTROL_REG_VALUE_OFFSET);
-	/* This will enable caches and prediction */
-	set_cr(control_reg_value);
+	_omap_sram_idle(omap3_arm_context, save_state);
 }
 
 void omap_sram_idle(void)
@@ -432,12 +406,15 @@ void omap_sram_idle(void)
 		sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
 	/*
-	 * omap3_arm_context is the location where ARM registers
-	 * get saved. The restore path then reads from this
-	 * location and restores them back.
+	 * omap3_arm_context is the location where some ARM context
+	 * get saved. The rest is placed on the stack, and restored
+	 * from there before resuming.
 	 */
-	_omap_sram_idle(omap3_arm_context, save_state);
-	cpu_init();
+	if (save_state == 1 || save_state == 3)
+		cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, save_state,
+			    omap34xx_do_sram_idle);
+	else
+		omap34xx_do_sram_idle(save_state);
 
 	/* Restore normal SDRC POWER settings */
 	if (omap_rev() >= OMAP3430_REV_ES3_0 &&
@@ -445,10 +422,6 @@ void omap_sram_idle(void)
 	    core_next_state == PWRDM_POWER_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
-	/* Restore table entry modified during MMU restoration */
-	if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
-		restore_table_entry();
-
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
 		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
arch/arm/mach-omap2/sleep34xx.S +3 -140

163 lines not on this page · raw message

Signature · 1 line
1.7.4.4
#25 lore raw

PATCH 23/25 ARM: pm: omap34xx: convert to generic suspend/resume support

Russell,

Just a minor remark:

Quoted 1 line · Russell King - ARM Linux

Convert sa11x0 to use the generic CPU suspend/resume support, rather

               ^^^^^^^ should be 'OMAP3'
Quoted 3 lines

than implementing its own version. ?Tested on 3430 LDP.

Jean

#26 lore raw

PATCH 23/25 ARM: pm: omap34xx: convert to generic suspend/resume support

Quoted 10 lines · Jean Pihet

Russell,

Just a minor remark:

Quoted 1 line · Russell King - ARM Linux

Convert sa11x0 to use the generic CPU suspend/resume support, rather

               ^^^^^^^ should be 'OMAP3'
Quoted 3 lines

than implementing its own version. ?Tested on 3430 LDP.

Thanks, fixed.

#27 lore raw

PATCH 24/25 ARM: pm: hide 1st and 2nd arguments to cpu_suspend from platform code

In reply to Russell King - ARM Linux

The first and second arguments shouldn't concern platform code, so hide them from each platforms caller.

---
 arch/arm/include/asm/suspend.h |   19 +++++++++++++++++++
 arch/arm/include/asm/system.h  |    2 --
 arch/arm/kernel/sleep.S        |    2 +-
 arch/arm/mach-omap2/pm34xx.c   |    5 +++--
 arch/arm/mach-pxa/palmz72.c    |    1 +
 arch/arm/mach-pxa/pxa25x.c     |    4 ++--
 arch/arm/mach-pxa/pxa27x.c     |    4 ++--
 arch/arm/mach-pxa/pxa3xx.c     |    3 ++-
 arch/arm/mach-pxa/zeus.c       |    4 ++--
 arch/arm/mach-sa1100/pm.c      |    3 ++-
 arch/arm/plat-samsung/pm.c     |    3 ++-
 11 files changed, 36 insertions(+), 14 deletions(-)
 create mode 100644 arch/arm/include/asm/suspend.h
arch/arm/include/asm/suspend.h new file +19 -0
new file mode 100644
index 0000000..8d5b446
@@ -0,0 +1,19 @@
+#ifndef __ASM_ARM_SUSPEND_H
+#define __ASM_ARM_SUSPEND_H
+
+#include <asm/memory.h>
+
+extern void cpu_resume(void);
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+static inline void cpu_suspend(unsigned long arg, void (*fn)(unsigned long))
+{
+	extern void __cpu_suspend(int, long, unsigned long,
+				  void (*)(unsigned long));
+	__cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+}
+
+#endif
arch/arm/include/asm/system.h +0 -2
index 50be605..832888d 100644
@@ -106,8 +106,6 @@ extern void __show_regs(struct pt_regs *);
 
 extern int cpu_architecture(void);
 extern void cpu_init(void);
-extern void cpu_suspend(int, long, unsigned long, void (*)(unsigned long));
-extern void cpu_resume(void);
 
 void arm_machine_restart(char mode, const char *cmd);
 extern void (*arm_pm_restart)(char str, const char *cmd);
arch/arm/kernel/sleep.S +1 -1
index 5392274..0bdcc72 100644
@@ -14,7 +14,7 @@
  *  r3 = suspend function
  * Note: does not return until system resumes
  */
-ENTRY(cpu_suspend)
+ENTRY(__cpu_suspend)
 	stmfd	sp!, {r4 - r11, lr}
 #ifdef MULTI_CPU
 	ldr	r10, =processor
arch/arm/mach-omap2/pm34xx.c +3 -2
index ae40177..3e9a13e 100644
@@ -31,6 +31,8 @@
 #include <linux/console.h>
 #include <trace/events/power.h>
 
+#include <asm/suspend.h>
+
 #include <plat/sram.h>
 #include "clockdomain.h"
 #include "powerdomain.h"
@@ -411,8 +413,7 @@ void omap_sram_idle(void)
 	 * from there before resuming.
 	 */
 	if (save_state == 1 || save_state == 3)
-		cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, save_state,
-			    omap34xx_do_sram_idle);
+		cpu_suspend(save_state, omap34xx_do_sram_idle);
 	else
 		omap34xx_do_sram_idle(save_state);
 
arch/arm/mach-pxa/palmz72.c +1 -0
index 65f24f0..5a5329b 100644
@@ -33,6 +33,7 @@
 #include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
+#include <asm/suspend.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
arch/arm/mach-pxa/pxa25x.c +2 -2
index fd7725c..9c434d2 100644
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 
 #include <asm/mach/map.h>
+#include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
@@ -244,8 +245,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
-		cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, PWRMODE_SLEEP,
-			    pxa25x_finish_suspend);
+		cpu_suspend(PWRMODE_SLEEP, pxa25x_finish_suspend);
 		break;
 	}
 }
arch/arm/mach-pxa/pxa27x.c +2 -2
index 824379d..9d2400b 100644
@@ -24,6 +24,7 @@
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/suspend.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
 #include <mach/pxa27x.h>
@@ -304,8 +305,7 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, pwrmode,
-			    pxa27x_finish_suspend);
+		cpu_suspend(pwrmode, pxa27x_finish_suspend);
 #ifndef CONFIG_IWMMXT
 		asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
 #endif
arch/arm/mach-pxa/pxa3xx.c +2 -1
index 220fd8c..9fe947b 100644
@@ -24,6 +24,7 @@
 #include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
+#include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 #include <mach/pxa3xx-regs.h>
@@ -167,7 +168,7 @@ static void pxa3xx_cpu_pm_suspend(void)
 	/* overwrite with the resume address */
 	*p = virt_to_phys(cpu_resume);
 
-	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, 0, pxa3xx_finish_suspend);
+	cpu_suspend(0, pxa3xx_finish_suspend);
 
 	*p = saved_data;
 
arch/arm/mach-pxa/zeus.c +2 -2
index 28eb410..9b99cc1 100644
@@ -31,6 +31,7 @@
 #include <linux/can/platform/mcp251x.h>
 
 #include <asm/mach-types.h>
+#include <asm/suspend.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
@@ -676,8 +677,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
 static void zeus_power_off(void)
 {
 	local_irq_disable();
-	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, PWRMODE_DEEPSLEEP,
-		    pxa27x_finish_suspend);
+	cpu_suspend(PWRMODE_DEEPSLEEP, pxa27x_finish_suspend);
 }
 #else
 #define zeus_power_off   NULL
arch/arm/mach-sa1100/pm.c +2 -1
index 259ed3b..cf9a1e9 100644
@@ -29,6 +29,7 @@
 
 #include <mach/hardware.h>
 #include <asm/memory.h>
+#include <asm/suspend.h>
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
@@ -75,7 +76,7 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	PSPR = virt_to_phys(cpu_resume);
 
 	/* go zzz */
-	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, 0, sa1100_finish_suspend);
+	cpu_suspend(0, sa1100_finish_suspend);
 
 	/*
 	 * Ensure not to come back here if it wasn't intended
arch/arm/plat-samsung/pm.c +2 -1
index 3a6d076..69d6b04 100644
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
@@ -298,7 +299,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.  */
 
-	cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, 0, pm_cpu_sleep);
+	cpu_suspend(0, pm_cpu_sleep);
 
 	/* restore the system state */
 
Signature · 1 line
1.7.4.4
#28 lore raw

PATCH 24/25 ARM: pm: hide 1st and 2nd arguments to cpu_suspend from platform code

Quoted 62 lines · Russell King - ARM Linux

The first and second arguments shouldn't concern platform code, so hide them from each platforms caller.

---
 arch/arm/include/asm/suspend.h |   19 +++++++++++++++++++
 arch/arm/include/asm/system.h  |    2 --
 arch/arm/kernel/sleep.S        |    2 +-
 arch/arm/mach-omap2/pm34xx.c   |    5 +++--
 arch/arm/mach-pxa/palmz72.c    |    1 +
 arch/arm/mach-pxa/pxa25x.c     |    4 ++--
 arch/arm/mach-pxa/pxa27x.c     |    4 ++--
 arch/arm/mach-pxa/pxa3xx.c     |    3 ++-
 arch/arm/mach-pxa/zeus.c       |    4 ++--
 arch/arm/mach-sa1100/pm.c      |    3 ++-
 arch/arm/plat-samsung/pm.c     |    3 ++-
 11 files changed, 36 insertions(+), 14 deletions(-)
 create mode 100644 arch/arm/include/asm/suspend.h
arch/arm/include/asm/suspend.h new file +19 -0
new file mode 100644
index 0000000..8d5b446
@@ -0,0 +1,19 @@
+#ifndef __ASM_ARM_SUSPEND_H
+#define __ASM_ARM_SUSPEND_H
+
+#include <asm/memory.h>
+
+extern void cpu_resume(void);
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+static inline void cpu_suspend(unsigned long arg, void (*fn)(unsigned long))
+{
+	extern void __cpu_suspend(int, long, unsigned long,
+				  void (*)(unsigned long));
+	__cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+}
+
+#endif
arch/arm/include/asm/system.h +0 -2
index 50be605..832888d 100644
@@ -106,8 +106,6 @@ extern void __show_regs(struct pt_regs *);
 
 extern int cpu_architecture(void);
 extern void cpu_init(void);
-extern void cpu_suspend(int, long, unsigned long, void (*)(unsigned long));
-extern void cpu_resume(void);
 
 void arm_machine_restart(char mode, const char *cmd);
 extern void (*arm_pm_restart)(char str, const char *cmd);
arch/arm/kernel/sleep.S +0 -0
index 5392274..0bdcc72 100644

arch/arm/kernel/sleep.S line 17

Quoted 5 lines
arch/arm/kernel/sleep.S +1 -1
@@ -14,7 +14,7 @@
  *  r3 = suspend function
  * Note: does not return until system resumes
  */
-ENTRY(cpu_suspend)
+ENTRY(__cpu_suspend)

You missed also changing the ENDPROC here, so it doesn't compile without:

arch/arm/kernel/sleep.S +1 -1
index 0bdcc72..c156d0e 100644
@@ -56,7 +56,7 @@ ENTRY(__cpu_suspend)
        bl      __cpuc_flush_kern_all
 #endif
        ldmfd   sp!, {r0, pc}           @ call suspend fn
-ENDPROC(cpu_suspend)
+ENDPROC(__cpu_suspend)
        .ltorg
 
 /*

Kevin

#29 lore raw

PATCH 25/25 ARM: pm: ensure our temporary page table entry is removed from the TLB

In reply to Russell King - ARM Linux

Ensure that our temporary page table entry is flushed from the TLB before we resume normal operations. This ensures that userspace won't trip over the stale TLB entry.

---
 arch/arm/include/asm/suspend.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/include/asm/suspend.h +2 -0
index 8d5b446..f8db9d0 100644
@@ -2,6 +2,7 @@
 #define __ASM_ARM_SUSPEND_H
 
 #include <asm/memory.h>
+#include <asm/tlbflush.h>
 
 extern void cpu_resume(void);
 
@@ -14,6 +15,7 @@ static inline void cpu_suspend(unsigned long arg, void (*fn)(unsigned long))
 	extern void __cpu_suspend(int, long, unsigned long,
 				  void (*)(unsigned long));
 	__cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+	flush_tlb_all();
 }
 
 #endif
Signature · 1 line
1.7.4.4
#30 lore raw

cover Re-jig cpu_suspend for a saner calling convention

In reply to Russell King - ARM Linux

Russell King - ARM Linux <[email protected]> writes:

[...]

Quoted 3 lines

Tested on Assabet (SA1100) and 3430LDP only.

Tested on OMAP: 3430/n900, 3530/Overo and 3630/Zoom3.

In addition to this series, I needed that ENDPROC fix as well as the v7_processor_functions patch just sent.

With those, I was able to hit full-chip retention and off-mode in both suspend and idle paths on the above platforms.

Kevin

#31 lore raw

cover Re-jig cpu_suspend for a saner calling convention

In reply to Russell King - ARM Linux

Hi Russell,

Quoted 40 lines · Russell King - ARM Linux

Version 3.

Currently cpu_suspend is not like a normal C function - when it's called it returns normally to a bunch of code which is not expected to return. The return path is via code pointed to by 'r3'.

It also corrupts a bunch of registers in ways which make it non-compliant with a C API.

If we do make this compliant as a normal C-like function, it eliminates this register saving, and also allows us to make greater savings. ?We also swap 'lr' and 'r3', so cpu_suspend effectively only returns to following code on resume - and r3 points to the suspend code.

I've also changed cpu_suspend() to have a saner visible prototype for calling from platforms, hiding the needed v:p offset parameter in the inline function.

So, this becomes:
static void soc_suspend(void)
{
? ? ? ?[soc specific preparation]

? ? ? ?cpu_suspend(soc_suspend_arg, soc_finish_suspend);

? ? ? ?[soc specific cleanup ]
}

where soc_suspend_fn can be either assembly or C code - but must never return. ?(See separate patch posted on 13th June to allow it to return.)

This patch series also merges the call to cpu_init() into cpu_suspend(), and makes cpu_init() call the per-CPU initialization function to ensure that various registers are setup (eg, clock switching on StrongARM, read-buffer enabled for userspace, etc.) ?This allows some more custom platform suspend code to be removed.

I've been able to convert OMAP3 suspend support and test it in both retention and off modes.

Quoted 6 lines

The only platform not converted to cpu_suspend() is the shmobile stuff, which I've requested their assistance with.

This patch set also eliminates 300 LOC from platform code.

Tested on Assabet (SA1100) and 3430LDP only.

That is a great set of patches! We are now close to have a clean suspend code, all the way from arch code to low level OMAP-specific ASM implementation.

FWIW:

Regards,
Jean

Quoted 36 lines
?arch/arm/include/asm/suspend.h ? ? ? ? ?| ? 21 ++++
?arch/arm/kernel/setup.c ? ? ? ? ? ? ? ? | ? 99 ++++++++++----------
?arch/arm/kernel/sleep.S ? ? ? ? ? ? ? ? | ? 73 ++++++---------
?arch/arm/mach-exynos4/pm.c ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-exynos4/sleep.S ? ? ? ? ? | ? 22 ----
?arch/arm/mach-omap2/pm34xx.c ? ? ? ? ? ?| ? 48 ++-------
?arch/arm/mach-omap2/sleep34xx.S ? ? ? ? | ?160 ++-----------------------------
?arch/arm/mach-pxa/include/mach/pm.h ? ? | ? ?4 +-
?arch/arm/mach-pxa/palmz72.c ? ? ? ? ? ? | ? ?1 +
?arch/arm/mach-pxa/pm.c ? ? ? ? ? ? ? ? ?| ? ?1 -
?arch/arm/mach-pxa/pxa25x.c ? ? ? ? ? ? ?| ? ?3 +-
?arch/arm/mach-pxa/pxa27x.c ? ? ? ? ? ? ?| ? 11 ++-
?arch/arm/mach-pxa/pxa3xx.c ? ? ? ? ? ? ?| ? 14 +++-
?arch/arm/mach-pxa/sleep.S ? ? ? ? ? ? ? | ? 55 ++---------
?arch/arm/mach-pxa/zeus.c ? ? ? ? ? ? ? ?| ? ?3 +-
?arch/arm/mach-s3c2412/pm.c ? ? ? ? ? ? ?| ? ?4 +-
?arch/arm/mach-s3c2416/pm.c ? ? ? ? ? ? ?| ? ?4 +-
?arch/arm/mach-s3c64xx/pm.c ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-s3c64xx/sleep.S ? ? ? ? ? | ? 23 -----
?arch/arm/mach-s5pv210/pm.c ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-s5pv210/sleep.S ? ? ? ? ? | ? 21 ----
?arch/arm/mach-sa1100/pm.c ? ? ? ? ? ? ? | ? ?7 +-
?arch/arm/mach-sa1100/sleep.S ? ? ? ? ? ?| ? 19 +----
?arch/arm/mm/proc-sa1100.S ? ? ? ? ? ? ? | ? ?4 +-
?arch/arm/mm/proc-v7.S ? ? ? ? ? ? ? ? ? | ? 10 ++-
?arch/arm/plat-s3c24xx/sleep.S ? ? ? ? ? | ? 25 -----
?arch/arm/plat-samsung/include/plat/pm.h | ? ?5 +-
?arch/arm/plat-samsung/pm.c ? ? ? ? ? ? ?| ? 11 +--

?28 files changed, 180 insertions(+), 474 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html