sleep.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. * k4 scratch
  22. */
  23. #define k0 r0
  24. #define k1 r1
  25. #define k4 r4
  26. /* manage self-refresh and enter standby mode.
  27. * this code will be copied to on-chip memory and executed from there.
  28. */
  29. .balign 4096,0,4096
  30. ENTRY(sh_mobile_standby)
  31. /* save original vbr */
  32. stc vbr, r1
  33. mova saved_vbr, r0
  34. mov.l r1, @r0
  35. /* point vbr to our on-chip memory page */
  36. ldc r5, vbr
  37. /* save return address */
  38. mova saved_spc, r0
  39. sts pr, r5
  40. mov.l r5, @r0
  41. /* save sr */
  42. mova saved_sr, r0
  43. stc sr, r5
  44. mov.l r5, @r0
  45. /* save mode flags */
  46. mova saved_mode, r0
  47. mov.l r4, @r0
  48. /* put mode flags in r0 */
  49. mov r4, r0
  50. tst #SUSP_SH_SF, r0
  51. bt skip_set_sf
  52. #ifdef CONFIG_CPU_SUBTYPE_SH7724
  53. /* DBSC: put memory in self-refresh mode */
  54. mov.l dben_reg, r4
  55. mov.l dben_data0, r1
  56. mov.l r1, @r4
  57. mov.l dbrfpdn0_reg, r4
  58. mov.l dbrfpdn0_data0, r1
  59. mov.l r1, @r4
  60. mov.l dbcmdcnt_reg, r4
  61. mov.l dbcmdcnt_data0, r1
  62. mov.l r1, @r4
  63. mov.l dbcmdcnt_reg, r4
  64. mov.l dbcmdcnt_data1, r1
  65. mov.l r1, @r4
  66. mov.l dbrfpdn0_reg, r4
  67. mov.l dbrfpdn0_data1, r1
  68. mov.l r1, @r4
  69. #else
  70. /* SBSC: disable power down and put in self-refresh mode */
  71. mov.l 1f, r4
  72. mov.l 2f, r1
  73. mov.l @r4, r2
  74. or r1, r2
  75. mov.l 3f, r3
  76. and r3, r2
  77. mov.l r2, @r4
  78. #endif
  79. skip_set_sf:
  80. tst #SUSP_SH_STANDBY, r0
  81. bt test_rstandby
  82. /* set mode to "software standby mode" */
  83. bra do_sleep
  84. mov #0x80, r1
  85. test_rstandby:
  86. tst #SUSP_SH_RSTANDBY, r0
  87. bt test_ustandby
  88. /* set mode to "r-standby mode" */
  89. bra do_sleep
  90. mov #0x20, r1
  91. test_ustandby:
  92. tst #SUSP_SH_USTANDBY, r0
  93. bt force_sleep
  94. /* set mode to "u-standby mode" */
  95. bra do_sleep
  96. mov #0x10, r1
  97. force_sleep:
  98. /* set mode to "sleep mode" */
  99. mov #0x00, r1
  100. do_sleep:
  101. /* setup and enter selected standby mode */
  102. mov.l 5f, r4
  103. mov.l r1, @r4
  104. again:
  105. sleep
  106. bra again
  107. nop
  108. restore_jump_vbr:
  109. /* setup spc with return address to c code */
  110. mov.l saved_spc, k0
  111. ldc k0, spc
  112. /* restore vbr */
  113. mov.l saved_vbr, k0
  114. ldc k0, vbr
  115. /* setup ssr with saved sr */
  116. mov.l saved_sr, k0
  117. ldc k0, ssr
  118. /* get mode flags */
  119. mov.l saved_mode, k0
  120. done_sleep:
  121. /* reset standby mode to sleep mode */
  122. mov.l 5f, k4
  123. mov #0x00, k1
  124. mov.l k1, @k4
  125. tst #SUSP_SH_SF, k0
  126. bt skip_restore_sf
  127. #ifdef CONFIG_CPU_SUBTYPE_SH7724
  128. /* DBSC: put memory in auto-refresh mode */
  129. mov.l dbrfpdn0_reg, k4
  130. mov.l dbrfpdn0_data0, k1
  131. mov.l k1, @k4
  132. nop /* sleep 140 ns */
  133. nop
  134. nop
  135. nop
  136. mov.l dbcmdcnt_reg, k4
  137. mov.l dbcmdcnt_data0, k1
  138. mov.l k1, @k4
  139. mov.l dbcmdcnt_reg, k4
  140. mov.l dbcmdcnt_data1, k1
  141. mov.l k1, @k4
  142. mov.l dben_reg, k4
  143. mov.l dben_data1, k1
  144. mov.l k1, @k4
  145. mov.l dbrfpdn0_reg, k4
  146. mov.l dbrfpdn0_data2, k1
  147. mov.l k1, @k4
  148. #else
  149. /* SBSC: set auto-refresh mode */
  150. mov.l 1f, k4
  151. mov.l @k4, k0
  152. mov.l 4f, k1
  153. and k1, k0
  154. mov.l k0, @k4
  155. mov.l 6f, k4
  156. mov.l 8f, k0
  157. mov.l @k4, k1
  158. mov #-1, k4
  159. add k4, k1
  160. or k1, k0
  161. mov.l 7f, k1
  162. mov.l k0, @k1
  163. #endif
  164. skip_restore_sf:
  165. /* jump to vbr vector */
  166. mov.l saved_vbr, k0
  167. mov.l offset_vbr, k4
  168. add k4, k0
  169. jmp @k0
  170. nop
  171. .balign 4
  172. saved_mode: .long 0
  173. saved_spc: .long 0
  174. saved_sr: .long 0
  175. saved_vbr: .long 0
  176. offset_vbr: .long 0x600
  177. #ifdef CONFIG_CPU_SUBTYPE_SH7724
  178. dben_reg: .long 0xfd000010 /* DBEN */
  179. dben_data0: .long 0
  180. dben_data1: .long 1
  181. dbrfpdn0_reg: .long 0xfd000040 /* DBRFPDN0 */
  182. dbrfpdn0_data0: .long 0
  183. dbrfpdn0_data1: .long 1
  184. dbrfpdn0_data2: .long 0x00010000
  185. dbcmdcnt_reg: .long 0xfd000014 /* DBCMDCNT */
  186. dbcmdcnt_data0: .long 2
  187. dbcmdcnt_data1: .long 4
  188. #else
  189. 1: .long 0xfe400008 /* SDCR0 */
  190. 2: .long 0x00000400
  191. 3: .long 0xffff7fff
  192. 4: .long 0xfffffbff
  193. #endif
  194. 5: .long 0xa4150020 /* STBCR */
  195. 6: .long 0xfe40001c /* RTCOR */
  196. 7: .long 0xfe400018 /* RTCNT */
  197. 8: .long 0xa55a0000
  198. /* interrupt vector @ 0x600 */
  199. .balign 0x400,0,0x400
  200. .long 0xdeadbeef
  201. .balign 0x200,0,0x200
  202. bra restore_jump_vbr
  203. nop
  204. sh_mobile_standby_end:
  205. ENTRY(sh_mobile_standby_size)
  206. .long sh_mobile_standby_end - sh_mobile_standby