All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] Generic CPU save/restore PM support
@ 2011-02-06 19:11 Russell King - ARM Linux
  2011-02-06 19:12 ` [PATCH 1/5] ARM: move cache/processor/fault glue to separate include files Russell King - ARM Linux
                   ` (5 more replies)
  0 siblings, 6 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-06 19:11 UTC (permalink / raw)
  To: linux-arm-kernel

The following patch series implements infrastructure to save/restore
CPU state on suspend/resume PM events, and updates SA11x0, PXA and
Samsung platforms to use this.

Not all CPU support files are updated with the necessary changes -
currently only ARM920, ARM926, SA11x0, XScale, XScale3, V6 and V7
CPUs are supported.

I've build-tested this for Assabet, PXA, and S3C2410, but not boot
tested it yet.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 1/5] ARM: move cache/processor/fault glue to separate include files
  2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
@ 2011-02-06 19:12 ` Russell King - ARM Linux
  2011-02-06 19:12 ` [PATCH 2/5] ARM: pm: add generic CPU suspend/resume support Russell King - ARM Linux
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-06 19:12 UTC (permalink / raw)
  To: linux-arm-kernel

This allows the cache/processor/fault glue to be more easily used
from assembler code.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/include/asm/cacheflush.h  |  133 +----------------
 arch/arm/include/asm/cpu-multi32.h |   69 --------
 arch/arm/include/asm/cpu-single.h  |   44 ------
 arch/arm/include/asm/glue-cache.h  |  146 ++++++++++++++++++
 arch/arm/include/asm/glue-df.h     |  110 +++++++++++++
 arch/arm/include/asm/glue-pf.h     |   57 +++++++
 arch/arm/include/asm/glue-proc.h   |  261 +++++++++++++++++++++++++++++++
 arch/arm/include/asm/glue.h        |  138 -----------------
 arch/arm/include/asm/proc-fns.h    |  299 ++++++++----------------------------
 arch/arm/kernel/asm-offsets.c      |    2 +
 arch/arm/kernel/entry-armv.S       |    3 +-
 11 files changed, 644 insertions(+), 618 deletions(-)
 delete mode 100644 arch/arm/include/asm/cpu-multi32.h
 delete mode 100644 arch/arm/include/asm/cpu-single.h
 create mode 100644 arch/arm/include/asm/glue-cache.h
 create mode 100644 arch/arm/include/asm/glue-df.h
 create mode 100644 arch/arm/include/asm/glue-pf.h
 create mode 100644 arch/arm/include/asm/glue-proc.h

diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 3acd8fa..18a5664 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -12,7 +12,7 @@
 
 #include <linux/mm.h>
 
-#include <asm/glue.h>
+#include <asm/glue-cache.h>
 #include <asm/shmparam.h>
 #include <asm/cachetype.h>
 #include <asm/outercache.h>
@@ -20,123 +20,6 @@
 #define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
- *	Cache Model
- *	===========
- */
-#undef _CACHE
-#undef MULTI_CACHE
-
-#if defined(CONFIG_CPU_CACHE_V3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_CACHE_V4)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v4
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
-    defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \
-    defined(CONFIG_CPU_ARM1026)
-# define MULTI_CACHE 1
-#endif
-
-#if defined(CONFIG_CPU_FA526)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE fa
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM926T)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm926
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM940T)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm940
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM946E)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm946
-# endif
-#endif
-
-#if defined(CONFIG_CPU_CACHE_V4WB)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v4wb
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSCALE)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE xscale
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSC3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE xsc3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_MOHAWK)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE mohawk
-# endif
-#endif
-
-#if defined(CONFIG_CPU_FEROCEON)
-# define MULTI_CACHE 1
-#endif
-
-#if defined(CONFIG_CPU_V6)
-//# ifdef _CACHE
-#  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v6
-//# endif
-#endif
-
-#if defined(CONFIG_CPU_V7)
-//# ifdef _CACHE
-#  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v7
-//# endif
-#endif
-
-#if !defined(_CACHE) && !defined(MULTI_CACHE)
-#error Unknown cache maintainence model
-#endif
-
-/*
  * This flag is used to indicate that the page pointed to by a pte is clean
  * and does not require cleaning before returning it to the user.
  */
@@ -249,19 +132,11 @@ extern struct cpu_cache_fns cpu_cache;
  * visible to the CPU.
  */
 #define dmac_map_area			cpu_cache.dma_map_area
-#define dmac_unmap_area		cpu_cache.dma_unmap_area
+#define dmac_unmap_area			cpu_cache.dma_unmap_area
 #define dmac_flush_range		cpu_cache.dma_flush_range
 
 #else
 
-#define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
-#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
-#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
-#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
-#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
-#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
-#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
-
 extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
@@ -276,10 +151,6 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
-#define dmac_map_area			__glue(_CACHE,_dma_map_area)
-#define dmac_unmap_area		__glue(_CACHE,_dma_unmap_area)
-#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
-
 extern void dmac_map_area(const void *, size_t, int);
 extern void dmac_unmap_area(const void *, size_t, int);
 extern void dmac_flush_range(const void *, const void *);
diff --git a/arch/arm/include/asm/cpu-multi32.h b/arch/arm/include/asm/cpu-multi32.h
deleted file mode 100644
index e2b5b0b..0000000
--- a/arch/arm/include/asm/cpu-multi32.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  arch/arm/include/asm/cpu-multi32.h
- *
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <asm/page.h>
-
-struct mm_struct;
-
-/*
- * Don't change this structure - ASM code
- * relies on it.
- */
-extern struct processor {
-	/* MISC
-	 * get data abort address/flags
-	 */
-	void (*_data_abort)(unsigned long pc);
-	/*
-	 * Retrieve prefetch fault address
-	 */
-	unsigned long (*_prefetch_abort)(unsigned long lr);
-	/*
-	 * Set up any processor specifics
-	 */
-	void (*_proc_init)(void);
-	/*
-	 * Disable any processor specifics
-	 */
-	void (*_proc_fin)(void);
-	/*
-	 * Special stuff for a reset
-	 */
-	void (*reset)(unsigned long addr) __attribute__((noreturn));
-	/*
-	 * Idle the processor
-	 */
-	int (*_do_idle)(void);
-	/*
-	 * Processor architecture specific
-	 */
-	/*
-	 * clean a virtual address range from the
-	 * D-cache without flushing the cache.
-	 */
-	void (*dcache_clean_area)(void *addr, int size);
-
-	/*
-	 * Set the page table
-	 */
-	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
-	/*
-	 * Set a possibly extended PTE.  Non-extended PTEs should
-	 * ignore 'ext'.
-	 */
-	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
-} processor;
-
-#define cpu_proc_init()			processor._proc_init()
-#define cpu_proc_fin()			processor._proc_fin()
-#define cpu_reset(addr)			processor.reset(addr)
-#define cpu_do_idle()			processor._do_idle()
-#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
-#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
-#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
diff --git a/arch/arm/include/asm/cpu-single.h b/arch/arm/include/asm/cpu-single.h
deleted file mode 100644
index f073a6d..0000000
--- a/arch/arm/include/asm/cpu-single.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  arch/arm/include/asm/cpu-single.h
- *
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/*
- * Single CPU
- */
-#ifdef __STDC__
-#define __catify_fn(name,x)	name##x
-#else
-#define __catify_fn(name,x)	name/**/x
-#endif
-#define __cpu_fn(name,x)	__catify_fn(name,x)
-
-/*
- * If we are supporting multiple CPUs, then we must use a table of
- * function pointers for this lot.  Otherwise, we can optimise the
- * table away.
- */
-#define cpu_proc_init			__cpu_fn(CPU_NAME,_proc_init)
-#define cpu_proc_fin			__cpu_fn(CPU_NAME,_proc_fin)
-#define cpu_reset			__cpu_fn(CPU_NAME,_reset)
-#define cpu_do_idle			__cpu_fn(CPU_NAME,_do_idle)
-#define cpu_dcache_clean_area		__cpu_fn(CPU_NAME,_dcache_clean_area)
-#define cpu_do_switch_mm		__cpu_fn(CPU_NAME,_switch_mm)
-#define cpu_set_pte_ext			__cpu_fn(CPU_NAME,_set_pte_ext)
-
-#include <asm/page.h>
-
-struct mm_struct;
-
-/* declare all the functions as extern */
-extern void cpu_proc_init(void);
-extern void cpu_proc_fin(void);
-extern int cpu_do_idle(void);
-extern void cpu_dcache_clean_area(void *, int);
-extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
-extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
-extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
new file mode 100644
index 0000000..0591d35
--- /dev/null
+++ b/arch/arm/include/asm/glue-cache.h
@@ -0,0 +1,146 @@
+/*
+ *  arch/arm/include/asm/glue-cache.h
+ *
+ *  Copyright (C) 1999-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_CACHE_H
+#define ASM_GLUE_CACHE_H
+
+#include <asm/glue.h>
+
+/*
+ *	Cache Model
+ *	===========
+ */
+#undef _CACHE
+#undef MULTI_CACHE
+
+#if defined(CONFIG_CPU_CACHE_V3)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
+    defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \
+    defined(CONFIG_CPU_ARM1026)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_FA526)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE fa
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM926T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm926
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM940T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm940
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM946E)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm946
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4WB)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4wb
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSCALE)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xscale
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSC3)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xsc3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_MOHAWK)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE mohawk
+# endif
+#endif
+
+#if defined(CONFIG_CPU_FEROCEON)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_V6)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v6
+//# endif
+#endif
+
+#if defined(CONFIG_CPU_V7)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v7
+//# endif
+#endif
+
+#if !defined(_CACHE) && !defined(MULTI_CACHE)
+#error Unknown cache maintainence model
+#endif
+
+#ifndef MULTI_CACHE
+#define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
+#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
+#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
+#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
+#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
+#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
+
+#define dmac_map_area			__glue(_CACHE,_dma_map_area)
+#define dmac_unmap_area			__glue(_CACHE,_dma_unmap_area)
+#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
new file mode 100644
index 0000000..354d571
--- /dev/null
+++ b/arch/arm/include/asm/glue-df.h
@@ -0,0 +1,110 @@
+/*
+ *  arch/arm/include/asm/glue-df.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000-2002 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_DF_H
+#define ASM_GLUE_DF_H
+
+#include <asm/glue.h>
+
+/*
+ *	Data Abort Model
+ *	================
+ *
+ *	We have the following to choose from:
+ *	  arm6          - ARM6 style
+ *	  arm7		- ARM7 style
+ *	  v4_early	- ARMv4 without Thumb early abort handler
+ *	  v4t_late	- ARMv4 with Thumb late abort handler
+ *	  v4t_early	- ARMv4 with Thumb early abort handler
+ *	  v5tej_early	- ARMv5 with Thumb and Java early abort handler
+ *	  xscale	- ARMv5 with Thumb with Xscale extensions
+ *	  v6_early	- ARMv6 generic early abort handler
+ *	  v7_early	- ARMv7 generic early abort handler
+ */
+#undef CPU_DABORT_HANDLER
+#undef MULTI_DABORT
+
+#if defined(CONFIG_CPU_ARM610)
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM710)
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_LV4T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4t_late_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV4
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV4T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4t_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV5TJ
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v5tj_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV5T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v5t_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV6
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v6_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV7
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v7_early_abort
+# endif
+#endif
+
+#ifndef CPU_DABORT_HANDLER
+#error Unknown data abort handler type
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue-pf.h b/arch/arm/include/asm/glue-pf.h
new file mode 100644
index 0000000..d385f37
--- /dev/null
+++ b/arch/arm/include/asm/glue-pf.h
@@ -0,0 +1,57 @@
+/*
+ *  arch/arm/include/asm/glue-pf.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000-2002 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_PF_H
+#define ASM_GLUE_PF_H
+
+#include <asm/glue.h>
+
+/*
+ *	Prefetch Abort Model
+ *	================
+ *
+ *	We have the following to choose from:
+ *	  legacy	- no IFSR, no IFAR
+ *	  v6		- ARMv6: IFSR, no IFAR
+ *	  v7		- ARMv7: IFSR and IFAR
+ */
+
+#undef CPU_PABORT_HANDLER
+#undef MULTI_PABORT
+
+#ifdef CONFIG_CPU_PABRT_LEGACY
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER legacy_pabort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_PABRT_V6
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER v6_pabort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_PABRT_V7
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER v7_pabort
+# endif
+#endif
+
+#ifndef CPU_PABORT_HANDLER
+#error Unknown prefetch abort handler type
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
new file mode 100644
index 0000000..e3bf443
--- /dev/null
+++ b/arch/arm/include/asm/glue-proc.h
@@ -0,0 +1,261 @@
+/*
+ *  arch/arm/include/asm/glue-proc.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_PROC_H
+#define ASM_GLUE_PROC_H
+
+#include <asm/glue.h>
+
+/*
+ * Work out if we need multiple CPU support
+ */
+#undef MULTI_CPU
+#undef CPU_NAME
+
+/*
+ * CPU_NAME - the prefix for CPU related functions
+ */
+
+#ifdef CONFIG_CPU_ARM610
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm6
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM7TDMI
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm7tdmi
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM710
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm7
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM720T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm720
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM740T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm740
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM9TDMI
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm9tdmi
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM920T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm920
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM922T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm922
+# endif
+#endif
+
+#ifdef CONFIG_CPU_FA526
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_fa526
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM925T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm925
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM926T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm926
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM940T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm940
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM946E
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm946
+# endif
+#endif
+
+#ifdef CONFIG_CPU_SA110
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_sa110
+# endif
+#endif
+
+#ifdef CONFIG_CPU_SA1100
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_sa1100
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1020
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1020
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1020E
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1020e
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1022
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1022
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1026
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1026
+# endif
+#endif
+
+#ifdef CONFIG_CPU_XSCALE
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_xscale
+# endif
+#endif
+
+#ifdef CONFIG_CPU_XSC3
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_xsc3
+# endif
+#endif
+
+#ifdef CONFIG_CPU_MOHAWK
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_mohawk
+# endif
+#endif
+
+#ifdef CONFIG_CPU_FEROCEON
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_feroceon
+# endif
+#endif
+
+#ifdef CONFIG_CPU_V6
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v6
+# endif
+#endif
+
+#ifdef CONFIG_CPU_V7
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7
+# endif
+#endif
+
+#ifndef MULTI_CPU
+#define cpu_proc_init			__glue(CPU_NAME,_proc_init)
+#define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
+#define cpu_reset			__glue(CPU_NAME,_reset)
+#define cpu_do_idle			__glue(CPU_NAME,_do_idle)
+#define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
+#define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
+#define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue.h b/arch/arm/include/asm/glue.h
index 234a3fc..0ec35d1 100644
--- a/arch/arm/include/asm/glue.h
+++ b/arch/arm/include/asm/glue.h
@@ -15,7 +15,6 @@
  */
 #ifdef __KERNEL__
 
-
 #ifdef __STDC__
 #define ____glue(name,fn)	name##fn
 #else
@@ -23,141 +22,4 @@
 #endif
 #define __glue(name,fn)		____glue(name,fn)
 
-
-
-/*
- *	Data Abort Model
- *	================
- *
- *	We have the following to choose from:
- *	  arm6          - ARM6 style
- *	  arm7		- ARM7 style
- *	  v4_early	- ARMv4 without Thumb early abort handler
- *	  v4t_late	- ARMv4 with Thumb late abort handler
- *	  v4t_early	- ARMv4 with Thumb early abort handler
- *	  v5tej_early	- ARMv5 with Thumb and Java early abort handler
- *	  xscale	- ARMv5 with Thumb with Xscale extensions
- *	  v6_early	- ARMv6 generic early abort handler
- *	  v7_early	- ARMv7 generic early abort handler
- */
-#undef CPU_DABORT_HANDLER
-#undef MULTI_DABORT
-
-#if defined(CONFIG_CPU_ARM610)
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM710)
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_LV4T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4t_late_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV4
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV4T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4t_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV5TJ
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v5tj_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV5T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v5t_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV6
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v6_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV7
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v7_early_abort
-# endif
-#endif
-
-#ifndef CPU_DABORT_HANDLER
-#error Unknown data abort handler type
-#endif
-
-/*
- *	Prefetch Abort Model
- *	================
- *
- *	We have the following to choose from:
- *	  legacy	- no IFSR, no IFAR
- *	  v6		- ARMv6: IFSR, no IFAR
- *	  v7		- ARMv7: IFSR and IFAR
- */
-
-#undef CPU_PABORT_HANDLER
-#undef MULTI_PABORT
-
-#ifdef CONFIG_CPU_PABRT_LEGACY
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER legacy_pabort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_PABRT_V6
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER v6_pabort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_PABRT_V7
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER v7_pabort
-# endif
-#endif
-
-#ifndef CPU_PABORT_HANDLER
-#error Unknown prefetch abort handler type
-#endif
-
 #endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 8fdae9b..6980215 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -13,248 +13,77 @@
 
 #ifdef __KERNEL__
 
+#include <asm/glue-proc.h>
+#include <asm/page.h>
 
-/*
- * Work out if we need multiple CPU support
- */
-#undef MULTI_CPU
-#undef CPU_NAME
+#ifndef __ASSEMBLY__
+
+struct mm_struct;
 
 /*
- * CPU_NAME - the prefix for CPU related functions
+ * Don't change this structure - ASM code relies on it.
  */
-
-#ifdef CONFIG_CPU_ARM610
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm6
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM7TDMI
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm7tdmi
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM710
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm7
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM720T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm720
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM740T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm740
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM9TDMI
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm9tdmi
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM920T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm920
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM922T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm922
-# endif
-#endif
-
-#ifdef CONFIG_CPU_FA526
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_fa526
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM925T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm925
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM926T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm926
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM940T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm940
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM946E
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm946
-# endif
-#endif
-
-#ifdef CONFIG_CPU_SA110
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_sa110
-# endif
-#endif
-
-#ifdef CONFIG_CPU_SA1100
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_sa1100
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1020
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1020
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1020E
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1020e
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1022
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1022
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1026
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1026
-# endif
-#endif
-
-#ifdef CONFIG_CPU_XSCALE
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_xscale
-# endif
-#endif
-
-#ifdef CONFIG_CPU_XSC3
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_xsc3
-# endif
-#endif
-
-#ifdef CONFIG_CPU_MOHAWK
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_mohawk
-# endif
-#endif
-
-#ifdef CONFIG_CPU_FEROCEON
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_feroceon
-# endif
-#endif
-
-#ifdef CONFIG_CPU_V6
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v6
-# endif
-#endif
-
-#ifdef CONFIG_CPU_V7
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v7
-# endif
-#endif
-
-#ifndef __ASSEMBLY__
+extern struct processor {
+	/* MISC
+	 * get data abort address/flags
+	 */
+	void (*_data_abort)(unsigned long pc);
+	/*
+	 * Retrieve prefetch fault address
+	 */
+	unsigned long (*_prefetch_abort)(unsigned long lr);
+	/*
+	 * Set up any processor specifics
+	 */
+	void (*_proc_init)(void);
+	/*
+	 * Disable any processor specifics
+	 */
+	void (*_proc_fin)(void);
+	/*
+	 * Special stuff for a reset
+	 */
+	void (*reset)(unsigned long addr) __attribute__((noreturn));
+	/*
+	 * Idle the processor
+	 */
+	int (*_do_idle)(void);
+	/*
+	 * Processor architecture specific
+	 */
+	/*
+	 * clean a virtual address range from the
+	 * D-cache without flushing the cache.
+	 */
+	void (*dcache_clean_area)(void *addr, int size);
+
+	/*
+	 * Set the page table
+	 */
+	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
+	/*
+	 * Set a possibly extended PTE.  Non-extended PTEs should
+	 * ignore 'ext'.
+	 */
+	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
+} processor;
 
 #ifndef MULTI_CPU
-#include <asm/cpu-single.h>
+extern void cpu_proc_init(void);
+extern void cpu_proc_fin(void);
+extern int cpu_do_idle(void);
+extern void cpu_dcache_clean_area(void *, int);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #else
-#include <asm/cpu-multi32.h>
+#define cpu_proc_init()			processor._proc_init()
+#define cpu_proc_fin()			processor._proc_fin()
+#define cpu_reset(addr)			processor.reset(addr)
+#define cpu_do_idle()			processor._do_idle()
+#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
+#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
+#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
 #include <asm/memory.h>
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 82da661..5302a91 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,8 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/glue-df.h>
+#include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2b46fea..e8d8856 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -16,7 +16,8 @@
  */
 
 #include <asm/memory.h>
-#include <asm/glue.h>
+#include <asm/glue-df.h>
+#include <asm/glue-pf.h>
 #include <asm/vfpmacros.h>
 #include <mach/entry-macro.S>
 #include <asm/thread_notify.h>
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
  2011-02-06 19:12 ` [PATCH 1/5] ARM: move cache/processor/fault glue to separate include files Russell King - ARM Linux
@ 2011-02-06 19:12 ` Russell King - ARM Linux
  2011-02-07 12:01   ` [PATCH v2 " Russell King - ARM Linux
  2011-02-06 19:13 ` [PATCH 3/5] ARM: pm: convert PXA to generic " Russell King - ARM Linux
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-06 19:12 UTC (permalink / raw)
  To: linux-arm-kernel

This adds core support for saving and restoring CPU coprocessor
registers for suspend/resume support.  This contains support for suspend
with ARM920, ARM926, SA11x0, PXA25x, PXA27x, PXA3xx and V6 CPUs.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/include/asm/glue-proc.h |    3 +
 arch/arm/include/asm/proc-fns.h  |    7 ++
 arch/arm/kernel/Makefile         |    1 +
 arch/arm/kernel/asm-offsets.c    |    9 +++
 arch/arm/kernel/sleep.S          |   76 +++++++++++++++++++++++
 arch/arm/mm/proc-arm1020.S       |    3 +
 arch/arm/mm/proc-arm1020e.S      |    3 +
 arch/arm/mm/proc-arm1022.S       |    3 +
 arch/arm/mm/proc-arm1026.S       |    3 +
 arch/arm/mm/proc-arm6_7.S        |    6 ++
 arch/arm/mm/proc-arm720.S        |    3 +
 arch/arm/mm/proc-arm740.S        |    3 +
 arch/arm/mm/proc-arm7tdmi.S      |    3 +
 arch/arm/mm/proc-arm920.S        |   34 ++++++++++
 arch/arm/mm/proc-arm922.S        |    3 +
 arch/arm/mm/proc-arm925.S        |    3 +
 arch/arm/mm/proc-arm926.S        |   34 ++++++++++
 arch/arm/mm/proc-arm940.S        |    3 +
 arch/arm/mm/proc-arm946.S        |    3 +
 arch/arm/mm/proc-arm9tdmi.S      |    3 +
 arch/arm/mm/proc-fa526.S         |    3 +
 arch/arm/mm/proc-feroceon.S      |    3 +
 arch/arm/mm/proc-mohawk.S        |    3 +
 arch/arm/mm/proc-sa110.S         |    3 +
 arch/arm/mm/proc-sa1100.S        |   43 +++++++++++++
 arch/arm/mm/proc-v6.S            |   43 +++++++++++++
 arch/arm/mm/proc-v7.S            |  124 ++++++++++++++++++++++++++++---------
 arch/arm/mm/proc-xsc3.S          |   78 +++++++++++++++++++++++-
 arch/arm/mm/proc-xscale.S        |   51 +++++++++++++++-
 29 files changed, 524 insertions(+), 33 deletions(-)
 create mode 100644 arch/arm/kernel/sleep.S

diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e3bf443..6469521 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -256,6 +256,9 @@
 #define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
 #define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
 #define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
+#define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
+#define cpu_do_resume			__glue(CPU_NAME,_do_resume)
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 6980215..8ec535e 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -66,6 +66,11 @@ extern struct processor {
 	 * ignore 'ext'.
 	 */
 	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
+
+	/* Suspend/resume */
+	unsigned int suspend_size;
+	void (*do_suspend)(void *);
+	void (*do_resume)(void *);
 } processor;
 
 #ifndef MULTI_CPU
@@ -86,6 +91,8 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
+extern void cpu_resume(void);
+
 #include <asm/memory.h>
 
 #ifdef CONFIG_MMU
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 185ee82..74554f1 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
+obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 5302a91..927522c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
@@ -116,6 +117,14 @@ int main(void)
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
 #endif
