[PATCH] ARM: S5PV210: Add Power Management Support

Kukjin Kim kgene.kim at samsung.com
Tue May 4 01:02:21 EDT 2010


From: Jongpill Lee <boyko.lee at samsung.com>

This patch adds suspend-to-ram support for S5PV210.

Signed-off-by: Jongpill Lee <boyko.lee at samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim at samsung.com>
---
 arch/arm/mach-s5pv210/Kconfig                |    6 +
 arch/arm/mach-s5pv210/Makefile               |    1 +
 arch/arm/mach-s5pv210/include/mach/pm-core.h |   43 ++++++
 arch/arm/mach-s5pv210/include/mach/pm.h      |   19 +++
 arch/arm/mach-s5pv210/mach-smdkc110.c        |    8 ++
 arch/arm/mach-s5pv210/mach-smdkv210.c        |    8 ++
 arch/arm/mach-s5pv210/pm.c                   |  116 +++++++++++++++++
 arch/arm/plat-s5p/Makefile                   |    4 +
 arch/arm/plat-s5p/include/plat/pm-s5p.h      |   23 +++
 arch/arm/plat-s5p/irq-pm.c                   |  113 +++++++++++++++
 arch/arm/plat-s5p/pm.c                       |  149 +++++++++++++++++++++
 arch/arm/plat-s5p/sleep.S                    |  188 ++++++++++++++++++++++++++
 arch/arm/plat-samsung/pm-gpio.c              |    4 +-
 13 files changed, 680 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-s5pv210/include/mach/pm-core.h
 create mode 100644 arch/arm/mach-s5pv210/include/mach/pm.h
 create mode 100644 arch/arm/mach-s5pv210/pm.c
 create mode 100644 arch/arm/plat-s5p/include/plat/pm-s5p.h
 create mode 100644 arch/arm/plat-s5p/irq-pm.c
 create mode 100644 arch/arm/plat-s5p/pm.c
 create mode 100644 arch/arm/plat-s5p/sleep.S

diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index f636113..be0a013 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -12,6 +12,7 @@ if ARCH_S5PV210
 config CPU_S5PV210
 	bool
 	select PLAT_S5P
+	select S5PV210_PM if PM
 	help
 	  Enable S5PV210 CPU support
 
@@ -43,4 +44,9 @@ config MACH_VOGUEV210
 
 endchoice
 
+config S5PV210_PM
+	bool
+	help
+	  Power Management code common to S5PV210
+
 endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index f1772ed..f31d6a4 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -13,6 +13,7 @@ obj-				:=
 # Core support for S5PV210 system
 
 obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o gpio.o irq-eint-group.o
