pm.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * SA1100 Power Management Routines
  3.  *
  4.  * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License.
  8.  *
  9.  * History:
  10.  *
  11.  * 2001-02-06: Cliff Brake         Initial code
  12.  *
  13.  * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
  14.  *  Chester Kuo <chester@linux.org.tw>
  15.  *  Save more value for the resume function! Support
  16.  *  Bitsy/Assabet/Freebird board
  17.  *
  18.  * 2001-08-29: Nicolas Pitre <nico@cam.org>
  19.  *  Cleaned up, pushed platform dependent stuff
  20.  *  in the platform specific files.
  21.  */
  22. #include <linux/config.h>
  23. #include <linux/init.h>
  24. #include <linux/pm.h>
  25. #include <linux/slab.h>
  26. #include <linux/sched.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/sysctl.h>
  29. #include <linux/errno.h>
  30. #include <asm/hardware.h>
  31. #include <asm/memory.h>
  32. #include <asm/system.h>
  33. #include <asm/leds.h>
  34. #include "sleep.h"
  35. /*
  36.  * Debug macros
  37.  */
  38. #undef DEBUG
  39. extern void sa1100_cpu_suspend(void);
  40. extern void sa1100_cpu_resume(void);
  41. extern unsigned long *sleep_save; /* virtual address */
  42. extern unsigned long  sleep_save_p; /* physical address */
  43. #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
  44. #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
  45. int pm_do_suspend(void)
  46. {
  47. /* set up pointer to sleep parameters */
  48. sleep_save = kmalloc(SLEEP_SAVE_SIZE*sizeof(long), GFP_ATOMIC);
  49. if (!sleep_save)
  50. return -ENOMEM;
  51. sleep_save_p = virt_to_phys(sleep_save);
  52. cli();
  53. leds_event(led_stop);
  54. /* preserve current time */
  55. RCNR = xtime.tv_sec;
  56. /* save vital registers */
  57. SAVE(OSCR);
  58. SAVE(OSMR0);
  59. SAVE(OSMR1);
  60. SAVE(OSMR2);
  61. SAVE(OSMR3);
  62. SAVE(OIER);
  63. SAVE(GPDR);
  64. SAVE(GRER);
  65. SAVE(GFER);
  66. SAVE(GAFR);
  67. SAVE(PPDR);
  68. SAVE(PPSR);
  69. SAVE(PPAR);
  70. SAVE(PSDR);
  71. SAVE(Ser1SDCR0);
  72. SAVE(ICMR);
  73. /* ... maybe a global variable initialized by arch code to set this? */
  74. GRER = PWER;
  75. GFER = 0;
  76. GEDR = GEDR;
  77. /* Clear previous reset status */
  78. RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
  79. /* set resume return address */
  80. PSPR = virt_to_phys(sa1100_cpu_resume);
  81. /* go zzz */
  82. sa1100_cpu_suspend();
  83. /* ensure not to come back here if it wasn't intended */
  84. PSPR = 0;
  85. #ifdef DEBUG
  86. printk(KERN_DEBUG "*** made it back from resumen");
  87. #endif
  88. /* restore registers */
  89. RESTORE(GPDR);
  90. RESTORE(GRER);
  91. RESTORE(GFER);
  92. RESTORE(GAFR);
  93. /* clear any edge detect bit */
  94. GEDR = GEDR;
  95. RESTORE(PPDR);
  96. RESTORE(PPSR);
  97. RESTORE(PPAR);
  98. RESTORE(PSDR);
  99. RESTORE(Ser1SDCR0);
  100. PSSR = PSSR_PH;
  101. RESTORE(OSMR0);
  102. RESTORE(OSMR1);
  103. RESTORE(OSMR2);
  104. RESTORE(OSMR3);
  105. RESTORE(OSCR);
  106. RESTORE(OIER);
  107. ICLR = 0;
  108. ICCR = 1;
  109. RESTORE(ICMR);
  110. /* restore current time */
  111. xtime.tv_sec = RCNR;
  112. leds_event(led_start);
  113. sti();
  114. kfree (sleep_save);
  115. /*
  116.  * Restore the CPU frequency settings.
  117.  */
  118. #ifdef CONFIG_CPU_FREQ
  119. cpufreq_restore();
  120. #endif
  121. return 0;
  122. }
  123. #ifdef CONFIG_SYSCTL
  124. /*
  125.  * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
  126.  * linux/sysctl.h.
  127.  *
  128.  * This means our interface here won't survive long - it needs a new
  129.  * interface.  Quick hack to get this working - use sysctl id 9999.
  130.  */
  131. #warning ACPI broke the kernel, this interface needs to be fixed up.
  132. #define CTL_ACPI 9999
  133. #define ACPI_S1_SLP_TYP 19
  134. /*
  135.  * Send us to sleep.
  136.  */
  137. static int sysctl_pm_do_suspend(void)
  138. {
  139. int retval;
  140. retval = pm_send_all(PM_SUSPEND, (void *)3);
  141. if (retval == 0) {
  142. retval = pm_do_suspend();
  143. pm_send_all(PM_RESUME, (void *)0);
  144. }
  145. return retval;
  146. }
  147. static struct ctl_table pm_table[] =
  148. {
  149. {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
  150. {0}
  151. };
  152. static struct ctl_table pm_dir_table[] =
  153. {
  154. {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
  155. {0}
  156. };
  157. /*
  158.  * Initialize power interface
  159.  */
  160. static int __init pm_init(void)
  161. {
  162. register_sysctl_table(pm_dir_table, 1);
  163. return 0;
  164. }
  165. __initcall(pm_init);
  166. #endif