]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / opensimpad-2.4.25-vrs2-pxa1-jpm1 / simpad-apm.diff
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
3 @@ -0,0 +1,268 @@
4 +/*
5 + * SA1100 Power Management Routines
6 + *
7 + * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
8 + *
9 + * This program is free software; you can redistribute it and/or
10 + * modify it under the terms of the GNU General Public License.
11 + *
12 + * History:
13 + *
14 + * 2001-02-06: Cliff Brake         Initial code
15 + *
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
20 + *
21 + * 2001-08-29: Nicolas Pitre <nico@cam.org>
22 + *                     Cleaned up, pushed platform dependent stuff
23 + *                     in the platform specific files.
24 + *
25 + * 2002-05-27: Nicolas Pitre   Killed sleep.h and the kmalloced save array.
26 + *                             Storage is local on the stack now.
27 + */
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>
38 +
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>
44 +
45 +
46 +#ifdef CONFIG_IPAQ_HANDHELD
47 +#include <asm/arch-sa1100/h3600_asic.h>
48 +#endif
49 +
50 +#define __KERNEL_SYSCALLS__
51 +#include <linux/unistd.h>
52 +
53 +/*
54 + * Debug macros
55 + */
56 +#undef DEBUG
57 +
58 +\f
59 +
60 +static char pm_helper_path[128] = "/sbin/pm_helper";
61 +extern int exec_usermodehelper(char *path, char **argv, char **envp);
62 +int debug_pm = 0;
63 +static int pm_helper_veto = 0;
64 +
65 +static int
66 +run_sbin_pm_helper( pm_request_t action )
67 +{
68 +       int i;
69 +       char *argv[3], *envp[8];
70 +
71 +       if (!pm_helper_path[0])
72 +               return 2;
73 +
74 +       if ( action != PM_SUSPEND && action != PM_RESUME )
75 +               return 1;
76 +
77 +       /* Be root */
78 +       current->uid = current->gid = 0;
79 +
80 +       i = 0;
81 +       argv[i++] = pm_helper_path;
82 +       argv[i++] = (action == PM_RESUME ? "resume" : "suspend");
83 +       argv[i] = 0;
84 +
85 +       i = 0;
86 +       /* minimal command environment */
87 +       envp[i++] = "HOME=/";
88 +       envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
89 +       envp[i] = 0;
90 +
91 +       /* other stuff we want to pass to /sbin/pm_helper */
92 +       return exec_usermodehelper (argv [0], argv, envp);
93 +}
94 +
95 +/*
96 + * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend.
97 + */
98 +int (*pm_suggest_suspend_hook)(int state);
99 +EXPORT_SYMBOL(pm_suggest_suspend_hook);
100 +
101 +/*
102 + * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume
103 + */
104 +int pm_use_sbin_pm_helper = 1;
105 +EXPORT_SYMBOL(pm_use_sbin_pm_helper);
106 +
107 +/*
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.
111 + */
112 +int (*pm_sysctl_suspend_hook)(int state);
113 +EXPORT_SYMBOL(pm_sysctl_suspend_hook);
114 +
115 +int pm_suspend(void);
116 +
117 +int pm_suggest_suspend(void)
118 +{
119 +       int retval;
120 +
121 +       if (pm_suggest_suspend_hook) {
122 +               if (pm_suggest_suspend_hook(PM_SUSPEND))
123 +                       return 0;
124 +       }
125 +       
126 +       if (pm_use_sbin_pm_helper) {
127 +               pid_t pid;
128 +               int res;
129 +               int status = 0;
130 +               unsigned int old_fs;
131 +               
132 +               pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 );
133 +               if ( pid < 0 )
134 +                       return pid;
135 +
136 +               if (debug_pm)
137 +                       printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid);    
138 +                       
139 +               old_fs = get_fs ();
140 +               set_fs (get_ds ());
141 +               res = waitpid(pid, &status, __WCLONE);
142 +               set_fs (old_fs);
143 +       
144 +               if ( pid != res ) {
145 +                       if (debug_pm)
146 +                               printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status );
147 +                       
148 +                       return -1;
149 +               }
150 +                       
151 +               /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/
152 +               if (( status & 0xff7f ) != 0 ) {
153 +                       if (pm_helper_veto) {
154 +                               if (debug_pm)
155 +                                       printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8);
156 +                               return -1;
157 +                       } else {
158 +                               if (debug_pm)
159 +                                       printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8);
160 +                       }
161 +               }
162 +       }
163 +
164 +       if (debug_pm)
165 +               printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ );
166 +
167 +       if (pm_sysctl_suspend_hook) {
168 +               if (pm_sysctl_suspend_hook(PM_SUSPEND))
169 +                       return 0;
170 +       }
171 +
172 +       retval = pm_suspend();
173 +       if (retval) {
174 +               if (debug_pm)
175 +                       printk(KERN_CRIT "pm_suspend returned %d\n", retval);
176 +               return retval;
177 +       }
178 +
179 +       if (pm_use_sbin_pm_helper) {
180 +               pid_t pid;
181 +               
182 +               if (debug_pm)
183 +                       printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__);
184 +
185 +               pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 );
186 +               if ( pid < 0 )
187 +                       return pid;
188 +                       
189 +               if ( pid != waitpid ( pid, NULL, __WCLONE ))
190 +                       return -1;
191 +       }
192 +
193 +       return 0;
194 +}
195 +
196 +EXPORT_SYMBOL(pm_suggest_suspend);
197 +
198 +
199 +/*
200 + * Send us to sleep.
201 + */
202 +int pm_suspend(void)
203 +{
204 +       int retval;
205 +
206 +       retval = pm_send_all(PM_SUSPEND, (void *)3);
207 +       if ( retval )
208 +               return retval;
209 +
210 +#ifdef CONFIG_IPAQ_HANDHELD
211 +       retval = h3600_power_management(PM_SUSPEND);
212 +       if (retval) {
213 +               pm_send_all(PM_RESUME, (void *)0);
214 +               return retval;
215 +       }
216 +#endif
217 +
218 +       retval = pm_do_suspend();
219 +
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();
224 +#endif
225 +
226 +       pm_send_all(PM_RESUME, (void *)0);
227 +
228 +       return retval;
229 +}
230 +EXPORT_SYMBOL(pm_suspend);
231 +
232 +#ifdef CONFIG_SYSCTL
233 +/*
234 + * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
235 + * linux/sysctl.h.
236 + *
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.
239 + */
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
243 +
244 +static struct ctl_table pm_table[] =
245 +{
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},
250 +       {0}
251 +};
252 +
253 +static struct ctl_table pm_dir_table[] =
254 +{
255 +       {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
256 +       {0}
257 +};
258 +
259 +/*
260 + * Initialize power interface
261 + */
262 +static int __init pm_init(void)
263 +{
264 +       register_sysctl_table(pm_dir_table, 1);
265 +       return 0;
266 +}
267 +
268 +__initcall(pm_init);
269 +
270 +#endif
271 +
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
274 @@ -32,9 +32,7 @@
275  
276  #include <asm/system.h>
277  #include <asm/hardware.h>
278 -#if FIXME
279  #include <asm/arch-sa1100/pm.h>
280 -#endif
281  
282  #ifdef CONFIG_IPAQ_HANDHELD
283  #include <asm/arch-sa1100/h3600_hal.h>
284 @@ -92,6 +91,8 @@
285         int             magic;
286         struct apm_user *       next;
287         int             suser: 1;
288 +       int             writer: 1;
289 +       int             reader: 1;
290         int             suspend_wait: 1;
291         int             suspend_result;
292         int             suspends_pending;
293 @@ -111,7 +112,7 @@
294  /*
295   * Local variables
296   */
297 -//static int                   suspends_pending;
298 +static int                     suspends_pending;
299  //static int                   standbys_pending;
300  //static int                   ignore_normal_resume;
301  
302 @@ -129,8 +130,6 @@
303  #else
304  static int                     power_off = 1;
305  #endif
306 -static int                     exit_kapmd;
307 -static int                     kapmd_running;
308  
309  static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
310  static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
311 @@ -190,6 +189,42 @@
312         return as->events[as->event_tail];
313  }
314  
315 +static void queue_event(apm_event_t event, struct apm_user *sender)
316 +{
317 +       struct apm_user *       as;
318 +
319 +       if (user_list == NULL)
320 +               return;
321 +       for (as = user_list; as != NULL; as = as->next) {
322 +               if ((as == sender) || (!as->reader))
323 +                       continue;
324 +               as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
325 +               if (as->event_head == as->event_tail) {
326 +                       static int notified;
327 +
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;
331 +               }
332 +               as->events[as->event_head] = event;
333 +               if ((!as->suser) || (!as->writer))
334 +                       continue;
335 +               switch (event) {
336 +               case APM_SYS_SUSPEND:
337 +               case APM_USER_SUSPEND:
338 +                       as->suspends_pending++;
339 +                       suspends_pending++;
340 +                       break;
341 +
342 +               case APM_SYS_STANDBY:
343 +               case APM_USER_STANDBY:
344 +                       as->standbys_pending++;
345 +                       break;
346 +               }
347 +       }
348 +       wake_up_interruptible(&apm_waitqueue);
349 +}
350 +
351  static int check_apm_user(struct apm_user *as, const char *func)
352  {
353         if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
354 @@ -228,7 +263,6 @@
355         i = count;
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))) {
360                         if (i < count)
361                                 break;
362 @@ -280,9 +314,17 @@
363                 return -EPERM;
364         switch (cmd) {
365          case APM_IOC_SUSPEND:
366 -#if FIXME
367 -               pm_suggest_suspend();
368 -#endif
369 +               if (as->suspends_read > 0) {
370 +                       as->suspends_read--;
371 +                       as->suspends_pending--;
372 +                       suspends_pending--;
373 +               } else {
374 +                       queue_event(APM_USER_SUSPEND, as);
375 +               }
376 +
377 +               if (suspends_pending <= 0)
378 +                       wake_up(&apm_suspend_waitqueue);
379 +               
380                 break;
381         default:
382                 return -EINVAL;
383 @@ -299,6 +341,20 @@
384                 return 0;
385         filp->private_data = NULL;
386         lock_kernel();
387 +       if (user_list == as)
388 +               user_list = as->next;
389 +       else {
390 +               struct apm_user *       as1;
391 +
392 +               for (as1 = user_list;
393 +                    (as1 != NULL) && (as1->next != as);
394 +                    as1 = as1->next)
395 +                       ;
396 +               if (as1 == NULL)
397 +                       printk(KERN_ERR "apm: filp not in user list\n");
398 +               else
399 +                       as1->next = as->next;
400 +       }
401         unlock_kernel();
402         kfree(as);
403         return 0;
404 @@ -326,6 +382,8 @@
405          * privileged operation -- cevans
406          */
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;
411         user_list = as;
412         filp->private_data = as;
413 @@ -409,34 +467,6 @@
414         return p - buf;
415  }
416  
417 -#ifndef MODULE
418 -static int __init apm_setup(char *str)
419 -{
420 -       int     invert;
421 -
422 -       while ((str != NULL) && (*str != '\0')) {
423 -               if (strncmp(str, "off", 3) == 0)
424 -                       apm_disabled = 1;
425 -               if (strncmp(str, "on", 2) == 0)
426 -                       apm_disabled = 0;
427 -               invert = (strncmp(str, "no-", 3) == 0);
428 -               if (invert)
429 -                       str += 3;
430 -               if (strncmp(str, "debug", 5) == 0)
431 -                       debug = !invert;
432 -               if ((strncmp(str, "power-off", 9) == 0) ||
433 -                   (strncmp(str, "power_off", 9) == 0))
434 -                       power_off = !invert;
435 -               str = strchr(str, ',');
436 -               if (str != NULL)
437 -                       str += strspn(str, ", \t");
438 -       }
439 -       return 1;
440 -}
441 -
442 -__setup("apm=", apm_setup);
443 -#endif
444 -
445  static struct file_operations apm_bios_fops = {
446         owner:          THIS_MODULE,
447         read:           do_read,
448 @@ -454,6 +484,50 @@
449  
450  #define APM_INIT_ERROR_RETURN  return -1
451  
452 +static pid_t apmd_pid;
453 +static DECLARE_COMPLETION(apmd_exited);
454 +
455 +static int apm(void *unused)
456 +{
457 +       unsigned short  bx;
458 +       unsigned short  cx;
459 +       unsigned short  dx;
460 +       int             error;
461 +       char *          power_stat;
462 +       char *          bat_stat;
463 +       DECLARE_WAITQUEUE(wait, current);
464 +       struct apm_user au, *as;
465 +
466 +       lock_kernel();
467 +
468 +       daemonize();
469 +
470 +       strcpy(current->comm, "kapmd");
471 +
472 +       as = &au;
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;
477 +       as->suser = 1;
478 +       as->writer = 1;
479 +       as->reader = 0;
480 +
481 +       for (;;) {
482 +               interruptible_sleep_on(&apm_suspend_waitqueue);
483 +               if (signal_pending (current))
484 +                       break;
485 +
486 +               pm_suggest_suspend();
487 +
488 +               queue_event(APM_NORMAL_RESUME, as);
489 +       }
490 +
491 +       unlock_kernel();
492 +
493 +       complete_and_exit(&apmd_exited, 0);
494 +}
495 +
496  /*
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
499 @@ -492,6 +564,8 @@
500  
501         misc_register(&apm_device);
502  
503 +       apmd_pid = kernel_thread(apm, NULL, 0);
504 +
505         return 0;
506  }
507  
508 @@ -499,11 +573,10 @@
509  {
510         misc_deregister(&apm_device);
511         remove_proc_entry("apm", NULL);
512 +       kill_proc (apmd_pid, SIGTERM, 1);
513 +       wait_for_completion(&apmd_exited);
514         if (power_off)
515                 pm_power_off = NULL;
516 -       exit_kapmd = 1;
517 -       while (kapmd_running)
518 -               schedule();
519         pm_active = 0;
520  }
521  
522 @@ -512,6 +585,7 @@
523  
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
533 @@ -0,0 +1,20 @@
534 +/*
535 + *
536 + * Declarations for ARM Linux Power Management
537 + *
538 + * Copyright 2002 Compaq Computer Corporation.
539 + *
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.
543 + *
544 + * Author: Jamey Hicks.
545 + *
546 + */
547 +
548 +
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
556 @@ -19,7 +19,7 @@
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 \
560 -               simpad.o
561 +               simpad.o pm-sa1100.o
562  
563  # These aren't present yet, and prevents a plain -ac kernel building.
564  # hwtimer.o
565 @@ -105,7 +105,7 @@
566  obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
567  
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
572  
573  # SIMpad specific
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
576 @@ -0,0 +1,225 @@
577 +/*
578 + * SA1100 Power Management Routines
579 + *
580 + * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
581 + *
582 + * This program is free software; you can redistribute it and/or
583 + * modify it under the terms of the GNU General Public License.
584 + *
585 + * History:
586 + *
587 + * 2001-02-06: Cliff Brake         Initial code
588 + *
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
593 + *
594 + * 2001-08-29: Nicolas Pitre <nico@cam.org>
595 + *                     Cleaned up, pushed platform dependent stuff
596 + *                     in the platform specific files.
597 + *
598 + * 2002-05-27: Nicolas Pitre   Killed sleep.h and the kmalloced save array.
599 + *                             Storage is local on the stack now.
600 + */
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>
611 +
612 +#include <asm/hardware.h>
613 +#include <asm/memory.h>
614 +#include <asm/system.h>
615 +#include <asm/leds.h>
616 +
617 +
618 +#ifdef CONFIG_IPAQ_HANDHELD
619 +#include <asm/arch/h3600_asic.h>
620 +#endif
621 +
622 +#define __KERNEL_SYSCALLS__
623 +#include <linux/unistd.h>
624 +
625 +extern void sa1100_cpu_suspend(void);
626 +extern void sa1100_cpu_resume(void);
627 +extern int debug_pm;
628 +
629 +#define SAVE(x)                sleep_save[SLEEP_SAVE_##x] = x
630 +#define RESTORE(x)     x = sleep_save[SLEEP_SAVE_##x]
631 +
632 +/*
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.
636 + */
637 +enum { SLEEP_SAVE_START = 0,
638 +
639 +       SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
640 +       SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
641 +
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,
644 +
645 +       SLEEP_SAVE_ICMR,
646 +#ifdef CONFIG_SA1100_SIMPAD
647 +       SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */
648 +#endif
649 +       SLEEP_SAVE_Ser1SDCR0,
650 +
651 +        SLEEP_SAVE_PWER,
652 +        SLEEP_SAVE_MSC1, SLEEP_SAVE_MSC2,
653 +
654 +       SLEEP_SAVE_SIZE
655 +};
656 +
657 +
658 +int pm_do_suspend(void)
659 +{
660 +       unsigned long sleep_save[SLEEP_SAVE_SIZE];
661 +
662 +       cli();
663 +
664 +       leds_event(led_stop);
665 +
666 +       /* preserve current time */
667 +       RCNR = xtime.tv_sec;
668 +
669 +       /* save vital registers */
670 +       SAVE(OSCR);
671 +       SAVE(OSMR0);
672 +       SAVE(OSMR1);
673 +       SAVE(OSMR2);
674 +       SAVE(OSMR3);
675 +       SAVE(OIER);
676 +
677 +       SAVE(GPDR);
678 +       SAVE(GRER);
679 +       SAVE(GFER);
680 +       SAVE(GAFR);
681 +
682 +       SAVE(PPDR);
683 +       SAVE(PPSR);
684 +       SAVE(PPAR);
685 +       SAVE(PSDR);
686 +
687 +       SAVE(Ser1SDCR0);
688 +
689 +       SAVE(ICMR);
690 +#ifdef CONFIG_SA1100_SIMPAD
691 +       SAVE(MECR);
692 +#endif
693 +        SAVE(PWER);
694 +        SAVE(MSC1);
695 +        SAVE(MSC2);
696 +
697 +       /* ... maybe a global variable initialized by arch code to set this? */
698 +       GRER &= PWER;
699 +       GFER &= PWER;
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;
705 +#endif
706 +       } else {
707 +               GFER = 0;
708 +               if (machine_is_jornada56x()) {
709 +                       /* jca */
710 +                       GFER = PWER;
711 +                       ICMR |= PWER;
712 +               }
713 +       }
714 +       GEDR = GEDR;
715 +
716 +       /* Clear previous reset status */
717 +       RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
718 +
719 +       /* set resume return address */
720 +       PSPR = virt_to_phys(sa1100_cpu_resume);
721 +
722 +       /* go zzz */
723 +       sa1100_cpu_suspend();
724 +
725 +       /* ensure not to come back here if it wasn't intended */
726 +       PSPR = 0;
727 +
728 +       if (debug_pm)
729 +               printk(KERN_CRIT "*** made it back from resume\n");
730 +
731 +#ifdef CONFIG_IPAQ_HANDHELD
732 +       if ( machine_is_ipaq()) {
733 +               ipaq_model_ops.gedr = GEDR;
734 +               ipaq_model_ops.icpr = ICPR;
735 +       }
736 +#endif
737 +
738 +       /* restore registers */
739 +       RESTORE(GPDR);
740 +       RESTORE(GRER);
741 +       RESTORE(GFER);
742 +       RESTORE(GAFR);
743 +
744 +       /* clear any edge detect bit */
745 +       GEDR = GEDR;
746 +
747 +       RESTORE(PPDR);
748 +       RESTORE(PPSR);
749 +       RESTORE(PPAR);
750 +       RESTORE(PSDR);
751 +
752 +       RESTORE(Ser1SDCR0);
753 +
754 +       PSSR = PSSR_PH;
755 +
756 +       RESTORE(OSMR0);
757 +       RESTORE(OSMR1);
758 +       RESTORE(OSMR2);
759 +       RESTORE(OSMR3);
760 +       RESTORE(OSCR);
761 +       RESTORE(OIER);
762 +
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;
767 +#endif
768 +       ICLR = 0;
769 +       ICCR = 1;
770 +       RESTORE(ICMR);
771 +#ifdef CONFIG_SA1100_SIMPAD
772 +       RESTORE(MECR);
773 +#endif
774 +       RESTORE(PWER);
775 +       RESTORE(MSC1);
776 +       RESTORE(MSC2);
777 +       /* restore current time */
778 +       xtime.tv_sec = RCNR;
779 +
780 +       leds_event(led_start);
781 +       
782 +       sti();
783 +
784 +       if (debug_pm)
785 +               printk("interrupts are enabled\n");
786 +
787 +       /*
788 +        * Restore the CPU frequency settings.
789 +        */
790 +#ifdef CONFIG_CPU_FREQ
791 +       cpufreq_restore();
792 +#endif
793 +       return 0;
794 +}
795 +
796 +unsigned long sleep_phys_sp(void *sp)
797 +{
798 +       return virt_to_phys(sp);
799 +}
800 +
801 +#include "pm-common.c"