diff options
author | Koen Kooi <koen@openembedded.org> | 2005-06-30 08:19:37 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2005-06-30 08:19:37 +0000 |
commit | c8e5702127e507e82e6f68a4b8c546803accea9d (patch) | |
tree | 00583491f40ecc640f2b28452af995e3a63a09d7 /packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff | |
parent | 87ec8ca4d2e2eb4d1c1e1e1a6b46a395d56805b9 (diff) |
import clean BK tree at cset 1.3670
Diffstat (limited to 'packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff')
-rw-r--r-- | packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff | 799 |
1 files changed, 799 insertions, 0 deletions
diff --git a/packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff b/packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff index e69de29bb2..dfdbd99237 100644 --- a/packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff +++ b/packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff @@ -0,0 +1,799 @@ +--- /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/arch/arm/mach-sa1100/pm-common.c 1970-01-01 01:00:00.000000000 +0100 ++++ arch/arm/mach-sa1100/pm-common.c 2004-07-04 14:56:34.000000000 +0200 +@@ -0,0 +1,268 @@ ++/* ++ * SA1100 Power Management Routines ++ * ++ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License. ++ * ++ * History: ++ * ++ * 2001-02-06: Cliff Brake Initial code ++ * ++ * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> & ++ * Chester Kuo <chester@linux.org.tw> ++ * Save more value for the resume function! Support ++ * Bitsy/Assabet/Freebird board ++ * ++ * 2001-08-29: Nicolas Pitre <nico@cam.org> ++ * Cleaned up, pushed platform dependent stuff ++ * in the platform specific files. ++ * ++ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. ++ * Storage is local on the stack now. ++ */ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/pm.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include <linux/interrupt.h> ++#include <linux/sysctl.h> ++#include <linux/errno.h> ++#include <linux/cpufreq.h> ++ ++#include <asm/hardware.h> ++#include <asm/memory.h> ++#include <asm/system.h> ++#include <asm/leds.h> ++#include <asm/uaccess.h> ++ ++ ++#ifdef CONFIG_IPAQ_HANDHELD ++#include <asm/arch-sa1100/h3600_asic.h> ++#endif ++ ++#define __KERNEL_SYSCALLS__ ++#include <linux/unistd.h> ++ ++/* ++ * Debug macros ++ */ ++#undef DEBUG ++ ++ ++ ++static char pm_helper_path[128] = "/sbin/pm_helper"; ++extern int exec_usermodehelper(char *path, char **argv, char **envp); ++int debug_pm = 0; ++static int pm_helper_veto = 0; ++ ++static int ++run_sbin_pm_helper( pm_request_t action ) ++{ ++ int i; ++ char *argv[3], *envp[8]; ++ ++ if (!pm_helper_path[0]) ++ return 2; ++ ++ if ( action != PM_SUSPEND && action != PM_RESUME ) ++ return 1; ++ ++ /* Be root */ ++ current->uid = current->gid = 0; ++ ++ i = 0; ++ argv[i++] = pm_helper_path; ++ argv[i++] = (action == PM_RESUME ? "resume" : "suspend"); ++ argv[i] = 0; ++ ++ i = 0; ++ /* minimal command environment */ ++ envp[i++] = "HOME=/"; ++ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; ++ envp[i] = 0; ++ ++ /* other stuff we want to pass to /sbin/pm_helper */ ++ return exec_usermodehelper (argv [0], argv, envp); ++} ++ ++/* ++ * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend. ++ */ ++int (*pm_suggest_suspend_hook)(int state); ++EXPORT_SYMBOL(pm_suggest_suspend_hook); ++ ++/* ++ * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume ++ */ ++int pm_use_sbin_pm_helper = 1; ++EXPORT_SYMBOL(pm_use_sbin_pm_helper); ++ ++/* ++ * If sysctl_pm_do_suspend_hook is non-NULL, it is called by sysctl_pm_do_suspend. ++ * If it returns a true value, then pm_suspend is not called. ++ * Use this to hook in apmd, for now. ++ */ ++int (*pm_sysctl_suspend_hook)(int state); ++EXPORT_SYMBOL(pm_sysctl_suspend_hook); ++ ++int pm_suspend(void); ++ ++int pm_suggest_suspend(void) ++{ ++ int retval; ++ ++ if (pm_suggest_suspend_hook) { ++ if (pm_suggest_suspend_hook(PM_SUSPEND)) ++ return 0; ++ } ++ ++ if (pm_use_sbin_pm_helper) { ++ pid_t pid; ++ int res; ++ int status = 0; ++ unsigned int old_fs; ++ ++ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 ); ++ if ( pid < 0 ) ++ return pid; ++ ++ if (debug_pm) ++ printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid); ++ ++ old_fs = get_fs (); ++ set_fs (get_ds ()); ++ res = waitpid(pid, &status, __WCLONE); ++ set_fs (old_fs); ++ ++ if ( pid != res ) { ++ if (debug_pm) ++ printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status ); ++ ++ return -1; ++ } ++ ++ /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/ ++ if (( status & 0xff7f ) != 0 ) { ++ if (pm_helper_veto) { ++ if (debug_pm) ++ printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8); ++ return -1; ++ } else { ++ if (debug_pm) ++ printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8); ++ } ++ } ++ } ++ ++ if (debug_pm) ++ printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ ); ++ ++ if (pm_sysctl_suspend_hook) { ++ if (pm_sysctl_suspend_hook(PM_SUSPEND)) ++ return 0; ++ } ++ ++ retval = pm_suspend(); ++ if (retval) { ++ if (debug_pm) ++ printk(KERN_CRIT "pm_suspend returned %d\n", retval); ++ return retval; ++ } ++ ++ if (pm_use_sbin_pm_helper) { ++ pid_t pid; ++ ++ if (debug_pm) ++ printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__); ++ ++ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 ); ++ if ( pid < 0 ) ++ return pid; ++ ++ if ( pid != waitpid ( pid, NULL, __WCLONE )) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(pm_suggest_suspend); ++ ++ ++/* ++ * Send us to sleep. ++ */ ++int pm_suspend(void) ++{ ++ int retval; ++ ++ retval = pm_send_all(PM_SUSPEND, (void *)3); ++ if ( retval ) ++ return retval; ++ ++#ifdef CONFIG_IPAQ_HANDHELD ++ retval = h3600_power_management(PM_SUSPEND); ++ if (retval) { ++ pm_send_all(PM_RESUME, (void *)0); ++ return retval; ++ } ++#endif ++ ++ retval = pm_do_suspend(); ++ ++#ifdef CONFIG_IPAQ_HANDHELD ++ /* Allow the power management routines to override resuming */ ++ while ( h3600_power_management(PM_RESUME) ) ++ retval = pm_do_suspend(); ++#endif ++ ++ pm_send_all(PM_RESUME, (void *)0); ++ ++ return retval; ++} ++EXPORT_SYMBOL(pm_suspend); ++ ++#ifdef CONFIG_SYSCTL ++/* ++ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than ++ * linux/sysctl.h. ++ * ++ * This means our interface here won't survive long - it needs a new ++ * interface. Quick hack to get this working - use sysctl id 9999. ++ */ ++#warning ACPI broke the kernel, this interface needs to be fixed up. ++#define CTL_ACPI 9999 ++#define ACPI_S1_SLP_TYP 19 ++ ++static struct ctl_table pm_table[] = ++{ ++/* {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_suspend},*/ ++ {2, "helper", pm_helper_path, sizeof(pm_helper_path), 0644, NULL, (proc_handler *)&proc_dostring}, ++ {3, "debug", &debug_pm, sizeof(debug_pm), 0644, NULL, (proc_handler *)&proc_dointvec}, ++ {4, "helper_veto", &pm_helper_veto, sizeof(pm_helper_veto), 0644, NULL, (proc_handler *)&proc_dointvec}, ++ {0} ++}; ++ ++static struct ctl_table pm_dir_table[] = ++{ ++ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, ++ {0} ++}; ++ ++/* ++ * Initialize power interface ++ */ ++static int __init pm_init(void) ++{ ++ register_sysctl_table(pm_dir_table, 1); ++ return 0; ++} ++ ++__initcall(pm_init); ++ ++#endif ++ +--- /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/arch/arm/mach-sa1100/apm.c 2004-07-01 21:10:30.000000000 +0200 ++++ arch/arm/mach-sa1100/apm.c 2004-07-04 14:53:38.000000000 +0200 +@@ -32,9 +32,7 @@ + + #include <asm/system.h> + #include <asm/hardware.h> +-#if FIXME + #include <asm/arch-sa1100/pm.h> +-#endif + + #ifdef CONFIG_IPAQ_HANDHELD + #include <asm/arch-sa1100/h3600_hal.h> +@@ -92,6 +91,8 @@ + int magic; + struct apm_user * next; + int suser: 1; ++ int writer: 1; ++ int reader: 1; + int suspend_wait: 1; + int suspend_result; + int suspends_pending; +@@ -111,7 +112,7 @@ + /* + * Local variables + */ +-//static int suspends_pending; ++static int suspends_pending; + //static int standbys_pending; + //static int ignore_normal_resume; + +@@ -129,8 +130,6 @@ + #else + static int power_off = 1; + #endif +-static int exit_kapmd; +-static int kapmd_running; + + static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); + static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); +@@ -190,6 +189,42 @@ + return as->events[as->event_tail]; + } + ++static void queue_event(apm_event_t event, struct apm_user *sender) ++{ ++ struct apm_user * as; ++ ++ if (user_list == NULL) ++ return; ++ for (as = user_list; as != NULL; as = as->next) { ++ if ((as == sender) || (!as->reader)) ++ continue; ++ as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; ++ if (as->event_head == as->event_tail) { ++ static int notified; ++ ++ if (notified++ == 0) ++ printk(KERN_ERR "apm: an event queue overflowed\n"); ++ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; ++ } ++ as->events[as->event_head] = event; ++ if ((!as->suser) || (!as->writer)) ++ continue; ++ switch (event) { ++ case APM_SYS_SUSPEND: ++ case APM_USER_SUSPEND: ++ as->suspends_pending++; ++ suspends_pending++; ++ break; ++ ++ case APM_SYS_STANDBY: ++ case APM_USER_STANDBY: ++ as->standbys_pending++; ++ break; ++ } ++ } ++ wake_up_interruptible(&apm_waitqueue); ++} ++ + static int check_apm_user(struct apm_user *as, const char *func) + { + if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { +@@ -228,7 +263,6 @@ + i = count; + while ((i >= sizeof(event)) && !queue_empty(as)) { + event = get_queued_event(as); +- printk(" do_read: event=%d\n", event); + if (copy_to_user(buf, &event, sizeof(event))) { + if (i < count) + break; +@@ -280,9 +314,17 @@ + return -EPERM; + switch (cmd) { + case APM_IOC_SUSPEND: +-#if FIXME +- pm_suggest_suspend(); +-#endif ++ if (as->suspends_read > 0) { ++ as->suspends_read--; ++ as->suspends_pending--; ++ suspends_pending--; ++ } else { ++ queue_event(APM_USER_SUSPEND, as); ++ } ++ ++ if (suspends_pending <= 0) ++ wake_up(&apm_suspend_waitqueue); ++ + break; + default: + return -EINVAL; +@@ -299,6 +341,20 @@ + return 0; + filp->private_data = NULL; + lock_kernel(); ++ if (user_list == as) ++ user_list = as->next; ++ else { ++ struct apm_user * as1; ++ ++ for (as1 = user_list; ++ (as1 != NULL) && (as1->next != as); ++ as1 = as1->next) ++ ; ++ if (as1 == NULL) ++ printk(KERN_ERR "apm: filp not in user list\n"); ++ else ++ as1->next = as->next; ++ } + unlock_kernel(); + kfree(as); + return 0; +@@ -326,6 +382,8 @@ + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); ++ as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; ++ as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; + as->next = user_list; + user_list = as; + filp->private_data = as; +@@ -409,34 +467,6 @@ + return p - buf; + } + +-#ifndef MODULE +-static int __init apm_setup(char *str) +-{ +- int invert; +- +- while ((str != NULL) && (*str != '\0')) { +- if (strncmp(str, "off", 3) == 0) +- apm_disabled = 1; +- if (strncmp(str, "on", 2) == 0) +- apm_disabled = 0; +- invert = (strncmp(str, "no-", 3) == 0); +- if (invert) +- str += 3; +- if (strncmp(str, "debug", 5) == 0) +- debug = !invert; +- if ((strncmp(str, "power-off", 9) == 0) || +- (strncmp(str, "power_off", 9) == 0)) +- power_off = !invert; +- str = strchr(str, ','); +- if (str != NULL) +- str += strspn(str, ", \t"); +- } +- return 1; +-} +- +-__setup("apm=", apm_setup); +-#endif +- + static struct file_operations apm_bios_fops = { + owner: THIS_MODULE, + read: do_read, +@@ -454,6 +484,48 @@ + + #define APM_INIT_ERROR_RETURN return -1 + ++static pid_t apmd_pid; ++static DECLARE_COMPLETION(apmd_exited); ++ ++static int apm(void *unused) ++{ ++ unsigned short bx; ++ unsigned short cx; ++ unsigned short dx; ++ int error; ++ char * power_stat; ++ char * bat_stat; ++ DECLARE_WAITQUEUE(wait, current); ++ struct apm_user au, *as; ++ ++ lock_kernel(); ++ ++ daemonize(); ++ ++ strcpy(current->comm, "kapmd"); ++ ++ as = &au; ++ as->magic = APM_BIOS_MAGIC; ++ as->event_tail = as->event_head = 0; ++ as->suspends_pending = as->standbys_pending = 0; ++ as->suspends_read = as->standbys_read = 0; ++ as->suser = 1; ++ as->writer = 1; ++ as->reader = 0; ++ ++ while (!signal_pending (current)) { ++ interruptible_sleep_on(&apm_suspend_waitqueue); ++ ++ pm_suggest_suspend(); ++ ++ queue_event(APM_NORMAL_RESUME, as); ++ } ++ ++ unlock_kernel(); ++ ++ complete_and_exit(&apmd_exited, 0); ++} ++ + /* + * Just start the APM thread. We do NOT want to do APM BIOS + * calls from anything but the APM thread, if for no other reason +@@ -492,6 +564,8 @@ + + misc_register(&apm_device); + ++ apmd_pid = kernel_thread(apm, NULL, 0); ++ + return 0; + } + +@@ -499,11 +573,10 @@ + { + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); ++ kill_proc (apmd_pid, SIGTERM, 1); ++ wait_for_completion(&apmd_exited); + if (power_off) + pm_power_off = NULL; +- exit_kapmd = 1; +- while (kapmd_running) +- schedule(); + pm_active = 0; + } + +@@ -512,6 +585,7 @@ + + MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell"); + MODULE_DESCRIPTION("A minimal emulation of APM"); ++MODULE_LICENSE("GPL"); + MODULE_PARM(debug, "i"); + MODULE_PARM_DESC(debug, "Enable debug mode"); + MODULE_PARM(power_off, "i"); +diff -bBaruN /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/include/asm-arm/arch-sa1100/pm.h include/asm-arm/arch/pm.h +--- /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/include/asm-arm/arch-sa1100/pm.h 1970-01-01 01:00:00.000000000 +0100 ++++ include/asm-arm/arch-sa1100/pm.h 2004-07-04 16:47:18.000000000 +0200 +@@ -0,0 +1,20 @@ ++/* ++ * ++ * Declarations for ARM Linux Power Management ++ * ++ * Copyright 2002 Compaq Computer Corporation. ++ * ++ * 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. ++ * ++ * Author: Jamey Hicks. ++ * ++ */ ++ ++ ++extern int (*pm_suggest_suspend_hook)(int state); ++extern int (*pm_sysctl_suspend_hook)(int state); ++extern int pm_use_sbin_pm_helper; ++extern int pm_suspend(void); ++extern int pm_suggest_suspend(void); /* triggers /sbin/pm_helper or queueing event to apmd */ +--- /mnt/bdisk/openembedded/oetmp/work/opensimpad-64+0-2.4.25-vrs2-pxa1-jpm1-r6/linux-2.4.25/arch/arm/mach-sa1100/Makefile 2004-07-04 19:39:48.000000000 +0200 ++++ arch/arm/mach-sa1100/Makefile 2004-07-04 17:11:35.000000000 +0200 +@@ -19,7 +19,7 @@ + flexanet.o freebird.o frodo.o generic.o h3600.o \ + huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \ + system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o \ +- simpad.o ++ simpad.o pm-sa1100.o + + # These aren't present yet, and prevents a plain -ac kernel building. + # hwtimer.o +@@ -105,7 +105,7 @@ + obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o + + # Miscelaneous functions +-obj-$(CONFIG_PM) += pm.o sleep.o ++obj-$(CONFIG_PM) += pm-sa1100.o sleep.o + obj-$(CONFIG_APM) += apm.o + + # SIMpad specific +--- /mnt/bdisk/openembedded/oetmp/work/opensimpad-64+0-2.4.25-vrs2-pxa1-jpm1-r6/linux-2.4.25/arch/arm/mach-sa1100/pm-sa1100.c 1970-01-01 01:00:00.000000000 +0100 ++++ arch/arm/mach-sa1100/pm-sa1100.c 2004-07-04 17:11:11.000000000 +0200 +@@ -0,0 +1,225 @@ ++/* ++ * SA1100 Power Management Routines ++ * ++ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License. ++ * ++ * History: ++ * ++ * 2001-02-06: Cliff Brake Initial code ++ * ++ * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> & ++ * Chester Kuo <chester@linux.org.tw> ++ * Save more value for the resume function! Support ++ * Bitsy/Assabet/Freebird board ++ * ++ * 2001-08-29: Nicolas Pitre <nico@cam.org> ++ * Cleaned up, pushed platform dependent stuff ++ * in the platform specific files. ++ * ++ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. ++ * Storage is local on the stack now. ++ */ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/pm.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include <linux/interrupt.h> ++#include <linux/sysctl.h> ++#include <linux/errno.h> ++#include <linux/cpufreq.h> ++ ++#include <asm/hardware.h> ++#include <asm/memory.h> ++#include <asm/system.h> ++#include <asm/leds.h> ++ ++ ++#ifdef CONFIG_IPAQ_HANDHELD ++#include <asm/arch/h3600_asic.h> ++#endif ++ ++#define __KERNEL_SYSCALLS__ ++#include <linux/unistd.h> ++ ++extern void sa1100_cpu_suspend(void); ++extern void sa1100_cpu_resume(void); ++extern int debug_pm; ++ ++#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x ++#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] ++ ++/* ++ * List of global SA11x0 peripheral registers to preserve. ++ * More ones like CP and general purpose register values are preserved ++ * with the stack location in sleep.S. ++ */ ++enum { SLEEP_SAVE_START = 0, ++ ++ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, ++ SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, ++ ++ SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR, ++ SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, ++ ++ SLEEP_SAVE_ICMR, ++#ifdef CONFIG_SA1100_SIMPAD ++ SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */ ++#endif ++ SLEEP_SAVE_Ser1SDCR0, ++ ++ SLEEP_SAVE_PWER, ++ SLEEP_SAVE_MSC1, SLEEP_SAVE_MSC2, ++ ++ SLEEP_SAVE_SIZE ++}; ++ ++ ++int pm_do_suspend(void) ++{ ++ unsigned long sleep_save[SLEEP_SAVE_SIZE]; ++ ++ cli(); ++ ++ leds_event(led_stop); ++ ++ /* preserve current time */ ++ RCNR = xtime.tv_sec; ++ ++ /* save vital registers */ ++ SAVE(OSCR); ++ SAVE(OSMR0); ++ SAVE(OSMR1); ++ SAVE(OSMR2); ++ SAVE(OSMR3); ++ SAVE(OIER); ++ ++ SAVE(GPDR); ++ SAVE(GRER); ++ SAVE(GFER); ++ SAVE(GAFR); ++ ++ SAVE(PPDR); ++ SAVE(PPSR); ++ SAVE(PPAR); ++ SAVE(PSDR); ++ ++ SAVE(Ser1SDCR0); ++ ++ SAVE(ICMR); ++#ifdef CONFIG_SA1100_SIMPAD ++ SAVE(MECR); ++#endif ++ SAVE(PWER); ++ SAVE(MSC1); ++ SAVE(MSC2); ++ ++ /* ... maybe a global variable initialized by arch code to set this? */ ++ GRER &= PWER; ++ GFER &= PWER; ++ // Ugly, but I need the AC inserted event ++ // In the future, we're going to care about DCD and USB interrupts as well ++ if ( machine_is_h3800()) { ++#ifdef CONFIG_IPAQ_HANDHELD ++ GFER = GPIO_H3800_AC_IN; ++#endif ++ } else { ++ GFER = 0; ++ if (machine_is_jornada56x()) { ++ /* jca */ ++ GFER = PWER; ++ ICMR |= PWER; ++ } ++ } ++ GEDR = GEDR; ++ ++ /* Clear previous reset status */ ++ RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; ++ ++ /* set resume return address */ ++ PSPR = virt_to_phys(sa1100_cpu_resume); ++ ++ /* go zzz */ ++ sa1100_cpu_suspend(); ++ ++ /* ensure not to come back here if it wasn't intended */ ++ PSPR = 0; ++ ++ if (debug_pm) ++ printk(KERN_CRIT "*** made it back from resume\n"); ++ ++#ifdef CONFIG_IPAQ_HANDHELD ++ if ( machine_is_ipaq()) { ++ ipaq_model_ops.gedr = GEDR; ++ ipaq_model_ops.icpr = ICPR; ++ } ++#endif ++ ++ /* restore registers */ ++ RESTORE(GPDR); ++ RESTORE(GRER); ++ RESTORE(GFER); ++ RESTORE(GAFR); ++ ++ /* clear any edge detect bit */ ++ GEDR = GEDR; ++ ++ RESTORE(PPDR); ++ RESTORE(PPSR); ++ RESTORE(PPAR); ++ RESTORE(PSDR); ++ ++ RESTORE(Ser1SDCR0); ++ ++ PSSR = PSSR_PH; ++ ++ RESTORE(OSMR0); ++ RESTORE(OSMR1); ++ RESTORE(OSMR2); ++ RESTORE(OSMR3); ++ RESTORE(OSCR); ++ RESTORE(OIER); ++ ++#ifdef CONFIG_IPAQ_HANDHELD ++/* OSMR0 may have fired before we went to sleep, but after interrupts ++ were shut off. Set OSMR0 to something plausible */ ++ OSMR0 = OSCR + LATCH; ++#endif ++ ICLR = 0; ++ ICCR = 1; ++ RESTORE(ICMR); ++#ifdef CONFIG_SA1100_SIMPAD ++ RESTORE(MECR); ++#endif ++ RESTORE(PWER); ++ RESTORE(MSC1); ++ RESTORE(MSC2); ++ /* restore current time */ ++ xtime.tv_sec = RCNR; ++ ++ leds_event(led_start); ++ ++ sti(); ++ ++ if (debug_pm) ++ printk("interrupts are enabled\n"); ++ ++ /* ++ * Restore the CPU frequency settings. ++ */ ++#ifdef CONFIG_CPU_FREQ ++ cpufreq_restore(); ++#endif ++ return 0; ++} ++ ++unsigned long sleep_phys_sp(void *sp) ++{ ++ return virt_to_phys(sp); ++} ++ ++#include "pm-common.c" |