[ARM] 5239/1: Palm Zire 72 power management support
authorSergey Lapin <slapin@ossfans.org>
Fri, 29 Aug 2008 14:53:24 +0000 (15:53 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 9 Oct 2008 14:12:07 +0000 (15:12 +0100)
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>
arch/arm/mach-pxa/include/mach/palmz72.h
arch/arm/mach-pxa/palmz72.c

index 8fd30bc..5032307 100644 (file)
 #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
 
index a90b4d7..2f730da 100644 (file)
@@ -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
  ******************************************************************************/