pm.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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 "lpc32xx.h"
  70. #include "common.h"
  71. #define TEMP_IRAM_AREA IO_ADDRESS(LPC32XX_IRAM_BASE)
  72. /*
  73. * Both STANDBY and MEM suspend states are handled the same with no
  74. * loss of CPU or memory state
  75. */
  76. static int lpc32xx_pm_enter(suspend_state_t state)
  77. {
  78. int (*lpc32xx_suspend_ptr) (void);
  79. void *iram_swap_area;
  80. /* Allocate some space for temporary IRAM storage */
  81. iram_swap_area = kmemdup((void *)TEMP_IRAM_AREA,
  82. lpc32xx_sys_suspend_sz, GFP_KERNEL);
  83. if (!iram_swap_area)
  84. return -ENOMEM;
  85. /*
  86. * Copy code to suspend system into IRAM. The suspend code
  87. * needs to run from IRAM as DRAM may no longer be available
  88. * when the PLL is stopped.
  89. */
  90. memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
  91. lpc32xx_sys_suspend_sz);
  92. flush_icache_range((unsigned long)TEMP_IRAM_AREA,
  93. (unsigned long)(TEMP_IRAM_AREA) + lpc32xx_sys_suspend_sz);
  94. /* Transfer to suspend code in IRAM */
  95. lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
  96. flush_cache_all();
  97. (void) lpc32xx_suspend_ptr();
  98. /* Restore original IRAM contents */
  99. memcpy((void *) TEMP_IRAM_AREA, iram_swap_area,
  100. lpc32xx_sys_suspend_sz);
  101. kfree(iram_swap_area);
  102. return 0;
  103. }
  104. static const struct platform_suspend_ops lpc32xx_pm_ops = {
  105. .valid = suspend_valid_only_mem,
  106. .enter = lpc32xx_pm_enter,
  107. };
  108. #define EMC_DYN_MEM_CTRL_OFS 0x20
  109. #define EMC_SRMMC (1 << 3)
  110. #define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS)
  111. static int __init lpc32xx_pm_init(void)
  112. {
  113. /*
  114. * Setup SDRAM self-refresh clock to automatically disable o
  115. * start of self-refresh. This only needs to be done once.
  116. */
  117. __raw_writel(__raw_readl(EMC_CTRL_REG) | EMC_SRMMC, EMC_CTRL_REG);
  118. suspend_set_ops(&lpc32xx_pm_ops);
  119. return 0;
  120. }
  121. arch_initcall(lpc32xx_pm_init);