pm.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * arch/arm/mach-lpc32xx/pm.c
  3. *
  4. * Original authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
  5. * Modified by Kevin Wells <kevin.wells@nxp.com>
  6. *
  7. * 2005 (c) MontaVista Software, Inc. This file is licensed under
  8. * the terms of the GNU General Public License version 2. This program
  9. * is licensed "as is" without any warranty of any kind, whether express
  10. * or implied.
  11. */
  12. /*
  13. * LPC32XX CPU and system power management
  14. *
  15. * The LPC32XX has three CPU modes for controlling system power: run,
  16. * direct-run, and halt modes. When switching between halt and run modes,
  17. * the CPU transistions through direct-run mode. For Linux, direct-run
  18. * mode is not used in normal operation. Halt mode is used when the
  19. * system is fully suspended.
  20. *
  21. * Run mode:
  22. * The ARM CPU clock (HCLK_PLL), HCLK bus clock, and PCLK bus clocks are
  23. * derived from the HCLK PLL. The HCLK and PCLK bus rates are divided from
  24. * the HCLK_PLL rate. Linux runs in this mode.
  25. *
  26. * Direct-run mode:
  27. * The ARM CPU clock, HCLK bus clock, and PCLK bus clocks are driven from
  28. * SYSCLK. SYSCLK is usually around 13MHz, but may vary based on SYSCLK
  29. * source or the frequency of the main oscillator. In this mode, the
  30. * HCLK_PLL can be safely enabled, changed, or disabled.
  31. *
  32. * Halt mode:
  33. * SYSCLK is gated off and the CPU and system clocks are halted.
  34. * Peripherals based on the 32KHz oscillator clock (ie, RTC, touch,
  35. * key scanner, etc.) still operate if enabled. In this state, an enabled
  36. * system event (ie, GPIO state change, RTC match, key press, etc.) will
  37. * wake the system up back into direct-run mode.
  38. *
  39. * DRAM refresh
  40. * DRAM clocking and refresh are slightly different for systems with DDR
  41. * DRAM or regular SDRAM devices. If SDRAM is used in the system, the
  42. * SDRAM will still be accessible in direct-run mode. In DDR based systems,
  43. * a transition to direct-run mode will stop all DDR accesses (no clocks).
  44. * Because of this, the code to switch power modes and the code to enter
  45. * and exit DRAM self-refresh modes must not be executed in DRAM. A small
  46. * section of IRAM is used instead for this.
  47. *
  48. * Suspend is handled with the following logic:
  49. * Backup a small area of IRAM used for the suspend code
  50. * Copy suspend code to IRAM
  51. * Transfer control to code in IRAM
  52. * Places DRAMs in self-refresh mode
  53. * Enter direct-run mode
  54. * Save state of HCLK_PLL PLL
  55. * Disable HCLK_PLL PLL
  56. * Enter halt mode - CPU and buses will stop
  57. * System enters direct-run mode when an enabled event occurs
  58. * HCLK PLL state is restored
  59. * Run mode is entered
  60. * DRAMS are placed back into normal mode
  61. * Code execution returns from IRAM
  62. * IRAM code are used for suspend is restored
  63. * Suspend mode is exited
  64. */
  65. #include <linux/suspend.h>
  66. #include <linux/io.h>
  67. #include <linux/slab.h>
  68. #include <asm/cacheflush.h>
  69. #include <mach/hardware.h>
  70. #include <mach/platform.h>
  71. #include "common.h"
  72. #include "clock.h"
  73. #define TEMP_IRAM_AREA IO_ADDRESS(LPC32XX_IRAM_BASE)
  74. /*
  75. * Both STANDBY and MEM suspend states are handled the same with no
  76. * loss of CPU or memory state
  77. */
  78. static int lpc32xx_pm_enter(suspend_state_t state)
  79. {
  80. int (*lpc32xx_suspend_ptr) (void);
  81. void *iram_swap_area;
  82. /* Allocate some space for temporary IRAM storage */
  83. iram_swap_area = kmalloc(lpc32xx_sys_suspend_sz, GFP_KERNEL);
  84. if (!iram_swap_area) {
  85. printk(KERN_ERR
  86. "PM Suspend: cannot allocate memory to save portion "
  87. "of SRAM\n");
  88. return -ENOMEM;
  89. }
  90. /* Backup a small area of IRAM used for the suspend code */
  91. memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
  92. lpc32xx_sys_suspend_sz);
  93. /*
  94. * Copy code to suspend system into IRAM. The suspend code
  95. * needs to run from IRAM as DRAM may no longer be available
  96. * when the PLL is stopped.
  97. */
  98. memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
  99. lpc32xx_sys_suspend_sz);
  100. flush_icache_range((unsigned long)TEMP_IRAM_AREA,
  101. (unsigned long)(TEMP_IRAM_AREA) + lpc32xx_sys_suspend_sz);
  102. /* Transfer to suspend code in IRAM */
  103. lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
  104. flush_cache_all();
  105. (void) lpc32xx_suspend_ptr();
  106. /* Restore original IRAM contents */
  107. memcpy((void *) TEMP_IRAM_AREA, iram_swap_area,
  108. lpc32xx_sys_suspend_sz);
  109. kfree(iram_swap_area);
  110. return 0;
  111. }
  112. static const struct platform_suspend_ops lpc32xx_pm_ops = {
  113. .valid = suspend_valid_only_mem,
  114. .enter = lpc32xx_pm_enter,
  115. };
  116. #define EMC_DYN_MEM_CTRL_OFS 0x20
  117. #define EMC_SRMMC (1 << 3)
  118. #define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS)
  119. static int __init lpc32xx_pm_init(void)
  120. {
  121. /*
  122. * Setup SDRAM self-refresh clock to automatically disable o
  123. * start of self-refresh. This only needs to be done once.
  124. */
  125. __raw_writel(__raw_readl(EMC_CTRL_REG) | EMC_SRMMC, EMC_CTRL_REG);
  126. suspend_set_ops(&lpc32xx_pm_ops);
  127. return 0;
  128. }
  129. arch_initcall(lpc32xx_pm_init);