+obj-$(CONFIG_S5PV210_PM)	+= pm.o
 
 # machine support
 
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
new file mode 100644
index 0000000..52050e4
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben at simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c
+ *
+ * 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.
+*/
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
+	__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+	/* nothing here yet */
+}
diff --git a/arch/arm/mach-s5pv210/include/mach/pm.h b/arch/arm/mach-s5pv210/include/mach/pm.h
new file mode 100644
index 0000000..897444b
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/pm.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/pm.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Headers for Power Management
+ *
+ * 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_ARCH_PM_H
+#define __ASM_ARCH_PM_H __FILE__
+
+#include <plat/pm.h>
+#include <plat/pm-s5p.h>
+
+#endif /* __ASM_ARCH_PM_H */
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 9c9829c..7c54ba3 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -26,6 +26,10 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 
+#if defined(CONFIG_PM)
+#include <mach/pm.h>
+#endif
+
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define S5PV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				 S3C2410_UCON_RXILEVEL |	\
@@ -83,6 +83,10 @@ static void __init smdkc110_map_io(void)
 
 static void __init smdkc110_machine_init(void)
 {
+#if defined(CONFIG_PM)
+	s3c_pm_init();
+#endif
+
 	platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
 }
 
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 9c9829c..7c54ba3 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -26,6 +26,10 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 
+#if defined(CONFIG_PM)
+#include <mach/pm.h>
+#endif
+
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define S5PV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				 S3C2410_UCON_RXILEVEL |	\
@@ -83,6 +83,10 @@ static void __init smdkv210_map_io(void)
 
 static void __init smdkv210_machine_init(void)
 {
+#if defined(CONFIG_PM)
+	s3c_pm_init();
+#endif
+
 	platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
 }
 
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
new file mode 100644
index 0000000..b446e87
--- /dev/null
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -0,0 +1,116 @@
+/* linux/arch/arm/mach-s5pv210/pm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Power Management support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.c
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben at simtec.co.uk>
+ *
+ * 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 <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/regs-gpio.h>
+#include <plat/cpu.h>
+#include <mach/pm.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-clock.h>
+
+void s5pv210_cpu_suspend(void)
+{
+	unsigned long tmp;
+
+	/* issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case */
+
+	tmp = 0;
+
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 5\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    ".word 0xe320f003" : : "r" (tmp));
+
+	/* we should never get past here */
+	panic("sleep resumed to originator?");
+}
+
+static void s5pv210_pm_prepare(void)
+{
+	unsigned int tmp;
+
+	/* ensure at least INFORM0 has the resume address */
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+
+	tmp = __raw_readl(S5P_SLEEP_CFG);
+	tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
+	__raw_writel(tmp, S5P_SLEEP_CFG);
+
+	/* WFI for SLEEP mode configuration by SYSCON */
+	tmp = __raw_readl(S5P_PWR_CFG);
+	tmp &= S5P_CFG_WFI_CLEAN;
+	tmp |= S5P_CFG_WFI_SLEEP;
+	__raw_writel(tmp, S5P_PWR_CFG);
+
+	/* SYSCON interrupt handling disable */
+	tmp = __raw_readl(S5P_OTHERS);
+	tmp |= S5P_OTHER_SYSC_INTOFF;
+	__raw_writel(tmp, S5P_OTHERS);
+
+	__raw_writel(0xffffffff, (VA_VIC0 + VIC_INT_ENABLE_CLEAR));
+	__raw_writel(0xffffffff, (VA_VIC1 + VIC_INT_ENABLE_CLEAR));
+	__raw_writel(0xffffffff, (VA_VIC2 + VIC_INT_ENABLE_CLEAR));
+	__raw_writel(0xffffffff, (VA_VIC3 + VIC_INT_ENABLE_CLEAR));
+}
+
+static int s5pv210_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = s5pv210_pm_prepare;
+	pm_cpu_sleep = s5pv210_cpu_suspend;
+
+	return 0;
+}
+
+static struct sleep_save s5pv210_sleep[] = {
+	/* nothing here yet */
+};
+
+static int s5pv210_pm_resume(struct sys_device *dev)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(S5P_OTHERS);
+	tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
+	__raw_writel(tmp , S5P_OTHERS);
+
+	s3c_pm_do_restore(s5pv210_sleep, ARRAY_SIZE(s5pv210_sleep));
+	return 0;
+}
+
+static struct sysdev_driver s5pv210_pm_driver = {
+	.add		= s5pv210_pm_add,
+	.resume		= s5pv210_pm_resume,
+};
+
+static __init int s5pv210_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
+}
+arch_initcall(s5pv210_pm_drvinit);
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index 00a7966..ac73bb1 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -19,3 +19,7 @@ obj-y				+= cpu.o
 obj-y				+= clock.o
 obj-y				+= irq.o irq-eint.o
 obj-y				+= setup-i2c0.o
