From 6419711a164ba1304fa8fbb75ae9485455e04dcd Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:06 +0000 Subject: [ARM] S3C: Move PM support functions to common location Start moving the PM code by moving all the common support functions to a common location in arch/arm/plat-s3c. With the move we rename the functions from s3cxxx_ to s3c_ to fit the new location. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c/Makefile | 4 ++ arch/arm/plat-s3c/include/plat/pm.h | 36 ++++++++++++-- arch/arm/plat-s3c/pm.c | 97 +++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 arch/arm/plat-s3c/pm.c (limited to 'arch/arm/plat-s3c') diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile index 39195f972d5..afd8d089ba1 100644 --- a/arch/arm/plat-s3c/Makefile +++ b/arch/arm/plat-s3c/Makefile @@ -18,6 +18,10 @@ obj-y += pwm-clock.o obj-y += gpio.o obj-y += gpio-config.o +# PM support + +obj-$(CONFIG_PM) += pm.o + # devices obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h index cc623667e48..a1520997ab8 100644 --- a/arch/arm/plat-s3c/include/plat/pm.h +++ b/arch/arm/plat-s3c/include/plat/pm.h @@ -1,6 +1,7 @@ /* linux/include/asm-arm/plat-s3c24xx/pm.h * * Copyright (c) 2004 Simtec Electronics + * http://armlinux.simtec.co.uk/ * Written by Ben Dooks, * * This program is free software; you can redistribute it and/or modify @@ -49,10 +50,18 @@ extern int s3c2410_cpu_save(unsigned long *saveblk); extern void s3c2410_cpu_suspend(void); extern void s3c2410_cpu_resume(void); -extern unsigned long s3c2410_sleep_save_phys; +extern unsigned long s3c_sleep_save_phys; /* sleep save info */ +/** + * struct sleep_save - save information for shared peripherals. + * @reg: Pointer to the register to save. + * @val: Holder for the value saved from reg. + * + * This describes a list of registers which is used by the pm core and + * other subsystem to save and restore register values over suspend. + */ struct sleep_save { void __iomem *reg; unsigned long val; @@ -61,8 +70,11 @@ struct sleep_save { #define SAVE_ITEM(x) \ { .reg = (x) } -extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count); -extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count); +/* helper functions to save/restore lists of registers. */ + +extern void s3c_pm_do_save(struct sleep_save *ptr, int count); +extern void s3c_pm_do_restore(struct sleep_save *ptr, int count); +extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); #ifdef CONFIG_PM extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state); @@ -71,3 +83,21 @@ extern int s3c24xx_irq_resume(struct sys_device *dev); #define s3c24xx_irq_suspend NULL #define s3c24xx_irq_resume NULL #endif + +/* PM debug functions */ + +#ifdef CONFIG_S3C2410_PM_DEBUG +/** + * s3c_pm_dbg() - low level debug function for use in suspend/resume. + * @msg: The message to print. + * + * This function is used mainly to debug the resume process before the system + * can rely on printk/console output. It uses the low-level debugging output + * routine printascii() to do its work. + */ +extern void s3c_pm_dbg(const char *msg, ...); + +#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt) +#else +#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt) +#endif diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c new file mode 100644 index 00000000000..122e9b91a7f --- /dev/null +++ b/arch/arm/plat-s3c/pm.c @@ -0,0 +1,97 @@ +/* linux/arch/arm/plat-s3c/pm.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2004,2006,2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C common power management (suspend to ram) support. + * + * 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 +#include +#include +#include + +#include + +/* for external use */ + +unsigned long s3c_pm_flags; + +#ifdef CONFIG_S3C2410_PM_DEBUG +extern void printascii(const char *); + +void s3c_pm_dbg(const char *fmt, ...) +{ + va_list va; + char buff[256]; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + + printascii(buff); +} +#endif /* CONFIG_S3C2410_PM_DEBUG */ + + +/* helper functions to save and restore register state */ + +/** + * s3c_pm_do_save() - save a set of registers for restoration on resume. + * @ptr: Pointer to an array of registers. + * @count: Size of the ptr array. + * + * Run through the list of registers given, saving their contents in the + * array for later restoration when we wakeup. + */ +void s3c_pm_do_save(struct sleep_save *ptr, int count) +{ + for (; count > 0; count--, ptr++) { + ptr->val = __raw_readl(ptr->reg); + S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val); + } +} + +/** + * s3c_pm_do_restore() - restore register values from the save list. + * @ptr: Pointer to an array of registers. + * @count: Size of the ptr array. + * + * Restore the register values saved from s3c_pm_do_save(). + * + * Note, we do not use S3C_PMDBG() in here, as the system may not have + * restore the UARTs state yet +*/ + +void s3c_pm_do_restore(struct sleep_save *ptr, int count) +{ + for (; count > 0; count--, ptr++) { + printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n", + ptr->reg, ptr->val, __raw_readl(ptr->reg)); + + __raw_writel(ptr->val, ptr->reg); + } +} + +/** + * s3c_pm_do_restore_core() - early restore register values from save list. + * + * This is similar to s3c_pm_do_restore() except we try and minimise the + * side effects of the function in case registers that hardware might need + * to work has been restored. + * + * WARNING: Do not put any debug in here that may effect memory or use + * peripherals, as things may be changing! +*/ + +void s3c_pm_do_restore_core(struct sleep_save *ptr, int count) +{ + for (; count > 0; count--, ptr++) + __raw_writel(ptr->val, ptr->reg); +} -- cgit v1.2.3