sleep.S 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
  3. *
  4. * Sleep mode and Standby modes support for SuperH Mobile
  5. *
  6. * Copyright (C) 2009 Magnus Damm
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #include <linux/sys.h>
  13. #include <linux/errno.h>
  14. #include <linux/linkage.h>
  15. #include <asm/asm-offsets.h>
  16. #include <asm/suspend.h>
  17. /*
  18. * Kernel mode register usage, see entry.S:
  19. * k0 scratch
  20. * k1 scratch
  21. */
  22. #define k0 r0
  23. #define k1 r1
  24. /* manage self-refresh and enter standby mode. must be self-contained.
  25. * this code will be copied to on-chip memory and executed from there.
  26. */
  27. .balign 4
  28. ENTRY(sh_mobile_sleep_enter_start)
  29. /* save mode flags */
  30. mov.l r4, @(SH_SLEEP_MODE, r5)
  31. /* save original vbr */
  32. stc vbr, r0
  33. mov.l r0, @(SH_SLEEP_VBR, r5)
  34. /* point vbr to our on-chip memory page */
  35. ldc r5, vbr
  36. /* save return address */
  37. sts pr, r0
  38. mov.l r0, @(SH_SLEEP_SPC, r5)
  39. /* save sr */
  40. stc sr, r0
  41. mov.l r0, @(SH_SLEEP_SR, r5)
  42. /* save sp */
  43. mov.l r15, @(SH_SLEEP_SP, r5)
  44. /* save stbcr */
  45. bsr save_register
  46. mov #SH_SLEEP_REG_STBCR, r0
  47. /* save mmu and cache context if needed */
  48. mov.l @(SH_SLEEP_MODE, r5), r0
  49. tst #SUSP_SH_MMU, r0
  50. bt skip_mmu_save_disable
  51. /* save mmu state */
  52. bsr save_register
  53. mov #SH_SLEEP_REG_PTEH, r0
  54. bsr save_register
  55. mov #SH_SLEEP_REG_PTEL, r0
  56. bsr save_register
  57. mov #SH_SLEEP_REG_TTB, r0
  58. bsr save_register
  59. mov #SH_SLEEP_REG_TEA, r0
  60. bsr save_register
  61. mov #SH_SLEEP_REG_MMUCR, r0
  62. bsr save_register
  63. mov #SH_SLEEP_REG_PTEA, r0
  64. bsr save_register
  65. mov #SH_SLEEP_REG_PASCR, r0
  66. bsr save_register
  67. mov #SH_SLEEP_REG_IRMCR, r0
  68. /* invalidate TLBs and disable the MMU */
  69. bsr get_register
  70. mov #SH_SLEEP_REG_MMUCR, r0
  71. mov #4, r1
  72. mov.l r1, @r0
  73. icbi @r0
  74. /* save cache registers and disable caches */
  75. bsr save_register
  76. mov #SH_SLEEP_REG_CCR, r0
  77. bsr save_register
  78. mov #SH_SLEEP_REG_RAMCR, r0
  79. bsr get_register
  80. mov #SH_SLEEP_REG_CCR, r0
  81. mov #0, r1
  82. mov.l r1, @r0
  83. icbi @r0
  84. skip_mmu_save_disable:
  85. /* call self-refresh entering code if needed */
  86. mov.l @(SH_SLEEP_MODE, r5), r0
  87. tst #SUSP_SH_SF, r0
  88. bt skip_set_sf
  89. mov.l @(SH_SLEEP_SF_PRE, r5), r0
  90. jsr @r0
  91. nop
  92. skip_set_sf:
  93. mov.l @(SH_SLEEP_MODE, r5), r0
  94. tst #SUSP_SH_STANDBY, r0
  95. bt test_rstandby
  96. /* set mode to "software standby mode" */
  97. bra do_sleep
  98. mov #0x80, r1
  99. test_rstandby:
  100. tst #SUSP_SH_RSTANDBY, r0
  101. bt test_ustandby
  102. /* setup BAR register */
  103. bsr get_register
  104. mov #SH_SLEEP_REG_BAR, r0
  105. mov.l @(SH_SLEEP_RESUME, r5), r1
  106. mov.l r1, @r0
  107. /* set mode to "r-standby mode" */
  108. bra do_sleep
  109. mov #0x20, r1
  110. test_ustandby:
  111. tst #SUSP_SH_USTANDBY, r0
  112. bt force_sleep
  113. /* set mode to "u-standby mode" */
  114. bra do_sleep
  115. mov #0x10, r1
  116. force_sleep:
  117. /* set mode to "sleep mode" */
  118. mov #0x00, r1
  119. do_sleep:
  120. /* setup and enter selected standby mode */
  121. bsr get_register
  122. mov #SH_SLEEP_REG_STBCR, r0
  123. mov.l r1, @r0
  124. again:
  125. sleep
  126. bra again
  127. nop
  128. save_register:
  129. add #SH_SLEEP_BASE_ADDR, r0
  130. mov.l @(r0, r5), r1
  131. add #-SH_SLEEP_BASE_ADDR, r0
  132. mov.l @r1, r1
  133. add #SH_SLEEP_BASE_DATA, r0
  134. mov.l r1, @(r0, r5)
  135. add #-SH_SLEEP_BASE_DATA, r0
  136. rts
  137. nop
  138. get_register:
  139. add #SH_SLEEP_BASE_ADDR, r0
  140. mov.l @(r0, r5), r0
  141. rts
  142. nop
  143. ENTRY(sh_mobile_sleep_enter_end)
  144. .balign 4
  145. ENTRY(sh_mobile_sleep_resume_start)
  146. /* figure out start address */
  147. bsr 0f
  148. nop
  149. 0:
  150. sts pr, k1
  151. mov.l 1f, k0
  152. and k0, k1
  153. /* store pointer to data area in VBR */
  154. ldc k1, vbr
  155. /* setup sr with saved sr */
  156. mov.l @(SH_SLEEP_SR, k1), k0
  157. ldc k0, sr
  158. /* now: user register set! */
  159. stc vbr, r5
  160. /* setup spc with return address to c code */
  161. mov.l @(SH_SLEEP_SPC, r5), r0
  162. ldc r0, spc
  163. /* restore vbr */
  164. mov.l @(SH_SLEEP_VBR, r5), r0
  165. ldc r0, vbr
  166. /* setup ssr with saved sr */
  167. mov.l @(SH_SLEEP_SR, r5), r0
  168. ldc r0, ssr
  169. /* restore sp */
  170. mov.l @(SH_SLEEP_SP, r5), r15
  171. /* restore sleep mode register */
  172. bsr restore_register
  173. mov #SH_SLEEP_REG_STBCR, r0
  174. /* call self-refresh resume code if needed */
  175. mov.l @(SH_SLEEP_MODE, r5), r0
  176. tst #SUSP_SH_SF, r0
  177. bt skip_restore_sf
  178. mov.l @(SH_SLEEP_SF_POST, r5), r0
  179. jsr @r0
  180. nop
  181. skip_restore_sf:
  182. /* restore mmu and cache state if needed */
  183. mov.l @(SH_SLEEP_MODE, r5), r0
  184. tst #SUSP_SH_MMU, r0
  185. bt skip_restore_mmu
  186. /* restore mmu state */
  187. bsr restore_register
  188. mov #SH_SLEEP_REG_PTEH, r0
  189. bsr restore_register
  190. mov #SH_SLEEP_REG_PTEL, r0
  191. bsr restore_register
  192. mov #SH_SLEEP_REG_TTB, r0
  193. bsr restore_register
  194. mov #SH_SLEEP_REG_TEA, r0
  195. bsr restore_register
  196. mov #SH_SLEEP_REG_PTEA, r0
  197. bsr restore_register
  198. mov #SH_SLEEP_REG_PASCR, r0
  199. bsr restore_register
  200. mov #SH_SLEEP_REG_IRMCR, r0
  201. bsr restore_register
  202. mov #SH_SLEEP_REG_MMUCR, r0
  203. icbi @r0
  204. /* restore cache settings */
  205. bsr restore_register
  206. mov #SH_SLEEP_REG_RAMCR, r0
  207. icbi @r0
  208. bsr restore_register
  209. mov #SH_SLEEP_REG_CCR, r0
  210. icbi @r0
  211. skip_restore_mmu:
  212. rte
  213. nop
  214. restore_register:
  215. add #SH_SLEEP_BASE_DATA, r0
  216. mov.l @(r0, r5), r1
  217. add #-SH_SLEEP_BASE_DATA, r0
  218. add #SH_SLEEP_BASE_ADDR, r0
  219. mov.l @(r0, r5), r0
  220. mov.l r1, @r0
  221. rts
  222. nop
  223. .balign 4
  224. 1: .long ~0x7ff
  225. ENTRY(sh_mobile_sleep_resume_end)