pm.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * linux/arch/arm/mach-omap2/pm.c
  3. *
  4. * OMAP2 Power Management Routines
  5. *
  6. * Copyright (C) 2006 Nokia Corporation
  7. * Tony Lindgren <tony@atomide.com>
  8. *
  9. * Copyright (C) 2005 Texas Instruments, Inc.
  10. * Richard Woodruff <r-woodruff2@ti.com>
  11. *
  12. * Based on pm.c for omap1
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License version 2 as
  16. * published by the Free Software Foundation.
  17. */
  18. #include <linux/pm.h>
  19. #include <linux/sched.h>
  20. #include <linux/proc_fs.h>
  21. #include <linux/pm.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/sysfs.h>
  24. #include <linux/module.h>
  25. #include <asm/io.h>
  26. #include <asm/irq.h>
  27. #include <asm/atomic.h>
  28. #include <asm/mach/time.h>
  29. #include <asm/mach/irq.h>
  30. #include <asm/mach-types.h>
  31. #include <asm/arch/irqs.h>
  32. #include <asm/arch/clock.h>
  33. #include <asm/arch/sram.h>
  34. #include <asm/arch/pm.h>
  35. static struct clk *vclk;
  36. static void (*omap2_sram_idle)(void);
  37. static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
  38. static void (*saved_idle)(void);
  39. void omap2_pm_idle(void)
  40. {
  41. local_irq_disable();
  42. local_fiq_disable();
  43. if (need_resched()) {
  44. local_fiq_enable();
  45. local_irq_enable();
  46. return;
  47. }
  48. /*
  49. * Since an interrupt may set up a timer, we don't want to
  50. * reprogram the hardware timer with interrupts enabled.
  51. * Re-enable interrupts only after returning from idle.
  52. */
  53. timer_dyn_reprogram();
  54. omap2_sram_idle();
  55. local_fiq_enable();
  56. local_irq_enable();
  57. }
  58. static int omap2_pm_prepare(suspend_state_t state)
  59. {
  60. int error = 0;
  61. /* We cannot sleep in idle until we have resumed */
  62. saved_idle = pm_idle;
  63. pm_idle = NULL;
  64. switch (state)
  65. {
  66. case PM_SUSPEND_STANDBY:
  67. case PM_SUSPEND_MEM:
  68. break;
  69. case PM_SUSPEND_DISK:
  70. return -ENOTSUPP;
  71. default:
  72. return -EINVAL;
  73. }
  74. return error;
  75. }
  76. static int omap2_pm_enter(suspend_state_t state)
  77. {
  78. switch (state)
  79. {
  80. case PM_SUSPEND_STANDBY:
  81. case PM_SUSPEND_MEM:
  82. /* FIXME: Add suspend */
  83. break;
  84. case PM_SUSPEND_DISK:
  85. return -ENOTSUPP;
  86. default:
  87. return -EINVAL;
  88. }
  89. return 0;
  90. }
  91. static int omap2_pm_finish(suspend_state_t state)
  92. {
  93. pm_idle = saved_idle;
  94. return 0;
  95. }
  96. static struct pm_ops omap_pm_ops = {
  97. .pm_disk_mode = 0,
  98. .prepare = omap2_pm_prepare,
  99. .enter = omap2_pm_enter,
  100. .finish = omap2_pm_finish,
  101. };
  102. int __init omap2_pm_init(void)
  103. {
  104. printk("Power Management for TI OMAP.\n");
  105. vclk = clk_get(NULL, "virt_prcm_set");
  106. if (IS_ERR(vclk)) {
  107. printk(KERN_ERR "Could not get PM vclk\n");
  108. return -ENODEV;
  109. }
  110. /*
  111. * We copy the assembler sleep/wakeup routines to SRAM.
  112. * These routines need to be in SRAM as that's the only
  113. * memory the MPU can see when it wakes up.
  114. */
  115. omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
  116. omap24xx_idle_loop_suspend_sz);
  117. omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
  118. omap24xx_cpu_suspend_sz);
  119. pm_set_ops(&omap_pm_ops);
  120. pm_idle = omap2_pm_idle;
  121. return 0;
  122. }
  123. __initcall(omap2_pm_init);