sleep.S 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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 general purpose registers to stack if needed */
  43. mov.l @(SH_SLEEP_MODE, r5), r0
  44. tst #SUSP_SH_REGS, r0
  45. bt skip_regs_save
  46. sts.l pr, @-r15
  47. mov.l r14, @-r15
  48. mov.l r13, @-r15
  49. mov.l r12, @-r15
  50. mov.l r11, @-r15
  51. mov.l r10, @-r15
  52. mov.l r9, @-r15
  53. mov.l r8, @-r15
  54. /* make sure bank0 is selected, save low registers */
  55. mov.l rb_bit, r9
  56. not r9, r9
  57. bsr set_sr
  58. mov #0, r10
  59. bsr save_low_regs
  60. nop
  61. /* switch to bank 1, save low registers */
  62. mov.l rb_bit, r10
  63. bsr set_sr
  64. mov #-1, r9
  65. bsr save_low_regs
  66. nop
  67. /* switch back to bank 0 */
  68. mov.l rb_bit, r9
  69. not r9, r9
  70. bsr set_sr
  71. mov #0, r10
  72. skip_regs_save:
  73. /* save sp, also set to internal ram */
  74. mov.l r15, @(SH_SLEEP_SP, r5)
  75. mov r5, r15
  76. /* save stbcr */
  77. bsr save_register
  78. mov #SH_SLEEP_REG_STBCR, r0
  79. /* save mmu and cache context if needed */
  80. mov.l @(SH_SLEEP_MODE, r5), r0
  81. tst #SUSP_SH_MMU, r0
  82. bt skip_mmu_save_disable
  83. /* save mmu state */
  84. bsr save_register
  85. mov #SH_SLEEP_REG_PTEH, r0
  86. bsr save_register
  87. mov #SH_SLEEP_REG_PTEL, r0
  88. bsr save_register
  89. mov #SH_SLEEP_REG_TTB, r0
  90. bsr save_register
  91. mov #SH_SLEEP_REG_TEA, r0
  92. bsr save_register
  93. mov #SH_SLEEP_REG_MMUCR, r0
  94. bsr save_register
  95. mov #SH_SLEEP_REG_PTEA, r0
  96. bsr save_register
  97. mov #SH_SLEEP_REG_PASCR, r0
  98. bsr save_register
  99. mov #SH_SLEEP_REG_IRMCR, r0
  100. /* invalidate TLBs and disable the MMU */
  101. bsr get_register
  102. mov #SH_SLEEP_REG_MMUCR, r0
  103. mov #4, r1
  104. mov.l r1, @r0
  105. icbi @r0
  106. /* save cache registers and disable caches */
  107. bsr save_register
  108. mov #SH_SLEEP_REG_CCR, r0
  109. bsr save_register
  110. mov #SH_SLEEP_REG_RAMCR, r0
  111. bsr get_register
  112. mov #SH_SLEEP_REG_CCR, r0
  113. mov #0, r1
  114. mov.l r1, @r0
  115. icbi @r0
  116. skip_mmu_save_disable:
  117. /* call self-refresh entering code if needed */
  118. mov.l @(SH_SLEEP_MODE, r5), r0
  119. tst #SUSP_SH_SF, r0
  120. bt skip_set_sf
  121. mov.l @(SH_SLEEP_SF_PRE, r5), r0
  122. jsr @r0
  123. nop
  124. skip_set_sf:
  125. mov.l @(SH_SLEEP_MODE, r5), r0
  126. tst #SUSP_SH_STANDBY, r0
  127. bt test_rstandby
  128. /* set mode to "software standby mode" */
  129. bra do_sleep
  130. mov #0x80, r1
  131. test_rstandby:
  132. tst #SUSP_SH_RSTANDBY, r0
  133. bt test_ustandby
  134. /* setup BAR register */
  135. bsr get_register
  136. mov #SH_SLEEP_REG_BAR, r0
  137. mov.l @(SH_SLEEP_RESUME, r5), r1
  138. mov.l r1, @r0
  139. /* set mode to "r-standby mode" */
  140. bra do_sleep
  141. mov #0x20, r1
  142. test_ustandby:
  143. tst #SUSP_SH_USTANDBY, r0
  144. bt force_sleep
  145. /* set mode to "u-standby mode" */
  146. bra do_sleep
  147. mov #0x10, r1
  148. force_sleep:
  149. /* set mode to "sleep mode" */
  150. mov #0x00, r1
  151. do_sleep:
  152. /* setup and enter selected standby mode */
  153. bsr get_register
  154. mov #SH_SLEEP_REG_STBCR, r0
  155. mov.l r1, @r0
  156. again:
  157. sleep
  158. bra again
  159. nop
  160. save_register:
  161. add #SH_SLEEP_BASE_ADDR, r0
  162. mov.l @(r0, r5), r1
  163. add #-SH_SLEEP_BASE_ADDR, r0
  164. mov.l @r1, r1
  165. add #SH_SLEEP_BASE_DATA, r0
  166. mov.l r1, @(r0, r5)
  167. add #-SH_SLEEP_BASE_DATA, r0
  168. rts
  169. nop
  170. get_register:
  171. add #SH_SLEEP_BASE_ADDR, r0
  172. mov.l @(r0, r5), r0
  173. rts
  174. nop
  175. set_sr:
  176. stc sr, r8
  177. and r9, r8
  178. or r10, r8
  179. ldc r8, sr
  180. rts
  181. nop
  182. save_low_regs:
  183. mov.l r7, @-r15
  184. mov.l r6, @-r15
  185. mov.l r5, @-r15
  186. mov.l r4, @-r15
  187. mov.l r3, @-r15
  188. mov.l r2, @-r15
  189. mov.l r1, @-r15
  190. rts
  191. mov.l r0, @-r15
  192. .balign 4
  193. rb_bit: .long 0x20000000 ! RB=1
  194. ENTRY(sh_mobile_sleep_enter_end)
  195. .balign 4
  196. ENTRY(sh_mobile_sleep_resume_start)
  197. /* figure out start address */
  198. bsr 0f
  199. nop
  200. 0:
  201. sts pr, k1
  202. mov.l 1f, k0
  203. and k0, k1
  204. /* store pointer to data area in VBR */
  205. ldc k1, vbr
  206. /* setup sr with saved sr */
  207. mov.l @(SH_SLEEP_SR, k1), k0
  208. ldc k0, sr
  209. /* now: user register set! */
  210. stc vbr, r5
  211. /* setup spc with return address to c code */
  212. mov.l @(SH_SLEEP_SPC, r5), r0
  213. ldc r0, spc
  214. /* restore vbr */
  215. mov.l @(SH_SLEEP_VBR, r5), r0
  216. ldc r0, vbr
  217. /* setup ssr with saved sr */
  218. mov.l @(SH_SLEEP_SR, r5), r0
  219. ldc r0, ssr
  220. /* restore sp */
  221. mov.l @(SH_SLEEP_SP, r5), r15
  222. /* restore sleep mode register */
  223. bsr restore_register
  224. mov #SH_SLEEP_REG_STBCR, r0
  225. /* call self-refresh resume code if needed */
  226. mov.l @(SH_SLEEP_MODE, r5), r0
  227. tst #SUSP_SH_SF, r0
  228. bt skip_restore_sf
  229. mov.l @(SH_SLEEP_SF_POST, r5), r0
  230. jsr @r0
  231. nop
  232. skip_restore_sf:
  233. /* restore mmu and cache state if needed */
  234. mov.l @(SH_SLEEP_MODE, r5), r0
  235. tst #SUSP_SH_MMU, r0
  236. bt skip_restore_mmu
  237. /* restore mmu state */
  238. bsr restore_register
  239. mov #SH_SLEEP_REG_PTEH, r0
  240. bsr restore_register
  241. mov #SH_SLEEP_REG_PTEL, r0
  242. bsr restore_register
  243. mov #SH_SLEEP_REG_TTB, r0
  244. bsr restore_register
  245. mov #SH_SLEEP_REG_TEA, r0
  246. bsr restore_register
  247. mov #SH_SLEEP_REG_PTEA, r0
  248. bsr restore_register
  249. mov #SH_SLEEP_REG_PASCR, r0
  250. bsr restore_register
  251. mov #SH_SLEEP_REG_IRMCR, r0
  252. bsr restore_register
  253. mov #SH_SLEEP_REG_MMUCR, r0
  254. icbi @r0
  255. /* restore cache settings */
  256. bsr restore_register
  257. mov #SH_SLEEP_REG_RAMCR, r0
  258. icbi @r0
  259. bsr restore_register
  260. mov #SH_SLEEP_REG_CCR, r0
  261. icbi @r0
  262. skip_restore_mmu:
  263. /* restore general purpose registers if needed */
  264. mov.l @(SH_SLEEP_MODE, r5), r0
  265. tst #SUSP_SH_REGS, r0
  266. bt skip_restore_regs
  267. /* switch to bank 1, restore low registers */
  268. mov.l _rb_bit, r10
  269. bsr _set_sr
  270. mov #-1, r9
  271. bsr restore_low_regs
  272. nop
  273. /* switch to bank0, restore low registers */
  274. mov.l _rb_bit, r9
  275. not r9, r9
  276. bsr _set_sr
  277. mov #0, r10
  278. bsr restore_low_regs
  279. nop
  280. /* restore the rest of the registers */
  281. mov.l @r15+, r8
  282. mov.l @r15+, r9
  283. mov.l @r15+, r10
  284. mov.l @r15+, r11
  285. mov.l @r15+, r12
  286. mov.l @r15+, r13
  287. mov.l @r15+, r14
  288. lds.l @r15+, pr
  289. skip_restore_regs:
  290. rte
  291. nop
  292. restore_register:
  293. add #SH_SLEEP_BASE_DATA, r0
  294. mov.l @(r0, r5), r1
  295. add #-SH_SLEEP_BASE_DATA, r0
  296. add #SH_SLEEP_BASE_ADDR, r0
  297. mov.l @(r0, r5), r0
  298. mov.l r1, @r0
  299. rts
  300. nop
  301. _set_sr:
  302. stc sr, r8
  303. and r9, r8
  304. or r10, r8
  305. ldc r8, sr
  306. rts
  307. nop
  308. restore_low_regs:
  309. mov.l @r15+, r0
  310. mov.l @r15+, r1
  311. mov.l @r15+, r2
  312. mov.l @r15+, r3
  313. mov.l @r15+, r4
  314. mov.l @r15+, r5
  315. mov.l @r15+, r6
  316. rts
  317. mov.l @r15+, r7
  318. .balign 4
  319. _rb_bit: .long 0x20000000 ! RB=1
  320. 1: .long ~0x7ff
  321. ENTRY(sh_mobile_sleep_resume_end)