sleep.S 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * (C) Copyright 2010, Amlogic, Inc. http://www.amlogic.com/
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  16. * MA 02111-1307 USA
  17. */
  18. #include <linux/linkage.h>
  19. #include <asm/assembler.h>
  20. #include <mach/memory.h>
  21. #include <mach/pctl.h>
  22. #include <mach/dmc.h>
  23. #include "sleep.h"
  24. #define HIU_GCLK_MPEG (0x50<<2)
  25. #define HHI_MPEG_CLK_CNTL (0x5d<<2)
  26. #define HIU_DDR_PLL_CTRL (0x68<<2)
  27. #define A9_AUTO_CLK0 (0x78<<2)
  28. #define HIU_DDR_RESET (0x102<<2)
  29. #define LED_PWM_REG0 (0x11da<<2)
  30. .text
  31. /*
  32. * Move Meson into deep sleep state
  33. *
  34. * Note: This code is copied to internal SRAM by PM code. When the Meson
  35. * wakes up it continues execution at the point it went to sleep.
  36. */
  37. ENTRY(meson_cpu_suspend)
  38. stmfd sp!, {r0-r12, lr} @ save registers on stack
  39. ldmia r0, {r0-r6}
  40. /*
  41. r0: pctl_reg_base;
  42. r1: mmc_reg_base;
  43. r2: hiu_reg_base;
  44. r3: power_key;
  45. r4: ddr_clk;
  46. r5: ddr_reg_backup;
  47. r6: core_voltage_adjust;
  48. */
  49. /* r9: led_pwm_reg0, r10: value of led_pwm_reg0*/
  50. mov r9, #0
  51. movw r9, #LED_PWM_REG0
  52. add r9, r9, r2
  53. ldr r10, [r9]
  54. /* turn on auto byte bypass */
  55. ldr r8, [r0, #PCTL_IOCR_ADDR]
  56. orr r8, r8, #(1<<25)
  57. str r8, [r0, #PCTL_IOCR_ADDR]
  58. /*
  59. * Switch DDR to self-refresh mode.
  60. */
  61. mov r8, #0x3
  62. str r8, [r0, #PCTL_SCTL_ADDR]
  63. mov r8, #MS_DLY
  64. 0: subs r8, r8, #0x1
  65. bne 0b
  66. /* DDR PHY power saving*/
  67. ldr r8, [r1, #MMC_PHY_CTRL-0x1000]
  68. orr r8, r8, #(1<<0)
  69. orr r8, r8, #(1<<8)
  70. orr r8, r8, #(1<<13)
  71. str r8, [r1, #MMC_PHY_CTRL-0x1000]
  72. /* hold dll reset */
  73. ldr r8, [r0, #PCTL_PHYCR_ADDR]
  74. bic r8, r8, #(1<<6)
  75. str r8, [r0, #PCTL_PHYCR_ADDR]
  76. /* enable dll bypass */
  77. ldr r8, [r0, #PCTL_DLLCR9_ADDR]
  78. orr r8, r8, #(1<<31)
  79. str r8, [r0, #PCTL_DLLCR9_ADDR]
  80. #ifdef TURN_OFF_DDR_PLL
  81. /* turn off ddr pll */
  82. ldr r8, [r2, #HIU_DDR_PLL_CTRL]
  83. orr r8, r8, #(1<<15)
  84. str r8, [r2, #HIU_DDR_PLL_CTRL]
  85. #else
  86. /* lower ddr pll */
  87. ldr r7, [r2, #HIU_DDR_PLL_CTRL]
  88. str r4, [r2, #HIU_DDR_PLL_CTRL]
  89. #endif
  90. /* ddr power gate */
  91. ldr r8, [r2, #HIU_GCLK_MPEG]
  92. bic r8, r8, #0x41
  93. str r8, [r2, #HIU_GCLK_MPEG]
  94. /* lower core voltage */
  95. bic r8, r10, #0x0f
  96. orr r8, r8, r6
  97. str r8, [r9]
  98. /* System goes to sleep beyond after this instruction */
  99. ldr r8, [r2, #A9_AUTO_CLK0]
  100. orr r8, r8, #(1<<1)
  101. str r8, [r2, #A9_AUTO_CLK0]
  102. bic r8, r8, #(1<<1)
  103. str r8, [r2, #A9_AUTO_CLK0]
  104. wfi
  105. ldr r8, [r2, #A9_AUTO_CLK0]
  106. bic r8, r8, #(1<<0)
  107. str r8, [r2, #A9_AUTO_CLK0]
  108. /* Wake up from sleep */
  109. /* restore core voltage */
  110. str r10, [r9]
  111. mov r8, #VOLTAGE_DLY
  112. 2: subs r8, r8, #0x1
  113. bne 2b
  114. /* ddr power gate */
  115. ldr r8, [r2, #HIU_GCLK_MPEG]
  116. orr r8, r8, #0x41
  117. str r8, [r2, #HIU_GCLK_MPEG]
  118. #ifdef TURN_OFF_DDR_PLL
  119. /* turn on ddr pll */
  120. ldr r8, [r2, #HIU_DDR_PLL_CTRL]
  121. bic r8, r8, #(1<<15)
  122. str r8, [r2, #HIU_DDR_PLL_CTRL]
  123. #else
  124. /* restore ddr pll */
  125. str r7, [r2, #HIU_DDR_PLL_CTRL]
  126. #endif
  127. /* Wait for PLL to lock */
  128. mov r8, #MS_DLY
  129. 3: subs r8, r8, #0x1
  130. bne 3b
  131. /* disable dll bypass */
  132. ldr r8, [r0, #PCTL_DLLCR9_ADDR]
  133. bic r8, r8, #(1<<31)
  134. str r8, [r0, #PCTL_DLLCR9_ADDR]
  135. /* release reset */
  136. ldr r8, [r0, #PCTL_PHYCR_ADDR]
  137. orr r8, r8, #(1<<6)
  138. str r8, [r0, #PCTL_PHYCR_ADDR]
  139. /* DDR PHY leave power saving mode*/
  140. ldr r8, [r1, #MMC_PHY_CTRL-0x1000]
  141. bic r8, r8, #(1<<8)
  142. str r8, [r1, #MMC_PHY_CTRL-0x1000]
  143. /* ddr back to normal mode */
  144. mov r8, #0x4
  145. str r8, [r0, #PCTL_SCTL_ADDR]
  146. mov r8, #MS_DLY
  147. 9: subs r8, r8, #0x1
  148. bne 9b
  149. /* Restore registers and return */
  150. ldmfd sp!, {r0-r12, pc}
  151. ENDPROC(meson_cpu_suspend)
  152. ENTRY(meson_cpu_suspend_sz)
  153. .word . - meson_cpu_suspend
  154. ENDPROC(meson_cpu_suspend_sz)