sleep.S 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * linux/arch/arm/plat-omap/sleep.S
  3. *
  4. * Low-level OMAP1510/1610 sleep/wakeUp support
  5. *
  6. * Initial SA1110 code:
  7. * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
  8. *
  9. * Adapted for PXA by Nicolas Pitre:
  10. * Copyright (c) 2002 Monta Vista Software, Inc.
  11. *
  12. * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
  13. *
  14. * This program is free software; you can redistribute it and/or modify it
  15. * under the terms of the GNU General Public License as published by the
  16. * Free Software Foundation; either version 2 of the License, or (at your
  17. * option) any later version.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  22. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  25. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * You should have received a copy of the GNU General Public License along
  31. * with this program; if not, write to the Free Software Foundation, Inc.,
  32. * 675 Mass Ave, Cambridge, MA 02139, USA.
  33. */
  34. #include <linux/config.h>
  35. #include <linux/linkage.h>
  36. #include <asm/assembler.h>
  37. #include <asm/arch/io.h>
  38. #include <asm/arch/pm.h>
  39. .text
  40. /*
  41. * Forces OMAP into idle state
  42. *
  43. * omapXXXX_idle_loop_suspend()
  44. *
  45. * Note: This code get's copied to internal SRAM at boot. When the OMAP
  46. * wakes up it continues execution at the point it went to sleep.
  47. *
  48. * Note: Because of slightly different configuration values we have
  49. * processor specific functions here.
  50. */
  51. #ifdef CONFIG_ARCH_OMAP1510
  52. ENTRY(omap1510_idle_loop_suspend)
  53. stmfd sp!, {r0 - r12, lr} @ save registers on stack
  54. @ load base address of ARM_IDLECT1 and ARM_IDLECT2
  55. mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
  56. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
  57. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
  58. @ turn off clock domains
  59. @ get ARM_IDLECT2 into r2
  60. ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  61. mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
  62. orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
  63. strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  64. @ request ARM idle
  65. @ get ARM_IDLECT1 into r1
  66. ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  67. orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff
  68. strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  69. mov r5, #IDLE_WAIT_CYCLES & 0xff
  70. orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
  71. l_1510: subs r5, r5, #1
  72. bne l_1510
  73. /*
  74. * Let's wait for the next clock tick to wake us up.
  75. */
  76. mov r0, #0
  77. mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
  78. /*
  79. * omap1510_idle_loop_suspend()'s resume point.
  80. *
  81. * It will just start executing here, so we'll restore stuff from the
  82. * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
  83. */
  84. @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
  85. @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
  86. strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  87. strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  88. ldmfd sp!, {r0 - r12, pc} @ restore regs and return
  89. ENTRY(omap1510_idle_loop_suspend_sz)
  90. .word . - omap1510_idle_loop_suspend
  91. #endif /* CONFIG_ARCH_OMAP1510 */
  92. #if defined(CONFIG_ARCH_OMAP16XX)
  93. ENTRY(omap1610_idle_loop_suspend)
  94. stmfd sp!, {r0 - r12, lr} @ save registers on stack
  95. @ load base address of ARM_IDLECT1 and ARM_IDLECT2
  96. mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
  97. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
  98. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
  99. @ turn off clock domains
  100. @ get ARM_IDLECT2 into r2
  101. ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  102. mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
  103. orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
  104. strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  105. @ request ARM idle
  106. @ get ARM_IDLECT1 into r1
  107. ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  108. orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff
  109. strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  110. mov r5, #IDLE_WAIT_CYCLES & 0xff
  111. orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
  112. l_1610: subs r5, r5, #1
  113. bne l_1610
  114. /*
  115. * Let's wait for the next clock tick to wake us up.
  116. */
  117. mov r0, #0
  118. mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
  119. /*
  120. * omap1610_idle_loop_suspend()'s resume point.
  121. *
  122. * It will just start executing here, so we'll restore stuff from the
  123. * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
  124. */
  125. @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
  126. @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
  127. strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  128. strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  129. ldmfd sp!, {r0 - r12, pc} @ restore regs and return
  130. ENTRY(omap1610_idle_loop_suspend_sz)
  131. .word . - omap1610_idle_loop_suspend
  132. #endif /* CONFIG_ARCH_OMAP16XX */
  133. /*
  134. * Forces OMAP into deep sleep state
  135. *
  136. * omapXXXX_cpu_suspend()
  137. *
  138. * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
  139. * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
  140. * in register r1.
  141. *
  142. * Note: This code get's copied to internal SRAM at boot. When the OMAP
  143. * wakes up it continues execution at the point it went to sleep.
  144. *
  145. * Note: Because of errata work arounds we have processor specific functions
  146. * here. They are mostly the same, but slightly different.
  147. *
  148. */
  149. #ifdef CONFIG_ARCH_OMAP1510
  150. ENTRY(omap1510_cpu_suspend)
  151. @ save registers on stack
  152. stmfd sp!, {r0 - r12, lr}
  153. @ load base address of Traffic Controller
  154. mov r4, #TCMIF_ASM_BASE & 0xff000000
  155. orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
  156. orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
  157. @ work around errata of OMAP1510 PDE bit for TC shut down
  158. @ clear PDE bit
  159. ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  160. bic r5, r5, #PDE_BIT & 0xff
  161. str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  162. @ set PWD_EN bit
  163. and r5, r5, #PWD_EN_BIT & 0xff
  164. str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  165. @ prepare to put SDRAM into self-refresh manually
  166. ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  167. orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
  168. orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
  169. str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  170. @ prepare to put EMIFS to Sleep
  171. ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  172. orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
  173. str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  174. @ load base address of ARM_IDLECT1 and ARM_IDLECT2
  175. mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
  176. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
  177. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
  178. @ turn off clock domains
  179. mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
  180. orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
  181. strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  182. @ request ARM idle
  183. mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
  184. orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
  185. strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  186. mov r5, #IDLE_WAIT_CYCLES & 0xff
  187. orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
  188. l_1510_2:
  189. subs r5, r5, #1
  190. bne l_1510_2
  191. /*
  192. * Let's wait for the next wake up event to wake us up. r0 can't be
  193. * used here because r0 holds ARM_IDLECT1
  194. */
  195. mov r2, #0
  196. mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
  197. /*
  198. * omap1510_cpu_suspend()'s resume point.
  199. *
  200. * It will just start executing here, so we'll restore stuff from the
  201. * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
  202. */
  203. strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  204. strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  205. @ restore regs and return
  206. ldmfd sp!, {r0 - r12, pc}
  207. ENTRY(omap1510_cpu_suspend_sz)
  208. .word . - omap1510_cpu_suspend
  209. #endif /* CONFIG_ARCH_OMAP1510 */
  210. #if defined(CONFIG_ARCH_OMAP16XX)
  211. ENTRY(omap1610_cpu_suspend)
  212. @ save registers on stack
  213. stmfd sp!, {r0 - r12, lr}
  214. @ Drain write cache
  215. mov r4, #0
  216. mcr p15, 0, r0, c7, c10, 4
  217. nop
  218. @ load base address of Traffic Controller
  219. mov r6, #TCMIF_ASM_BASE & 0xff000000
  220. orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
  221. orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
  222. @ prepare to put SDRAM into self-refresh manually
  223. ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  224. orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
  225. orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
  226. str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  227. @ prepare to put EMIFS to Sleep
  228. ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  229. orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
  230. str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  231. @ load base address of ARM_IDLECT1 and ARM_IDLECT2
  232. mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
  233. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
  234. orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
  235. @ turn off clock domains
  236. @ do not disable PERCK (0x04)
  237. mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
  238. orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
  239. strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  240. @ request ARM idle
  241. mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
  242. orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
  243. strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  244. @ disable instruction cache
  245. mrc p15, 0, r9, c1, c0, 0
  246. bic r2, r9, #0x1000
  247. mcr p15, 0, r2, c1, c0, 0
  248. nop
  249. /*
  250. * Let's wait for the next wake up event to wake us up. r0 can't be
  251. * used here because r0 holds ARM_IDLECT1
  252. */
  253. mov r2, #0
  254. mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
  255. /*
  256. * omap1610_cpu_suspend()'s resume point.
  257. *
  258. * It will just start executing here, so we'll restore stuff from the
  259. * stack.
  260. */
  261. @ re-enable Icache
  262. mcr p15, 0, r9, c1, c0, 0
  263. @ reset the ARM_IDLECT1 and ARM_IDLECT2.
  264. strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
  265. strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
  266. @ Restore EMIFF controls
  267. str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  268. str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  269. @ restore regs and return
  270. ldmfd sp!, {r0 - r12, pc}
  271. ENTRY(omap1610_cpu_suspend_sz)
  272. .word . - omap1610_cpu_suspend
  273. #endif /* CONFIG_ARCH_OMAP16XX */