+#ifdef MULTI_CPU
+  DEFINE(CPU_SLEEP_SIZE,	offsetof(struct processor, suspend_size));
+  DEFINE(CPU_DO_SUSPEND,	offsetof(struct processor, do_suspend));
+  DEFINE(CPU_DO_RESUME,		offsetof(struct processor, do_resume));
+#endif
+#ifdef MULTI_CACHE
+  DEFINE(CACHE_FLUSH_KERN_ALL,	offsetof(struct cpu_cache_fns, flush_kern_all));
+#endif
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
new file mode 100644
index 0000000..02c9d83
--- /dev/null
+++ b/arch/arm/kernel/sleep.S
@@ -0,0 +1,76 @@
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/glue-cache.h>
+#include <asm/glue-proc.h>
+	.text
+
+/*
+ * Save CPU state for a suspend
+ *  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
+ */
+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!, {r2, r3, ip}		@ save virt SP + phys resume fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1			@ convert SP to phys
+	str	r2, [r3]			@ save phys SP
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND]	@ save CPU state
+#else
+	mov	r2, sp				@ current virtual SP
+	ldr	r0, =cpu_suspend_size
+	sub	sp, sp, r0			@ allocate CPU state on stack
+	mov	r0, sp				@ save pointer
+	stmfd	sp!, {r2, r3}
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1			@ convert SP to phys
+	str	r2, [r3]			@ save phys SP
+	bl	cpu_do_suspend
+#endif
+
+	@ clean data cache
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	mov	lr, r9
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	mov	lr, r9
+	b	__cpuc_flush_kern_all
+#endif
+ENDPROC(cpu_suspend)
+	.ltorg
+
+/*
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+	.data
+	.align
+ENTRY(cpu_resume)
+	ldr	r0, sleep_save_sp	@ stack phys addr
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
+#ifdef MULTI_CPU
+	ldmia	r0!, {sp, lr, pc}	@ load stack + return fn + resume fn
+#else
+	ldmia	r0!, {sp, lr}		@ load stack + return fn
+	b	cpu_do_resume
+#endif
+ENDPROC(cpu_resume)
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index bcf748d..226e3d8 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -493,6 +493,9 @@ arm1020_processor_functions:
 	.word	cpu_arm1020_dcache_clean_area
 	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index ab7ec26..86d9c2c 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -474,6 +474,9 @@ arm1020e_processor_functions:
 	.word	cpu_arm1020e_dcache_clean_area
 	.word	cpu_arm1020e_switch_mm
 	.word	cpu_arm1020e_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 831c5e5..83d3dd3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -457,6 +457,9 @@ arm1022_processor_functions:
 	.word	cpu_arm1022_dcache_clean_area
 	.word	cpu_arm1022_switch_mm
 	.word	cpu_arm1022_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1022_processor_functions, . - arm1022_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index e3f7e9a..686043e 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -452,6 +452,9 @@ arm1026_processor_functions:
 	.word	cpu_arm1026_dcache_clean_area
 	.word	cpu_arm1026_switch_mm
 	.word	cpu_arm1026_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1026_processor_functions, . - arm1026_processor_functions
 
 	.section .rodata
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 6a7be18..5f79dc4 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions)
 		.word	cpu_arm6_dcache_clean_area
 		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions)
 		.word	cpu_arm7_dcache_clean_area
 		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index c285395..665266d 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions)
 		.word	cpu_arm720_dcache_clean_area
 		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 38b27dc..6f9d12e 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions)
 	.word	cpu_arm740_dcache_clean_area
 	.word	cpu_arm740_switch_mm
 	.word	0			@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm740_processor_functions, . - arm740_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 0c9786d..e4c165c 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions)
 		.word	cpu_arm7tdmi_dcache_clean_area
 		.word	cpu_arm7tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 6109f27..b5946ff 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -387,6 +387,37 @@ ENTRY(cpu_arm920_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm920_suspend_size
+.equ	arm920_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm920_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm920_do_suspend)
+
+ENTRY(arm920_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mcr	p15, 0, r7, c1, c0, 0	@ Control register
+	nop
+	mov	pc, lr
+ENDPROC(arm920_do_resume)
+#else
+#define arm920_do_suspend	0
+#define arm920_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm920_setup, #function
@@ -432,6 +463,9 @@ arm920_processor_functions:
 	.word	cpu_arm920_dcache_clean_area
 	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte_ext
+	.word	arm920_suspend_size
+	.word	arm920_do_suspend
+	.word	arm920_do_resume
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index bb2f0f4..36154b1 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -436,6 +436,9 @@ arm922_processor_functions:
 	.word	cpu_arm922_dcache_clean_area
 	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index c13e01a..89c5e00 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -503,6 +503,9 @@ arm925_processor_functions:
 	.word	cpu_arm925_dcache_clean_area
 	.word	cpu_arm925_switch_mm
 	.word	cpu_arm925_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm925_processor_functions, . - arm925_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 42eb431..97095e9 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -401,6 +401,37 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm926_suspend_size
+.equ	arm926_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm926_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm926_do_suspend)
+
+ENTRY(arm926_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mcr	p15, 0, r7, c1, c0, 0	@ Control register
+	nop
+	mov	pc, lr
+ENDPROC(arm926_do_resume)
+#else
+#define arm926_do_suspend	0
+#define arm926_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm926_setup, #function
@@ -456,6 +487,9 @@ arm926_processor_functions:
 	.word	cpu_arm926_dcache_clean_area
 	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte_ext
+	.word	arm926_suspend_size
+	.word	arm926_do_suspend
+	.word	arm926_do_resume
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 7b11cdb..26aea3f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions)
 	.word	cpu_arm940_dcache_clean_area
 	.word	cpu_arm940_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm940_processor_functions, . - arm940_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 1a5bbf0..8063345 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions)
 	.word	cpu_arm946_dcache_clean_area
 	.word	cpu_arm946_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm946_processor_functions, . - arm946_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db67e31..7b7ebd4 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions)
 		.word	cpu_arm9tdmi_dcache_clean_area
 		.word	cpu_arm9tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7c9ad62..fc2a4ae 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -195,6 +195,9 @@ fa526_processor_functions:
 	.word	cpu_fa526_dcache_clean_area
 	.word	cpu_fa526_switch_mm
 	.word	cpu_fa526_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	fa526_processor_functions, . - fa526_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b4597ed..d3883ee 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -554,6 +554,9 @@ feroceon_processor_functions:
 	.word	cpu_feroceon_dcache_clean_area
 	.word	cpu_feroceon_switch_mm
 	.word	cpu_feroceon_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	feroceon_processor_functions, . - feroceon_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 4458ee6..9d4f2ae 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -388,6 +388,9 @@ mohawk_processor_functions:
 	.word	cpu_mohawk_dcache_clean_area
 	.word	cpu_mohawk_switch_mm
 	.word	cpu_mohawk_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	mohawk_processor_functions, . - mohawk_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 5aa8d59..46f09ed 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions)
 	.word	cpu_sa110_dcache_clean_area
 	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 2ac4e6f..37e5361 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,6 +169,46 @@ ENTRY(cpu_sa1100_set_pte_ext)
 #endif
 	mov	pc, lr
 
+.globl	cpu_sa1100_suspend_size
+.equ	cpu_sa1100_suspend_size, 4*4
+#ifdef CONFIG_PM
+ENTRY(cpu_sa1100_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
+	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r6, c13, c0, 0		@ PID
+	mrc	p15, 0, r7, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r7}			@ store cp regs
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_sa1100_do_suspend)
+
+ENTRY(cpu_sa1100_do_resume)
+	ldmia	r0, {r4 - r7}			@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@ flush I+D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
+	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
+
+	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
+	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r6, c13, c0, 0		@ PID
+	b	cpu_sa1100_turn_mmu_on
+ENDPROC(cpu_sa1100_do_resume)
+	.align	5
+cpu_sa1100_turn_mmu_on:
+	mcr	p15, 0, r7, c1, c0, 0		@ turn on MMU, caches, etc.
+	nop
+	mov	pc, lr				@ jump to virtual addr
+	nop
+	nop
+	nop
+ENDPROC(cpu_sa1100_turn_mmu_on)
+#else
+#define cpu_sa1100_do_suspend	0
+#define cpu_sa1100_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__sa1100_setup, #function
@@ -218,6 +258,9 @@ ENTRY(sa1100_processor_functions)
 	.word	cpu_sa1100_dcache_clean_area
 	.word	cpu_sa1100_switch_mm
 	.word	cpu_sa1100_set_pte_ext
+	.word	cpu_sa1100_suspend_size
+	.word	cpu_sa1100_do_suspend
+	.word	cpu_sa1100_do_resume
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 59a7e1f..838b031 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -121,6 +121,46 @@ ENTRY(cpu_v6_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
+.globl	cpu_v6_suspend_size
+.equ	cpu_v6_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_v6_do_suspend)
+	stmfd	sp!, {r4 - r10, 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 base 0
+	mrc	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r8, c1, c0, 1	@ auxillary control register
+	mrc	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r10, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4- r10, pc}
+ENDPROC(cpu_v6_do_suspend)
+
+ENTRY(cpu_v6_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
+	ldmia	r0, {r4 - r10}
+	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 base 0
+	mcr	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r8, c1, c0, 1	@ auxillary control register
+	mcr	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, ip, c7, c5, 4	@ ISB
+	mcr	p15, 0, r10, c1, c0, 0	@ turn MMU back on
+	nop
+	mov	pc, lr			@ jump to return fn
+ENDPROC(cpu_v6_do_resume)
+#else
+#define cpu_v6_do_suspend 0
+#define cpu_v6_do_resume 0
+#endif
 
 
 	.type	cpu_v6_name, #object
@@ -206,6 +246,9 @@ ENTRY(v6_processor_functions)
 	.word	cpu_v6_dcache_clean_area
 	.word	cpu_v6_switch_mm
 	.word	cpu_v6_set_pte_ext
+	.word	cpu_v6_suspend_size
+	.word	cpu_v6_do_suspend
+	.word	cpu_v6_do_resume
 	.size	v6_processor_functions, . - v6_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 0c1172b..17dfb12 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -171,6 +171,95 @@ cpu_v7_name:
 	.ascii	"ARMv7 Processor"
 	.align
 
+	/*
+	 * Memory region attributes with SCTLR.TRE=1
+	 *
+	 *   n = TEX[0],C,B
+	 *   TR = PRRR[2n+1:2n]		- memory type
+	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
+	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
+	 *
+	 *			n	TR	IR	OR
+	 *   UNCACHED		000	00
+	 *   BUFFERABLE		001	10	00	00
+	 *   WRITETHROUGH	010	10	10	10
+	 *   WRITEBACK		011	10	11	11
+	 *   reserved		110
+	 *   WRITEALLOC		111	10	01	01
+	 *   DEV_SHARED		100	01
+	 *   DEV_NONSHARED	100	01
+	 *   DEV_WC		001	10
+	 *   DEV_CACHED		011	10
+	 *
+	 * Other attributes:
+	 *
+	 *   DS0 = PRRR[16] = 0		- device shareable property
+	 *   DS1 = PRRR[17] = 1		- device shareable property
+	 *   NS0 = PRRR[18] = 0		- normal shareable property
+	 *   NS1 = PRRR[19] = 1		- normal shareable property
+	 *   NOS = PRRR[24+n] = 1	- not outer shareable
+	 */
+.equ	PRRR,	0xff0a81a8
+.equ	NMRR,	0x40e040e0
+
+.globl	cpu_v7_suspend_size
+.equ	cpu_v7_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_v7_do_suspend)
+	stmfd	sp!, {r4 - r10, 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	@ TTB 0
+	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r8, c1, c0, 0	@ Control register
+	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_v7_do_suspend)
+
+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 - r10}
+	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	@ TTB 0
+	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, r9, c1, c0, 1	@ Auxillary control register
+	mcr	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	ldr	r4, =PRRR		@ PRRR
+	ldr	r5, =NMRR		@ NMRR
+	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
+	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
+	isb
+
+	mov	r6, r6, lsr #14		@ get TTB0 base
+	mov	r6, r6, lsl #14
+	ldr	r2, =0x40e
+
+	adr	r4, cpu_v7_turn_mmu_on
+	mov	r4, r4, lsr #20
+	orr	r3, r2, r4, lsl #20	@ phys addr
+	ldr	r5, [r6, r4, lsl #2]	@ save old translation
+	str	r3, [r6, r4, lsl #2]	@ virt index
+
+	ldr	r2, =cpu_v7_resume_after_mmu
+	b	cpu_v7_turn_mmu_on
+ENDPROC(cpu_v7_do_resume)
+	.align	3
+cpu_v7_turn_mmu_on:
+	mcr	p15, 0, r8, c1, c0, 0	@ turn on MMU, etc
+	dsb
+	mov	pc, r2
+ENDPROC(cpu_v7_turn_mmu_on)
+cpu_v7_resume_after_mmu:
+	str	r5, [r6, r4, lsl #2]	@ restore old translation
+	mov	pc, lr
+ENDPROC(cpu_v7_resume_after_mmu)
+
 	__CPUINIT
 
 /*
@@ -276,36 +365,8 @@ __v7_setup:
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	/*
-	 * Memory region attributes with SCTLR.TRE=1
-	 *
-	 *   n = TEX[0],C,B
-	 *   TR = PRRR[2n+1:2n]		- memory type
-	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
-	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
-	 *
-	 *			n	TR	IR	OR
-	 *   UNCACHED		000	00
-	 *   BUFFERABLE		001	10	00	00
-	 *   WRITETHROUGH	010	10	10	10
-	 *   WRITEBACK		011	10	11	11
-	 *   reserved		110
-	 *   WRITEALLOC		111	10	01	01
-	 *   DEV_SHARED		100	01
-	 *   DEV_NONSHARED	100	01
-	 *   DEV_WC		001	10
-	 *   DEV_CACHED		011	10
-	 *
-	 * Other attributes:
-	 *
-	 *   DS0 = PRRR[16] = 0		- device shareable property
-	 *   DS1 = PRRR[17] = 1		- device shareable property
-	 *   NS0 = PRRR[18] = 0		- normal shareable property
-	 *   NS1 = PRRR[19] = 1		- normal shareable property
-	 *   NOS = PRRR[24+n] = 1	- not outer shareable
-	 */
-	ldr	r5, =0xff0a81a8			@ PRRR
-	ldr	r6, =0x40e040e0			@ NMRR
+	ldr	r5, =PRRR			@ PRRR
+	ldr	r6, =NMRR			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
@@ -351,6 +412,9 @@ ENTRY(v7_processor_functions)
 	.word	cpu_v7_dcache_clean_area
 	.word	cpu_v7_switch_mm
 	.word	cpu_v7_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	v7_processor_functions, . - v7_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index ec26355..054c1e8 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -413,9 +413,82 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	mov	pc, lr
 
 	.ltorg
-
 	.align
 
+.globl	cpu_xsc3_suspend_size
+.equ	cpu_xsc3_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_xsc3_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmia	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xsc3_do_suspend)
+
+ENTRY(cpu_xsc3_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, r1, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, r1, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, r1, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r8, r8, lsr #14
+	mov	r8, r8, lsl #14
+	ldr	r2, =0x542e
+
+	adr	r4, cpu_xsc3_turn_on_mmu
+	mov	r4, r4, lsr #20
+	orr	r3, r2, r4, lsl #20
+	ldr	r5, [r8, r4, lsl #2]
+	str     r3, [r8, r4, lsl #2]
+
+	@ Mapping page table address in the page table
+	mov	r6, r8, lsr #20
+	orr	r3, r2, r6, lsl #20
+	ldr	r7, [r8, r6, lsl #2]
+	str	r3, [r8, r6, lsl #2]
+
+	ldr	r2, =cpu_xsc3_resume_after_mmu	@ absolute virtual address
+	b	cpu_xsc3_turn_on_mmu	@ cache align execution
+ENDPROC(cpu_xsc3_do_resume)
+	.align	5
+cpu_xsc3_turn_on_mmu:
+	mcr	p15, 0, r10, c1, c0, 0	@ turn on MMU, caches, etc.
+	@ Let us ensure we jump to resume_after_mmu only when the mcr above
+	@ actually took effect.  They call it the "cpwait" operation.
+	mrc	p15, 0, r0, c2, c0, 0	@ queue a dependency on CP15
+	sub	pc, r2, r0, lsr #32	@ jump to virtual addr
+	nop
+	nop
+	nop
+ENDPROC(cpu_xsc3_mmu_on)
+cpu_xsc3_resume_after_mmu:
+	/* restore the temporary mapping */
+	str	r5, [r8, r4, lsl #2]
+	str	r7, [r8, r6, lsl #2]
+	mov	pc, lr
+ENDPROC(cpu_xsc3_resume_after_mmu)
+#else
+#define cpu_xsc3_do_suspend	0
+#define cpu_xsc3_do_resume		0
+#endif
+
 	__CPUINIT
 
 	.type	__xsc3_setup, #function
@@ -476,6 +549,9 @@ ENTRY(xsc3_processor_functions)
 	.word	cpu_xsc3_dcache_clean_area
 	.word	cpu_xsc3_switch_mm
 	.word	cpu_xsc3_set_pte_ext
+	.word	cpu_xsc3_suspend_size
+	.word	cpu_xsc3_do_suspend
+	.word	cpu_xsc3_do_resume
 	.size	xsc3_processor_functions, . - xsc3_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 5a37c5e..0cdf3cf 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -513,11 +513,55 @@ ENTRY(cpu_xscale_set_pte_ext)
 	xscale_set_pte_ext_epilogue
 	mov	pc, lr
 
-
 	.ltorg
-
 	.align
 
+.globl	cpu_xscale_suspend_size
+.equ	cpu_xscale_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_xscale_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xscale_do_suspend)
+
+ENTRY(cpu_xscale_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	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, BTB
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	b	cpu_xscale_mmu_on
+ENDPROC(cpu_xscale_do_resume)
+	.align	5
+cpu_xscale_mmu_on:
+	mcr	p15, 0, r10, c1, c0, 0	@ turn on MMU, caches, etc.
+	@ Let us ensure we jump to resume_after_mmu only when the mcr above
+	@ actually took effect.  They call it the "cpwait" operation.
+	mrc	p15, 0, r0, c2, c0, 0	@ queue a dependency on CP15
+	sub	pc, lr, r0, lsr #32	@ jump to virtual addr
+	nop
+	nop
+	nop
+ENDPROC(cpu_xscale_mmu_on)
+#else
+#define cpu_xscale_do_suspend	0
+#define cpu_xscale_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xscale_setup, #function
@@ -565,6 +609,9 @@ ENTRY(xscale_processor_functions)
 	.word	cpu_xscale_dcache_clean_area
 	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte_ext
+	.word	cpu_xscale_suspend_size
+	.word	cpu_xscale_do_suspend
+	.word	cpu_xscale_do_resume
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
 	.section ".rodata"
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 3/5] ARM: pm: convert PXA to generic suspend/resume support
  2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
  2011-02-06 19:12 ` [PATCH 1/5] ARM: move cache/processor/fault glue to separate include files Russell King - ARM Linux
  2011-02-06 19:12 ` [PATCH 2/5] ARM: pm: add generic CPU suspend/resume support Russell King - ARM Linux
@ 2011-02-06 19:13 ` Russell King - ARM Linux
  2011-02-06 19:13 ` [PATCH 4/5] ARM: pm: convert sa11x0 " Russell King - ARM Linux
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-06 19:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-pxa/include/mach/pm.h |    5 +-
 arch/arm/mach-pxa/palmz72.c         |    2 +-
 arch/arm/mach-pxa/pm.c              |    5 -
 arch/arm/mach-pxa/pxa25x.c          |    4 +-
 arch/arm/mach-pxa/pxa27x.c          |    4 +-
 arch/arm/mach-pxa/pxa3xx.c          |    7 +-
 arch/arm/mach-pxa/sleep.S           |  184 +++--------------------------------
 arch/arm/mach-pxa/zeus.c            |    2 +-
 8 files changed, 24 insertions(+), 189 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index fd8360c..f15afe0 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -22,9 +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);
-extern void pxa27x_cpu_suspend(unsigned int);
-extern void pxa_cpu_resume(void);
+extern void pxa25x_cpu_suspend(unsigned int, long);
+extern void pxa27x_cpu_suspend(unsigned int, long);
 
 extern int pxa_pm_enter(suspend_state_t state);
 extern int pxa_pm_prepare(void);
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 7bf4017..3010193 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -212,7 +212,7 @@ static unsigned long store_ptr;
 static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
 {
 	/* setup the resume_info struct for the original bootloader */
-	palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume;
+	palmz72_resume_info.resume_addr = (u32) cpu_resume;
 
 	/* Storing memory touched by ROM */
 	store_ptr = *PALMZ72_SAVE_DWORD;
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 978e1b2..f377f0d 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -67,11 +67,6 @@ int pxa_pm_enter(suspend_state_t state)
 
 EXPORT_SYMBOL_GPL(pxa_pm_enter);
 
-unsigned long sleep_phys_sp(void *sp)
-{
-	return virt_to_phys(sp);
-}
-
 static int pxa_pm_valid(suspend_state_t state)
 {
 	if (pxa_cpu_pm_fns)
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index fbc5b77..0727e48 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -244,7 +244,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
-		pxa25x_cpu_suspend(PWRMODE_SLEEP);
+		pxa25x_cpu_suspend(PWRMODE_SLEEP, PHYS_OFFSET - PAGE_OFFSET);
 		break;
 	}
 }
@@ -252,7 +252,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 static int pxa25x_cpu_pm_prepare(void)
 {
 	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 	return 0;
 }
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 987301f..28b11be 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -300,7 +300,7 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(pwrmode);
+		pxa27x_cpu_suspend(pwrmode, PHYS_OFFSET - PAGE_OFFSET);
 		break;
 	}
 }
@@ -313,7 +313,7 @@ static int pxa27x_cpu_pm_valid(suspend_state_t state)
 static int pxa27x_cpu_pm_prepare(void)
 {
 	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 	return 0;
 }
 
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index a7a19e1..1230343 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -142,8 +142,7 @@ static void pxa3xx_cpu_pm_suspend(void)
 	volatile unsigned long *p = (volatile void *)0xc0000000;
 	unsigned long saved_data = *p;
 
-	extern void pxa3xx_cpu_suspend(void);
-	extern void pxa3xx_cpu_resume(void);
+	extern void pxa3xx_cpu_suspend(long);
 
 	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
 	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
@@ -161,9 +160,9 @@ static void pxa3xx_cpu_pm_suspend(void)
 	PSPR = 0x5c014000;
 
 	/* overwrite with the resume address */
-	*p = virt_to_phys(pxa3xx_cpu_resume);
+	*p = virt_to_phys(cpu_resume);
 
-	pxa3xx_cpu_suspend();
+	pxa3xx_cpu_suspend(PHYS_OFFSET - PAGE_OFFSET);
 
 	*p = saved_data;
 
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index c551da8..24822b0 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -22,33 +22,6 @@
 
 		.text
 
-pxa_cpu_save_cp:
-	@ get coprocessor registers
-	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
-	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mrc	p15, 0, r5, c13, c0, 0		@ PID
-	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
-	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
-
-	bic	r3, r3, #2			@ clear frequency change bit
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r10, sp
-	stmfd	sp!, {r3 - r10}
-
-	mov	pc, lr
-
-pxa_cpu_save_sp:
-	@ preserve phys address of stack
-	mov	r0, sp
-	str	lr, [sp, #-4]!
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-	ldr	pc, [sp], #4
-
 #ifdef CONFIG_PXA3xx
 /*
  * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
@@ -64,91 +37,14 @@ ENTRY(pxa3xx_cpu_suspend)
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
-
-	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
-	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mrc	p15, 0, r5, c13, c0, 0		@ PID
-	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
-	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
-
-	bic	r3, r3, #2			@ clear frequency change bit
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r10, sp
-	stmfd	sp!, {r3 - r10}
-
-	@ store physical address of stack pointer
-	mov	r0, sp
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-
-	@ clean data cache
-	bl	xsc3_flush_kern_cache_all
+	mov	r1, r0
+	ldr	r3, =pxa_cpu_resume	@ resume function
+	bl	cpu_suspend
 
 	mov	r0, #0x06		@ S2D3C4 mode
 	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
 
 20:	b	20b			@ waiting for sleep
-
-	.data
-	.align 5
-/*
- * pxa3xx_cpu_resume
- */
-
-ENTRY(pxa3xx_cpu_resume)
-
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
-	msr	cpsr_c, r0
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
-	mcr	p15, 0, r1, c7, c10, 4		@ drain write (&fill) buffer
-	mcr	p15, 0, r1, c7, c5, 4		@ flush prefetch buffer
-	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
-
-	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
-
-	@ temporarily map resume_turn_on_mmu into the page table,
-	@ otherwise prefetch abort occurs after MMU is turned on
-	mov	r1, r7
-	bic	r1, r1, #0x00ff
-	bic	r1, r1, #0x3f00
-	ldr	r2, =0x542e
-
-	adr	r3, resume_turn_on_mmu
-	mov	r3, r3, lsr #20
-	orr	r4, r2, r3, lsl #20
-	ldr	r5, [r1, r3, lsl #2]
-	str     r4, [r1, r3, lsl #2]
-
-	@ Mapping page table address in the page table
-	mov	r6, r1, lsr #20
-	orr	r7, r2, r6, lsl #20
-	ldr	r8, [r1, r6, lsl #2]
-	str	r7, [r1, r6, lsl #2]
-
-	ldr	r2, =pxa3xx_resume_after_mmu	@ absolute virtual address
-	b	resume_turn_on_mmu		@ cache align execution
-
-	.text
-pxa3xx_resume_after_mmu:
-	/* restore the temporary mapping */
-	str	r5, [r1, r3, lsl #2]
-	str	r8, [r1, r6, lsl #2]
-	b	resume_after_mmu
-
 #endif /* CONFIG_PXA3xx */
 
 #ifdef CONFIG_PXA27x
@@ -166,20 +62,15 @@ ENTRY(pxa27x_cpu_suspend)
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-
-	bl	pxa_cpu_save_cp
-
-	mov	r5, r0				@ save sleep mode
-	bl	pxa_cpu_save_sp
-
-	@ clean data cache
-	bl	xscale_flush_kern_cache_all
+	mov	r4, r0				@ save sleep mode
+	ldr	r3, =pxa_cpu_resume		@ resume function
+	bl	cpu_suspend
 
 	@ Put the processor to sleep
 	@ (also workaround for sighting 28071)
 
 	@ prepare value for sleep mode
-	mov	r1, r5				@ sleep mode
+	mov	r1, r4				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -216,21 +107,16 @@ ENTRY(pxa27x_cpu_suspend)
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
+ * r1 = v:p offset
  */
 
 ENTRY(pxa25x_cpu_suspend)
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-
-	bl	pxa_cpu_save_cp
-
-	mov	r5, r0				@ save sleep mode
-	bl	pxa_cpu_save_sp
-
-	@ clean data cache
-	bl	xscale_flush_kern_cache_all
-
+	mov	r4, r0				@ save sleep mode
+	ldr	r3, =pxa_cpu_resume		@ resume function
+	bl	cpu_suspend
 	@ prepare value for sleep mode
-	mov	r1, r5				@ sleep mode
+	mov	r1, r4				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -317,53 +203,9 @@ pxa_cpu_do_suspend:
  * pxa_cpu_resume()
  *
  * entry point from bootloader into kernel during resume
- *
- * Note: Yes, part of the following code is located into the .data section.
- *       This is to allow sleep_save_sp to be accessed with a relative load
- *       while we can't rely on any MMU translation.  We could have put
- *       sleep_save_sp in the .text section as well, but some setups might
- *       insist on it to be truly read-only.
  */
-
-	.data
-	.align 5
-ENTRY(pxa_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
-	msr	cpsr_c, r0
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldr	r2, =resume_after_mmu		@ its absolute virtual address
-	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
-
-	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, BTB
-
-	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
-	b	resume_turn_on_mmu		@ cache align execution
-
 	.align 5
-resume_turn_on_mmu:
-	mcr 	p15, 0, r9, c1, c0, 0		@ turn on MMU, caches, etc.
-
-	@ Let us ensure we jump to resume_after_mmu only when the mcr above
-	@ actually took effect.  They call it the "cpwait" operation.
-	mrc	p15, 0, r0, c2, c0, 0		@ queue a dependency on CP15
-	sub	pc, r2, r0, lsr #32		@ jump to virtual addr
-	nop
-	nop
-	nop
-
-sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
-
-	.text
-resume_after_mmu:
+pxa_cpu_resume:
 	ldmfd	sp!, {r2, r3}
 #ifndef CONFIG_IWMMXT
 	mar	acc0, r2, r3
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index f4b053b..b92aa3b 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -676,7 +676,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
 static void zeus_power_off(void)
 {
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP);
+	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PHYS_OFFSET - PAGE_OFFSET);
 }
 #else
 #define zeus_power_off   NULL
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 4/5] ARM: pm: convert sa11x0 to generic suspend/resume support
  2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
                   ` (2 preceding siblings ...)
  2011-02-06 19:13 ` [PATCH 3/5] ARM: pm: convert PXA to generic " Russell King - ARM Linux
@ 2011-02-06 19:13 ` Russell King - ARM Linux
  2011-02-07 18:11   ` Russell King - ARM Linux
  2011-02-06 19:13 ` [PATCH 5/5] ARM: pm: convert samsung platforms " Russell King - ARM Linux
  2011-02-07  5:42 ` [RFC] Generic CPU save/restore PM support Kukjin Kim
  5 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-06 19:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-sa1100/pm.c    |   12 ++-----
 arch/arm/mach-sa1100/sleep.S |   72 ++---------------------------------------
 2 files changed, 7 insertions(+), 77 deletions(-)

diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index ab9fc44..c4661aa 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -32,8 +32,7 @@
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
-extern void sa1100_cpu_suspend(void);
-extern void sa1100_cpu_resume(void);
+extern void sa1100_cpu_suspend(long);
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
@@ -73,10 +72,10 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
 
 	/* set resume return address */
-	PSPR = virt_to_phys(sa1100_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 
 	/* go zzz */
-	sa1100_cpu_suspend();
+	sa1100_cpu_suspend(PHYS_OFFSET - PAGE_OFFSET);
 
 	cpu_init();
 
@@ -115,11 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	return 0;
 }
 
-unsigned long sleep_phys_sp(void *sp)
-{
-	return virt_to_phys(sp);
-}
-
 static const struct platform_suspend_ops sa11x0_pm_ops = {
 	.enter		= sa11x0_pm_enter,
 	.valid		= suspend_valid_only_mem,
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S
index 80f31ba..04f2a61 100644
--- a/arch/arm/mach-sa1100/sleep.S
+++ b/arch/arm/mach-sa1100/sleep.S
@@ -20,12 +20,7 @@
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 
-
-
 		.text
-
-
-
 /*
  * sa1100_cpu_suspend()
  *
@@ -34,27 +29,10 @@
  */
 
 ENTRY(sa1100_cpu_suspend)
-
 	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack
-
-	@ get coprocessor registers
-	mrc 	p15, 0, r4, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r6, c13, c0, 0		@ PID
-	mrc 	p15, 0, r7, c1, c0, 0		@ control reg
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r8, sp
-	stmfd	sp!, {r4 - r8}
-
-	@ preserve phys address of stack
-	mov	r0, sp
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-
-	@ clean data cache and invalidate WB
-	bl	v4wb_flush_kern_cache_all
+	mov	r1, r0
+	ldr	r3, =sa1100_cpu_resume		@ return function
+	bl	cpu_suspend
 
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
@@ -166,50 +144,8 @@ sa1110_sdram_controller_fix:
  * cpu_sa1100_resume()
  *
  * entry point from bootloader into kernel during resume
- *
- * Note: Yes, part of the following code is located into the .data section.
- *       This is to allow sleep_save_sp to be accessed with a relative load
- *       while we can't rely on any MMU translation.  We could have put
- *       sleep_save_sp in the .text section as well, but some setups might
- *       insist on it to be truly read-only.
  */
-
-	.data
-	.align 5
-ENTRY(sa1100_cpu_resume)
-	mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
-	msr	cpsr_c, r0			@ set SVC, irqs off
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldr	r2, =resume_after_mmu		@ its absolute virtual address
-	ldmfd	r0, {r4 - r7, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0   	@ flush I+D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
-	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
-	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
-
-	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
-	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r6, c13, c0, 0		@ PID
-	b	resume_turn_on_mmu		@ cache align execution
-
 	.align 5
-resume_turn_on_mmu:
-	mcr 	p15, 0, r7, c1, c0, 0		@ turn on MMU, caches, etc.
-	nop
-	mov	pc, r2				@ jump to virtual addr
-	nop
-	nop
-	nop
-
-sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
-
-	.text
-resume_after_mmu:
+sa1100_cpu_resume:
 	mcr	p15, 0, r1, c15, c1, 2		@ enable clock switching
 	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
-
-
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 5/5] ARM: pm: convert samsung platforms to generic suspend/resume support
  2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
                   ` (3 preceding siblings ...)
  2011-02-06 19:13 ` [PATCH 4/5] ARM: pm: convert sa11x0 " Russell King - ARM Linux
@ 2011-02-06 19:13 ` Russell King - ARM Linux
  2011-02-07  5:42 ` [RFC] Generic CPU save/restore PM support Kukjin Kim
  5 siblings, 0 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-06 19:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Russell King <rmk+kernel@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@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, 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

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC] Generic CPU save/restore PM support
  2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
                   ` (4 preceding siblings ...)
  2011-02-06 19:13 ` [PATCH 5/5] ARM: pm: convert samsung platforms " Russell King - ARM Linux
@ 2011-02-07  5:42 ` Kukjin Kim
  2011-02-07 10:44   ` Russell King - ARM Linux
  5 siblings, 1 reply; 33+ messages in thread
From: Kukjin Kim @ 2011-02-07  5:42 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux wrote:
> 
> The following patch series implements infrastructure to save/restore
> CPU state on suspend/resume PM events, and updates SA11x0, PXA and
> Samsung platforms to use this.
> 
> Not all CPU support files are updated with the necessary changes -
> currently only ARM920, ARM926, SA11x0, XScale, XScale3, V6 and V7
> CPUs are supported.
> 
> I've build-tested this for Assabet, PXA, and S3C2410, but not boot
> tested it yet.
> 
Hi Russell,

Occurs following build error with s5pv210_defconfig.
(I applied your patches into my some branch which is based on 38-rc3 for
test)

arch/arm/mm/proc-v7.S:207: error: unterminated #ifdef

Let you know the test result on my board after fixing it.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [RFC] Generic CPU save/restore PM support
  2011-02-07  5:42 ` [RFC] Generic CPU save/restore PM support Kukjin Kim
@ 2011-02-07 10:44   ` Russell King - ARM Linux
  0 siblings, 0 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 10:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 02:42:15PM +0900, Kukjin Kim wrote:
> Russell King - ARM Linux wrote:
> > 
> > The following patch series implements infrastructure to save/restore
> > CPU state on suspend/resume PM events, and updates SA11x0, PXA and
> > Samsung platforms to use this.
> > 
> > Not all CPU support files are updated with the necessary changes -
> > currently only ARM920, ARM926, SA11x0, XScale, XScale3, V6 and V7
> > CPUs are supported.
> > 
> > I've build-tested this for Assabet, PXA, and S3C2410, but not boot
> > tested it yet.
> > 
> Hi Russell,
> 
> Occurs following build error with s5pv210_defconfig.
> (I applied your patches into my some branch which is based on 38-rc3 for
> test)
> 
> arch/arm/mm/proc-v7.S:207: error: unterminated #ifdef
> 
> Let you know the test result on my board after fixing it.

There is an issue here which I missed when pulling the code out of
s5pv210, so you'll also need this.  This also fixes Xscale3 to operate
in the same manner.

diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index abffa81..45d1024 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -203,7 +203,7 @@ cpu_v7_name:
 .equ	NMRR,	0x40e040e0
 
 .globl	cpu_v7_suspend_size
-.equ	cpu_v7_suspend_size, 4 * 7
+.equ	cpu_v7_suspend_size, 4 * 8
 #ifdef CONFIG_PM
 ENTRY(cpu_v7_do_suspend)
 	stmfd	sp!, {r4 - r10, lr}
@@ -214,7 +214,7 @@ ENTRY(cpu_v7_do_suspend)
 	mrc	p15, 0, r8, c1, c0, 0	@ Control register
 	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
 	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
-	stmia	r0, {r4 - r10}
+	stmia	r0, {r1, r4 - r10}
 	ldmfd	sp!, {r4 - r10, pc}
 ENDPROC(cpu_v7_do_suspend)
 
@@ -222,7 +222,7 @@ 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 - r10}
+	ldmia	r0, {r1, r4 - r10}
 	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	@ TTB 0
@@ -245,6 +245,7 @@ ENTRY(cpu_v7_do_resume)
 	orr	r3, r2, r4, lsl #20	@ phys addr
 	ldr	r5, [r6, r4, lsl #2]	@ save old translation
 	str	r3, [r6, r4, lsl #2]	@ virt index
+	sub	r6, r6, r1		@ convert to virt translation base
 
 	ldr	r2, =cpu_v7_resume_after_mmu
 	b	cpu_v7_turn_mmu_on
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 054c1e8..9b3a0bf 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -416,7 +416,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	.align
 
 .globl	cpu_xsc3_suspend_size
-.equ	cpu_xsc3_suspend_size, 4 * 7
+.equ	cpu_xsc3_suspend_size, 4 * 8
 #ifdef CONFIG_PM
 ENTRY(cpu_xsc3_do_suspend)
 	stmfd	sp!, {r4 - r10, lr}
@@ -428,17 +428,17 @@ ENTRY(cpu_xsc3_do_suspend)
 	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
 	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
 	bic	r4, r4, #2		@ clear frequency change bit
-	stmia	r0, {r4 - r10}		@ store cp regs
+	stmia	r0, {r1, r4 - r10}	@ store v:p offset + cp regs
 	ldmia	sp!, {r4 - r10, pc}
 ENDPROC(cpu_xsc3_do_suspend)
 
 ENTRY(cpu_xsc3_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c7, 0	@ invalidate I & D caches, BTB
-	mcr	p15, 0, r1, c7, c10, 4	@ drain write (&fill) buffer
-	mcr	p15, 0, r1, c7, c5, 4	@ flush prefetch buffer
-	mcr	p15, 0, r1, c8, c7, 0	@ invalidate I & D TLBs
+	ldmia	r0, {r1, r4 - r10}	@ load v:p offset + cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, ip, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
 	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
 	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mcr	p15, 0, r6, c13, c0, 0	@ PID
@@ -457,12 +457,7 @@ ENTRY(cpu_xsc3_do_resume)
 	orr	r3, r2, r4, lsl #20
 	ldr	r5, [r8, r4, lsl #2]
 	str     r3, [r8, r4, lsl #2]
-
-	@ Mapping page table address in the page table
-	mov	r6, r8, lsr #20
-	orr	r3, r2, r6, lsl #20
-	ldr	r7, [r8, r6, lsl #2]
-	str	r3, [r8, r6, lsl #2]
+	sub	r8, r8, r1		@ convert to virt table base
 
 	ldr	r2, =cpu_xsc3_resume_after_mmu	@ absolute virtual address
 	b	cpu_xsc3_turn_on_mmu	@ cache align execution
@@ -481,7 +476,6 @@ ENDPROC(cpu_xsc3_mmu_on)
 cpu_xsc3_resume_after_mmu:
 	/* restore the temporary mapping */
 	str	r5, [r8, r4, lsl #2]
-	str	r7, [r8, r6, lsl #2]
 	mov	pc, lr
 ENDPROC(cpu_xsc3_resume_after_mmu)
 #else

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-06 19:12 ` [PATCH 2/5] ARM: pm: add generic CPU suspend/resume support Russell King - ARM Linux
@ 2011-02-07 12:01   ` Russell King - ARM Linux
  2011-02-07 12:10     ` [PATCH v3 " Russell King - ARM Linux
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 12:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 06, 2011 at 07:12:28PM +0000, Russell King - ARM Linux wrote:
> This adds core support for saving and restoring CPU coprocessor
> registers for suspend/resume support.  This contains support for suspend
> with ARM920, ARM926, SA11x0, PXA25x, PXA27x, PXA3xx and V6 CPUs.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---

Here's v2 of this patch.  I've moved the MMU handling code into
arch/arm/kernel/sleep.S, so everyone can benefit from having this handled
in the same way, much like we do in head.S.  I've also added a full
cache flush after the MMU is turned on to ensure that we don't leak
any cache lines into userspace for the MMU resume code.  This should
make things a little more robust.

 arch/arm/include/asm/glue-proc.h |    3 +
 arch/arm/include/asm/proc-fns.h  |    7 ++
 arch/arm/kernel/Makefile         |    1 +
 arch/arm/kernel/asm-offsets.c    |    9 +++
 arch/arm/kernel/sleep.S          |  109 ++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-arm1020.S       |    3 +
 arch/arm/mm/proc-arm1020e.S      |    3 +
 arch/arm/mm/proc-arm1022.S       |    3 +
 arch/arm/mm/proc-arm1026.S       |    3 +
 arch/arm/mm/proc-arm6_7.S        |    6 ++
 arch/arm/mm/proc-arm720.S        |    3 +
 arch/arm/mm/proc-arm740.S        |    3 +
 arch/arm/mm/proc-arm7tdmi.S      |    3 +
 arch/arm/mm/proc-arm920.S        |   37 ++++++++++++
 arch/arm/mm/proc-arm922.S        |    3 +
 arch/arm/mm/proc-arm925.S        |    3 +
 arch/arm/mm/proc-arm926.S        |   37 ++++++++++++
 arch/arm/mm/proc-arm940.S        |    3 +
 arch/arm/mm/proc-arm946.S        |    3 +
 arch/arm/mm/proc-arm9tdmi.S      |    3 +
 arch/arm/mm/proc-fa526.S         |    3 +
 arch/arm/mm/proc-feroceon.S      |    3 +
 arch/arm/mm/proc-mohawk.S        |    3 +
 arch/arm/mm/proc-sa110.S         |    3 +
 arch/arm/mm/proc-sa1100.S        |   39 +++++++++++++
 arch/arm/mm/proc-v6.S            |   48 ++++++++++++++++
 arch/arm/mm/proc-v7.S            |  114 ++++++++++++++++++++++++++++----------
 arch/arm/mm/proc-xsc3.S          |   48 ++++++++++++++++-
 arch/arm/mm/proc-xscale.S        |   45 ++++++++++++++-
 29 files changed, 518 insertions(+), 33 deletions(-)

diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e3bf443..6469521 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -256,6 +256,9 @@
 #define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
 #define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
 #define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
+#define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
+#define cpu_do_resume			__glue(CPU_NAME,_do_resume)
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 6980215..8ec535e 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -66,6 +66,11 @@ extern struct processor {
 	 * ignore 'ext'.
 	 */
 	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
+
+	/* Suspend/resume */
+	unsigned int suspend_size;
+	void (*do_suspend)(void *);
+	void (*do_resume)(void *);
 } processor;
 
 #ifndef MULTI_CPU
@@ -86,6 +91,8 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
+extern void cpu_resume(void);
+
 #include <asm/memory.h>
 
 #ifdef CONFIG_MMU
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 185ee82..74554f1 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
+obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 5302a91..927522c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
@@ -116,6 +117,14 @@ int main(void)
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
 #endif
+#ifdef MULTI_CPU
+  DEFINE(CPU_SLEEP_SIZE,	offsetof(struct processor, suspend_size));
+  DEFINE(CPU_DO_SUSPEND,	offsetof(struct processor, do_suspend));
+  DEFINE(CPU_DO_RESUME,		offsetof(struct processor, do_resume));
+#endif
+#ifdef MULTI_CACHE
+  DEFINE(CACHE_FLUSH_KERN_ALL,	offsetof(struct cpu_cache_fns, flush_kern_all));
+#endif
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
new file mode 100644
index 0000000..ebe9ee8
--- /dev/null
+++ b/arch/arm/kernel/sleep.S
@@ -0,0 +1,109 @@
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/glue-cache.h>
+#include <asm/glue-proc.h>
+	.text
+
+/*
+ * Save CPU state for a suspend
+ *  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
+ */
+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, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+	str	r2, [r3]		@ save phys SP
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
+#else
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, =cpu_suspend_size
+	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
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+	str	r2, [r3]		@ save phys SP
+	bl	cpu_do_suspend
+#endif
+
+	@ flush data cache
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	mov	lr, r9
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	mov	lr, r9
+	b	__cpuc_flush_kern_all
+#endif
+ENDPROC(cpu_suspend)
+	.ltorg
+
+/*
+ * r0 = control register value
+ * r1 = v:p offset (preserved by cpu_do_resume)
+ * r2 = phys page table base
+ * r3 = L1 section flags
+ */
+ENTRY(cpu_resume_mmu)
+	adr	r4, cpu_resume_turn_mmu_on
+	mov	r4, r4, lsr #20
+	orr	r3, r3, r4, lsl #20
+	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
+	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
+	sub	r2, r2, r1
+	ldr	r3, =cpu_resume_after_mmu
+	b	cpu_resume_turn_mmu_on
+ENDPROC(cpu_resume_mmu)
+	.align	5
+cpu_resume_turn_mmu_on:
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, caches, etc
+	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
+	mov	r0, r0
+	mov	r0, r0
+	sub	pc, r3			@ jump to virtual address
+ENDPROC(cpu_resume_turn_mmu_on)
+cpu_resume_after_mmu:
+	str	r5, [r2, r4, lsl #2]	@ restore old mapping
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	b	__cpuc_flush_kern_all
+#endif
+
+/*
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+	.data
+	.align
+ENTRY(cpu_resume)
+	ldr	r0, sleep_save_sp	@ stack phys addr
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
+#ifdef MULTI_CPU
+	ldmia	r0!, {r1, sp, lr, pc}	@ load v:p, stack, return fn, resume fn
+#else
+	ldmia	r0!, {r1, sp, lr}	@ load v:p, stack, return fn
+	b	cpu_do_resume
+#endif
+ENDPROC(cpu_resume)
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index bcf748d..226e3d8 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -493,6 +493,9 @@ arm1020_processor_functions:
 	.word	cpu_arm1020_dcache_clean_area
 	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index ab7ec26..86d9c2c 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -474,6 +474,9 @@ arm1020e_processor_functions:
 	.word	cpu_arm1020e_dcache_clean_area
 	.word	cpu_arm1020e_switch_mm
 	.word	cpu_arm1020e_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 831c5e5..83d3dd3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -457,6 +457,9 @@ arm1022_processor_functions:
 	.word	cpu_arm1022_dcache_clean_area
 	.word	cpu_arm1022_switch_mm
 	.word	cpu_arm1022_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1022_processor_functions, . - arm1022_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index e3f7e9a..686043e 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -452,6 +452,9 @@ arm1026_processor_functions:
 	.word	cpu_arm1026_dcache_clean_area
 	.word	cpu_arm1026_switch_mm
 	.word	cpu_arm1026_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1026_processor_functions, . - arm1026_processor_functions
 
 	.section .rodata
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 6a7be18..5f79dc4 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions)
 		.word	cpu_arm6_dcache_clean_area
 		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions)
 		.word	cpu_arm7_dcache_clean_area
 		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index c285395..665266d 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions)
 		.word	cpu_arm720_dcache_clean_area
 		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 38b27dc..6f9d12e 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions)
 	.word	cpu_arm740_dcache_clean_area
 	.word	cpu_arm740_switch_mm
 	.word	0			@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm740_processor_functions, . - arm740_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 0c9786d..e4c165c 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions)
 		.word	cpu_arm7tdmi_dcache_clean_area
 		.word	cpu_arm7tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 6109f27..b2705de 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -387,6 +387,40 @@ ENTRY(cpu_arm920_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm920_suspend_size
+.equ	arm920_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm920_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm920_do_suspend)
+
+ENTRY(arm920_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(arm920_do_resume)
+#else
+#define arm920_do_suspend	0
+#define arm920_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm920_setup, #function
@@ -432,6 +466,9 @@ arm920_processor_functions:
 	.word	cpu_arm920_dcache_clean_area
 	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte_ext
+	.word	arm920_suspend_size
+	.word	arm920_do_suspend
+	.word	arm920_do_resume
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index bb2f0f4..36154b1 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -436,6 +436,9 @@ arm922_processor_functions:
 	.word	cpu_arm922_dcache_clean_area
 	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index c13e01a..89c5e00 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -503,6 +503,9 @@ arm925_processor_functions:
 	.word	cpu_arm925_dcache_clean_area
 	.word	cpu_arm925_switch_mm
 	.word	cpu_arm925_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm925_processor_functions, . - arm925_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 42eb431..3beb784 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -401,6 +401,40 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm926_suspend_size
+.equ	arm926_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm926_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm926_do_suspend)
+
+ENTRY(arm926_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(arm926_do_resume)
+#else
+#define arm926_do_suspend	0
+#define arm926_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm926_setup, #function
@@ -456,6 +490,9 @@ arm926_processor_functions:
 	.word	cpu_arm926_dcache_clean_area
 	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte_ext
+	.word	arm926_suspend_size
+	.word	arm926_do_suspend
+	.word	arm926_do_resume
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 7b11cdb..26aea3f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions)
 	.word	cpu_arm940_dcache_clean_area
 	.word	cpu_arm940_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm940_processor_functions, . - arm940_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 1a5bbf0..8063345 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions)
 	.word	cpu_arm946_dcache_clean_area
 	.word	cpu_arm946_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm946_processor_functions, . - arm946_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db67e31..7b7ebd4 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions)
 		.word	cpu_arm9tdmi_dcache_clean_area
 		.word	cpu_arm9tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7c9ad62..fc2a4ae 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -195,6 +195,9 @@ fa526_processor_functions:
 	.word	cpu_fa526_dcache_clean_area
 	.word	cpu_fa526_switch_mm
 	.word	cpu_fa526_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	fa526_processor_functions, . - fa526_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b4597ed..d3883ee 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -554,6 +554,9 @@ feroceon_processor_functions:
 	.word	cpu_feroceon_dcache_clean_area
 	.word	cpu_feroceon_switch_mm
 	.word	cpu_feroceon_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	feroceon_processor_functions, . - feroceon_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 4458ee6..9d4f2ae 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -388,6 +388,9 @@ mohawk_processor_functions:
 	.word	cpu_mohawk_dcache_clean_area
 	.word	cpu_mohawk_switch_mm
 	.word	cpu_mohawk_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	mohawk_processor_functions, . - mohawk_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 5aa8d59..46f09ed 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions)
 	.word	cpu_sa110_dcache_clean_area
 	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 2ac4e6f..74483d1 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,6 +169,42 @@ ENTRY(cpu_sa1100_set_pte_ext)
 #endif
 	mov	pc, lr
 
+.globl	cpu_sa1100_suspend_size
+.equ	cpu_sa1100_suspend_size, 4*4
+#ifdef CONFIG_PM
+ENTRY(cpu_sa1100_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
+	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r6, c13, c0, 0		@ PID
+	mrc	p15, 0, r7, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r7}			@ store cp regs
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_sa1100_do_suspend)
+
+ENTRY(cpu_sa1100_do_resume)
+	ldmia	r0, {r4 - r7}			@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@ flush I+D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
+	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
+
+	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
+	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r6, c13, c0, 0		@ PID
+	mov	r0, r7				@ control register
+	mov	r2, r5, lsr #14			@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_sa1100_do_resume)
+#else
+#define cpu_sa1100_do_suspend	0
+#define cpu_sa1100_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__sa1100_setup, #function
@@ -218,6 +254,9 @@ ENTRY(sa1100_processor_functions)
 	.word	cpu_sa1100_dcache_clean_area
 	.word	cpu_sa1100_switch_mm
 	.word	cpu_sa1100_set_pte_ext
+	.word	cpu_sa1100_suspend_size
+	.word	cpu_sa1100_do_suspend
+	.word	cpu_sa1100_do_resume
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 59a7e1f..c86f451 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -121,6 +121,51 @@ ENTRY(cpu_v6_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
+.globl	cpu_v6_suspend_size
+.equ	cpu_v6_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_v6_do_suspend)
+	stmfd	sp!, {r4 - r10, 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 base 0
+	mrc	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r8, c1, c0, 1	@ auxillary control register
+	mrc	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r10, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4- r10, pc}
+ENDPROC(cpu_v6_do_suspend)
+
+ENTRY(cpu_v6_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
+	ldmia	r0, {r4 - r10}
+	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 base 0
+	mcr	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r8, c1, c0, 1	@ auxillary control register
+	mcr	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, ip, c7, c5, 4	@ ISB
+	mov	r0, r10			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v6_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v6_do_suspend 0
+#define cpu_v6_do_resume 0
+#endif
 
 
 	.type	cpu_v6_name, #object
@@ -206,6 +251,9 @@ ENTRY(v6_processor_functions)
 	.word	cpu_v6_dcache_clean_area
 	.word	cpu_v6_switch_mm
 	.word	cpu_v6_set_pte_ext
+	.word	cpu_v6_suspend_size
+	.word	cpu_v6_do_suspend
+	.word	cpu_v6_do_resume
 	.size	v6_processor_functions, . - v6_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 0c1172b..8e6142d 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -171,6 +171,85 @@ cpu_v7_name:
 	.ascii	"ARMv7 Processor"
 	.align
 
+	/*
+	 * Memory region attributes with SCTLR.TRE=1
+	 *
+	 *   n = TEX[0],C,B
+	 *   TR = PRRR[2n+1:2n]		- memory type
+	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
+	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
+	 *
+	 *			n	TR	IR	OR
+	 *   UNCACHED		000	00
+	 *   BUFFERABLE		001	10	00	00
+	 *   WRITETHROUGH	010	10	10	10
+	 *   WRITEBACK		011	10	11	11
+	 *   reserved		110
+	 *   WRITEALLOC		111	10	01	01
+	 *   DEV_SHARED		100	01
+	 *   DEV_NONSHARED	100	01
+	 *   DEV_WC		001	10
+	 *   DEV_CACHED		011	10
+	 *
+	 * Other attributes:
+	 *
+	 *   DS0 = PRRR[16] = 0		- device shareable property
+	 *   DS1 = PRRR[17] = 1		- device shareable property
+	 *   NS0 = PRRR[18] = 0		- normal shareable property
+	 *   NS1 = PRRR[19] = 1		- normal shareable property
+	 *   NOS = PRRR[24+n] = 1	- not outer shareable
+	 */
+.equ	PRRR,	0xff0a81a8
+.equ	NMRR,	0x40e040e0
+
+/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
+.globl	cpu_v7_suspend_size
+.equ	cpu_v7_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_v7_do_suspend)
+	stmfd	sp!, {r4 - r10, 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	@ TTB 0
+	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r8, c1, c0, 0	@ Control register
+	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_v7_do_suspend)
+
+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 - r10}
+	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	@ TTB 0
+	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, r9, c1, c0, 1	@ Auxillary control register
+	mcr	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	ldr	r4, =PRRR		@ PRRR
+	ldr	r5, =NMRR		@ NMRR
+	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
+	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
+	isb
+	mov	r0, r8			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v7_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v7_do_suspend	0
+#define cpu_v7_do_resume	0
+#endif
+
 	__CPUINIT
 
 /*
@@ -276,36 +355,8 @@ __v7_setup:
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	/*
-	 * Memory region attributes with SCTLR.TRE=1
-	 *
-	 *   n = TEX[0],C,B
-	 *   TR = PRRR[2n+1:2n]		- memory type
-	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
-	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
-	 *
-	 *			n	TR	IR	OR
-	 *   UNCACHED		000	00
-	 *   BUFFERABLE		001	10	00	00
-	 *   WRITETHROUGH	010	10	10	10
-	 *   WRITEBACK		011	10	11	11
-	 *   reserved		110
-	 *   WRITEALLOC		111	10	01	01
-	 *   DEV_SHARED		100	01
-	 *   DEV_NONSHARED	100	01
-	 *   DEV_WC		001	10
-	 *   DEV_CACHED		011	10
-	 *
-	 * Other attributes:
-	 *
-	 *   DS0 = PRRR[16] = 0		- device shareable property
-	 *   DS1 = PRRR[17] = 1		- device shareable property
-	 *   NS0 = PRRR[18] = 0		- normal shareable property
-	 *   NS1 = PRRR[19] = 1		- normal shareable property
-	 *   NOS = PRRR[24+n] = 1	- not outer shareable
-	 */
-	ldr	r5, =0xff0a81a8			@ PRRR
-	ldr	r6, =0x40e040e0			@ NMRR
+	ldr	r5, =PRRR			@ PRRR
+	ldr	r6, =NMRR			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
@@ -351,6 +402,9 @@ ENTRY(v7_processor_functions)
 	.word	cpu_v7_dcache_clean_area
 	.word	cpu_v7_switch_mm
 	.word	cpu_v7_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	v7_processor_functions, . - v7_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index ec26355..63d8b20 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -413,9 +413,52 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	mov	pc, lr
 
 	.ltorg
-
 	.align
 
+.globl	cpu_xsc3_suspend_size
+.equ	cpu_xsc3_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_xsc3_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r1, r4 - r10}	@ store v:p offset + cp regs
+	ldmia	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xsc3_do_suspend)
+
+ENTRY(cpu_xsc3_do_resume)
+	ldmia	r0, {r1, r4 - r10}	@ load v:p offset + cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, ip, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =0x542e		@ section flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_xsc3_do_resume)
+#else
+#define cpu_xsc3_do_suspend	0
+#define cpu_xsc3_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xsc3_setup, #function
@@ -476,6 +519,9 @@ ENTRY(xsc3_processor_functions)
 	.word	cpu_xsc3_dcache_clean_area
 	.word	cpu_xsc3_switch_mm
 	.word	cpu_xsc3_set_pte_ext
+	.word	cpu_xsc3_suspend_size
+	.word	cpu_xsc3_do_suspend
+	.word	cpu_xsc3_do_resume
 	.size	xsc3_processor_functions, . - xsc3_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 5a37c5e..086038c 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -513,11 +513,49 @@ ENTRY(cpu_xscale_set_pte_ext)
 	xscale_set_pte_ext_epilogue
 	mov	pc, lr
 
-
 	.ltorg
-
 	.align
 
+.globl	cpu_xscale_suspend_size
+.equ	cpu_xscale_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_xscale_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xscale_do_suspend)
+
+ENTRY(cpu_xscale_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_xscale_do_resume)
+#else
+#define cpu_xscale_do_suspend	0
+#define cpu_xscale_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xscale_setup, #function
@@ -565,6 +603,9 @@ ENTRY(xscale_processor_functions)
 	.word	cpu_xscale_dcache_clean_area
 	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte_ext
+	.word	cpu_xscale_suspend_size
+	.word	cpu_xscale_do_suspend
+	.word	cpu_xscale_do_resume
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
 	.section ".rodata"

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 12:01   ` [PATCH v2 " Russell King - ARM Linux
@ 2011-02-07 12:10     ` Russell King - ARM Linux
  2011-02-07 13:21       ` saeed bishara
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 12:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 12:01:04PM +0000, Russell King - ARM Linux wrote:
> On Sun, Feb 06, 2011 at 07:12:28PM +0000, Russell King - ARM Linux wrote:
> > This adds core support for saving and restoring CPU coprocessor
> > registers for suspend/resume support.  This contains support for suspend
> > with ARM920, ARM926, SA11x0, PXA25x, PXA27x, PXA3xx and V6 CPUs.
> > 
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > ---

Gah.  No sooner than v2, than there's a v3 of this patch, replacing a
typo'd sub rather than mov instruction, and adding a .ltorg to avoid
.text wastage.

 arch/arm/include/asm/glue-proc.h |    3 +
 arch/arm/include/asm/proc-fns.h  |    7 ++
 arch/arm/kernel/Makefile         |    1 +
 arch/arm/kernel/asm-offsets.c    |    9 +++
 arch/arm/kernel/sleep.S          |  110 ++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-arm1020.S       |    3 +
 arch/arm/mm/proc-arm1020e.S      |    3 +
 arch/arm/mm/proc-arm1022.S       |    3 +
 arch/arm/mm/proc-arm1026.S       |    3 +
 arch/arm/mm/proc-arm6_7.S        |    6 ++
 arch/arm/mm/proc-arm720.S        |    3 +
 arch/arm/mm/proc-arm740.S        |    3 +
 arch/arm/mm/proc-arm7tdmi.S      |    3 +
 arch/arm/mm/proc-arm920.S        |   37 ++++++++++++
 arch/arm/mm/proc-arm922.S        |    3 +
 arch/arm/mm/proc-arm925.S        |    3 +
 arch/arm/mm/proc-arm926.S        |   37 ++++++++++++
 arch/arm/mm/proc-arm940.S        |    3 +
 arch/arm/mm/proc-arm946.S        |    3 +
 arch/arm/mm/proc-arm9tdmi.S      |    3 +
 arch/arm/mm/proc-fa526.S         |    3 +
 arch/arm/mm/proc-feroceon.S      |    3 +
 arch/arm/mm/proc-mohawk.S        |    3 +
 arch/arm/mm/proc-sa110.S         |    3 +
 arch/arm/mm/proc-sa1100.S        |   39 +++++++++++++
 arch/arm/mm/proc-v6.S            |   48 ++++++++++++++++
 arch/arm/mm/proc-v7.S            |  114 ++++++++++++++++++++++++++++----------
 arch/arm/mm/proc-xsc3.S          |   48 ++++++++++++++++-
 arch/arm/mm/proc-xscale.S        |   45 ++++++++++++++-
 29 files changed, 519 insertions(+), 33 deletions(-)

diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e3bf443..6469521 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -256,6 +256,9 @@
 #define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
 #define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
 #define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
+#define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
+#define cpu_do_resume			__glue(CPU_NAME,_do_resume)
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 6980215..8ec535e 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -66,6 +66,11 @@ extern struct processor {
 	 * ignore 'ext'.
 	 */
 	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
+
+	/* Suspend/resume */
+	unsigned int suspend_size;
+	void (*do_suspend)(void *);
+	void (*do_resume)(void *);
 } processor;
 
 #ifndef MULTI_CPU
@@ -86,6 +91,8 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
+extern void cpu_resume(void);
+
 #include <asm/memory.h>
 
 #ifdef CONFIG_MMU
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 185ee82..74554f1 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
+obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 5302a91..927522c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
@@ -116,6 +117,14 @@ int main(void)
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
 #endif
+#ifdef MULTI_CPU
+  DEFINE(CPU_SLEEP_SIZE,	offsetof(struct processor, suspend_size));
+  DEFINE(CPU_DO_SUSPEND,	offsetof(struct processor, do_suspend));
+  DEFINE(CPU_DO_RESUME,		offsetof(struct processor, do_resume));
+#endif
+#ifdef MULTI_CACHE
+  DEFINE(CACHE_FLUSH_KERN_ALL,	offsetof(struct cpu_cache_fns, flush_kern_all));
+#endif
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
new file mode 100644
index 0000000..9f106fa
--- /dev/null
+++ b/arch/arm/kernel/sleep.S
@@ -0,0 +1,110 @@
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/glue-cache.h>
+#include <asm/glue-proc.h>
+	.text
+
+/*
+ * Save CPU state for a suspend
+ *  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
+ */
+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, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+	str	r2, [r3]		@ save phys SP
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
+#else
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, =cpu_suspend_size
+	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
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+	str	r2, [r3]		@ save phys SP
+	bl	cpu_do_suspend
+#endif
+
+	@ flush data cache
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	mov	lr, r9
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	mov	lr, r9
+	b	__cpuc_flush_kern_all
+#endif
+ENDPROC(cpu_suspend)
+	.ltorg
+
+/*
+ * r0 = control register value
+ * r1 = v:p offset (preserved by cpu_do_resume)
+ * r2 = phys page table base
+ * r3 = L1 section flags
+ */
+ENTRY(cpu_resume_mmu)
+	adr	r4, cpu_resume_turn_mmu_on
+	mov	r4, r4, lsr #20
+	orr	r3, r3, r4, lsl #20
+	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
+	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
+	sub	r2, r2, r1
+	ldr	r3, =cpu_resume_after_mmu
+	b	cpu_resume_turn_mmu_on
+ENDPROC(cpu_resume_mmu)
+	.ltorg
+	.align	5
+cpu_resume_turn_mmu_on:
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, caches, etc
+	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
+	mov	r0, r0
+	mov	r0, r0
+	mov	pc, r3			@ jump to virtual address
+ENDPROC(cpu_resume_turn_mmu_on)
+cpu_resume_after_mmu:
+	str	r5, [r2, r4, lsl #2]	@ restore old mapping
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	b	__cpuc_flush_kern_all
+#endif
+
+/*
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+	.data
+	.align
+ENTRY(cpu_resume)
+	ldr	r0, sleep_save_sp	@ stack phys addr
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
+#ifdef MULTI_CPU
+	ldmia	r0!, {r1, sp, lr, pc}	@ load v:p, stack, return fn, resume fn
+#else
+	ldmia	r0!, {r1, sp, lr}	@ load v:p, stack, return fn
+	b	cpu_do_resume
+#endif
+ENDPROC(cpu_resume)
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index bcf748d..226e3d8 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -493,6 +493,9 @@ arm1020_processor_functions:
 	.word	cpu_arm1020_dcache_clean_area
 	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index ab7ec26..86d9c2c 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -474,6 +474,9 @@ arm1020e_processor_functions:
 	.word	cpu_arm1020e_dcache_clean_area
 	.word	cpu_arm1020e_switch_mm
 	.word	cpu_arm1020e_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 831c5e5..83d3dd3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -457,6 +457,9 @@ arm1022_processor_functions:
 	.word	cpu_arm1022_dcache_clean_area
 	.word	cpu_arm1022_switch_mm
 	.word	cpu_arm1022_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1022_processor_functions, . - arm1022_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index e3f7e9a..686043e 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -452,6 +452,9 @@ arm1026_processor_functions:
 	.word	cpu_arm1026_dcache_clean_area
 	.word	cpu_arm1026_switch_mm
 	.word	cpu_arm1026_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1026_processor_functions, . - arm1026_processor_functions
 
 	.section .rodata
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 6a7be18..5f79dc4 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions)
 		.word	cpu_arm6_dcache_clean_area
 		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions)
 		.word	cpu_arm7_dcache_clean_area
 		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index c285395..665266d 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions)
 		.word	cpu_arm720_dcache_clean_area
 		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 38b27dc..6f9d12e 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions)
 	.word	cpu_arm740_dcache_clean_area
 	.word	cpu_arm740_switch_mm
 	.word	0			@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm740_processor_functions, . - arm740_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 0c9786d..e4c165c 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions)
 		.word	cpu_arm7tdmi_dcache_clean_area
 		.word	cpu_arm7tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 6109f27..b2705de 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -387,6 +387,40 @@ ENTRY(cpu_arm920_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm920_suspend_size
+.equ	arm920_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm920_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm920_do_suspend)
+
+ENTRY(arm920_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(arm920_do_resume)
+#else
+#define arm920_do_suspend	0
+#define arm920_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm920_setup, #function
@@ -432,6 +466,9 @@ arm920_processor_functions:
 	.word	cpu_arm920_dcache_clean_area
 	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte_ext
+	.word	arm920_suspend_size
+	.word	arm920_do_suspend
+	.word	arm920_do_resume
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index bb2f0f4..36154b1 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -436,6 +436,9 @@ arm922_processor_functions:
 	.word	cpu_arm922_dcache_clean_area
 	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index c13e01a..89c5e00 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -503,6 +503,9 @@ arm925_processor_functions:
 	.word	cpu_arm925_dcache_clean_area
 	.word	cpu_arm925_switch_mm
 	.word	cpu_arm925_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm925_processor_functions, . - arm925_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 42eb431..3beb784 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -401,6 +401,40 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm926_suspend_size
+.equ	arm926_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm926_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm926_do_suspend)
+
+ENTRY(arm926_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(arm926_do_resume)
+#else
+#define arm926_do_suspend	0
+#define arm926_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm926_setup, #function
@@ -456,6 +490,9 @@ arm926_processor_functions:
 	.word	cpu_arm926_dcache_clean_area
 	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte_ext
+	.word	arm926_suspend_size
+	.word	arm926_do_suspend
+	.word	arm926_do_resume
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 7b11cdb..26aea3f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions)
 	.word	cpu_arm940_dcache_clean_area
 	.word	cpu_arm940_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm940_processor_functions, . - arm940_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 1a5bbf0..8063345 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions)
 	.word	cpu_arm946_dcache_clean_area
 	.word	cpu_arm946_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm946_processor_functions, . - arm946_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db67e31..7b7ebd4 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions)
 		.word	cpu_arm9tdmi_dcache_clean_area
 		.word	cpu_arm9tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7c9ad62..fc2a4ae 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -195,6 +195,9 @@ fa526_processor_functions:
 	.word	cpu_fa526_dcache_clean_area
 	.word	cpu_fa526_switch_mm
 	.word	cpu_fa526_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	fa526_processor_functions, . - fa526_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b4597ed..d3883ee 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -554,6 +554,9 @@ feroceon_processor_functions:
 	.word	cpu_feroceon_dcache_clean_area
 	.word	cpu_feroceon_switch_mm
 	.word	cpu_feroceon_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	feroceon_processor_functions, . - feroceon_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 4458ee6..9d4f2ae 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -388,6 +388,9 @@ mohawk_processor_functions:
 	.word	cpu_mohawk_dcache_clean_area
 	.word	cpu_mohawk_switch_mm
 	.word	cpu_mohawk_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	mohawk_processor_functions, . - mohawk_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 5aa8d59..46f09ed 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions)
 	.word	cpu_sa110_dcache_clean_area
 	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 2ac4e6f..74483d1 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,6 +169,42 @@ ENTRY(cpu_sa1100_set_pte_ext)
 #endif
 	mov	pc, lr
 
+.globl	cpu_sa1100_suspend_size
+.equ	cpu_sa1100_suspend_size, 4*4
+#ifdef CONFIG_PM
+ENTRY(cpu_sa1100_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
+	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r6, c13, c0, 0		@ PID
+	mrc	p15, 0, r7, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r7}			@ store cp regs
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_sa1100_do_suspend)
+
+ENTRY(cpu_sa1100_do_resume)
+	ldmia	r0, {r4 - r7}			@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@ flush I+D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
+	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
+
+	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
+	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r6, c13, c0, 0		@ PID
+	mov	r0, r7				@ control register
+	mov	r2, r5, lsr #14			@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_sa1100_do_resume)
+#else
+#define cpu_sa1100_do_suspend	0
+#define cpu_sa1100_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__sa1100_setup, #function
@@ -218,6 +254,9 @@ ENTRY(sa1100_processor_functions)
 	.word	cpu_sa1100_dcache_clean_area
 	.word	cpu_sa1100_switch_mm
 	.word	cpu_sa1100_set_pte_ext
+	.word	cpu_sa1100_suspend_size
+	.word	cpu_sa1100_do_suspend
+	.word	cpu_sa1100_do_resume
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 59a7e1f..c86f451 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -121,6 +121,51 @@ ENTRY(cpu_v6_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
+.globl	cpu_v6_suspend_size
+.equ	cpu_v6_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_v6_do_suspend)
+	stmfd	sp!, {r4 - r10, 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 base 0
+	mrc	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r8, c1, c0, 1	@ auxillary control register
+	mrc	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r10, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4- r10, pc}
+ENDPROC(cpu_v6_do_suspend)
+
+ENTRY(cpu_v6_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
+	ldmia	r0, {r4 - r10}
+	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 base 0
+	mcr	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r8, c1, c0, 1	@ auxillary control register
+	mcr	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, ip, c7, c5, 4	@ ISB
+	mov	r0, r10			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v6_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v6_do_suspend 0
+#define cpu_v6_do_resume 0
+#endif
 
 
 	.type	cpu_v6_name, #object
@@ -206,6 +251,9 @@ ENTRY(v6_processor_functions)
 	.word	cpu_v6_dcache_clean_area
 	.word	cpu_v6_switch_mm
 	.word	cpu_v6_set_pte_ext
+	.word	cpu_v6_suspend_size
+	.word	cpu_v6_do_suspend
+	.word	cpu_v6_do_resume
 	.size	v6_processor_functions, . - v6_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 0c1172b..8e6142d 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -171,6 +171,85 @@ cpu_v7_name:
 	.ascii	"ARMv7 Processor"
 	.align
 
+	/*
+	 * Memory region attributes with SCTLR.TRE=1
+	 *
+	 *   n = TEX[0],C,B
+	 *   TR = PRRR[2n+1:2n]		- memory type
+	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
+	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
+	 *
+	 *			n	TR	IR	OR
+	 *   UNCACHED		000	00
+	 *   BUFFERABLE		001	10	00	00
+	 *   WRITETHROUGH	010	10	10	10
+	 *   WRITEBACK		011	10	11	11
+	 *   reserved		110
+	 *   WRITEALLOC		111	10	01	01
+	 *   DEV_SHARED		100	01
+	 *   DEV_NONSHARED	100	01
+	 *   DEV_WC		001	10
+	 *   DEV_CACHED		011	10
+	 *
+	 * Other attributes:
+	 *
+	 *   DS0 = PRRR[16] = 0		- device shareable property
+	 *   DS1 = PRRR[17] = 1		- device shareable property
+	 *   NS0 = PRRR[18] = 0		- normal shareable property
+	 *   NS1 = PRRR[19] = 1		- normal shareable property
+	 *   NOS = PRRR[24+n] = 1	- not outer shareable
+	 */
+.equ	PRRR,	0xff0a81a8
+.equ	NMRR,	0x40e040e0
+
+/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
+.globl	cpu_v7_suspend_size
+.equ	cpu_v7_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_v7_do_suspend)
+	stmfd	sp!, {r4 - r10, 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	@ TTB 0
+	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r8, c1, c0, 0	@ Control register
+	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_v7_do_suspend)
+
+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 - r10}
+	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	@ TTB 0
+	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, r9, c1, c0, 1	@ Auxillary control register
+	mcr	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	ldr	r4, =PRRR		@ PRRR
+	ldr	r5, =NMRR		@ NMRR
+	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
+	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
+	isb
+	mov	r0, r8			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v7_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v7_do_suspend	0
+#define cpu_v7_do_resume	0
+#endif
+
 	__CPUINIT
 
 /*
@@ -276,36 +355,8 @@ __v7_setup:
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	/*
-	 * Memory region attributes with SCTLR.TRE=1
-	 *
-	 *   n = TEX[0],C,B
-	 *   TR = PRRR[2n+1:2n]		- memory type
-	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
-	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
-	 *
-	 *			n	TR	IR	OR
-	 *   UNCACHED		000	00
-	 *   BUFFERABLE		001	10	00	00
-	 *   WRITETHROUGH	010	10	10	10
-	 *   WRITEBACK		011	10	11	11
-	 *   reserved		110
-	 *   WRITEALLOC		111	10	01	01
-	 *   DEV_SHARED		100	01
-	 *   DEV_NONSHARED	100	01
-	 *   DEV_WC		001	10
-	 *   DEV_CACHED		011	10
-	 *
-	 * Other attributes:
-	 *
-	 *   DS0 = PRRR[16] = 0		- device shareable property
-	 *   DS1 = PRRR[17] = 1		- device shareable property
-	 *   NS0 = PRRR[18] = 0		- normal shareable property
-	 *   NS1 = PRRR[19] = 1		- normal shareable property
-	 *   NOS = PRRR[24+n] = 1	- not outer shareable
-	 */
-	ldr	r5, =0xff0a81a8			@ PRRR
-	ldr	r6, =0x40e040e0			@ NMRR
+	ldr	r5, =PRRR			@ PRRR
+	ldr	r6, =NMRR			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
@@ -351,6 +402,9 @@ ENTRY(v7_processor_functions)
 	.word	cpu_v7_dcache_clean_area
 	.word	cpu_v7_switch_mm
 	.word	cpu_v7_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	v7_processor_functions, . - v7_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index ec26355..63d8b20 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -413,9 +413,52 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	mov	pc, lr
 
 	.ltorg
-
 	.align
 
+.globl	cpu_xsc3_suspend_size
+.equ	cpu_xsc3_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_xsc3_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r1, r4 - r10}	@ store v:p offset + cp regs
+	ldmia	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xsc3_do_suspend)
+
+ENTRY(cpu_xsc3_do_resume)
+	ldmia	r0, {r1, r4 - r10}	@ load v:p offset + cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, ip, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =0x542e		@ section flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_xsc3_do_resume)
+#else
+#define cpu_xsc3_do_suspend	0
+#define cpu_xsc3_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xsc3_setup, #function
@@ -476,6 +519,9 @@ ENTRY(xsc3_processor_functions)
 	.word	cpu_xsc3_dcache_clean_area
 	.word	cpu_xsc3_switch_mm
 	.word	cpu_xsc3_set_pte_ext
+	.word	cpu_xsc3_suspend_size
+	.word	cpu_xsc3_do_suspend
+	.word	cpu_xsc3_do_resume
 	.size	xsc3_processor_functions, . - xsc3_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 5a37c5e..086038c 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -513,11 +513,49 @@ ENTRY(cpu_xscale_set_pte_ext)
 	xscale_set_pte_ext_epilogue
 	mov	pc, lr
 
-
 	.ltorg
-
 	.align
 
+.globl	cpu_xscale_suspend_size
+.equ	cpu_xscale_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_xscale_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xscale_do_suspend)
+
+ENTRY(cpu_xscale_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_xscale_do_resume)
+#else
+#define cpu_xscale_do_suspend	0
+#define cpu_xscale_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xscale_setup, #function
@@ -565,6 +603,9 @@ ENTRY(xscale_processor_functions)
 	.word	cpu_xscale_dcache_clean_area
 	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte_ext
+	.word	cpu_xscale_suspend_size
+	.word	cpu_xscale_do_suspend
+	.word	cpu_xscale_do_resume
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
 	.section ".rodata"

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 12:10     ` [PATCH v3 " Russell King - ARM Linux
@ 2011-02-07 13:21       ` saeed bishara
  2011-02-07 13:34         ` Russell King - ARM Linux
  0 siblings, 1 reply; 33+ messages in thread
From: saeed bishara @ 2011-02-07 13:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 7, 2011 at 2:10 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Feb 07, 2011 at 12:01:04PM +0000, Russell King - ARM Linux wrote:
>> On Sun, Feb 06, 2011 at 07:12:28PM +0000, Russell King - ARM Linux wrote:
>> > This adds core support for saving and restoring CPU coprocessor
>> > registers for suspend/resume support. ?This contains support for suspend
>> > with ARM920, ARM926, SA11x0, PXA25x, PXA27x, PXA3xx and V6 CPUs.
>> >
>> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> > ---
>
> Gah. ?No sooner than v2, than there's a v3 of this patch, replacing a
> typo'd sub rather than mov instruction, and adding a .ltorg to avoid
> .text wastage.
>
> ?arch/arm/include/asm/glue-proc.h | ? ?3 +
> ?arch/arm/include/asm/proc-fns.h ?| ? ?7 ++
> ?arch/arm/kernel/Makefile ? ? ? ? | ? ?1 +
> ?arch/arm/kernel/asm-offsets.c ? ?| ? ?9 +++
> ?arch/arm/kernel/sleep.S ? ? ? ? ?| ?110 ++++++++++++++++++++++++++++++++++++
> ?arch/arm/mm/proc-arm1020.S ? ? ? | ? ?3 +
> ?arch/arm/mm/proc-arm1020e.S ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm1022.S ? ? ? | ? ?3 +
> ?arch/arm/mm/proc-arm1026.S ? ? ? | ? ?3 +
> ?arch/arm/mm/proc-arm6_7.S ? ? ? ?| ? ?6 ++
> ?arch/arm/mm/proc-arm720.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm740.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm7tdmi.S ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm920.S ? ? ? ?| ? 37 ++++++++++++
> ?arch/arm/mm/proc-arm922.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm925.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm926.S ? ? ? ?| ? 37 ++++++++++++
> ?arch/arm/mm/proc-arm940.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm946.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-arm9tdmi.S ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-fa526.S ? ? ? ? | ? ?3 +
> ?arch/arm/mm/proc-feroceon.S ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-mohawk.S ? ? ? ?| ? ?3 +
> ?arch/arm/mm/proc-sa110.S ? ? ? ? | ? ?3 +
> ?arch/arm/mm/proc-sa1100.S ? ? ? ?| ? 39 +++++++++++++
> ?arch/arm/mm/proc-v6.S ? ? ? ? ? ?| ? 48 ++++++++++++++++
> ?arch/arm/mm/proc-v7.S ? ? ? ? ? ?| ?114 ++++++++++++++++++++++++++++----------
> ?arch/arm/mm/proc-xsc3.S ? ? ? ? ?| ? 48 ++++++++++++++++-
> ?arch/arm/mm/proc-xscale.S ? ? ? ?| ? 45 ++++++++++++++-
> ?29 files changed, 519 insertions(+), 33 deletions(-)
>
> diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
> index e3bf443..6469521 100644
> --- a/arch/arm/include/asm/glue-proc.h
> +++ b/arch/arm/include/asm/glue-proc.h
> @@ -256,6 +256,9 @@
> ?#define cpu_dcache_clean_area ? ? ? ? ?__glue(CPU_NAME,_dcache_clean_area)
> ?#define cpu_do_switch_mm ? ? ? ? ? ? ? __glue(CPU_NAME,_switch_mm)
> ?#define cpu_set_pte_ext ? ? ? ? ? ? ? ? ? ? ? ?__glue(CPU_NAME,_set_pte_ext)
> +#define cpu_suspend_size ? ? ? ? ? ? ? __glue(CPU_NAME,_suspend_size)
> +#define cpu_do_suspend ? ? ? ? ? ? ? ? __glue(CPU_NAME,_do_suspend)
> +#define cpu_do_resume ? ? ? ? ? ? ? ? ?__glue(CPU_NAME,_do_resume)
> ?#endif
>
> ?#endif
> diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
> index 6980215..8ec535e 100644
> --- a/arch/arm/include/asm/proc-fns.h
> +++ b/arch/arm/include/asm/proc-fns.h
> @@ -66,6 +66,11 @@ extern struct processor {
> ? ? ? ? * ignore 'ext'.
> ? ? ? ? */
> ? ? ? ?void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
> +
> + ? ? ? /* Suspend/resume */
> + ? ? ? unsigned int suspend_size;
> + ? ? ? void (*do_suspend)(void *);
> + ? ? ? void (*do_resume)(void *);
> ?} processor;
>
> ?#ifndef MULTI_CPU
> @@ -86,6 +91,8 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
> ?#define cpu_do_switch_mm(pgd,mm) ? ? ? processor.switch_mm(pgd,mm)
> ?#endif
>
> +extern void cpu_resume(void);
> +
> ?#include <asm/memory.h>
>
> ?#ifdef CONFIG_MMU
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index 185ee82..74554f1 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES) ? ? ? ? += armksyms.o module.o
> ?obj-$(CONFIG_ARTHUR) ? ? ? ? ? += arthur.o
> ?obj-$(CONFIG_ISA_DMA) ? ? ? ? ?+= dma-isa.o
> ?obj-$(CONFIG_PCI) ? ? ? ? ? ? ?+= bios32.o isa.o
> +obj-$(CONFIG_PM) ? ? ? ? ? ? ? += sleep.o
> ?obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
> ?obj-$(CONFIG_SMP) ? ? ? ? ? ? ?+= smp.o smp_tlb.o
> ?obj-$(CONFIG_HAVE_ARM_SCU) ? ? += smp_scu.o
> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> index 5302a91..927522c 100644
> --- a/arch/arm/kernel/asm-offsets.c
> +++ b/arch/arm/kernel/asm-offsets.c
> @@ -13,6 +13,7 @@
> ?#include <linux/sched.h>
> ?#include <linux/mm.h>
> ?#include <linux/dma-mapping.h>
> +#include <asm/cacheflush.h>
> ?#include <asm/glue-df.h>
> ?#include <asm/glue-pf.h>
> ?#include <asm/mach/arch.h>
> @@ -116,6 +117,14 @@ int main(void)
> ?#ifdef MULTI_PABORT
> ? DEFINE(PROCESSOR_PABT_FUNC, ?offsetof(struct processor, _prefetch_abort));
> ?#endif
> +#ifdef MULTI_CPU
> + ?DEFINE(CPU_SLEEP_SIZE, ? ? ? offsetof(struct processor, suspend_size));
> + ?DEFINE(CPU_DO_SUSPEND, ? ? ? offsetof(struct processor, do_suspend));
> + ?DEFINE(CPU_DO_RESUME, ? ? ? ? ? ? ? ?offsetof(struct processor, do_resume));
> +#endif
> +#ifdef MULTI_CACHE
> + ?DEFINE(CACHE_FLUSH_KERN_ALL, offsetof(struct cpu_cache_fns, flush_kern_all));
> +#endif
> ? BLANK();
> ? DEFINE(DMA_BIDIRECTIONAL, ? ?DMA_BIDIRECTIONAL);
> ? DEFINE(DMA_TO_DEVICE, ? ? ? ? ? ? ? ?DMA_TO_DEVICE);
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> new file mode 100644
> index 0000000..9f106fa
> --- /dev/null
> +++ b/arch/arm/kernel/sleep.S
> @@ -0,0 +1,110 @@
> +#include <linux/linkage.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/assembler.h>
> +#include <asm/glue-cache.h>
> +#include <asm/glue-proc.h>
> + ? ? ? .text
> +
> +/*
> + * Save CPU state for a suspend
> + * ?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
> + */
> +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, r3, ip} ? @ save v:p, virt SP, retfn, phys resume fn
> + ? ? ? ldr ? ? r3, =sleep_save_sp
> + ? ? ? add ? ? r2, sp, r1 ? ? ? ? ? ? ?@ convert SP to phys
> + ? ? ? str ? ? r2, [r3] ? ? ? ? ? ? ? ?@ save phys SP
> + ? ? ? mov ? ? lr, pc
> + ? ? ? ldr ? ? pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
> +#else
> + ? ? ? mov ? ? r2, sp ? ? ? ? ? ? ? ? ?@ current virtual SP
> + ? ? ? ldr ? ? r0, =cpu_suspend_size
> + ? ? ? 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
> + ? ? ? ldr ? ? r3, =sleep_save_sp
> + ? ? ? add ? ? r2, sp, r1 ? ? ? ? ? ? ?@ convert SP to phys
> + ? ? ? str ? ? r2, [r3] ? ? ? ? ? ? ? ?@ save phys SP
> + ? ? ? bl ? ? ?cpu_do_suspend
> +#endif
> +
> + ? ? ? @ flush data cache
> +#ifdef MULTI_CACHE
> + ? ? ? ldr ? ? r10, =cpu_cache
> + ? ? ? mov ? ? lr, r9
> + ? ? ? ldr ? ? pc, [r10, #CACHE_FLUSH_KERN_ALL]
> +#else
> + ? ? ? mov ? ? lr, r9
> + ? ? ? b ? ? ? __cpuc_flush_kern_all
> +#endif
> +ENDPROC(cpu_suspend)
> + ? ? ? .ltorg
> +
> +/*
> + * r0 = control register value
> + * r1 = v:p offset (preserved by cpu_do_resume)
> + * r2 = phys page table base
> + * r3 = L1 section flags
> + */
> +ENTRY(cpu_resume_mmu)
> + ? ? ? adr ? ? r4, cpu_resume_turn_mmu_on
> + ? ? ? mov ? ? r4, r4, lsr #20
> + ? ? ? orr ? ? r3, r3, r4, lsl #20
> + ? ? ? ldr ? ? r5, [r2, r4, lsl #2] ? ?@ save old mapping
> + ? ? ? str ? ? r3, [r2, r4, lsl #2] ? ?@ setup 1:1 mapping for mmu code
this code doesn't look smp save, it modifies page table that could be
used by another cpu. I suggest to create (at  boot time) identity page
table and use it in order to do mmu on.
saeed

> + ? ? ? sub ? ? r2, r2, r1
> + ? ? ? ldr ? ? r3, =cpu_resume_after_mmu
> + ? ? ? b ? ? ? cpu_resume_turn_mmu_on
> +ENDPROC(cpu_resume_mmu)
> + ? ? ? .ltorg
> + ? ? ? .align ?5
> +cpu_resume_turn_mmu_on:
> + ? ? ? mcr ? ? p15, 0, r0, c1, c0, 0 ? @ turn on MMU, caches, etc
> + ? ? ? mrc ? ? p15, 0, r0, c0, c0, 0 ? @ read id reg
> + ? ? ? mov ? ? r0, r0
> + ? ? ? mov ? ? r0, r0
> + ? ? ? mov ? ? pc, r3 ? ? ? ? ? ? ? ? ?@ jump to virtual address
> +ENDPROC(cpu_resume_turn_mmu_on)
> +cpu_resume_after_mmu:
> + ? ? ? str ? ? r5, [r2, r4, lsl #2] ? ?@ restore old mapping
> +#ifdef MULTI_CACHE
> + ? ? ? ldr ? ? r10, =cpu_cache
> + ? ? ? ldr ? ? pc, [r10, #CACHE_FLUSH_KERN_ALL]
> +#else
> + ? ? ? b ? ? ? __cpuc_flush_kern_all
> +#endif
> +
> +/*
> + * Note: Yes, part of the following code is located into the .data section.
> + * ? ? ? This is to allow sleep_save_sp to be accessed with a relative load
> + * ? ? ? while we can't rely on any MMU translation. ?We could have put
> + * ? ? ? sleep_save_sp in the .text section as well, but some setups might
> + * ? ? ? insist on it to be truly read-only.
> + */
> + ? ? ? .data
> + ? ? ? .align
> +ENTRY(cpu_resume)
> + ? ? ? ldr ? ? r0, sleep_save_sp ? ? ? @ stack phys addr
> + ? ? ? msr ? ? cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
> +#ifdef MULTI_CPU
> + ? ? ? ldmia ? r0!, {r1, sp, lr, pc} ? @ load v:p, stack, return fn, resume fn
> +#else
> + ? ? ? ldmia ? r0!, {r1, sp, lr} ? ? ? @ load v:p, stack, return fn
> + ? ? ? b ? ? ? cpu_do_resume
> +#endif
> +ENDPROC(cpu_resume)
> +
> +sleep_save_sp:
> + ? ? ? .word ? 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @ preserve stack phys ptr here
> diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
> index bcf748d..226e3d8 100644
> --- a/arch/arm/mm/proc-arm1020.S
> +++ b/arch/arm/mm/proc-arm1020.S
> @@ -493,6 +493,9 @@ arm1020_processor_functions:
> ? ? ? ?.word ? cpu_arm1020_dcache_clean_area
> ? ? ? ?.word ? cpu_arm1020_switch_mm
> ? ? ? ?.word ? cpu_arm1020_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm1020_processor_functions, . - arm1020_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
> index ab7ec26..86d9c2c 100644
> --- a/arch/arm/mm/proc-arm1020e.S
> +++ b/arch/arm/mm/proc-arm1020e.S
> @@ -474,6 +474,9 @@ arm1020e_processor_functions:
> ? ? ? ?.word ? cpu_arm1020e_dcache_clean_area
> ? ? ? ?.word ? cpu_arm1020e_switch_mm
> ? ? ? ?.word ? cpu_arm1020e_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm1020e_processor_functions, . - arm1020e_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
> index 831c5e5..83d3dd3 100644
> --- a/arch/arm/mm/proc-arm1022.S
> +++ b/arch/arm/mm/proc-arm1022.S
> @@ -457,6 +457,9 @@ arm1022_processor_functions:
> ? ? ? ?.word ? cpu_arm1022_dcache_clean_area
> ? ? ? ?.word ? cpu_arm1022_switch_mm
> ? ? ? ?.word ? cpu_arm1022_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm1022_processor_functions, . - arm1022_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
> index e3f7e9a..686043e 100644
> --- a/arch/arm/mm/proc-arm1026.S
> +++ b/arch/arm/mm/proc-arm1026.S
> @@ -452,6 +452,9 @@ arm1026_processor_functions:
> ? ? ? ?.word ? cpu_arm1026_dcache_clean_area
> ? ? ? ?.word ? cpu_arm1026_switch_mm
> ? ? ? ?.word ? cpu_arm1026_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm1026_processor_functions, . - arm1026_processor_functions
>
> ? ? ? ?.section .rodata
> diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
> index 6a7be18..5f79dc4 100644
> --- a/arch/arm/mm/proc-arm6_7.S
> +++ b/arch/arm/mm/proc-arm6_7.S
> @@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions)
> ? ? ? ? ? ? ? ?.word ? cpu_arm6_dcache_clean_area
> ? ? ? ? ? ? ? ?.word ? cpu_arm6_switch_mm
> ? ? ? ? ? ? ? ?.word ? cpu_arm6_set_pte_ext
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> ? ? ? ? ? ? ? ?.size ? arm6_processor_functions, . - arm6_processor_functions
>
> ?/*
> @@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions)
> ? ? ? ? ? ? ? ?.word ? cpu_arm7_dcache_clean_area
> ? ? ? ? ? ? ? ?.word ? cpu_arm7_switch_mm
> ? ? ? ? ? ? ? ?.word ? cpu_arm7_set_pte_ext
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> ? ? ? ? ? ? ? ?.size ? arm7_processor_functions, . - arm7_processor_functions
>
> ? ? ? ? ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
> index c285395..665266d 100644
> --- a/arch/arm/mm/proc-arm720.S
> +++ b/arch/arm/mm/proc-arm720.S
> @@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions)
> ? ? ? ? ? ? ? ?.word ? cpu_arm720_dcache_clean_area
> ? ? ? ? ? ? ? ?.word ? cpu_arm720_switch_mm
> ? ? ? ? ? ? ? ?.word ? cpu_arm720_set_pte_ext
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> ? ? ? ? ? ? ? ?.size ? arm720_processor_functions, . - arm720_processor_functions
>
> ? ? ? ? ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
> index 38b27dc..6f9d12e 100644
> --- a/arch/arm/mm/proc-arm740.S
> +++ b/arch/arm/mm/proc-arm740.S
> @@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions)
> ? ? ? ?.word ? cpu_arm740_dcache_clean_area
> ? ? ? ?.word ? cpu_arm740_switch_mm
> ? ? ? ?.word ? 0 ? ? ? ? ? ? ? ? ? ? ? @ cpu_*_set_pte
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm740_processor_functions, . - arm740_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
> index 0c9786d..e4c165c 100644
> --- a/arch/arm/mm/proc-arm7tdmi.S
> +++ b/arch/arm/mm/proc-arm7tdmi.S
> @@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions)
> ? ? ? ? ? ? ? ?.word ? cpu_arm7tdmi_dcache_clean_area
> ? ? ? ? ? ? ? ?.word ? cpu_arm7tdmi_switch_mm
> ? ? ? ? ? ? ? ?.word ? 0 ? ? ? ? ? ? ? @ cpu_*_set_pte
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> ? ? ? ? ? ? ? ?.size ? arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
>
> ? ? ? ? ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
> index 6109f27..b2705de 100644
> --- a/arch/arm/mm/proc-arm920.S
> +++ b/arch/arm/mm/proc-arm920.S
> @@ -387,6 +387,40 @@ ENTRY(cpu_arm920_set_pte_ext)
> ?#endif
> ? ? ? ?mov ? ? pc, lr
>
> +/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
> +.globl arm920_suspend_size
> +.equ ? arm920_suspend_size, 4 * 3
> +#ifdef CONFIG_PM
> +ENTRY(arm920_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r7, lr}
> + ? ? ? mrc ? ? p15, 0, r4, c13, c0, 0 ?@ PID
> + ? ? ? mrc ? ? p15, 0, r5, c3, c0, 0 ? @ Domain ID
> + ? ? ? mrc ? ? p15, 0, r6, c2, c0, 0 ? @ TTB address
> + ? ? ? mrc ? ? p15, 0, r7, c1, c0, 0 ? @ Control register
> + ? ? ? stmia ? r0, {r4 - r7}
> + ? ? ? ldmfd ? sp!, {r4 - r7, pc}
> +ENDPROC(arm920_do_suspend)
> +
> +ENTRY(arm920_do_resume)
> + ? ? ? mov ? ? ip, #0
> + ? ? ? mcr ? ? p15, 0, ip, c8, c7, 0 ? @ invalidate I+D TLBs
> + ? ? ? mcr ? ? p15, 0, ip, c7, c7, 0 ? @ invalidate I+D caches
> + ? ? ? ldmia ? r0, {r4 - r7}
> + ? ? ? mcr ? ? p15, 0, r4, c13, c0, 0 ?@ PID
> + ? ? ? mcr ? ? p15, 0, r5, c3, c0, 0 ? @ Domain ID
> + ? ? ? mcr ? ? p15, 0, r6, c2, c0, 0 ? @ TTB address
> + ? ? ? mov ? ? r0, r7 ? ? ? ? ? ? ? ? ?@ control register
> + ? ? ? mov ? ? r2, r6, lsr #14 ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
> + ? ? ? ? ? ? ? ? ? ?PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(arm920_do_resume)
> +#else
> +#define arm920_do_suspend ? ? ?0
> +#define arm920_do_resume ? ? ? 0
> +#endif
> +
> ? ? ? ?__CPUINIT
>
> ? ? ? ?.type ? __arm920_setup, #function
> @@ -432,6 +466,9 @@ arm920_processor_functions:
> ? ? ? ?.word ? cpu_arm920_dcache_clean_area
> ? ? ? ?.word ? cpu_arm920_switch_mm
> ? ? ? ?.word ? cpu_arm920_set_pte_ext
> + ? ? ? .word ? arm920_suspend_size
> + ? ? ? .word ? arm920_do_suspend
> + ? ? ? .word ? arm920_do_resume
> ? ? ? ?.size ? arm920_processor_functions, . - arm920_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
> index bb2f0f4..36154b1 100644
> --- a/arch/arm/mm/proc-arm922.S
> +++ b/arch/arm/mm/proc-arm922.S
> @@ -436,6 +436,9 @@ arm922_processor_functions:
> ? ? ? ?.word ? cpu_arm922_dcache_clean_area
> ? ? ? ?.word ? cpu_arm922_switch_mm
> ? ? ? ?.word ? cpu_arm922_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm922_processor_functions, . - arm922_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
> index c13e01a..89c5e00 100644
> --- a/arch/arm/mm/proc-arm925.S
> +++ b/arch/arm/mm/proc-arm925.S
> @@ -503,6 +503,9 @@ arm925_processor_functions:
> ? ? ? ?.word ? cpu_arm925_dcache_clean_area
> ? ? ? ?.word ? cpu_arm925_switch_mm
> ? ? ? ?.word ? cpu_arm925_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm925_processor_functions, . - arm925_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
> index 42eb431..3beb784 100644
> --- a/arch/arm/mm/proc-arm926.S
> +++ b/arch/arm/mm/proc-arm926.S
> @@ -401,6 +401,40 @@ ENTRY(cpu_arm926_set_pte_ext)
> ?#endif
> ? ? ? ?mov ? ? pc, lr
>
> +/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
> +.globl arm926_suspend_size
> +.equ ? arm926_suspend_size, 4 * 3
> +#ifdef CONFIG_PM
> +ENTRY(arm926_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r7, lr}
> + ? ? ? mrc ? ? p15, 0, r4, c13, c0, 0 ?@ PID
> + ? ? ? mrc ? ? p15, 0, r5, c3, c0, 0 ? @ Domain ID
> + ? ? ? mrc ? ? p15, 0, r6, c2, c0, 0 ? @ TTB address
> + ? ? ? mrc ? ? p15, 0, r7, c1, c0, 0 ? @ Control register
> + ? ? ? stmia ? r0, {r4 - r7}
> + ? ? ? ldmfd ? sp!, {r4 - r7, pc}
> +ENDPROC(arm926_do_suspend)
> +
> +ENTRY(arm926_do_resume)
> + ? ? ? mov ? ? ip, #0
> + ? ? ? mcr ? ? p15, 0, ip, c8, c7, 0 ? @ invalidate I+D TLBs
> + ? ? ? mcr ? ? p15, 0, ip, c7, c7, 0 ? @ invalidate I+D caches
> + ? ? ? ldmia ? r0, {r4 - r7}
> + ? ? ? mcr ? ? p15, 0, r4, c13, c0, 0 ?@ PID
> + ? ? ? mcr ? ? p15, 0, r5, c3, c0, 0 ? @ Domain ID
> + ? ? ? mcr ? ? p15, 0, r6, c2, c0, 0 ? @ TTB address
> + ? ? ? mov ? ? r0, r7 ? ? ? ? ? ? ? ? ?@ control register
> + ? ? ? mov ? ? r2, r6, lsr #14 ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
> + ? ? ? ? ? ? ? ? ? ?PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(arm926_do_resume)
> +#else
> +#define arm926_do_suspend ? ? ?0
> +#define arm926_do_resume ? ? ? 0
> +#endif
> +
> ? ? ? ?__CPUINIT
>
> ? ? ? ?.type ? __arm926_setup, #function
> @@ -456,6 +490,9 @@ arm926_processor_functions:
> ? ? ? ?.word ? cpu_arm926_dcache_clean_area
> ? ? ? ?.word ? cpu_arm926_switch_mm
> ? ? ? ?.word ? cpu_arm926_set_pte_ext
> + ? ? ? .word ? arm926_suspend_size
> + ? ? ? .word ? arm926_do_suspend
> + ? ? ? .word ? arm926_do_resume
> ? ? ? ?.size ? arm926_processor_functions, . - arm926_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
> index 7b11cdb..26aea3f 100644
> --- a/arch/arm/mm/proc-arm940.S
> +++ b/arch/arm/mm/proc-arm940.S
> @@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions)
> ? ? ? ?.word ? cpu_arm940_dcache_clean_area
> ? ? ? ?.word ? cpu_arm940_switch_mm
> ? ? ? ?.word ? 0 ? ? ? ? ? ? ? @ cpu_*_set_pte
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm940_processor_functions, . - arm940_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
> index 1a5bbf0..8063345 100644
> --- a/arch/arm/mm/proc-arm946.S
> +++ b/arch/arm/mm/proc-arm946.S
> @@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions)
> ? ? ? ?.word ? cpu_arm946_dcache_clean_area
> ? ? ? ?.word ? cpu_arm946_switch_mm
> ? ? ? ?.word ? 0 ? ? ? ? ? ? ? @ cpu_*_set_pte
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? arm946_processor_functions, . - arm946_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
> index db67e31..7b7ebd4 100644
> --- a/arch/arm/mm/proc-arm9tdmi.S
> +++ b/arch/arm/mm/proc-arm9tdmi.S
> @@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions)
> ? ? ? ? ? ? ? ?.word ? cpu_arm9tdmi_dcache_clean_area
> ? ? ? ? ? ? ? ?.word ? cpu_arm9tdmi_switch_mm
> ? ? ? ? ? ? ? ?.word ? 0 ? ? ? ? ? ? ? @ cpu_*_set_pte
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> + ? ? ? ? ? ? ? .word ? 0
> ? ? ? ? ? ? ? ?.size ? arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
>
> ? ? ? ? ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
> index 7c9ad62..fc2a4ae 100644
> --- a/arch/arm/mm/proc-fa526.S
> +++ b/arch/arm/mm/proc-fa526.S
> @@ -195,6 +195,9 @@ fa526_processor_functions:
> ? ? ? ?.word ? cpu_fa526_dcache_clean_area
> ? ? ? ?.word ? cpu_fa526_switch_mm
> ? ? ? ?.word ? cpu_fa526_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? fa526_processor_functions, . - fa526_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
> index b4597ed..d3883ee 100644
> --- a/arch/arm/mm/proc-feroceon.S
> +++ b/arch/arm/mm/proc-feroceon.S
> @@ -554,6 +554,9 @@ feroceon_processor_functions:
> ? ? ? ?.word ? cpu_feroceon_dcache_clean_area
> ? ? ? ?.word ? cpu_feroceon_switch_mm
> ? ? ? ?.word ? cpu_feroceon_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? feroceon_processor_functions, . - feroceon_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
> index 4458ee6..9d4f2ae 100644
> --- a/arch/arm/mm/proc-mohawk.S
> +++ b/arch/arm/mm/proc-mohawk.S
> @@ -388,6 +388,9 @@ mohawk_processor_functions:
> ? ? ? ?.word ? cpu_mohawk_dcache_clean_area
> ? ? ? ?.word ? cpu_mohawk_switch_mm
> ? ? ? ?.word ? cpu_mohawk_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? mohawk_processor_functions, . - mohawk_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
> index 5aa8d59..46f09ed 100644
> --- a/arch/arm/mm/proc-sa110.S
> +++ b/arch/arm/mm/proc-sa110.S
> @@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions)
> ? ? ? ?.word ? cpu_sa110_dcache_clean_area
> ? ? ? ?.word ? cpu_sa110_switch_mm
> ? ? ? ?.word ? cpu_sa110_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? sa110_processor_functions, . - sa110_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
> index 2ac4e6f..74483d1 100644
> --- a/arch/arm/mm/proc-sa1100.S
> +++ b/arch/arm/mm/proc-sa1100.S
> @@ -169,6 +169,42 @@ ENTRY(cpu_sa1100_set_pte_ext)
> ?#endif
> ? ? ? ?mov ? ? pc, lr
>
> +.globl cpu_sa1100_suspend_size
> +.equ ? cpu_sa1100_suspend_size, 4*4
> +#ifdef CONFIG_PM
> +ENTRY(cpu_sa1100_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r7, lr}
> + ? ? ? mrc ? ? p15, 0, r4, c3, c0, 0 ? ? ? ? ? @ domain ID
> + ? ? ? mrc ? ? p15, 0, r5, c2, c0, 0 ? ? ? ? ? @ translation table base addr
> + ? ? ? mrc ? ? p15, 0, r6, c13, c0, 0 ? ? ? ? ?@ PID
> + ? ? ? mrc ? ? p15, 0, r7, c1, c0, 0 ? ? ? ? ? @ control reg
> + ? ? ? stmia ? r0, {r4 - r7} ? ? ? ? ? ? ? ? ? @ store cp regs
> + ? ? ? ldmfd ? sp!, {r4 - r7, pc}
> +ENDPROC(cpu_sa1100_do_suspend)
> +
> +ENTRY(cpu_sa1100_do_resume)
> + ? ? ? ldmia ? r0, {r4 - r7} ? ? ? ? ? ? ? ? ? @ load cp regs
> + ? ? ? mov ? ? r1, #0
> + ? ? ? mcr ? ? p15, 0, r1, c8, c7, 0 ? ? ? ? ? @ flush I+D TLBs
> + ? ? ? mcr ? ? p15, 0, r1, c7, c7, 0 ? ? ? ? ? @ flush I&D cache
> + ? ? ? mcr ? ? p15, 0, r1, c9, c0, 0 ? ? ? ? ? @ invalidate RB
> + ? ? ? mcr ? ? p15, 0, r1, c9, c0, 5 ? ? ? ? ? @ allow user space to use RB
> +
> + ? ? ? mcr ? ? p15, 0, r4, c3, c0, 0 ? ? ? ? ? @ domain ID
> + ? ? ? mcr ? ? p15, 0, r5, c2, c0, 0 ? ? ? ? ? @ translation table base addr
> + ? ? ? mcr ? ? p15, 0, r6, c13, c0, 0 ? ? ? ? ?@ PID
> + ? ? ? mov ? ? r0, r7 ? ? ? ? ? ? ? ? ? ? ? ? ?@ control register
> + ? ? ? mov ? ? r2, r5, lsr #14 ? ? ? ? ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
> + ? ? ? ? ? ? ? ? ? ?PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(cpu_sa1100_do_resume)
> +#else
> +#define cpu_sa1100_do_suspend ?0
> +#define cpu_sa1100_do_resume ? 0
> +#endif
> +
> ? ? ? ?__CPUINIT
>
> ? ? ? ?.type ? __sa1100_setup, #function
> @@ -218,6 +254,9 @@ ENTRY(sa1100_processor_functions)
> ? ? ? ?.word ? cpu_sa1100_dcache_clean_area
> ? ? ? ?.word ? cpu_sa1100_switch_mm
> ? ? ? ?.word ? cpu_sa1100_set_pte_ext
> + ? ? ? .word ? cpu_sa1100_suspend_size
> + ? ? ? .word ? cpu_sa1100_do_suspend
> + ? ? ? .word ? cpu_sa1100_do_resume
> ? ? ? ?.size ? sa1100_processor_functions, . - sa1100_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
> index 59a7e1f..c86f451 100644
> --- a/arch/arm/mm/proc-v6.S
> +++ b/arch/arm/mm/proc-v6.S
> @@ -121,6 +121,51 @@ ENTRY(cpu_v6_set_pte_ext)
> ?#endif
> ? ? ? ?mov ? ? pc, lr
>
> +/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
> +.globl cpu_v6_suspend_size
> +.equ ? cpu_v6_suspend_size, 4 * 7
> +#ifdef CONFIG_PM
> +ENTRY(cpu_v6_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r10, 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 base 0
> + ? ? ? mrc ? ? p15, 0, r7, c2, c0, 1 ? @ Translation table base 1
> + ? ? ? mrc ? ? p15, 0, r8, c1, c0, 1 ? @ auxillary control register
> + ? ? ? mrc ? ? p15, 0, r9, c1, c0, 2 ? @ co-processor access control
> + ? ? ? mrc ? ? p15, 0, r10, c1, c0, 0 ?@ control register
> + ? ? ? stmia ? r0, {r4 - r10}
> + ? ? ? ldmfd ? sp!, {r4- r10, pc}
> +ENDPROC(cpu_v6_do_suspend)
> +
> +ENTRY(cpu_v6_do_resume)
> + ? ? ? mov ? ? ip, #0
> + ? ? ? mcr ? ? p15, 0, ip, c7, c14, 0 ?@ clean+invalidate D cache
> + ? ? ? mcr ? ? p15, 0, ip, c7, c5, 0 ? @ invalidate I cache
> + ? ? ? mcr ? ? p15, 0, ip, c7, c15, 0 ?@ clean+invalidate cache
> + ? ? ? mcr ? ? p15, 0, ip, c7, c10, 4 ?@ drain write buffer
> + ? ? ? ldmia ? r0, {r4 - r10}
> + ? ? ? 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 base 0
> + ? ? ? mcr ? ? p15, 0, r7, c2, c0, 1 ? @ Translation table base 1
> + ? ? ? mcr ? ? p15, 0, r8, c1, c0, 1 ? @ auxillary control register
> + ? ? ? mcr ? ? p15, 0, r9, c1, c0, 2 ? @ co-processor access control
> + ? ? ? mcr ? ? p15, 0, ip, c2, c0, 2 ? @ TTB control register
> + ? ? ? mcr ? ? p15, 0, ip, c7, c5, 4 ? @ ISB
> + ? ? ? mov ? ? r0, r10 ? ? ? ? ? ? ? ? @ control register
> + ? ? ? mov ? ? r2, r6, lsr #14 ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, cpu_resume_l1_flags
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(cpu_v6_do_resume)
> +cpu_resume_l1_flags:
> + ? ? ? ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
> + ? ? ? ALT_UP(.long ?PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
> +#else
> +#define cpu_v6_do_suspend 0
> +#define cpu_v6_do_resume 0
> +#endif
>
>
> ? ? ? ?.type ? cpu_v6_name, #object
> @@ -206,6 +251,9 @@ ENTRY(v6_processor_functions)
> ? ? ? ?.word ? cpu_v6_dcache_clean_area
> ? ? ? ?.word ? cpu_v6_switch_mm
> ? ? ? ?.word ? cpu_v6_set_pte_ext
> + ? ? ? .word ? cpu_v6_suspend_size
> + ? ? ? .word ? cpu_v6_do_suspend
> + ? ? ? .word ? cpu_v6_do_resume
> ? ? ? ?.size ? v6_processor_functions, . - v6_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index 0c1172b..8e6142d 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S
> @@ -171,6 +171,85 @@ cpu_v7_name:
> ? ? ? ?.ascii ?"ARMv7 Processor"
> ? ? ? ?.align
>
> + ? ? ? /*
> + ? ? ? ?* Memory region attributes with SCTLR.TRE=1
> + ? ? ? ?*
> + ? ? ? ?* ? n = TEX[0],C,B
> + ? ? ? ?* ? TR = PRRR[2n+1:2n] ? ? ? ? - memory type
> + ? ? ? ?* ? IR = NMRR[2n+1:2n] ? ? ? ? - inner cacheable property
> + ? ? ? ?* ? OR = NMRR[2n+17:2n+16] ? ? - outer cacheable property
> + ? ? ? ?*
> + ? ? ? ?* ? ? ? ? ? ? ? ? ? ? ?n ? ? ? TR ? ? ?IR ? ? ?OR
> + ? ? ? ?* ? UNCACHED ? ? ? ? ? 000 ? ? 00
> + ? ? ? ?* ? BUFFERABLE ? ? ? ? 001 ? ? 10 ? ? ?00 ? ? ?00
> + ? ? ? ?* ? WRITETHROUGH ? ? ? 010 ? ? 10 ? ? ?10 ? ? ?10
> + ? ? ? ?* ? WRITEBACK ? ? ? ? ?011 ? ? 10 ? ? ?11 ? ? ?11
> + ? ? ? ?* ? reserved ? ? ? ? ? 110
> + ? ? ? ?* ? WRITEALLOC ? ? ? ? 111 ? ? 10 ? ? ?01 ? ? ?01
> + ? ? ? ?* ? DEV_SHARED ? ? ? ? 100 ? ? 01
> + ? ? ? ?* ? DEV_NONSHARED ? ? ?100 ? ? 01
> + ? ? ? ?* ? DEV_WC ? ? ? ? ? ? 001 ? ? 10
> + ? ? ? ?* ? DEV_CACHED ? ? ? ? 011 ? ? 10
> + ? ? ? ?*
> + ? ? ? ?* Other attributes:
> + ? ? ? ?*
> + ? ? ? ?* ? DS0 = PRRR[16] = 0 ? ? ? ? - device shareable property
> + ? ? ? ?* ? DS1 = PRRR[17] = 1 ? ? ? ? - device shareable property
> + ? ? ? ?* ? NS0 = PRRR[18] = 0 ? ? ? ? - normal shareable property
> + ? ? ? ?* ? NS1 = PRRR[19] = 1 ? ? ? ? - normal shareable property
> + ? ? ? ?* ? NOS = PRRR[24+n] = 1 ? ? ? - not outer shareable
> + ? ? ? ?*/
> +.equ ? PRRR, ? 0xff0a81a8
> +.equ ? NMRR, ? 0x40e040e0
> +
> +/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
> +.globl cpu_v7_suspend_size
> +.equ ? cpu_v7_suspend_size, 4 * 7
> +#ifdef CONFIG_PM
> +ENTRY(cpu_v7_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r10, 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 ? @ TTB 0
> + ? ? ? mrc ? ? p15, 0, r7, c2, c0, 1 ? @ TTB 1
> + ? ? ? mrc ? ? p15, 0, r8, c1, c0, 0 ? @ Control register
> + ? ? ? mrc ? ? p15, 0, r9, c1, c0, 1 ? @ Auxiliary control register
> + ? ? ? mrc ? ? p15, 0, r10, c1, c0, 2 ?@ Co-processor access control
> + ? ? ? stmia ? r0, {r4 - r10}
> + ? ? ? ldmfd ? sp!, {r4 - r10, pc}
> +ENDPROC(cpu_v7_do_suspend)
> +
> +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 - r10}
> + ? ? ? 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 ? @ TTB 0
> + ? ? ? mcr ? ? p15, 0, r7, c2, c0, 1 ? @ TTB 1
> + ? ? ? mcr ? ? p15, 0, ip, c2, c0, 2 ? @ TTB control register
> + ? ? ? mcr ? ? p15, 0, r9, c1, c0, 1 ? @ Auxillary control register
> + ? ? ? mcr ? ? p15, 0, r10, c1, c0, 2 ?@ Co-processor access control
> + ? ? ? ldr ? ? r4, =PRRR ? ? ? ? ? ? ? @ PRRR
> + ? ? ? ldr ? ? r5, =NMRR ? ? ? ? ? ? ? @ NMRR
> + ? ? ? mcr ? ? p15, 0, r4, c10, c2, 0 ?@ write PRRR
> + ? ? ? mcr ? ? p15, 0, r5, c10, c2, 1 ?@ write NMRR
> + ? ? ? isb
> + ? ? ? mov ? ? r0, r8 ? ? ? ? ? ? ? ? ?@ control register
> + ? ? ? mov ? ? r2, r6, lsr #14 ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, cpu_resume_l1_flags
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(cpu_v7_do_resume)
> +cpu_resume_l1_flags:
> + ? ? ? ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
> + ? ? ? ALT_UP(.long ?PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
> +#else
> +#define cpu_v7_do_suspend ? ? ?0
> +#define cpu_v7_do_resume ? ? ? 0
> +#endif
> +
> ? ? ? ?__CPUINIT
>
> ?/*
> @@ -276,36 +355,8 @@ __v7_setup:
> ? ? ? ?ALT_SMP(orr ? ? r4, r4, #TTB_FLAGS_SMP)
> ? ? ? ?ALT_UP(orr ? ? ?r4, r4, #TTB_FLAGS_UP)
> ? ? ? ?mcr ? ? p15, 0, r4, c2, c0, 1 ? ? ? ? ? @ load TTB1
> - ? ? ? /*
> - ? ? ? ?* Memory region attributes with SCTLR.TRE=1
> - ? ? ? ?*
> - ? ? ? ?* ? n = TEX[0],C,B
> - ? ? ? ?* ? TR = PRRR[2n+1:2n] ? ? ? ? - memory type
> - ? ? ? ?* ? IR = NMRR[2n+1:2n] ? ? ? ? - inner cacheable property
> - ? ? ? ?* ? OR = NMRR[2n+17:2n+16] ? ? - outer cacheable property
> - ? ? ? ?*
> - ? ? ? ?* ? ? ? ? ? ? ? ? ? ? ?n ? ? ? TR ? ? ?IR ? ? ?OR
> - ? ? ? ?* ? UNCACHED ? ? ? ? ? 000 ? ? 00
> - ? ? ? ?* ? BUFFERABLE ? ? ? ? 001 ? ? 10 ? ? ?00 ? ? ?00
> - ? ? ? ?* ? WRITETHROUGH ? ? ? 010 ? ? 10 ? ? ?10 ? ? ?10
> - ? ? ? ?* ? WRITEBACK ? ? ? ? ?011 ? ? 10 ? ? ?11 ? ? ?11
> - ? ? ? ?* ? reserved ? ? ? ? ? 110
> - ? ? ? ?* ? WRITEALLOC ? ? ? ? 111 ? ? 10 ? ? ?01 ? ? ?01
> - ? ? ? ?* ? DEV_SHARED ? ? ? ? 100 ? ? 01
> - ? ? ? ?* ? DEV_NONSHARED ? ? ?100 ? ? 01
> - ? ? ? ?* ? DEV_WC ? ? ? ? ? ? 001 ? ? 10
> - ? ? ? ?* ? DEV_CACHED ? ? ? ? 011 ? ? 10
> - ? ? ? ?*
> - ? ? ? ?* Other attributes:
> - ? ? ? ?*
> - ? ? ? ?* ? DS0 = PRRR[16] = 0 ? ? ? ? - device shareable property
> - ? ? ? ?* ? DS1 = PRRR[17] = 1 ? ? ? ? - device shareable property
> - ? ? ? ?* ? NS0 = PRRR[18] = 0 ? ? ? ? - normal shareable property
> - ? ? ? ?* ? NS1 = PRRR[19] = 1 ? ? ? ? - normal shareable property
> - ? ? ? ?* ? NOS = PRRR[24+n] = 1 ? ? ? - not outer shareable
> - ? ? ? ?*/
> - ? ? ? ldr ? ? r5, =0xff0a81a8 ? ? ? ? ? ? ? ? @ PRRR
> - ? ? ? ldr ? ? r6, =0x40e040e0 ? ? ? ? ? ? ? ? @ NMRR
> + ? ? ? ldr ? ? r5, =PRRR ? ? ? ? ? ? ? ? ? ? ? @ PRRR
> + ? ? ? ldr ? ? r6, =NMRR ? ? ? ? ? ? ? ? ? ? ? @ NMRR
> ? ? ? ?mcr ? ? p15, 0, r5, c10, c2, 0 ? ? ? ? ?@ write PRRR
> ? ? ? ?mcr ? ? p15, 0, r6, c10, c2, 1 ? ? ? ? ?@ write NMRR
> ?#endif
> @@ -351,6 +402,9 @@ ENTRY(v7_processor_functions)
> ? ? ? ?.word ? cpu_v7_dcache_clean_area
> ? ? ? ?.word ? cpu_v7_switch_mm
> ? ? ? ?.word ? cpu_v7_set_pte_ext
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> + ? ? ? .word ? 0
> ? ? ? ?.size ? v7_processor_functions, . - v7_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
> index ec26355..63d8b20 100644
> --- a/arch/arm/mm/proc-xsc3.S
> +++ b/arch/arm/mm/proc-xsc3.S
> @@ -413,9 +413,52 @@ ENTRY(cpu_xsc3_set_pte_ext)
> ? ? ? ?mov ? ? pc, lr
>
> ? ? ? ?.ltorg
> -
> ? ? ? ?.align
>
> +.globl cpu_xsc3_suspend_size
> +.equ ? cpu_xsc3_suspend_size, 4 * 8
> +#ifdef CONFIG_PM
> +ENTRY(cpu_xsc3_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r10, lr}
> + ? ? ? mrc ? ? p14, 0, r4, c6, c0, 0 ? @ clock configuration, for turbo mode
> + ? ? ? mrc ? ? p15, 0, r5, c15, c1, 0 ?@ CP access reg
> + ? ? ? mrc ? ? p15, 0, r6, c13, c0, 0 ?@ PID
> + ? ? ? mrc ? ? p15, 0, r7, c3, c0, 0 ? @ domain ID
> + ? ? ? mrc ? ? p15, 0, r8, c2, c0, 0 ? @ translation table base addr
> + ? ? ? mrc ? ? p15, 0, r9, c1, c0, 1 ? @ auxiliary control reg
> + ? ? ? mrc ? ? p15, 0, r10, c1, c0, 0 ?@ control reg
> + ? ? ? bic ? ? r4, r4, #2 ? ? ? ? ? ? ?@ clear frequency change bit
> + ? ? ? stmia ? r0, {r1, r4 - r10} ? ? ?@ store v:p offset + cp regs
> + ? ? ? ldmia ? sp!, {r4 - r10, pc}
> +ENDPROC(cpu_xsc3_do_suspend)
> +
> +ENTRY(cpu_xsc3_do_resume)
> + ? ? ? ldmia ? r0, {r1, r4 - r10} ? ? ?@ load v:p offset + cp regs
> + ? ? ? mov ? ? ip, #0
> + ? ? ? mcr ? ? p15, 0, ip, c7, c7, 0 ? @ invalidate I & D caches, BTB
> + ? ? ? mcr ? ? p15, 0, ip, c7, c10, 4 ?@ drain write (&fill) buffer
> + ? ? ? mcr ? ? p15, 0, ip, c7, c5, 4 ? @ flush prefetch buffer
> + ? ? ? mcr ? ? p15, 0, ip, c8, c7, 0 ? @ invalidate I & D TLBs
> + ? ? ? mcr ? ? p14, 0, r4, c6, c0, 0 ? @ clock configuration, turbo mode.
> + ? ? ? mcr ? ? p15, 0, r5, c15, c1, 0 ?@ CP access reg
> + ? ? ? mcr ? ? p15, 0, r6, c13, c0, 0 ?@ PID
> + ? ? ? mcr ? ? p15, 0, r7, c3, c0, 0 ? @ domain ID
> + ? ? ? mcr ? ? p15, 0, r8, c2, c0, 0 ? @ translation table base addr
> + ? ? ? mcr ? ? p15, 0, r9, c1, c0, 1 ? @ auxiliary control reg
> +
> + ? ? ? @ temporarily map resume_turn_on_mmu into the page table,
> + ? ? ? @ otherwise prefetch abort occurs after MMU is turned on
> + ? ? ? mov ? ? r0, r10 ? ? ? ? ? ? ? ? @ control register
> + ? ? ? mov ? ? r2, r8, lsr #14 ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, =0x542e ? ? ? ? ? ? @ section flags
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(cpu_xsc3_do_resume)
> +#else
> +#define cpu_xsc3_do_suspend ? ?0
> +#define cpu_xsc3_do_resume ? ? 0
> +#endif
> +
> ? ? ? ?__CPUINIT
>
> ? ? ? ?.type ? __xsc3_setup, #function
> @@ -476,6 +519,9 @@ ENTRY(xsc3_processor_functions)
> ? ? ? ?.word ? cpu_xsc3_dcache_clean_area
> ? ? ? ?.word ? cpu_xsc3_switch_mm
> ? ? ? ?.word ? cpu_xsc3_set_pte_ext
> + ? ? ? .word ? cpu_xsc3_suspend_size
> + ? ? ? .word ? cpu_xsc3_do_suspend
> + ? ? ? .word ? cpu_xsc3_do_resume
> ? ? ? ?.size ? xsc3_processor_functions, . - xsc3_processor_functions
>
> ? ? ? ?.section ".rodata"
> diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
> index 5a37c5e..086038c 100644
> --- a/arch/arm/mm/proc-xscale.S
> +++ b/arch/arm/mm/proc-xscale.S
> @@ -513,11 +513,49 @@ ENTRY(cpu_xscale_set_pte_ext)
> ? ? ? ?xscale_set_pte_ext_epilogue
> ? ? ? ?mov ? ? pc, lr
>
> -
> ? ? ? ?.ltorg
> -
> ? ? ? ?.align
>
> +.globl cpu_xscale_suspend_size
> +.equ ? cpu_xscale_suspend_size, 4 * 7
> +#ifdef CONFIG_PM
> +ENTRY(cpu_xscale_do_suspend)
> + ? ? ? stmfd ? sp!, {r4 - r10, lr}
> + ? ? ? mrc ? ? p14, 0, r4, c6, c0, 0 ? @ clock configuration, for turbo mode
> + ? ? ? mrc ? ? p15, 0, r5, c15, c1, 0 ?@ CP access reg
> + ? ? ? mrc ? ? p15, 0, r6, c13, c0, 0 ?@ PID
> + ? ? ? mrc ? ? p15, 0, r7, c3, c0, 0 ? @ domain ID
> + ? ? ? mrc ? ? p15, 0, r8, c2, c0, 0 ? @ translation table base addr
> + ? ? ? mrc ? ? p15, 0, r9, c1, c1, 0 ? @ auxiliary control reg
> + ? ? ? mrc ? ? p15, 0, r10, c1, c0, 0 ?@ control reg
> + ? ? ? bic ? ? r4, r4, #2 ? ? ? ? ? ? ?@ clear frequency change bit
> + ? ? ? stmia ? r0, {r4 - r10} ? ? ? ? ?@ store cp regs
> + ? ? ? ldmfd ? sp!, {r4 - r10, pc}
> +ENDPROC(cpu_xscale_do_suspend)
> +
> +ENTRY(cpu_xscale_do_resume)
> + ? ? ? ldmia ? r0, {r4 - r10} ? ? ? ? ?@ load cp regs
> + ? ? ? mov ? ? ip, #0
> + ? ? ? mcr ? ? p15, 0, ip, c8, c7, 0 ? @ invalidate I & D TLBs
> + ? ? ? mcr ? ? p15, 0, ip, c7, c7, 0 ? @ invalidate I & D caches, BTB
> + ? ? ? mcr ? ? p14, 0, r4, c6, c0, 0 ? @ clock configuration, turbo mode.
> + ? ? ? mcr ? ? p15, 0, r5, c15, c1, 0 ?@ CP access reg
> + ? ? ? mcr ? ? p15, 0, r6, c13, c0, 0 ?@ PID
> + ? ? ? mcr ? ? p15, 0, r7, c3, c0, 0 ? @ domain ID
> + ? ? ? mcr ? ? p15, 0, r8, c2, c0, 0 ? @ translation table base addr
> + ? ? ? mcr ? ? p15, 0, r9, c1, c1, 0 ? @ auxiliary control reg
> + ? ? ? mov ? ? r0, r10 ? ? ? ? ? ? ? ? @ control register
> + ? ? ? mov ? ? r2, r8, lsr #14 ? ? ? ? @ get TTB0 base
> + ? ? ? mov ? ? r2, r2, lsl #14
> + ? ? ? ldr ? ? r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
> + ? ? ? ? ? ? ? ? ? ?PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
> + ? ? ? b ? ? ? cpu_resume_mmu
> +ENDPROC(cpu_xscale_do_resume)
> +#else
> +#define cpu_xscale_do_suspend ?0
> +#define cpu_xscale_do_resume ? 0
> +#endif
> +
> ? ? ? ?__CPUINIT
>
> ? ? ? ?.type ? __xscale_setup, #function
> @@ -565,6 +603,9 @@ ENTRY(xscale_processor_functions)
> ? ? ? ?.word ? cpu_xscale_dcache_clean_area
> ? ? ? ?.word ? cpu_xscale_switch_mm
> ? ? ? ?.word ? cpu_xscale_set_pte_ext
> + ? ? ? .word ? cpu_xscale_suspend_size
> + ? ? ? .word ? cpu_xscale_do_suspend
> + ? ? ? .word ? cpu_xscale_do_resume
> ? ? ? ?.size ? xscale_processor_functions, . - xscale_processor_functions
>
> ? ? ? ?.section ".rodata"
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 13:21       ` saeed bishara
@ 2011-02-07 13:34         ` Russell King - ARM Linux
  2011-02-07 14:04           ` saeed bishara
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 13:34 UTC (permalink / raw)
  To: linux-arm-kernel

http://en.wikipedia.org/wiki/Posting_style#Trimming_and_reformatting

It's really not nice to page down and down and down to find out the one
or two lines that actually contain something useful - or in my case
scroll through the first three pages, then go to the bottom and start
scrolling up.  It wastes time.

Please *always* trim the quoted text down to the context that's relevant
for your reply, like this:

On Mon, Feb 07, 2011 at 03:21:51PM +0200, saeed bishara wrote:
> On Mon, Feb 7, 2011 at 2:10 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > +ENTRY(cpu_resume_mmu)
> > + ? ? ? adr ? ? r4, cpu_resume_turn_mmu_on
> > + ? ? ? mov ? ? r4, r4, lsr #20
> > + ? ? ? orr ? ? r3, r3, r4, lsl #20
> > + ? ? ? ldr ? ? r5, [r2, r4, lsl #2] ? ?@ save old mapping
> > + ? ? ? str ? ? r3, [r2, r4, lsl #2] ? ?@ setup 1:1 mapping for mmu code
> this code doesn't look smp save, it modifies page table that could be
> used by another cpu. I suggest to create (at  boot time) identity page
> table and use it in order to do mmu on.

When you suspend/resume, the other CPUs will be hot-unplugged before
suspend, and hot-plugged after resume.  SMP issues really don't come
in here, and there's not really many other ways to solve the inherent
races involved with turning on the MMU.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 13:34         ` Russell King - ARM Linux
@ 2011-02-07 14:04           ` saeed bishara
  2011-02-07 14:17             ` Russell King - ARM Linux
  0 siblings, 1 reply; 33+ messages in thread
From: saeed bishara @ 2011-02-07 14:04 UTC (permalink / raw)
  To: linux-arm-kernel

> It's really not nice to page down and down and down to find out the one
> or two lines that actually contain something useful - or in my case
> scroll through the first three pages, then go to the bottom and start
> scrolling up. ?It wastes time.
sorry
>
>> this code doesn't look smp save, it modifies page table that could be
>> used by another cpu. I suggest to create (at ?boot time) identity page
>> table and use it in order to do mmu on.
>
> When you suspend/resume, the other CPUs will be hot-unplugged before
> suspend, and hot-plugged after resume. ?SMP issues really don't come
> in here, and there's not really many other ways to solve the inherent
> races involved with turning on the MMU.
that's right, but in the future this code can be used also for
cpuidle, so please take that into account.
also,  I think cpu_resume_after_mmu  needs to invalidates the TLB
after restoring the old mapping.
one more comment, don't you need to restore the context ID cp15 register?
saeed
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:04           ` saeed bishara
@ 2011-02-07 14:17             ` Russell King - ARM Linux
  2011-02-07 14:27               ` saeed bishara
                                 ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 14:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 04:04:09PM +0200, saeed bishara wrote:
> > It's really not nice to page down and down and down to find out the one
> > or two lines that actually contain something useful - or in my case
> > scroll through the first three pages, then go to the bottom and start
> > scrolling up. ?It wastes time.
> sorry
> >
> >> this code doesn't look smp save, it modifies page table that could be
> >> used by another cpu. I suggest to create (at ?boot time) identity page
> >> table and use it in order to do mmu on.
> >
> > When you suspend/resume, the other CPUs will be hot-unplugged before
> > suspend, and hot-plugged after resume. ?SMP issues really don't come
> > in here, and there's not really many other ways to solve the inherent
> > races involved with turning on the MMU.
> that's right, but in the future this code can be used also for
> cpuidle, so please take that into account.

As I've said, there's not much other choice here.  We _have_ to have an
identity mapping in place to bring the MMU back online, or we'll crash.
That's non-optional.  So if this is a problem for cpuidle, cpuidle needs
to ensure that a page table switch has happened prior to the CPU going
down which _can_ be safely modified.

> also,  I think cpu_resume_after_mmu  needs to invalidates the TLB
> after restoring the old mapping.

Probably - and that's not going to be soo easy to work into this...
I'll see later this afternoon about adding that.

> one more comment, don't you need to restore the context ID cp15 register?

Yes it does, and I wonder why the Samsung folk aren't doing so.  Here's
v4 with that added.

 arch/arm/include/asm/glue-proc.h |    3 +
 arch/arm/include/asm/proc-fns.h  |    7 ++
 arch/arm/kernel/Makefile         |    1 +
 arch/arm/kernel/asm-offsets.c    |    9 +++
 arch/arm/kernel/sleep.S          |  110 ++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-arm1020.S       |    3 +
 arch/arm/mm/proc-arm1020e.S      |    3 +
 arch/arm/mm/proc-arm1022.S       |    3 +
 arch/arm/mm/proc-arm1026.S       |    3 +
 arch/arm/mm/proc-arm6_7.S        |    6 ++
 arch/arm/mm/proc-arm720.S        |    3 +
 arch/arm/mm/proc-arm740.S        |    3 +
 arch/arm/mm/proc-arm7tdmi.S      |    3 +
 arch/arm/mm/proc-arm920.S        |   37 ++++++++++++
 arch/arm/mm/proc-arm922.S        |    3 +
 arch/arm/mm/proc-arm925.S        |    3 +
 arch/arm/mm/proc-arm926.S        |   37 ++++++++++++
 arch/arm/mm/proc-arm940.S        |    3 +
 arch/arm/mm/proc-arm946.S        |    3 +
 arch/arm/mm/proc-arm9tdmi.S      |    3 +
 arch/arm/mm/proc-fa526.S         |    3 +
 arch/arm/mm/proc-feroceon.S      |    3 +
 arch/arm/mm/proc-mohawk.S        |    3 +
 arch/arm/mm/proc-sa110.S         |    3 +
 arch/arm/mm/proc-sa1100.S        |   39 +++++++++++++
 arch/arm/mm/proc-v6.S            |   50 ++++++++++++++++
 arch/arm/mm/proc-v7.S            |  116 ++++++++++++++++++++++++++++----------
 arch/arm/mm/proc-xsc3.S          |   48 +++++++++++++++-
 arch/arm/mm/proc-xscale.S        |   45 ++++++++++++++-
 29 files changed, 523 insertions(+), 33 deletions(-)

diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e3bf443..6469521 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -256,6 +256,9 @@
 #define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
 #define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
 #define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
+#define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
+#define cpu_do_resume			__glue(CPU_NAME,_do_resume)
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 6980215..8ec535e 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -66,6 +66,11 @@ extern struct processor {
 	 * ignore 'ext'.
 	 */
 	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
+
+	/* Suspend/resume */
+	unsigned int suspend_size;
+	void (*do_suspend)(void *);
+	void (*do_resume)(void *);
 } processor;
 
 #ifndef MULTI_CPU
@@ -86,6 +91,8 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
+extern void cpu_resume(void);
+
 #include <asm/memory.h>
 
 #ifdef CONFIG_MMU
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 185ee82..74554f1 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
+obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 5302a91..927522c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
@@ -116,6 +117,14 @@ int main(void)
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
 #endif
+#ifdef MULTI_CPU
+  DEFINE(CPU_SLEEP_SIZE,	offsetof(struct processor, suspend_size));
+  DEFINE(CPU_DO_SUSPEND,	offsetof(struct processor, do_suspend));
+  DEFINE(CPU_DO_RESUME,		offsetof(struct processor, do_resume));
+#endif
+#ifdef MULTI_CACHE
+  DEFINE(CACHE_FLUSH_KERN_ALL,	offsetof(struct cpu_cache_fns, flush_kern_all));
+#endif
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
new file mode 100644
index 0000000..9f106fa
--- /dev/null
+++ b/arch/arm/kernel/sleep.S
@@ -0,0 +1,110 @@
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/glue-cache.h>
+#include <asm/glue-proc.h>
+	.text
+
+/*
+ * Save CPU state for a suspend
+ *  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
+ */
+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, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+	str	r2, [r3]		@ save phys SP
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
+#else
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, =cpu_suspend_size
+	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
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+	str	r2, [r3]		@ save phys SP
+	bl	cpu_do_suspend
+#endif
+
+	@ flush data cache
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	mov	lr, r9
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	mov	lr, r9
+	b	__cpuc_flush_kern_all
+#endif
+ENDPROC(cpu_suspend)
+	.ltorg
+
+/*
+ * r0 = control register value
+ * r1 = v:p offset (preserved by cpu_do_resume)
+ * r2 = phys page table base
+ * r3 = L1 section flags
+ */
+ENTRY(cpu_resume_mmu)
+	adr	r4, cpu_resume_turn_mmu_on
+	mov	r4, r4, lsr #20
+	orr	r3, r3, r4, lsl #20
+	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
+	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
+	sub	r2, r2, r1
+	ldr	r3, =cpu_resume_after_mmu
+	b	cpu_resume_turn_mmu_on
+ENDPROC(cpu_resume_mmu)
+	.ltorg
+	.align	5
+cpu_resume_turn_mmu_on:
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, caches, etc
+	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
+	mov	r0, r0
+	mov	r0, r0
+	mov	pc, r3			@ jump to virtual address
+ENDPROC(cpu_resume_turn_mmu_on)
+cpu_resume_after_mmu:
+	str	r5, [r2, r4, lsl #2]	@ restore old mapping
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	b	__cpuc_flush_kern_all
+#endif
+
+/*
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+	.data
+	.align
+ENTRY(cpu_resume)
+	ldr	r0, sleep_save_sp	@ stack phys addr
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
+#ifdef MULTI_CPU
+	ldmia	r0!, {r1, sp, lr, pc}	@ load v:p, stack, return fn, resume fn
+#else
+	ldmia	r0!, {r1, sp, lr}	@ load v:p, stack, return fn
+	b	cpu_do_resume
+#endif
+ENDPROC(cpu_resume)
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index bcf748d..226e3d8 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -493,6 +493,9 @@ arm1020_processor_functions:
 	.word	cpu_arm1020_dcache_clean_area
 	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index ab7ec26..86d9c2c 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -474,6 +474,9 @@ arm1020e_processor_functions:
 	.word	cpu_arm1020e_dcache_clean_area
 	.word	cpu_arm1020e_switch_mm
 	.word	cpu_arm1020e_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 831c5e5..83d3dd3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -457,6 +457,9 @@ arm1022_processor_functions:
 	.word	cpu_arm1022_dcache_clean_area
 	.word	cpu_arm1022_switch_mm
 	.word	cpu_arm1022_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1022_processor_functions, . - arm1022_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index e3f7e9a..686043e 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -452,6 +452,9 @@ arm1026_processor_functions:
 	.word	cpu_arm1026_dcache_clean_area
 	.word	cpu_arm1026_switch_mm
 	.word	cpu_arm1026_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1026_processor_functions, . - arm1026_processor_functions
 
 	.section .rodata
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 6a7be18..5f79dc4 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions)
 		.word	cpu_arm6_dcache_clean_area
 		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions)
 		.word	cpu_arm7_dcache_clean_area
 		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index c285395..665266d 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions)
 		.word	cpu_arm720_dcache_clean_area
 		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 38b27dc..6f9d12e 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions)
 	.word	cpu_arm740_dcache_clean_area
 	.word	cpu_arm740_switch_mm
 	.word	0			@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm740_processor_functions, . - arm740_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 0c9786d..e4c165c 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions)
 		.word	cpu_arm7tdmi_dcache_clean_area
 		.word	cpu_arm7tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 6109f27..b2705de 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -387,6 +387,40 @@ ENTRY(cpu_arm920_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm920_suspend_size
+.equ	arm920_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm920_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm920_do_suspend)
+
+ENTRY(arm920_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(arm920_do_resume)
+#else
+#define arm920_do_suspend	0
+#define arm920_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm920_setup, #function
@@ -432,6 +466,9 @@ arm920_processor_functions:
 	.word	cpu_arm920_dcache_clean_area
 	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte_ext
+	.word	arm920_suspend_size
+	.word	arm920_do_suspend
+	.word	arm920_do_resume
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index bb2f0f4..36154b1 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -436,6 +436,9 @@ arm922_processor_functions:
 	.word	cpu_arm922_dcache_clean_area
 	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index c13e01a..89c5e00 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -503,6 +503,9 @@ arm925_processor_functions:
 	.word	cpu_arm925_dcache_clean_area
 	.word	cpu_arm925_switch_mm
 	.word	cpu_arm925_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm925_processor_functions, . - arm925_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 42eb431..3beb784 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -401,6 +401,40 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	arm926_suspend_size
+.equ	arm926_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(arm926_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(arm926_do_suspend)
+
+ENTRY(arm926_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(arm926_do_resume)
+#else
+#define arm926_do_suspend	0
+#define arm926_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm926_setup, #function
@@ -456,6 +490,9 @@ arm926_processor_functions:
 	.word	cpu_arm926_dcache_clean_area
 	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte_ext
+	.word	arm926_suspend_size
+	.word	arm926_do_suspend
+	.word	arm926_do_resume
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 7b11cdb..26aea3f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions)
 	.word	cpu_arm940_dcache_clean_area
 	.word	cpu_arm940_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm940_processor_functions, . - arm940_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 1a5bbf0..8063345 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions)
 	.word	cpu_arm946_dcache_clean_area
 	.word	cpu_arm946_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm946_processor_functions, . - arm946_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db67e31..7b7ebd4 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions)
 		.word	cpu_arm9tdmi_dcache_clean_area
 		.word	cpu_arm9tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7c9ad62..fc2a4ae 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -195,6 +195,9 @@ fa526_processor_functions:
 	.word	cpu_fa526_dcache_clean_area
 	.word	cpu_fa526_switch_mm
 	.word	cpu_fa526_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	fa526_processor_functions, . - fa526_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b4597ed..d3883ee 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -554,6 +554,9 @@ feroceon_processor_functions:
 	.word	cpu_feroceon_dcache_clean_area
 	.word	cpu_feroceon_switch_mm
 	.word	cpu_feroceon_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	feroceon_processor_functions, . - feroceon_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 4458ee6..9d4f2ae 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -388,6 +388,9 @@ mohawk_processor_functions:
 	.word	cpu_mohawk_dcache_clean_area
 	.word	cpu_mohawk_switch_mm
 	.word	cpu_mohawk_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	mohawk_processor_functions, . - mohawk_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 5aa8d59..46f09ed 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions)
 	.word	cpu_sa110_dcache_clean_area
 	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 2ac4e6f..74483d1 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,6 +169,42 @@ ENTRY(cpu_sa1100_set_pte_ext)
 #endif
 	mov	pc, lr
 
+.globl	cpu_sa1100_suspend_size
+.equ	cpu_sa1100_suspend_size, 4*4
+#ifdef CONFIG_PM
+ENTRY(cpu_sa1100_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
+	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r6, c13, c0, 0		@ PID
+	mrc	p15, 0, r7, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r7}			@ store cp regs
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_sa1100_do_suspend)
+
+ENTRY(cpu_sa1100_do_resume)
+	ldmia	r0, {r4 - r7}			@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@ flush I+D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
+	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
+
+	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
+	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r6, c13, c0, 0		@ PID
+	mov	r0, r7				@ control register
+	mov	r2, r5, lsr #14			@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_sa1100_do_resume)
+#else
+#define cpu_sa1100_do_suspend	0
+#define cpu_sa1100_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__sa1100_setup, #function
@@ -218,6 +254,9 @@ ENTRY(sa1100_processor_functions)
 	.word	cpu_sa1100_dcache_clean_area
 	.word	cpu_sa1100_switch_mm
 	.word	cpu_sa1100_set_pte_ext
+	.word	cpu_sa1100_suspend_size
+	.word	cpu_sa1100_do_suspend
+	.word	cpu_sa1100_do_resume
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 59a7e1f..832b6bd 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -121,6 +121,53 @@ ENTRY(cpu_v6_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
+.globl	cpu_v6_suspend_size
+.equ	cpu_v6_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_v6_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, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ Translation table base 0
+	mrc	p15, 0, r8, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r9, c1, c0, 1	@ auxillary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r11, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r11}
+	ldmfd	sp!, {r4- r11, pc}
+ENDPROC(cpu_v6_do_suspend)
+
+ENTRY(cpu_v6_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
+	ldmia	r0, {r4 - r11}
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0	@ Translation table base 0
+	mcr	p15, 0, r8, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r9, c1, c0, 1	@ auxillary control register
+	mcr	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, ip, c7, c5, 4	@ ISB
+	mov	r0, r11			@ control register
+	mov	r2, r7, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v6_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v6_do_suspend 0
+#define cpu_v6_do_resume 0
+#endif
 
 
 	.type	cpu_v6_name, #object
@@ -206,6 +253,9 @@ ENTRY(v6_processor_functions)
 	.word	cpu_v6_dcache_clean_area
 	.word	cpu_v6_switch_mm
 	.word	cpu_v6_set_pte_ext
+	.word	cpu_v6_suspend_size
+	.word	cpu_v6_do_suspend
+	.word	cpu_v6_do_resume
 	.size	v6_processor_functions, . - v6_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 0c1172b..a5187dd 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -171,6 +171,87 @@ cpu_v7_name:
 	.ascii	"ARMv7 Processor"
 	.align
 
+	/*
+	 * Memory region attributes with SCTLR.TRE=1
+	 *
+	 *   n = TEX[0],C,B
+	 *   TR = PRRR[2n+1:2n]		- memory type
+	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
+	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
+	 *
+	 *			n	TR	IR	OR
+	 *   UNCACHED		000	00
+	 *   BUFFERABLE		001	10	00	00
+	 *   WRITETHROUGH	010	10	10	10
+	 *   WRITEBACK		011	10	11	11
+	 *   reserved		110
+	 *   WRITEALLOC		111	10	01	01
+	 *   DEV_SHARED		100	01
+	 *   DEV_NONSHARED	100	01
+	 *   DEV_WC		001	10
+	 *   DEV_CACHED		011	10
+	 *
+	 * Other attributes:
+	 *
+	 *   DS0 = PRRR[16] = 0		- device shareable property
+	 *   DS1 = PRRR[17] = 1		- device shareable property
+	 *   NS0 = PRRR[18] = 0		- normal shareable property
+	 *   NS1 = PRRR[19] = 1		- normal shareable property
+	 *   NOS = PRRR[24+n] = 1	- not outer shareable
+	 */
+.equ	PRRR,	0xff0a81a8
+.equ	NMRR,	0x40e040e0
+
+/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
+.globl	cpu_v7_suspend_size
+.equ	cpu_v7_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+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, 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}
+	ldmfd	sp!, {r4 - r11, pc}
+ENDPROC(cpu_v7_do_suspend)
+
+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}
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	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
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, r10, c1, c0, 1	@ Auxillary control register
+	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	ldr	r4, =PRRR		@ PRRR
+	ldr	r5, =NMRR		@ NMRR
+	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
+	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
+	isb
+	mov	r0, r9			@ control register
+	mov	r2, r7, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v7_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v7_do_suspend	0
+#define cpu_v7_do_resume	0
+#endif
+
 	__CPUINIT
 
 /*
@@ -276,36 +357,8 @@ __v7_setup:
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	/*
-	 * Memory region attributes with SCTLR.TRE=1
-	 *
-	 *   n = TEX[0],C,B
-	 *   TR = PRRR[2n+1:2n]		- memory type
-	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
-	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
-	 *
-	 *			n	TR	IR	OR
-	 *   UNCACHED		000	00
-	 *   BUFFERABLE		001	10	00	00
-	 *   WRITETHROUGH	010	10	10	10
-	 *   WRITEBACK		011	10	11	11
-	 *   reserved		110
-	 *   WRITEALLOC		111	10	01	01
-	 *   DEV_SHARED		100	01
-	 *   DEV_NONSHARED	100	01
-	 *   DEV_WC		001	10
-	 *   DEV_CACHED		011	10
-	 *
-	 * Other attributes:
-	 *
-	 *   DS0 = PRRR[16] = 0		- device shareable property
-	 *   DS1 = PRRR[17] = 1		- device shareable property
-	 *   NS0 = PRRR[18] = 0		- normal shareable property
-	 *   NS1 = PRRR[19] = 1		- normal shareable property
-	 *   NOS = PRRR[24+n] = 1	- not outer shareable
-	 */
-	ldr	r5, =0xff0a81a8			@ PRRR
-	ldr	r6, =0x40e040e0			@ NMRR
+	ldr	r5, =PRRR			@ PRRR
+	ldr	r6, =NMRR			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
@@ -351,6 +404,9 @@ ENTRY(v7_processor_functions)
 	.word	cpu_v7_dcache_clean_area
 	.word	cpu_v7_switch_mm
 	.word	cpu_v7_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	v7_processor_functions, . - v7_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index ec26355..63d8b20 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -413,9 +413,52 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	mov	pc, lr
 
 	.ltorg
-
 	.align
 
+.globl	cpu_xsc3_suspend_size
+.equ	cpu_xsc3_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_xsc3_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r1, r4 - r10}	@ store v:p offset + cp regs
+	ldmia	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xsc3_do_suspend)
+
+ENTRY(cpu_xsc3_do_resume)
+	ldmia	r0, {r1, r4 - r10}	@ load v:p offset + cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, ip, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =0x542e		@ section flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_xsc3_do_resume)
+#else
+#define cpu_xsc3_do_suspend	0
+#define cpu_xsc3_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xsc3_setup, #function
@@ -476,6 +519,9 @@ ENTRY(xsc3_processor_functions)
 	.word	cpu_xsc3_dcache_clean_area
 	.word	cpu_xsc3_switch_mm
 	.word	cpu_xsc3_set_pte_ext
+	.word	cpu_xsc3_suspend_size
+	.word	cpu_xsc3_do_suspend
+	.word	cpu_xsc3_do_resume
 	.size	xsc3_processor_functions, . - xsc3_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 5a37c5e..086038c 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -513,11 +513,49 @@ ENTRY(cpu_xscale_set_pte_ext)
 	xscale_set_pte_ext_epilogue
 	mov	pc, lr
 
-
 	.ltorg
-
 	.align
 
+.globl	cpu_xscale_suspend_size
+.equ	cpu_xscale_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_xscale_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xscale_do_suspend)
+
+ENTRY(cpu_xscale_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_xscale_do_resume)
+#else
+#define cpu_xscale_do_suspend	0
+#define cpu_xscale_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xscale_setup, #function
@@ -565,6 +603,9 @@ ENTRY(xscale_processor_functions)
 	.word	cpu_xscale_dcache_clean_area
 	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte_ext
+	.word	cpu_xscale_suspend_size
+	.word	cpu_xscale_do_suspend
+	.word	cpu_xscale_do_resume
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
 	.section ".rodata"

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:17             ` Russell King - ARM Linux
@ 2011-02-07 14:27               ` saeed bishara
  2011-02-07 14:33                 ` Russell King - ARM Linux
  2011-02-08  8:08               ` Colin Cross
  2011-02-10  3:15               ` Colin Cross
  2 siblings, 1 reply; 33+ messages in thread
From: saeed bishara @ 2011-02-07 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

> As I've said, there's not much other choice here. ?We _have_ to have an
> identity mapping in place to bring the MMU back online, or we'll crash.
> That's non-optional. ?So if this is a problem for cpuidle, cpuidle needs
> to ensure that a page table switch has happened prior to the CPU going
> down which _can_ be safely modified.
I fully agree with you, but what I was suggesting is to create
temporary identity page table at boot time, the resume code will load
that page table (Context ID will be loaded with unique ASID), enable
mmu, then the original page table and Context ID will be restored.

saeed

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:27               ` saeed bishara
@ 2011-02-07 14:33                 ` Russell King - ARM Linux
  2011-02-07 14:58                   ` saeed bishara
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 14:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 04:27:34PM +0200, saeed bishara wrote:
> > As I've said, there's not much other choice here. ?We _have_ to have an
> > identity mapping in place to bring the MMU back online, or we'll crash.
> > That's non-optional. ?So if this is a problem for cpuidle, cpuidle needs
> > to ensure that a page table switch has happened prior to the CPU going
> > down which _can_ be safely modified.
> I fully agree with you, but what I was suggesting is to create
> temporary identity page table at boot time, the resume code will load
> that page table (Context ID will be loaded with unique ASID), enable
> mmu, then the original page table and Context ID will be restored.

That's much easier to do in C code than in the assembly code.  Let's
keep the assembly code as simple as possible...

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:33                 ` Russell King - ARM Linux
@ 2011-02-07 14:58                   ` saeed bishara
  2011-02-07 15:02                     ` Russell King - ARM Linux
  0 siblings, 1 reply; 33+ messages in thread
From: saeed bishara @ 2011-02-07 14:58 UTC (permalink / raw)
  To: linux-arm-kernel

>> I fully agree with you, but what I was suggesting is to create
>> temporary identity page table at boot time, the resume code will load
>> that page table (Context ID will be loaded with unique ASID), enable
>> mmu, then the original page table and Context ID will be restored.
>
> That's much easier to do in C code than in the assembly code. ?Let's
> keep the assembly code as simple as possible...
well, the allocation of the identity page table doesn't need to be
done in assembly code. this is the similar to what you did in
__cpu_up.
for example, this allocation can be done in arch/arm/kernel/setup.c.
the assembly code only need to know the offset of this page table.
looks that there are several usages for the identity page table (smp
boot, kexec, pm), maybe all those clients can share the same one.

you may also consider loading this identity page table before calling
suspend flow, thus saving all the v:p stuff, and the resume code will
take care for restoring the original page table after enabling the
mmu.
saeed

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:58                   ` saeed bishara
@ 2011-02-07 15:02                     ` Russell King - ARM Linux
  2011-02-08 10:21                       ` Lorenzo Pieralisi
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 15:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 04:58:05PM +0200, saeed bishara wrote:
> well, the allocation of the identity page table doesn't need to be
> done in assembly code. this is the similar to what you did in
> __cpu_up.
> for example, this allocation can be done in arch/arm/kernel/setup.c.
> the assembly code only need to know the offset of this page table.
> looks that there are several usages for the identity page table (smp
> boot, kexec, pm), maybe all those clients can share the same one.

We don't want to allocate this at boot time, because it will require
additional maintainence when L1 page tables are added for ioremap() etc.

I feel that it's best to leave it as-is, as this is the method everyone
has been using to date.  When it becomes a problem, we can then look at
resolving it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 4/5] ARM: pm: convert sa11x0 to generic suspend/resume support
  2011-02-06 19:13 ` [PATCH 4/5] ARM: pm: convert sa11x0 " Russell King - ARM Linux
@ 2011-02-07 18:11   ` Russell King - ARM Linux
  0 siblings, 0 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 18:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 06, 2011 at 07:13:25PM +0000, Russell King - ARM Linux wrote:
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Now tested this on Assabet, and it works fine there.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:17             ` Russell King - ARM Linux
  2011-02-07 14:27               ` saeed bishara
@ 2011-02-08  8:08               ` Colin Cross
  2011-02-10  3:15               ` Colin Cross
  2 siblings, 0 replies; 33+ messages in thread
From: Colin Cross @ 2011-02-08  8:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 7, 2011 at 8:17 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

<snip>

> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> new file mode 100644
> index 0000000..9f106fa
> --- /dev/null
> +++ b/arch/arm/kernel/sleep.S
> @@ -0,0 +1,110 @@
> +#include <linux/linkage.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/assembler.h>
> +#include <asm/glue-cache.h>
> +#include <asm/glue-proc.h>
> + ? ? ? .text
> +
> +/*
> + * Save CPU state for a suspend
> + * ?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
> + */
> +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, r3, ip} ? @ save v:p, virt SP, retfn, phys resume fn
> + ? ? ? ldr ? ? r3, =sleep_save_sp
The global variable will prevent using this function to save the state
of multiple CPUs during idle.

<snip>

> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index 0c1172b..a5187dd 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S

<snip>

> +/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
> +.globl cpu_v7_suspend_size
> +.equ ? cpu_v7_suspend_size, 4 * 8
> +#ifdef CONFIG_PM
> +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, 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}
> + ? ? ? ldmfd ? sp!, {r4 - r11, pc}
> +ENDPROC(cpu_v7_do_suspend)

Should the FIQ banked registers be saved in here, or by the driver
that set them?

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 15:02                     ` Russell King - ARM Linux
@ 2011-02-08 10:21                       ` Lorenzo Pieralisi
  2011-02-08 11:23                         ` Russell King - ARM Linux
  0 siblings, 1 reply; 33+ messages in thread
From: Lorenzo Pieralisi @ 2011-02-08 10:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

On Mon, 2011-02-07 at 15:02 +0000, Russell King - ARM Linux wrote:
> On Mon, Feb 07, 2011 at 04:58:05PM +0200, saeed bishara wrote:
> > well, the allocation of the identity page table doesn't need to be
> > done in assembly code. this is the similar to what you did in
> > __cpu_up.
> > for example, this allocation can be done in arch/arm/kernel/setup.c.
> > the assembly code only need to know the offset of this page table.
> > looks that there are several usages for the identity page table (smp
> > boot, kexec, pm), maybe all those clients can share the same one.
> 
> We don't want to allocate this at boot time, because it will require
> additional maintainence when L1 page tables are added for ioremap() etc.
> 
> I feel that it's best to leave it as-is, as this is the method everyone
> has been using to date.  When it becomes a problem, we can then look at
> resolving it.
> 

For v7 MP cpuidle it is already critical, we do need to have a page
table copy for the resume path to be MP safe. The same goes for the
stack pointer global variable which should be per cpu.
Maybe we can just provide an API to pass the page table pointer, then
see how to allocate it and when.
In which branch do these patches live in order to test them and 
provide feedback ?

Many thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-08 10:21                       ` Lorenzo Pieralisi
@ 2011-02-08 11:23                         ` Russell King - ARM Linux
  2011-02-08 12:33                           ` Russell King - ARM Linux
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-08 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 08, 2011 at 10:21:52AM +0000, Lorenzo Pieralisi wrote:
> Hi Russell,
> 
> On Mon, 2011-02-07 at 15:02 +0000, Russell King - ARM Linux wrote:
> > On Mon, Feb 07, 2011 at 04:58:05PM +0200, saeed bishara wrote:
> > > well, the allocation of the identity page table doesn't need to be
> > > done in assembly code. this is the similar to what you did in
> > > __cpu_up.
> > > for example, this allocation can be done in arch/arm/kernel/setup.c.
> > > the assembly code only need to know the offset of this page table.
> > > looks that there are several usages for the identity page table (smp
> > > boot, kexec, pm), maybe all those clients can share the same one.
> > 
> > We don't want to allocate this at boot time, because it will require
> > additional maintainence when L1 page tables are added for ioremap() etc.
> > 
> > I feel that it's best to leave it as-is, as this is the method everyone
> > has been using to date.  When it becomes a problem, we can then look at
> > resolving it.
> > 
> 
> For v7 MP cpuidle it is already critical, we do need to have a page
> table copy for the resume path to be MP safe.
> Maybe we can just provide an API to pass the page table pointer, then
> see how to allocate it and when.

As I already said - allocate a page table before hand and switch to it,
free it afterwards.  This code does not need to have the complexities
of page table allocation mixed into it.

> The same goes for the stack pointer global variable which should be
> per cpu.

Yes, but this is what is currently done, so at the present time I'm
just sorting out what's already in the kernel.  If we need further
changes, then that needs to be built on top of this.

> In which branch do these patches live in order to test them and 
> provide feedback ?

They're not published yet as I'm waiting for feedback on them, etc.
They're still receiving the odd tweak as comments are received.

Let's get this so that the current suspend/resume code can use it, and
has been tested with it, and then think about adding other uses to it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-08 11:23                         ` Russell King - ARM Linux
@ 2011-02-08 12:33                           ` Russell King - ARM Linux
  2011-02-08 14:25                             ` Lorenzo Pieralisi
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-08 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 08, 2011 at 11:23:23AM +0000, Russell King - ARM Linux wrote:
> > The same goes for the stack pointer global variable which should be
> > per cpu.
> 
> Yes, but this is what is currently done, so at the present time I'm
> just sorting out what's already in the kernel.  If we need further
> changes, then that needs to be built on top of this.

Like this:

 arch/arm/kernel/sleep.S |   26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 9f106fa..e10618f 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -25,7 +25,14 @@ ENTRY(cpu_suspend)
 	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
+	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
@@ -36,7 +43,14 @@ ENTRY(cpu_suspend)
 	stmfd	sp!, {r1, r2, r3}	@ save v:p, virt SP, return 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
 	bl	cpu_do_suspend
 #endif
 
@@ -96,7 +110,15 @@ cpu_resume_after_mmu:
 	.data
 	.align
 ENTRY(cpu_resume)
+#ifdef CONFIG_SMP
+	adr	r0, sleep_save_sp
+	ALT_SMP(mrc p15, 0, r1, c0, c0, 5)
+	ALT_UP(mov r1, #0)
+	and	r1, r1, #15
+	ldr	r0, [r0, r1, lsl #2]	@ stack phys addr
+#else
 	ldr	r0, sleep_save_sp	@ stack phys addr
+#endif
 	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
 #ifdef MULTI_CPU
 	ldmia	r0!, {r1, sp, lr, pc}	@ load v:p, stack, return fn, resume fn
@@ -107,4 +129,6 @@ ENTRY(cpu_resume)
 ENDPROC(cpu_resume)
 
 sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
+	.rept	CONFIG_NR_CPUS
+	.long	0				@ preserve stack phys ptr here
+	.endr

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-08 12:33                           ` Russell King - ARM Linux
@ 2011-02-08 14:25                             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 33+ messages in thread
From: Lorenzo Pieralisi @ 2011-02-08 14:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2011-02-08 at 12:33 +0000, Russell King - ARM Linux wrote:

<snip>

> > Yes, but this is what is currently done, so at the present time I'm
> > just sorting out what's already in the kernel.  If we need further
> > changes, then that needs to be built on top of this.
> 
> Like this:
> 
>  arch/arm/kernel/sleep.S |   26 +++++++++++++++++++++++++-
>  1 files changed, 25 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> index 9f106fa..e10618f 100644
> --- a/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -25,7 +25,14 @@ ENTRY(cpu_suspend)
>  	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
> +	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

<snip>
	
>  sleep_save_sp:
> -	.word	0				@ preserve stack phys ptr here
> +	.rept	CONFIG_NR_CPUS
> +	.long	0				@ preserve stack phys ptr here
> +	.endr
> 

Yes Russell, thanks that's what we are currently doing for MP, it looks 
ok. As for the page tables, I know you already replied and I took your
point. It is on the cpuidle path so page tables should be created in C,
beforehand as you pointed out (with the 1:1 map required), once for all.
I just wanted to say, maybe we can save the pgd pointer (with the
required 1:1 for MMU on) in a pc-relative addressable location that you
can retrieve on resume, eliminating the code changing the original page
table and replacing it with pgd switching.
But again it is just a suggestion, I understand your point, no need to
comment further.

Many thanks,
Lorenzo

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-07 14:17             ` Russell King - ARM Linux
  2011-02-07 14:27               ` saeed bishara
  2011-02-08  8:08               ` Colin Cross
@ 2011-02-10  3:15               ` Colin Cross
  2011-02-11 11:58                 ` Russell King - ARM Linux
  2 siblings, 1 reply; 33+ messages in thread
From: Colin Cross @ 2011-02-10  3:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 7, 2011 at 6:17 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index 0c1172b..a5187dd 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S
> +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, 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

The diagnostic register also needs to be saved to keep the errata bits
set in __v7_setup.

> + ? ? ? stmia ? r0, {r4 - r11}
> + ? ? ? ldmfd ? sp!, {r4 - r11, pc}
> +ENDPROC(cpu_v7_do_suspend)
> +
> +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

Does this need the same ALT_SMP/ALT_UP combo as v7_flush_icache_all?

<snip>

Tegra2 suspend and cpuidle works on top of this patch and the patch
that adds SMP support to sleep_save_sp.  Tegra seems to need to
invalidate the entire l1 data cache before enabling it, so I'm using a
custom reset vector that branches to cpu_resume, and I'm handling the
TLB invalidate in the function cpu_resume returns to.

Tested-by: Colin Cross <ccross@android.com>

Are you targeting 2.6.39 with these patches?  They replace a few
hundred lines of code in the Tegra2 suspend, hotplug, and idle
patches, so I'd like to wait until this is in before pushing mine.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-10  3:15               ` Colin Cross
@ 2011-02-11 11:58                 ` Russell King - ARM Linux
  2011-02-11 12:07                   ` Santosh Shilimkar
  2011-02-14  0:27                   ` Kukjin Kim
  0 siblings, 2 replies; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-11 11:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 09, 2011 at 07:15:25PM -0800, Colin Cross wrote:
> The diagnostic register also needs to be saved to keep the errata bits
> set in __v7_setup.

Saving I've no problem with.  Restoring gets hairy with kernels running
in non-secure mode, as we can't just write the register - we don't know
whether we are running in secure or non-secure mode.  A write to the
register in NS mode will crash.

Santosh: is the diagnostic register on OMAP4 re-initialized by the secure
code on OMAP?

> > + ? ? ? stmia ? r0, {r4 - r11}
> > + ? ? ? ldmfd ? sp!, {r4 - r11, pc}
> > +ENDPROC(cpu_v7_do_suspend)
> > +
> > +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
> 
> Does this need the same ALT_SMP/ALT_UP combo as v7_flush_icache_all?

That depends whether you the CPU which is resuming is part of a coherent
SMP system at that point.  This instruction will invalidate the I-cache
for the local CPU only, whereas the c7, c1 variant will invalidate the
instruction caches of all CPUs within the inner sharable domain.

Has anything changed in the other CPUs as a result of this CPU resuming
at this point?  I don't think so, so I think we just need to ensure that
the local CPU instruction cache is invalidated at this point.

> Tegra2 suspend and cpuidle works on top of this patch and the patch
> that adds SMP support to sleep_save_sp.  Tegra seems to need to
> invalidate the entire l1 data cache before enabling it,

As it's undefined what state the data cache is in on resume, I'm surprised
the s5pv210 code doesn't also need a D-cache invalidate too.  Maybe Samsung
folk can answer that.

> so I'm using a
> custom reset vector that branches to cpu_resume, and I'm handling the
> TLB invalidate in the function cpu_resume returns to.
> 
> Tested-by: Colin Cross <ccross@android.com>
> 
> Are you targeting 2.6.39 with these patches?  They replace a few
> hundred lines of code in the Tegra2 suspend, hotplug, and idle
> patches, so I'd like to wait until this is in before pushing mine.

Undecided at the moment.  It's great that you've tested it, and I've
also tested it on Assabet, but PXA and Samsung stuff hasn't been
tested yet.  I guess I could just push the generic and sa1100 bits for
2.6.39, unless the remainder gets tested.

Once the above issues have answers, I'll see about posting a new set of
patches.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-11 11:58                 ` Russell King - ARM Linux
@ 2011-02-11 12:07                   ` Santosh Shilimkar
  2011-02-12 14:50                     ` Russell King - ARM Linux
  2011-02-14  0:27                   ` Kukjin Kim
  1 sibling, 1 reply; 33+ messages in thread
From: Santosh Shilimkar @ 2011-02-11 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-
> arm-kernel-bounces at lists.infradead.org] On Behalf Of Russell King -
> ARM Linux
> Sent: Friday, February 11, 2011 5:29 PM
> To: Colin Cross; Santosh Shilimkar; Kukjin Kim
> Cc: saeed bishara; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume
> support
>
> On Wed, Feb 09, 2011 at 07:15:25PM -0800, Colin Cross wrote:
> > The diagnostic register also needs to be saved to keep the errata
> bits
> > set in __v7_setup.
>
> Saving I've no problem with.  Restoring gets hairy with kernels
> running
> in non-secure mode, as we can't just write the register - we don't
> know
> whether we are running in secure or non-secure mode.  A write to the
> register in NS mode will crash.
>
> Santosh: is the diagnostic register on OMAP4 re-initialized by the
> secure code on OMAP?
>
There is a Monitor secure API, needs to be called from non-secure
software to set this diagnostic registers in resume path.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-11 12:07                   ` Santosh Shilimkar
@ 2011-02-12 14:50                     ` Russell King - ARM Linux
  2011-02-12 15:09                       ` Santosh Shilimkar
  0 siblings, 1 reply; 33+ messages in thread
From: Russell King - ARM Linux @ 2011-02-12 14:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 11, 2011 at 05:37:04PM +0530, Santosh Shilimkar wrote:
> There is a Monitor secure API, needs to be called from non-secure
> software to set this diagnostic registers in resume path.

It would be an idea to get the OMAP sleep code up to date so that I can
look at OMAPs requirements for this to be useful.

As the current code stands, I don't see any reason why the sleep34xx code
can't use this infrastructure, but I'm loathed to start modifying that if
there's outstanding code changes in that area.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-12 14:50                     ` Russell King - ARM Linux
@ 2011-02-12 15:09                       ` Santosh Shilimkar
  2011-02-28 18:17                           ` Santosh Shilimkar
  2011-02-28 18:21                         ` Jean Pihet
  0 siblings, 2 replies; 33+ messages in thread
From: Santosh Shilimkar @ 2011-02-12 15:09 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Sent: Saturday, February 12, 2011 8:20 PM
> To: Santosh Shilimkar
> Cc: Colin Cross; Kukjin Kim; saeed bishara; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume
> support
>
> On Fri, Feb 11, 2011 at 05:37:04PM +0530, Santosh Shilimkar wrote:
> > There is a Monitor secure API, needs to be called from non-secure
> > software to set this diagnostic registers in resume path.
>
> It would be an idea to get the OMAP sleep code up to date so that I
> can
> look at OMAPs requirements for this to be useful.
>
> As the current code stands, I don't see any reason why the sleep34xx
> code
> can't use this infrastructure, but I'm loathed to start modifying
> that if there's outstanding code changes in that area.

Yep. There are few issues out there with sleep34xx code.
	- Secure APIs
	- Current code needs to be cleaned up to remove
	unwanted registers save restore
	- Some part of the code on OMAP3 must be run from
	SRAM. It can't run from DDR
	- AUXCTLR, Diagnostic registers aren't accessible
	in secure mode.
	- L2 cache needs to be handled with secure APIs.
	- Code sequence needs to handle errata's handling
	which accesses OMAP PM registers.

Few of the above are getting addressed for this merge window.

So my plan was to take a look at generic suspend after the
merge window. By that time your generic stuff and omap
cleanup would have got merged hopefully.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-11 11:58                 ` Russell King - ARM Linux
  2011-02-11 12:07                   ` Santosh Shilimkar
@ 2011-02-14  0:27                   ` Kukjin Kim
  1 sibling, 0 replies; 33+ messages in thread
From: Kukjin Kim @ 2011-02-14  0:27 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux wrote:
> 
> On Wed, Feb 09, 2011 at 07:15:25PM -0800, Colin Cross wrote:
> > The diagnostic register also needs to be saved to keep the errata bits
> > set in __v7_setup.
> 
> Saving I've no problem with.  Restoring gets hairy with kernels running
> in non-secure mode, as we can't just write the register - we don't know
> whether we are running in secure or non-secure mode.  A write to the
> register in NS mode will crash.
> 
> Santosh: is the diagnostic register on OMAP4 re-initialized by the secure
> code on OMAP?
> 
> > > +       stmia   r0, {r4 - r11}
> > > +       ldmfd   sp!, {r4 - r11, pc}
> > > +ENDPROC(cpu_v7_do_suspend)
> > > +
> > > +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
> >
> > Does this need the same ALT_SMP/ALT_UP combo as v7_flush_icache_all?
> 
> That depends whether you the CPU which is resuming is part of a coherent
> SMP system at that point.  This instruction will invalidate the I-cache
> for the local CPU only, whereas the c7, c1 variant will invalidate the
> instruction caches of all CPUs within the inner sharable domain.
> 
> Has anything changed in the other CPUs as a result of this CPU resuming
> at this point?  I don't think so, so I think we just need to ensure that
> the local CPU instruction cache is invalidated at this point.
> 
> > Tegra2 suspend and cpuidle works on top of this patch and the patch
> > that adds SMP support to sleep_save_sp.  Tegra seems to need to
> > invalidate the entire l1 data cache before enabling it,
> 
> As it's undefined what state the data cache is in on resume, I'm surprised
> the s5pv210 code doesn't also need a D-cache invalidate too.  Maybe Samsung
> folk can answer that.
> 

Now, it works fine with omission D-cache invalidate on S5PV210. Basically, Samsung S5P SoCs have some kind of hardware initialization code. So I'm not sure it has something for it, will/need to check it to hardware guys soon :) Then let you know about that ;)

As a note, I will test your updated generic CPU suspend/resume support on Samsung SoCs also, if any available branch which has p2v patches for it, please let me know. Anyway sorry for late testing on board.

Have a nice weekend.
Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-12 15:09                       ` Santosh Shilimkar
@ 2011-02-28 18:17                           ` Santosh Shilimkar
  2011-02-28 18:21                         ` Jean Pihet
  1 sibling, 0 replies; 33+ messages in thread
From: Santosh Shilimkar @ 2011-02-28 18:17 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Colin Cross, Kukjin Kim, saeed bishara, linux-arm-kernel, linux-omap

+ linux-omap on this thread.

> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
> Sent: Saturday, February 12, 2011 8:40 PM
> To: Russell King - ARM Linux
> Cc: Colin Cross; Kukjin Kim; saeed bishara; linux-arm-
> kernel@lists.infradead.org
> Subject: RE: [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume
> support
>
> > -----Original Message-----
> > From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk]
> > Sent: Saturday, February 12, 2011 8:20 PM
> > To: Santosh Shilimkar
> > Cc: Colin Cross; Kukjin Kim; saeed bishara; linux-arm-
> > kernel@lists.infradead.org
> > Subject: Re: [PATCH v3 2/5] ARM: pm: add generic CPU
> suspend/resume
> > support
> >
> > On Fri, Feb 11, 2011 at 05:37:04PM +0530, Santosh Shilimkar wrote:
> > > There is a Monitor secure API, needs to be called from non-
> secure
> > > software to set this diagnostic registers in resume path.
> >
> > It would be an idea to get the OMAP sleep code up to date so that
> I
> > can
> > look at OMAPs requirements for this to be useful.
> >
> > As the current code stands, I don't see any reason why the
> sleep34xx
> > code
> > can't use this infrastructure, but I'm loathed to start modifying
> > that if there's outstanding code changes in that area.
>
> Yep. There are few issues out there with sleep34xx code.
> 	- Secure APIs
> 	- Current code needs to be cleaned up to remove
> 	unwanted registers save restore
> 	- Some part of the code on OMAP3 must be run from
> 	SRAM. It can't run from DDR
> 	- AUXCTLR, Diagnostic registers aren't accessible
> 	in secure mode.
> 	- L2 cache needs to be handled with secure APIs.
> 	- Code sequence needs to handle errata's handling
> 	which accesses OMAP PM registers.
>
> Few of the above are getting addressed for this merge window.
>
> So my plan was to take a look at generic suspend after the
> merge window. By that time your generic stuff and omap
> cleanup would have got merged hopefully.
>
> Regards,
> Santosh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
@ 2011-02-28 18:17                           ` Santosh Shilimkar
  0 siblings, 0 replies; 33+ messages in thread
From: Santosh Shilimkar @ 2011-02-28 18:17 UTC (permalink / raw)
  To: linux-arm-kernel

+ linux-omap on this thread.

> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
> Sent: Saturday, February 12, 2011 8:40 PM
> To: Russell King - ARM Linux
> Cc: Colin Cross; Kukjin Kim; saeed bishara; linux-arm-
> kernel at lists.infradead.org
> Subject: RE: [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume
> support
>
> > -----Original Message-----
> > From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> > Sent: Saturday, February 12, 2011 8:20 PM
> > To: Santosh Shilimkar
> > Cc: Colin Cross; Kukjin Kim; saeed bishara; linux-arm-
> > kernel at lists.infradead.org
> > Subject: Re: [PATCH v3 2/5] ARM: pm: add generic CPU
> suspend/resume
> > support
> >
> > On Fri, Feb 11, 2011 at 05:37:04PM +0530, Santosh Shilimkar wrote:
> > > There is a Monitor secure API, needs to be called from non-
> secure
> > > software to set this diagnostic registers in resume path.
> >
> > It would be an idea to get the OMAP sleep code up to date so that
> I
> > can
> > look at OMAPs requirements for this to be useful.
> >
> > As the current code stands, I don't see any reason why the
> sleep34xx
> > code
> > can't use this infrastructure, but I'm loathed to start modifying
> > that if there's outstanding code changes in that area.
>
> Yep. There are few issues out there with sleep34xx code.
> 	- Secure APIs
> 	- Current code needs to be cleaned up to remove
> 	unwanted registers save restore
> 	- Some part of the code on OMAP3 must be run from
> 	SRAM. It can't run from DDR
> 	- AUXCTLR, Diagnostic registers aren't accessible
> 	in secure mode.
> 	- L2 cache needs to be handled with secure APIs.
> 	- Code sequence needs to handle errata's handling
> 	which accesses OMAP PM registers.
>
> Few of the above are getting addressed for this merge window.
>
> So my plan was to take a look at generic suspend after the
> merge window. By that time your generic stuff and omap
> cleanup would have got merged hopefully.
>
> Regards,
> Santosh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume support
  2011-02-12 15:09                       ` Santosh Shilimkar
  2011-02-28 18:17                           ` Santosh Shilimkar
@ 2011-02-28 18:21                         ` Jean Pihet
  1 sibling, 0 replies; 33+ messages in thread
From: Jean Pihet @ 2011-02-28 18:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Feb 12, 2011 at 4:09 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
>> -----Original Message-----
>> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
>> Sent: Saturday, February 12, 2011 8:20 PM
>> To: Santosh Shilimkar
>> Cc: Colin Cross; Kukjin Kim; saeed bishara; linux-arm-
>> kernel at lists.infradead.org
>> Subject: Re: [PATCH v3 2/5] ARM: pm: add generic CPU suspend/resume
>> support
>>
>> On Fri, Feb 11, 2011 at 05:37:04PM +0530, Santosh Shilimkar wrote:
>> > There is a Monitor secure API, needs to be called from non-secure
>> > software to set this diagnostic registers in resume path.
>>
>> It would be an idea to get the OMAP sleep code up to date so that I
>> can
>> look at OMAPs requirements for this to be useful.
>>
>> As the current code stands, I don't see any reason why the sleep34xx
>> code
>> can't use this infrastructure, but I'm loathed to start modifying
>> that if there's outstanding code changes in that area.
>
> Yep. There are few issues out there with sleep34xx code.
> ? ? ? ?- Secure APIs
> ? ? ? ?- Current code needs to be cleaned up to remove
> ? ? ? ?unwanted registers save restore
> ? ? ? ?- Some part of the code on OMAP3 must be run from
> ? ? ? ?SRAM. It can't run from DDR
This is not the highest priority for now, I will have to come back
later on this.

> ? ? ? ?- AUXCTLR, Diagnostic registers aren't accessible
> ? ? ? ?in secure mode.
> ? ? ? ?- L2 cache needs to be handled with secure APIs.
> ? ? ? ?- Code sequence needs to handle errata's handling
> ? ? ? ?which accesses OMAP PM registers.
Also there is some on-going work to support Thumb-2, adding Dave.

>
> Few of the above are getting addressed for this merge window.
>
> So my plan was to take a look at generic suspend after the
> merge window. By that time your generic stuff and omap
> cleanup would have got merged hopefully.
Agree!

>
> Regards,
> Santosh

Regards,
Jean

>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2011-02-28 18:21 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-06 19:11 [RFC] Generic CPU save/restore PM support Russell King - ARM Linux
2011-02-06 19:12 ` [PATCH 1/5] ARM: move cache/processor/fault glue to separate include files Russell King - ARM Linux
2011-02-06 19:12 ` [PATCH 2/5] ARM: pm: add generic CPU suspend/resume support Russell King - ARM Linux
2011-02-07 12:01   ` [PATCH v2 " Russell King - ARM Linux
2011-02-07 12:10     ` [PATCH v3 " Russell King - ARM Linux
2011-02-07 13:21       ` saeed bishara
2011-02-07 13:34         ` Russell King - ARM Linux
2011-02-07 14:04           ` saeed bishara
2011-02-07 14:17             ` Russell King - ARM Linux
2011-02-07 14:27               ` saeed bishara
2011-02-07 14:33                 ` Russell King - ARM Linux
2011-02-07 14:58                   ` saeed bishara
2011-02-07 15:02                     ` Russell King - ARM Linux
2011-02-08 10:21                       ` Lorenzo Pieralisi
2011-02-08 11:23                         ` Russell King - ARM Linux
2011-02-08 12:33                           ` Russell King - ARM Linux
2011-02-08 14:25                             ` Lorenzo Pieralisi
2011-02-08  8:08               ` Colin Cross
2011-02-10  3:15               ` Colin Cross
2011-02-11 11:58                 ` Russell King - ARM Linux
2011-02-11 12:07                   ` Santosh Shilimkar
2011-02-12 14:50                     ` Russell King - ARM Linux
2011-02-12 15:09                       ` Santosh Shilimkar
2011-02-28 18:17                         ` Santosh Shilimkar
2011-02-28 18:17                           ` Santosh Shilimkar
2011-02-28 18:21                         ` Jean Pihet
2011-02-14  0:27                   ` Kukjin Kim
2011-02-06 19:13 ` [PATCH 3/5] ARM: pm: convert PXA to generic " Russell King - ARM Linux
2011-02-06 19:13 ` [PATCH 4/5] ARM: pm: convert sa11x0 " Russell King - ARM Linux
2011-02-07 18:11   ` Russell King - ARM Linux
2011-02-06 19:13 ` [PATCH 5/5] ARM: pm: convert samsung platforms " Russell King - ARM Linux
2011-02-07  5:42 ` [RFC] Generic CPU save/restore PM support Kukjin Kim
2011-02-07 10:44   ` Russell King - ARM Linux

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.