1 --- /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
2 +++ arch/arm/mach-sa1100/pm-common.c 2004-07-04 14:56:34.000000000 +0200
5 + * SA1100 Power Management Routines
7 + * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
9 + * This program is free software; you can redistribute it and/or
10 + * modify it under the terms of the GNU General Public License.
14 + * 2001-02-06: Cliff Brake Initial code
16 + * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
17 + * Chester Kuo <chester@linux.org.tw>
18 + * Save more value for the resume function! Support
19 + * Bitsy/Assabet/Freebird board
21 + * 2001-08-29: Nicolas Pitre <nico@cam.org>
22 + * Cleaned up, pushed platform dependent stuff
23 + * in the platform specific files.
25 + * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
26 + * Storage is local on the stack now.
28 +#include <linux/config.h>
29 +#include <linux/module.h>
30 +#include <linux/init.h>
31 +#include <linux/pm.h>
32 +#include <linux/slab.h>
33 +#include <linux/sched.h>
34 +#include <linux/interrupt.h>
35 +#include <linux/sysctl.h>
36 +#include <linux/errno.h>
37 +#include <linux/cpufreq.h>
39 +#include <asm/hardware.h>
40 +#include <asm/memory.h>
41 +#include <asm/system.h>
42 +#include <asm/leds.h>
43 +#include <asm/uaccess.h>
46 +#ifdef CONFIG_IPAQ_HANDHELD
47 +#include <asm/arch-sa1100/h3600_asic.h>
50 +#define __KERNEL_SYSCALLS__
51 +#include <linux/unistd.h>
60 +static char pm_helper_path[128] = "/sbin/pm_helper";
61 +extern int exec_usermodehelper(char *path, char **argv, char **envp);
63 +static int pm_helper_veto = 0;
66 +run_sbin_pm_helper( pm_request_t action )
69 + char *argv[3], *envp[8];
71 + if (!pm_helper_path[0])
74 + if ( action != PM_SUSPEND && action != PM_RESUME )
78 + current->uid = current->gid = 0;
81 + argv[i++] = pm_helper_path;
82 + argv[i++] = (action == PM_RESUME ? "resume" : "suspend");
86 + /* minimal command environment */
87 + envp[i++] = "HOME=/";
88 + envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
91 + /* other stuff we want to pass to /sbin/pm_helper */
92 + return exec_usermodehelper (argv [0], argv, envp);
96 + * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend.
98 +int (*pm_suggest_suspend_hook)(int state);
99 +EXPORT_SYMBOL(pm_suggest_suspend_hook);
102 + * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume
104 +int pm_use_sbin_pm_helper = 1;
105 +EXPORT_SYMBOL(pm_use_sbin_pm_helper);
108 + * If sysctl_pm_do_suspend_hook is non-NULL, it is called by sysctl_pm_do_suspend.
109 + * If it returns a true value, then pm_suspend is not called.
110 + * Use this to hook in apmd, for now.
112 +int (*pm_sysctl_suspend_hook)(int state);
113 +EXPORT_SYMBOL(pm_sysctl_suspend_hook);
115 +int pm_suspend(void);
117 +int pm_suggest_suspend(void)
121 + if (pm_suggest_suspend_hook) {
122 + if (pm_suggest_suspend_hook(PM_SUSPEND))
126 + if (pm_use_sbin_pm_helper) {
130 + unsigned int old_fs;
132 + pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 );
137 + printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid);
139 + old_fs = get_fs ();
140 + set_fs (get_ds ());
141 + res = waitpid(pid, &status, __WCLONE);
144 + if ( pid != res ) {
146 + printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status );
151 + /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/
152 + if (( status & 0xff7f ) != 0 ) {
153 + if (pm_helper_veto) {
155 + printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8);
159 + printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8);
165 + printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ );
167 + if (pm_sysctl_suspend_hook) {
168 + if (pm_sysctl_suspend_hook(PM_SUSPEND))
172 + retval = pm_suspend();
175 + printk(KERN_CRIT "pm_suspend returned %d\n", retval);
179 + if (pm_use_sbin_pm_helper) {
183 + printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__);
185 + pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 );
189 + if ( pid != waitpid ( pid, NULL, __WCLONE ))
196 +EXPORT_SYMBOL(pm_suggest_suspend);
200 + * Send us to sleep.
202 +int pm_suspend(void)
206 + retval = pm_send_all(PM_SUSPEND, (void *)3);
210 +#ifdef CONFIG_IPAQ_HANDHELD
211 + retval = h3600_power_management(PM_SUSPEND);
213 + pm_send_all(PM_RESUME, (void *)0);
218 + retval = pm_do_suspend();
220 +#ifdef CONFIG_IPAQ_HANDHELD
221 + /* Allow the power management routines to override resuming */
222 + while ( h3600_power_management(PM_RESUME) )
223 + retval = pm_do_suspend();
226 + pm_send_all(PM_RESUME, (void *)0);
230 +EXPORT_SYMBOL(pm_suspend);
232 +#ifdef CONFIG_SYSCTL
234 + * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
237 + * This means our interface here won't survive long - it needs a new
238 + * interface. Quick hack to get this working - use sysctl id 9999.
240 +#warning ACPI broke the kernel, this interface needs to be fixed up.
241 +#define CTL_ACPI 9999
242 +#define ACPI_S1_SLP_TYP 19
244 +static struct ctl_table pm_table[] =
246 +/* {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_suspend},*/
247 + {2, "helper", pm_helper_path, sizeof(pm_helper_path), 0644, NULL, (proc_handler *)&proc_dostring},
248 + {3, "debug", &debug_pm, sizeof(debug_pm), 0644, NULL, (proc_handler *)&proc_dointvec},
249 + {4, "helper_veto", &pm_helper_veto, sizeof(pm_helper_veto), 0644, NULL, (proc_handler *)&proc_dointvec},
253 +static struct ctl_table pm_dir_table[] =
255 + {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
260 + * Initialize power interface
262 +static int __init pm_init(void)
264 + register_sysctl_table(pm_dir_table, 1);
268 +__initcall(pm_init);
272 --- /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
273 +++ arch/arm/mach-sa1100/apm.c 2004-07-04 14:53:38.000000000 +0200
276 #include <asm/system.h>
277 #include <asm/hardware.h>
279 #include <asm/arch-sa1100/pm.h>
282 #ifdef CONFIG_IPAQ_HANDHELD
283 #include <asm/arch-sa1100/h3600_hal.h>
286 struct apm_user * next;
292 int suspends_pending;
297 -//static int suspends_pending;
298 +static int suspends_pending;
299 //static int standbys_pending;
300 //static int ignore_normal_resume;
304 static int power_off = 1;
306 -static int exit_kapmd;
307 -static int kapmd_running;
309 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
310 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
312 return as->events[as->event_tail];
315 +static void queue_event(apm_event_t event, struct apm_user *sender)
317 + struct apm_user * as;
319 + if (user_list == NULL)
321 + for (as = user_list; as != NULL; as = as->next) {
322 + if ((as == sender) || (!as->reader))
324 + as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
325 + if (as->event_head == as->event_tail) {
326 + static int notified;
328 + if (notified++ == 0)
329 + printk(KERN_ERR "apm: an event queue overflowed\n");
330 + as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
332 + as->events[as->event_head] = event;
333 + if ((!as->suser) || (!as->writer))
336 + case APM_SYS_SUSPEND:
337 + case APM_USER_SUSPEND:
338 + as->suspends_pending++;
339 + suspends_pending++;
342 + case APM_SYS_STANDBY:
343 + case APM_USER_STANDBY:
344 + as->standbys_pending++;
348 + wake_up_interruptible(&apm_waitqueue);
351 static int check_apm_user(struct apm_user *as, const char *func)
353 if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
356 while ((i >= sizeof(event)) && !queue_empty(as)) {
357 event = get_queued_event(as);
358 - printk(" do_read: event=%d\n", event);
359 if (copy_to_user(buf, &event, sizeof(event))) {
365 case APM_IOC_SUSPEND:
367 - pm_suggest_suspend();
369 + if (as->suspends_read > 0) {
370 + as->suspends_read--;
371 + as->suspends_pending--;
372 + suspends_pending--;
374 + queue_event(APM_USER_SUSPEND, as);
377 + if (suspends_pending <= 0)
378 + wake_up(&apm_suspend_waitqueue);
385 filp->private_data = NULL;
387 + if (user_list == as)
388 + user_list = as->next;
390 + struct apm_user * as1;
392 + for (as1 = user_list;
393 + (as1 != NULL) && (as1->next != as);
397 + printk(KERN_ERR "apm: filp not in user list\n");
399 + as1->next = as->next;
405 * privileged operation -- cevans
407 as->suser = capable(CAP_SYS_ADMIN);
408 + as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
409 + as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
410 as->next = user_list;
412 filp->private_data = as;
418 -static int __init apm_setup(char *str)
422 - while ((str != NULL) && (*str != '\0')) {
423 - if (strncmp(str, "off", 3) == 0)
425 - if (strncmp(str, "on", 2) == 0)
427 - invert = (strncmp(str, "no-", 3) == 0);
430 - if (strncmp(str, "debug", 5) == 0)
432 - if ((strncmp(str, "power-off", 9) == 0) ||
433 - (strncmp(str, "power_off", 9) == 0))
434 - power_off = !invert;
435 - str = strchr(str, ',');
437 - str += strspn(str, ", \t");
442 -__setup("apm=", apm_setup);
445 static struct file_operations apm_bios_fops = {
450 #define APM_INIT_ERROR_RETURN return -1
452 +static pid_t apmd_pid;
453 +static DECLARE_COMPLETION(apmd_exited);
455 +static int apm(void *unused)
463 + DECLARE_WAITQUEUE(wait, current);
464 + struct apm_user au, *as;
470 + strcpy(current->comm, "kapmd");
473 + as->magic = APM_BIOS_MAGIC;
474 + as->event_tail = as->event_head = 0;
475 + as->suspends_pending = as->standbys_pending = 0;
476 + as->suspends_read = as->standbys_read = 0;
482 + interruptible_sleep_on(&apm_suspend_waitqueue);
483 + if (signal_pending (current))
486 + pm_suggest_suspend();
488 + queue_event(APM_NORMAL_RESUME, as);
493 + complete_and_exit(&apmd_exited, 0);
497 * Just start the APM thread. We do NOT want to do APM BIOS
498 * calls from anything but the APM thread, if for no other reason
501 misc_register(&apm_device);
503 + apmd_pid = kernel_thread(apm, NULL, 0);
508 @@ -499,11 +573,10 @@
510 misc_deregister(&apm_device);
511 remove_proc_entry("apm", NULL);
512 + kill_proc (apmd_pid, SIGTERM, 1);
513 + wait_for_completion(&apmd_exited);
517 - while (kapmd_running)
524 MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell");
525 MODULE_DESCRIPTION("A minimal emulation of APM");
526 +MODULE_LICENSE("GPL");
527 MODULE_PARM(debug, "i");
528 MODULE_PARM_DESC(debug, "Enable debug mode");
529 MODULE_PARM(power_off, "i");
530 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
531 --- /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
532 +++ include/asm-arm/arch-sa1100/pm.h 2004-07-04 16:47:18.000000000 +0200
536 + * Declarations for ARM Linux Power Management
538 + * Copyright 2002 Compaq Computer Corporation.
540 + * This program is free software; you can redistribute it and/or modify
541 + * it under the terms of the GNU General Public License version 2 as
542 + * published by the Free Software Foundation.
544 + * Author: Jamey Hicks.
549 +extern int (*pm_suggest_suspend_hook)(int state);
550 +extern int (*pm_sysctl_suspend_hook)(int state);
551 +extern int pm_use_sbin_pm_helper;
552 +extern int pm_suspend(void);
553 +extern int pm_suggest_suspend(void); /* triggers /sbin/pm_helper or queueing event to apmd */
554 --- /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
555 +++ arch/arm/mach-sa1100/Makefile 2004-07-04 17:11:35.000000000 +0200
557 flexanet.o freebird.o frodo.o generic.o h3600.o \
558 huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \
559 system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o \
561 + simpad.o pm-sa1100.o
563 # These aren't present yet, and prevents a plain -ac kernel building.
566 obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
568 # Miscelaneous functions
569 -obj-$(CONFIG_PM) += pm.o sleep.o
570 +obj-$(CONFIG_PM) += pm-sa1100.o sleep.o
571 obj-$(CONFIG_APM) += apm.o
574 --- /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
575 +++ arch/arm/mach-sa1100/pm-sa1100.c 2004-07-04 17:11:11.000000000 +0200
578 + * SA1100 Power Management Routines
580 + * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
582 + * This program is free software; you can redistribute it and/or
583 + * modify it under the terms of the GNU General Public License.
587 + * 2001-02-06: Cliff Brake Initial code
589 + * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
590 + * Chester Kuo <chester@linux.org.tw>
591 + * Save more value for the resume function! Support
592 + * Bitsy/Assabet/Freebird board
594 + * 2001-08-29: Nicolas Pitre <nico@cam.org>
595 + * Cleaned up, pushed platform dependent stuff
596 + * in the platform specific files.
598 + * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
599 + * Storage is local on the stack now.
601 +#include <linux/config.h>
602 +#include <linux/module.h>
603 +#include <linux/init.h>
604 +#include <linux/pm.h>
605 +#include <linux/slab.h>
606 +#include <linux/sched.h>
607 +#include <linux/interrupt.h>
608 +#include <linux/sysctl.h>
609 +#include <linux/errno.h>
610 +#include <linux/cpufreq.h>
612 +#include <asm/hardware.h>
613 +#include <asm/memory.h>
614 +#include <asm/system.h>
615 +#include <asm/leds.h>
618 +#ifdef CONFIG_IPAQ_HANDHELD
619 +#include <asm/arch/h3600_asic.h>
622 +#define __KERNEL_SYSCALLS__
623 +#include <linux/unistd.h>
625 +extern void sa1100_cpu_suspend(void);
626 +extern void sa1100_cpu_resume(void);
627 +extern int debug_pm;
629 +#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
630 +#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
633 + * List of global SA11x0 peripheral registers to preserve.
634 + * More ones like CP and general purpose register values are preserved
635 + * with the stack location in sleep.S.
637 +enum { SLEEP_SAVE_START = 0,
639 + SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
640 + SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
642 + SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
643 + SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
646 +#ifdef CONFIG_SA1100_SIMPAD
647 + SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */
649 + SLEEP_SAVE_Ser1SDCR0,
652 + SLEEP_SAVE_MSC1, SLEEP_SAVE_MSC2,
658 +int pm_do_suspend(void)
660 + unsigned long sleep_save[SLEEP_SAVE_SIZE];
664 + leds_event(led_stop);
666 + /* preserve current time */
667 + RCNR = xtime.tv_sec;
669 + /* save vital registers */
690 +#ifdef CONFIG_SA1100_SIMPAD
697 + /* ... maybe a global variable initialized by arch code to set this? */
700 + // Ugly, but I need the AC inserted event
701 + // In the future, we're going to care about DCD and USB interrupts as well
702 + if ( machine_is_h3800()) {
703 +#ifdef CONFIG_IPAQ_HANDHELD
704 + GFER = GPIO_H3800_AC_IN;
708 + if (machine_is_jornada56x()) {
716 + /* Clear previous reset status */
717 + RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
719 + /* set resume return address */
720 + PSPR = virt_to_phys(sa1100_cpu_resume);
723 + sa1100_cpu_suspend();
725 + /* ensure not to come back here if it wasn't intended */
729 + printk(KERN_CRIT "*** made it back from resume\n");
731 +#ifdef CONFIG_IPAQ_HANDHELD
732 + if ( machine_is_ipaq()) {
733 + ipaq_model_ops.gedr = GEDR;
734 + ipaq_model_ops.icpr = ICPR;
738 + /* restore registers */
744 + /* clear any edge detect bit */
752 + RESTORE(Ser1SDCR0);
763 +#ifdef CONFIG_IPAQ_HANDHELD
764 +/* OSMR0 may have fired before we went to sleep, but after interrupts
765 + were shut off. Set OSMR0 to something plausible */
766 + OSMR0 = OSCR + LATCH;
771 +#ifdef CONFIG_SA1100_SIMPAD
777 + /* restore current time */
778 + xtime.tv_sec = RCNR;
780 + leds_event(led_start);
785 + printk("interrupts are enabled\n");
788 + * Restore the CPU frequency settings.
790 +#ifdef CONFIG_CPU_FREQ
796 +unsigned long sleep_phys_sp(void *sp)
798 + return virt_to_phys(sp);
801 +#include "pm-common.c"