diff options
-rw-r--r-- | arch/arm/mach-s3c2410/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2412-pm.c | 128 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2412.c | 40 |
4 files changed, 137 insertions, 40 deletions
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 458b36b2353b..e50a73f93d3d 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -176,6 +176,13 @@ config CPU_S3C2412_ONLY !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412 default y if CPU_S3C2412 +config S3C2412_PM + bool + default y if PM + depends on CPU_S3C2412 + help + Internal config node to apply S3C2412 power management + config CPU_S3C2412 bool depends on ARCH_S3C2410 diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 94aef371a529..d66013365b6b 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -38,6 +38,8 @@ obj-$(CONFIG_CPU_S3C2412) += s3c2412-irq.o obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o obj-dma-$(CONFIG_CPU_S3C2412) += s3c2412-dma.o +obj-$(CONFIG_S3C2412_PM) += s3c2412-pm.o + # # S3C244X support diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2410/s3c2412-pm.c new file mode 100644 index 000000000000..19b63322d259 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412-pm.c @@ -0,0 +1,128 @@ +/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@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/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/sysdev.h> +#include <linux/platform_device.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/irq.h> + +#include <asm/arch/regs-power.h> +#include <asm/arch/regs-gpioj.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-dsc.h> + +#include "cpu.h" +#include "pm.h" + +#include "s3c2412.h" + +static void s3c2412_cpu_suspend(void) +{ + unsigned long tmp; + + /* set our standby method to sleep */ + + tmp = __raw_readl(S3C2412_PWRCFG); + tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP; + __raw_writel(tmp, S3C2412_PWRCFG); + + /* 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, 4\n\t" + "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp)); + + /* we should never get past here */ + + panic("sleep resumed to originator?"); +} + +static void s3c2412_pm_prepare(void) +{ +} + +static int s3c2412_pm_add(struct sys_device *sysdev) +{ + pm_cpu_prep = s3c2412_pm_prepare; + pm_cpu_sleep = s3c2412_cpu_suspend; + + return 0; +} + +static struct sleep_save s3c2412_sleep[] = { + SAVE_ITEM(S3C2412_DSC0), + SAVE_ITEM(S3C2412_DSC1), + SAVE_ITEM(S3C2413_GPJDAT), + SAVE_ITEM(S3C2413_GPJCON), + SAVE_ITEM(S3C2413_GPJUP), + + /* save the PWRCFG to get back to original sleep method */ + + SAVE_ITEM(S3C2412_PWRCFG), + + /* save the sleep configuration anyway, just in case these + * get damaged during wakeup */ + + SAVE_ITEM(S3C2412_GPBSLPCON), + SAVE_ITEM(S3C2412_GPCSLPCON), + SAVE_ITEM(S3C2412_GPDSLPCON), + SAVE_ITEM(S3C2412_GPESLPCON), + SAVE_ITEM(S3C2412_GPFSLPCON), + SAVE_ITEM(S3C2412_GPGSLPCON), + SAVE_ITEM(S3C2412_GPHSLPCON), + SAVE_ITEM(S3C2413_GPJSLPCON), +}; + +static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state) +{ + s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); + return 0; +} + +static int s3c2412_pm_resume(struct sys_device *dev) +{ + unsigned long tmp; + + tmp = __raw_readl(S3C2412_PWRCFG); + tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK; + tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE; + __raw_writel(tmp, S3C2412_PWRCFG); + + s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); + return 0; +} + +static struct sysdev_driver s3c2412_pm_driver = { + .add = s3c2412_pm_add, + .suspend = s3c2412_pm_suspend, + .resume = s3c2412_pm_resume, +}; + +static __init int s3c2412_pm_init(void) +{ + return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver); +} + +arch_initcall(s3c2412_pm_init); diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c index ea25078cf4f8..e76431c41461 100644 --- a/arch/arm/mach-s3c2410/s3c2412.c +++ b/arch/arm/mach-s3c2410/s3c2412.c @@ -158,48 +158,8 @@ void __init s3c2412_init_clocks(int xtal) * as a driver which may support both 2410 and 2440 may try and use it. */ -#ifdef CONFIG_PM -static struct sleep_save s3c2412_sleep[] = { - SAVE_ITEM(S3C2412_DSC0), - SAVE_ITEM(S3C2412_DSC1), - SAVE_ITEM(S3C2413_GPJDAT), - SAVE_ITEM(S3C2413_GPJCON), - SAVE_ITEM(S3C2413_GPJUP), - - /* save the sleep configuration anyway, just in case these - * get damaged during wakeup */ - - SAVE_ITEM(S3C2412_GPBSLPCON), - SAVE_ITEM(S3C2412_GPCSLPCON), - SAVE_ITEM(S3C2412_GPDSLPCON), - SAVE_ITEM(S3C2412_GPESLPCON), - SAVE_ITEM(S3C2412_GPFSLPCON), - SAVE_ITEM(S3C2412_GPGSLPCON), - SAVE_ITEM(S3C2412_GPHSLPCON), - SAVE_ITEM(S3C2413_GPJSLPCON), -}; - -static int s3c2412_suspend(struct sys_device *dev, pm_message_t state) -{ - s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); - return 0; -} - -static int s3c2412_resume(struct sys_device *dev) -{ - s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); - return 0; -} - -#else -#define s3c2412_suspend NULL -#define s3c2412_resume NULL -#endif - struct sysdev_class s3c2412_sysclass = { set_kset_name("s3c2412-core"), - .suspend = s3c2412_suspend, - .resume = s3c2412_resume }; static int __init s3c2412_core_init(void) |