+
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= irq-pm.o
+obj-$(CONFIG_PM)		+= sleep.o
diff --git a/arch/arm/plat-s5p/include/plat/pm-s5p.h b/arch/arm/plat-s5p/include/plat/pm-s5p.h
new file mode 100644
index 0000000..6bba23f
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/pm-s5p.h
@@ -0,0 +1,23 @@
+/* linux/arch/arm/plat-s5p/include/plat/pm-s5p.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Definitions for Power Management
+ *
+ * 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.
+*/
+
+/* helper functions to save/restore lists of registers. */
+
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
+extern int s5p_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s5p_irq_resume(struct sys_device *dev);
+#else
+#define s3c_irq_wake NULL
+#define s5p_irq_suspend NULL
+#define s5p_irq_resume NULL
+#endif
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c
new file mode 100644
index 0000000..b6839d1
--- /dev/null
+++ b/arch/arm/plat-s5p/irq-pm.c
@@ -0,0 +1,113 @@
+/* linux/arch/arm/plat-s5p/irq-pm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/plat-s3c24xx/irq-pm.c,
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben at simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+
+#include <plat/cpu.h>
+#include <plat/irqs.h>
+#include <mach/pm.h>
+#include <mach/map.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-irq.h>
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM,
+ * as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow	= 0x00000006L;
+unsigned long s3c_irqwake_eintallow	= 0xffffffffL;
+
+int s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long irqbit;
+
+	switch (irqno) {
+	case IRQ_RTC_TIC:
+	case IRQ_RTC_ALARM:
+		irqbit = 1 << (irqno + 1 - IRQ_RTC_ALARM);
+		if (!state)
+			s3c_irqwake_intmask |= irqbit;
+		else
+			s3c_irqwake_intmask &= ~irqbit;
+		break;
+	default:
+		return -ENOENT;
+	}
+	return 0;
+}
+
+/* this lot should be really saved by the IRQ code */
+/* VICXADDRESSXX initilaization to be needed */
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(VA_VIC0 + VIC_INT_SELECT),
+	SAVE_ITEM(VA_VIC1 + VIC_INT_SELECT),
+	SAVE_ITEM(VA_VIC2 + VIC_INT_SELECT),
+	SAVE_ITEM(VA_VIC3 + VIC_INT_SELECT),
+
+	SAVE_ITEM(VA_VIC0 + VIC_INT_ENABLE),
+	SAVE_ITEM(VA_VIC1 + VIC_INT_ENABLE),
+	SAVE_ITEM(VA_VIC2 + VIC_INT_ENABLE),
+	SAVE_ITEM(VA_VIC3 + VIC_INT_ENABLE),
+
+	SAVE_ITEM(VA_VIC0 + VIC_INT_SOFT),
+	SAVE_ITEM(VA_VIC1 + VIC_INT_SOFT),
+	SAVE_ITEM(VA_VIC2 + VIC_INT_SOFT),
+	SAVE_ITEM(VA_VIC3 + VIC_INT_SOFT),
+};
+
+static struct sleep_save eint_save[] = {
+	SAVE_ITEM(S5P_EINT30CON),
+	SAVE_ITEM(S5P_EINT31CON),
+	SAVE_ITEM(S5P_EINT32CON),
+	SAVE_ITEM(S5P_EINT33CON),
+
+	SAVE_ITEM(S5P_EINT30FLTCON0),
+	SAVE_ITEM(S5P_EINT30FLTCON1),
+	SAVE_ITEM(S5P_EINT31FLTCON0),
+	SAVE_ITEM(S5P_EINT31FLTCON1),
+	SAVE_ITEM(S5P_EINT32FLTCON0),
+	SAVE_ITEM(S5P_EINT32FLTCON1),
+	SAVE_ITEM(S5P_EINT33FLTCON0),
+	SAVE_ITEM(S5P_EINT33FLTCON1),
+
+	SAVE_ITEM(S5P_EINT30MASK),
+	SAVE_ITEM(S5P_EINT31MASK),
+	SAVE_ITEM(S5P_EINT32MASK),
+	SAVE_ITEM(S5P_EINT33MASK),
+};
+
+int s5p_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
+	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+	return 0;
+}
+
+int s5p_irq_resume(struct sys_device *dev)
+{
+	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+	s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
+
+	return 0;
+}
diff --git a/arch/arm/plat-s5p/pm.c b/arch/arm/plat-s5p/pm.c
new file mode 100644
index 0000000..397b60a
--- /dev/null
+++ b/arch/arm/plat-s5p/pm.c
@@ -0,0 +1,149 @@
+/* linux/arch/arm/plat-s5p/pm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com/
+ *
+ * S5P Power Manager (Suspend-To-RAM) support
+ *
+ * Based on arch/arm/plat-s3c24xx/pm.c
+ * Copyright (c) 2004,2006 Simtec Electronics
+ *	Ben Dooks <ben at simtec.co.uk>
+ *
+ * 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 <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+
+#include <mach/map.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-timer.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+#include <mach/regs-irq.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/pm.h>
+
+#define PFX "s5p pm: "
+
+static struct sleep_save core_save[] = {
+	/* Clock source */
+	SAVE_ITEM(S5P_CLK_SRC0),
+	SAVE_ITEM(S5P_CLK_SRC1),
+	SAVE_ITEM(S5P_CLK_SRC2),
+	SAVE_ITEM(S5P_CLK_SRC3),
+	SAVE_ITEM(S5P_CLK_SRC4),
+	SAVE_ITEM(S5P_CLK_SRC5),
+	SAVE_ITEM(S5P_CLK_SRC6),
+
+	/* Clock source Mask */
+	SAVE_ITEM(S5P_CLK_SRC_MASK0),
+	SAVE_ITEM(S5P_CLK_SRC_MASK1),
+
+	/* Clock Divider */
+	SAVE_ITEM(S5P_CLK_DIV0),
+	SAVE_ITEM(S5P_CLK_DIV1),
+	SAVE_ITEM(S5P_CLK_DIV2),
+	SAVE_ITEM(S5P_CLK_DIV3),
+	SAVE_ITEM(S5P_CLK_DIV4),
+	SAVE_ITEM(S5P_CLK_DIV5),
+	SAVE_ITEM(S5P_CLK_DIV6),
+	SAVE_ITEM(S5P_CLK_DIV7),
+
+	/* Clock Main Gate */
+	SAVE_ITEM(S5P_CLKGATE_MAIN0),
+	SAVE_ITEM(S5P_CLKGATE_MAIN1),
+	SAVE_ITEM(S5P_CLKGATE_MAIN2),
+
+	/* Clock source Peri Gate */
+	SAVE_ITEM(S5P_CLKGATE_PERI0),
+	SAVE_ITEM(S5P_CLKGATE_PERI1),
+
+	/* Clock source SCLK Gate */
+	SAVE_ITEM(S5P_CLKGATE_SCLK0),
+	SAVE_ITEM(S5P_CLKGATE_SCLK1),
+
+	/* Clock IP Clock gate */
+	SAVE_ITEM(S5P_CLKGATE_IP0),
+	SAVE_ITEM(S5P_CLKGATE_IP1),
+	SAVE_ITEM(S5P_CLKGATE_IP2),
+	SAVE_ITEM(S5P_CLKGATE_IP3),
+	SAVE_ITEM(S5P_CLKGATE_IP4),
+
+	/* Clock Blcok and Bus gate */
+	SAVE_ITEM(S5P_CLKGATE_BLOCK),
+	SAVE_ITEM(S5P_CLKGATE_BUS0),
+
+	/* Clock ETC */
+	SAVE_ITEM(S5P_CLK_OUT),
+
+	/* PWM Register */
+	SAVE_ITEM(S3C2410_TCFG0),
+	SAVE_ITEM(S3C2410_TCFG1),
+	SAVE_ITEM(S3C64XX_TINT_CSTAT),
+	SAVE_ITEM(S3C2410_TCON),
+	SAVE_ITEM(S3C2410_TCNTB(0)),
+	SAVE_ITEM(S3C2410_TCMPB(0)),
+	SAVE_ITEM(S3C2410_TCNTO(0)),
+};
+
+static struct sleep_save sromc_save[] = {
+	SAVE_ITEM(S5P_SROM_BW),
+	SAVE_ITEM(S5P_SROM_BC0),
+	SAVE_ITEM(S5P_SROM_BC1),
+	SAVE_ITEM(S5P_SROM_BC2),
+	SAVE_ITEM(S5P_SROM_BC3),
+	SAVE_ITEM(S5P_SROM_BC4),
+	SAVE_ITEM(S5P_SROM_BC5),
+};
+
+/* s3c_pm_check_resume_pin
+ *
+ * check to see if the pin is configured correctly for sleep mode, and
+ * make any necessary adjustments if it is not
+*/
+
+static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+{
+	/* nothing here yet */
+}
+
+/* s3c_pm_configure_extint
+ *
+ * configure all external interrupt pins
+*/
+
+void s3c_pm_configure_extint(void)
+{
+	/* nothing here yet */
+}
+
+void s3c_pm_restore_core(void)
+{
+	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+	s3c_pm_do_restore(sromc_save, ARRAY_SIZE(sromc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+	s3c_pm_do_save(sromc_save, ARRAY_SIZE(sromc_save));
+	s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
+}
diff --git a/arch/arm/plat-s5p/sleep.S b/arch/arm/plat-s5p/sleep.S
new file mode 100644
index 0000000..ca9f08e
--- /dev/null
+++ b/arch/arm/plat-s5p/sleep.S
@@ -0,0 +1,188 @@
+/* linux/arch/arm/plat-s5p/sleep.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 power Manager (Suspend-To-RAM) support
+ * Based on S3C2410 sleep code by:
+ * 	Ben Dooks, (c) 2004 Simtec Electronics
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <asm/asm-offsets.h>
+#include <asm/memory.h>
+#include <asm/system.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+#include <plat/regs-serial.h>
+
+/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
+ * reset the UART configuration, only enable if you really need this!
+*/
+	.text
+
+	/* s3c_cpu_save
+	 *
+	 * entry:
+	 *	r0 = save address (virtual addr of s3c_sleep_save_phys)
+	*/
+
+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 }
+
+	@@ write our state back to RAM
+	bl	s3c_pm_cb_flushcache
+
+	@@ jump to final code to send system to sleep
+	ldr	r0, =pm_cpu_sleep
+	@@ldr	pc, [ r0 ]
+	ldr	r0, [ r0 ]
+	mov	pc, r0
+
+	@@ return to the caller, after having the MMU
+	@@ turned on, this restores the last bits from the
+	@@ stack
+resume_with_mmu:
+	/* delete added mmu table list */
+	ldr	r9 , =(PAGE_OFFSET - PHYS_OFFSET)
+	add	r4, r4, r9
+	str	r12, [r4]
+
+	ldmfd	sp!, { r3 - r12, pc }
+
+	.ltorg
+
+	@@ the next bits sit in the .data segment, even though they
+	@@ happen to be code... the s5pv210_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
+	 * s5pv210_cpu_resume entry.
+	*/
+
+	.word	0x2bedf00d
+
+	/* 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)
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+	msr	cpsr_c, r0
+
+	@@ load UART to allow us to print the two characters for
+	@@ resume debug
+
+	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 controls
+	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
+	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
+
+	/* calculate first section address into r8 */
+	mov	r4, r6
+	ldr	r5, =0x3fff
+	bic	r4, r4, r5
+	ldr	r11, =0xe010f000
+	ldr	r10, [r11, #0]
+	mov	r10, r10 ,LSR #18
+	bic	r10, r10, #0x3
+	orr	r4, r4, r10
+
+	/* calculate mmu list value into r9 */
+	mov 	r10, r10, LSL #18
+	ldr	r5, =0x40e
+	orr	r10, r10, r5
+
+	/* back up originally data */
+
+	ldr	r12, [r4]
+
+	/* Added list about mmu */
+	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
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index 69a4c7f..88ab73c 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -192,7 +192,7 @@ struct s3c_gpio_pm s3c_gpio_pm_2bit = {
 	.resume = s3c_gpio_pm_2bit_resume,
 };
 
-#ifdef CONFIG_ARCH_S3C64XX
+#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
 static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
 {
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
@@ -302,7 +302,7 @@ struct s3c_gpio_pm s3c_gpio_pm_4bit = {
 	.save	= s3c_gpio_pm_4bit_save,
 	.resume = s3c_gpio_pm_4bit_resume,
 };
-#endif /* CONFIG_ARCH_S3C64XX */
+#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
 
 /**
  * s3c_pm_save_gpio() - save gpio chip data for suspend
-- 
1.6.2.5




More information about the linux-arm-kernel mailing list