diff options
-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 ******************************************************************************/ |