sleep.S 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. /* call self-refresh entering code if needed */
  46. mov.l @(SH_SLEEP_MODE, r5), r0
  47. tst #SUSP_SH_SF, r0
  48. bt skip_set_sf
  49. mov.l @(SH_SLEEP_SF_PRE, r5), r0
  50. jsr @r0
  51. nop
  52. skip_set_sf:
  53. mov.l @(SH_SLEEP_MODE, r5), r0
  54. tst #SUSP_SH_STANDBY, r0
  55. bt test_rstandby
  56. /* set mode to "software standby mode" */
  57. bra do_sleep
  58. mov #0x80, r1
  59. test_rstandby:
  60. tst #SUSP_SH_RSTANDBY, r0
  61. bt test_ustandby
  62. /* set mode to "r-standby mode" */
  63. bra do_sleep
  64. mov #0x20, r1
  65. test_ustandby:
  66. tst #SUSP_SH_USTANDBY, r0
  67. bt force_sleep
  68. /* set mode to "u-standby mode" */
  69. bra do_sleep
  70. mov #0x10, r1
  71. force_sleep:
  72. /* set mode to "sleep mode" */
  73. mov #0x00, r1
  74. do_sleep:
  75. /* setup and enter selected standby mode */
  76. bsr get_register
  77. mov #SH_SLEEP_REG_STBCR, r0
  78. mov.l r1, @r0
  79. again:
  80. sleep
  81. bra again
  82. nop
  83. save_register:
  84. add #SH_SLEEP_BASE_ADDR, r0
  85. mov.l @(r0, r5), r1
  86. add #-SH_SLEEP_BASE_ADDR, r0
  87. mov.l @r1, r1
  88. add #SH_SLEEP_BASE_DATA, r0
  89. mov.l r1, @(r0, r5)
  90. add #-SH_SLEEP_BASE_DATA, r0
  91. rts
  92. nop
  93. get_register:
  94. add #SH_SLEEP_BASE_ADDR, r0
  95. mov.l @(r0, r5), r0
  96. rts
  97. nop
  98. ENTRY(sh_mobile_sleep_enter_end)
  99. .balign 4
  100. ENTRY(sh_mobile_sleep_resume_start)
  101. /* figure out start address */
  102. bsr 0f
  103. nop
  104. 0:
  105. sts pr, k1
  106. mov.l 1f, k0
  107. and k0, k1
  108. /* store pointer to data area in VBR */
  109. ldc k1, vbr
  110. /* setup sr with saved sr */
  111. mov.l @(SH_SLEEP_SR, k1), k0
  112. ldc k0, sr
  113. /* now: user register set! */
  114. stc vbr, r5
  115. /* setup spc with return address to c code */
  116. mov.l @(SH_SLEEP_SPC, r5), r0
  117. ldc r0, spc
  118. /* restore vbr */
  119. mov.l @(SH_SLEEP_VBR, r5), r0
  120. ldc r0, vbr
  121. /* setup ssr with saved sr */
  122. mov.l @(SH_SLEEP_SR, r5), r0
  123. ldc r0, ssr
  124. /* restore sleep mode register */
  125. bsr restore_register
  126. mov #SH_SLEEP_REG_STBCR, r0
  127. /* call self-refresh resume code if needed */
  128. mov.l @(SH_SLEEP_MODE, r5), r0
  129. tst #SUSP_SH_SF, r0
  130. bt skip_restore_sf
  131. mov.l @(SH_SLEEP_SF_POST, r5), r0
  132. jsr @r0
  133. nop
  134. skip_restore_sf:
  135. rte
  136. nop
  137. restore_register:
  138. add #SH_SLEEP_BASE_DATA, r0
  139. mov.l @(r0, r5), r1
  140. add #-SH_SLEEP_BASE_DATA, r0
  141. add #SH_SLEEP_BASE_ADDR, r0
  142. mov.l @(r0, r5), r0
  143. mov.l r1, @r0
  144. rts
  145. nop
  146. .balign 4
  147. 1: .long ~0x7ff
  148. ENTRY(sh_mobile_sleep_resume_end)