sleep.S 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 stbcr */
  43. bsr save_register
  44. mov #SH_SLEEP_REG_STBCR, r0
  45. /* save mmu and cache context if needed */
  46. mov.l @(SH_SLEEP_MODE, r5), r0
  47. tst #SUSP_SH_MMU, r0
  48. bt skip_mmu_save_disable
  49. /* save mmu state */
  50. bsr save_register
  51. mov #SH_SLEEP_REG_PTEH, r0
  52. bsr save_register
  53. mov #SH_SLEEP_REG_PTEL, r0
  54. bsr save_register
  55. mov #SH_SLEEP_REG_TTB, r0
  56. bsr save_register
  57. mov #SH_SLEEP_REG_TEA, r0
  58. bsr save_register
  59. mov #SH_SLEEP_REG_MMUCR, r0
  60. bsr save_register
  61. mov #SH_SLEEP_REG_PTEA, r0
  62. bsr save_register
  63. mov #SH_SLEEP_REG_PASCR, r0
  64. bsr save_register
  65. mov #SH_SLEEP_REG_IRMCR, r0
  66. /* invalidate TLBs and disable the MMU */
  67. bsr get_register
  68. mov #SH_SLEEP_REG_MMUCR, r0
  69. mov #4, r1
  70. mov.l r1, @r0
  71. icbi @r0
  72. /* save cache registers and disable caches */
  73. bsr save_register
  74. mov #SH_SLEEP_REG_CCR, r0
  75. bsr save_register
  76. mov #SH_SLEEP_REG_RAMCR, r0
  77. bsr get_register
  78. mov #SH_SLEEP_REG_CCR, r0
  79. mov #0, r1
  80. mov.l r1, @r0
  81. icbi @r0
  82. skip_mmu_save_disable:
  83. /* call self-refresh entering code if needed */
  84. mov.l @(SH_SLEEP_MODE, r5), r0
  85. tst #SUSP_SH_SF, r0
  86. bt skip_set_sf
  87. mov.l @(SH_SLEEP_SF_PRE, r5), r0
  88. jsr @r0
  89. nop
  90. skip_set_sf:
  91. mov.l @(SH_SLEEP_MODE, r5), r0
  92. tst #SUSP_SH_STANDBY, r0
  93. bt test_rstandby
  94. /* set mode to "software standby mode" */
  95. bra do_sleep
  96. mov #0x80, r1
  97. test_rstandby:
  98. tst #SUSP_SH_RSTANDBY, r0
  99. bt test_ustandby
  100. /* set mode to "r-standby mode" */
  101. bra do_sleep
  102. mov #0x20, r1
  103. test_ustandby:
  104. tst #SUSP_SH_USTANDBY, r0
  105. bt force_sleep
  106. /* set mode to "u-standby mode" */
  107. bra do_sleep
  108. mov #0x10, r1
  109. force_sleep:
  110. /* set mode to "sleep mode" */
  111. mov #0x00, r1
  112. do_sleep:
  113. /* setup and enter selected standby mode */
  114. bsr get_register
  115. mov #SH_SLEEP_REG_STBCR, r0
  116. mov.l r1, @r0
  117. again:
  118. sleep
  119. bra again
  120. nop
  121. save_register:
  122. add #SH_SLEEP_BASE_ADDR, r0
  123. mov.l @(r0, r5), r1
  124. add #-SH_SLEEP_BASE_ADDR, r0
  125. mov.l @r1, r1
  126. add #SH_SLEEP_BASE_DATA, r0
  127. mov.l r1, @(r0, r5)
  128. add #-SH_SLEEP_BASE_DATA, r0
  129. rts
  130. nop
  131. get_register:
  132. add #SH_SLEEP_BASE_ADDR, r0
  133. mov.l @(r0, r5), r0
  134. rts
  135. nop
  136. ENTRY(sh_mobile_sleep_enter_end)
  137. .balign 4
  138. ENTRY(sh_mobile_sleep_resume_start)
  139. /* figure out start address */
  140. bsr 0f
  141. nop
  142. 0:
  143. sts pr, k1
  144. mov.l 1f, k0
  145. and k0, k1
  146. /* store pointer to data area in VBR */
  147. ldc k1, vbr
  148. /* setup sr with saved sr */
  149. mov.l @(SH_SLEEP_SR, k1), k0
  150. ldc k0, sr
  151. /* now: user register set! */
  152. stc vbr, r5
  153. /* setup spc with return address to c code */
  154. mov.l @(SH_SLEEP_SPC, r5), r0
  155. ldc r0, spc
  156. /* restore vbr */
  157. mov.l @(SH_SLEEP_VBR, r5), r0
  158. ldc r0, vbr
  159. /* setup ssr with saved sr */
  160. mov.l @(SH_SLEEP_SR, r5), r0
  161. ldc r0, ssr
  162. /* restore sleep mode register */
  163. bsr restore_register
  164. mov #SH_SLEEP_REG_STBCR, r0
  165. /* call self-refresh resume code if needed */
  166. mov.l @(SH_SLEEP_MODE, r5), r0
  167. tst #SUSP_SH_SF, r0
  168. bt skip_restore_sf
  169. mov.l @(SH_SLEEP_SF_POST, r5), r0
  170. jsr @r0
  171. nop
  172. skip_restore_sf:
  173. /* restore mmu and cache state if needed */
  174. mov.l @(SH_SLEEP_MODE, r5), r0
  175. tst #SUSP_SH_MMU, r0
  176. bt skip_restore_mmu
  177. /* restore mmu state */
  178. bsr restore_register
  179. mov #SH_SLEEP_REG_PTEH, r0
  180. bsr restore_register
  181. mov #SH_SLEEP_REG_PTEL, r0
  182. bsr restore_register
  183. mov #SH_SLEEP_REG_TTB, r0
  184. bsr restore_register
  185. mov #SH_SLEEP_REG_TEA, r0
  186. bsr restore_register
  187. mov #SH_SLEEP_REG_PTEA, r0
  188. bsr restore_register
  189. mov #SH_SLEEP_REG_PASCR, r0
  190. bsr restore_register
  191. mov #SH_SLEEP_REG_IRMCR, r0
  192. bsr restore_register
  193. mov #SH_SLEEP_REG_MMUCR, r0
  194. icbi @r0
  195. /* restore cache settings */
  196. bsr restore_register
  197. mov #SH_SLEEP_REG_RAMCR, r0
  198. icbi @r0
  199. bsr restore_register
  200. mov #SH_SLEEP_REG_CCR, r0
  201. icbi @r0
  202. skip_restore_mmu:
  203. rte
  204. nop
  205. restore_register:
  206. add #SH_SLEEP_BASE_DATA, r0
  207. mov.l @(r0, r5), r1
  208. add #-SH_SLEEP_BASE_DATA, r0
  209. add #SH_SLEEP_BASE_ADDR, r0
  210. mov.l @(r0, r5), r0
  211. mov.l r1, @r0
  212. rts
  213. nop
  214. .balign 4
  215. 1: .long ~0x7ff
  216. ENTRY(sh_mobile_sleep_resume_end)