diff options
author | Sergey Lapin <slapin@ossfans.org> | 2008-08-29 15:53:24 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-10-09 15:12:07 +0100 |
commit | fda50a1c49ad7483eaa29a268d560422c413933f (patch) | |
tree | d7b066fd49df37879f261c92f8b1bfcce4aad402 /arch/arm | |
parent | d8aa0251f12546e9bd1e9ee1d9782d6492819a04 (diff) |
[ARM] 5239/1: Palm Zire 72 power management support
This patch contains Palm Zire 72 power
management support.
Depends on #5238/1
Signed-off-by: Sergey Lapin <slapin@ossfans.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-pxa/include/mach/palmz72.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-pxa/palmz72.c | 74 |
2 files changed, 87 insertions, 0 deletions
diff --git a/arch/arm/mach-pxa/include/mach/palmz72.h b/arch/arm/mach-pxa/include/mach/palmz72.h index 8fd30bcecb7..5032307ebf7 100644 --- a/arch/arm/mach-pxa/include/mach/palmz72.h +++ b/arch/arm/mach-pxa/include/mach/palmz72.h @@ -63,5 +63,18 @@ #define PALMZ72_PRESCALER 0x3F #define PALMZ72_PERIOD_NS 3500 +#ifdef CONFIG_PM +struct palmz72_resume_info { + u32 magic0; /* 0x0 */ + u32 magic1; /* 0x4 */ + u32 resume_addr; /* 0x8 */ + u32 pad[11]; /* 0xc..0x37 */ + u32 arm_control; /* 0x38 */ + u32 aux_control; /* 0x3c */ + u32 ttb; /* 0x40 */ + u32 domain_access; /* 0x44 */ + u32 process_id; /* 0x48 */ +}; +#endif #endif diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index a90b4d77a20..2f730da3bba 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -449,6 +449,80 @@ static struct pxafb_mach_info palmz72_lcd_screen = { .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, }; +#ifdef CONFIG_PM + +/* We have some black magic here + * PalmOS ROM on recover expects special struct physical address + * to be transferred via PSPR. Using this struct PalmOS restores + * its state after sleep. As for Linux, we need to setup it the + * same way. More than that, PalmOS ROM changes some values in memory. + * For now only one location is found, which needs special treatment. + * Thanks to Alex Osborne, Andrzej Zaborowski, and lots of other people + * for reading backtraces for me :) + */ + +#define PALMZ72_SAVE_DWORD ((unsigned long *)0xc0000050) + +static struct palmz72_resume_info palmz72_resume_info = { + .magic0 = 0xb4e6, + .magic1 = 1, + + /* reset state, MMU off etc */ + .arm_control = 0, + .aux_control = 0, + .ttb = 0, + .domain_access = 0, + .process_id = 0, +}; + +static unsigned long store_ptr; + +/* sys_device for Palm Zire 72 PM */ + +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; + + /* Storing memory touched by ROM */ + store_ptr = *PALMZ72_SAVE_DWORD; + + /* Setting PSPR to a proper value */ + PSPR = virt_to_phys(&palmz72_resume_info); + + return 0; +} + +static int palmz72_pm_resume(struct sys_device *dev) +{ + *PALMZ72_SAVE_DWORD = store_ptr; + return 0; +} + +static struct sysdev_class palmz72_pm_sysclass = { + .name = "palmz72_pm", + .suspend = palmz72_pm_suspend, + .resume = palmz72_pm_resume, +}; + +static struct sys_device palmz72_pm_device = { + .cls = &palmz72_pm_sysclass, +}; + +static int __init palmz72_pm_init(void) +{ + int ret = -ENODEV; + if (machine_is_palmz72()) { + ret = sysdev_class_register(&palmz72_pm_sysclass); + if (ret == 0) + ret = sysdev_register(&palmz72_pm_device); + } + return ret; +} + +device_initcall(palmz72_pm_init); +#endif + /****************************************************************************** * Machine init ******************************************************************************/ |