swsusp.S 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* SPDX-License-Identifier: GPL-2.0
  2. *
  3. * arch/sh/kernel/cpu/sh3/swsusp.S
  4. *
  5. * Copyright (C) 2009 Magnus Damm
  6. */
  7. #include <linux/sys.h>
  8. #include <linux/errno.h>
  9. #include <linux/linkage.h>
  10. #include <asm/asm-offsets.h>
  11. #include <asm/page.h>
  12. #define k0 r0
  13. #define k1 r1
  14. #define k2 r2
  15. #define k3 r3
  16. #define k4 r4
  17. ! swsusp_arch_resume()
  18. ! - copy restore_pblist pages
  19. ! - restore registers from swsusp_arch_regs_cpu0
  20. ENTRY(swsusp_arch_resume)
  21. mov.l 1f, r15
  22. mov.l 2f, r4
  23. mov.l @r4, r4
  24. swsusp_copy_loop:
  25. mov r4, r0
  26. cmp/eq #0, r0
  27. bt swsusp_restore_regs
  28. mov.l @(PBE_ADDRESS, r4), r2
  29. mov.l @(PBE_ORIG_ADDRESS, r4), r5
  30. mov #(PAGE_SIZE >> 10), r3
  31. shll8 r3
  32. shlr2 r3 /* PAGE_SIZE / 16 */
  33. swsusp_copy_page:
  34. dt r3
  35. mov.l @r2+,r1 /* 16n+0 */
  36. mov.l r1,@r5
  37. add #4,r5
  38. mov.l @r2+,r1 /* 16n+4 */
  39. mov.l r1,@r5
  40. add #4,r5
  41. mov.l @r2+,r1 /* 16n+8 */
  42. mov.l r1,@r5
  43. add #4,r5
  44. mov.l @r2+,r1 /* 16n+12 */
  45. mov.l r1,@r5
  46. bf/s swsusp_copy_page
  47. add #4,r5
  48. bra swsusp_copy_loop
  49. mov.l @(PBE_NEXT, r4), r4
  50. swsusp_restore_regs:
  51. ! BL=0: R7->R0 is bank0
  52. mov.l 3f, r8
  53. mov.l 4f, r5
  54. jsr @r5
  55. nop
  56. ! BL=1: R7->R0 is bank1
  57. lds k2, pr
  58. ldc k3, ssr
  59. mov.l @r15+, r0
  60. mov.l @r15+, r1
  61. mov.l @r15+, r2
  62. mov.l @r15+, r3
  63. mov.l @r15+, r4
  64. mov.l @r15+, r5
  65. mov.l @r15+, r6
  66. mov.l @r15+, r7
  67. rte
  68. nop
  69. ! BL=0: R7->R0 is bank0
  70. .align 2
  71. 1: .long swsusp_arch_regs_cpu0
  72. 2: .long restore_pblist
  73. 3: .long 0x20000000 ! RB=1
  74. 4: .long restore_regs
  75. ! swsusp_arch_suspend()
  76. ! - prepare pc for resume, return from function without swsusp_save on resume
  77. ! - save registers in swsusp_arch_regs_cpu0
  78. ! - call swsusp_save write suspend image
  79. ENTRY(swsusp_arch_suspend)
  80. sts pr, r0 ! save pr in r0
  81. mov r15, r2 ! save sp in r2
  82. mov r8, r5 ! save r8 in r5
  83. stc sr, r1
  84. ldc r1, ssr ! save sr in ssr
  85. mov.l 1f, r1
  86. ldc r1, spc ! setup pc value for resuming
  87. mov.l 5f, r15 ! use swsusp_arch_regs_cpu0 as stack
  88. mov.l 6f, r3
  89. add r3, r15 ! save from top of structure
  90. ! BL=0: R7->R0 is bank0
  91. mov.l 2f, r3 ! get new SR value for bank1
  92. mov #0, r4
  93. mov.l 7f, r1
  94. jsr @r1 ! switch to bank1 and save bank1 r7->r0
  95. not r4, r4
  96. ! BL=1: R7->R0 is bank1
  97. stc r2_bank, k0 ! fetch old sp from r2_bank0
  98. mov.l 3f, k4 ! SR bits to clear in k4
  99. mov.l 8f, k1
  100. jsr @k1 ! switch to bank0 and save all regs
  101. stc r0_bank, k3 ! fetch old pr from r0_bank0
  102. ! BL=0: R7->R0 is bank0
  103. mov r2, r15 ! restore old sp
  104. mov r5, r8 ! restore old r8
  105. stc ssr, r1
  106. ldc r1, sr ! restore old sr
  107. lds r0, pr ! restore old pr
  108. mov.l 4f, r0
  109. jmp @r0
  110. nop
  111. swsusp_call_save:
  112. mov r2, r15 ! restore old sp
  113. mov r5, r8 ! restore old r8
  114. lds r0, pr ! restore old pr
  115. rts
  116. mov #0, r0
  117. .align 2
  118. 1: .long swsusp_call_save
  119. 2: .long 0x20000000 ! RB=1
  120. 3: .long 0xdfffffff ! RB=0
  121. 4: .long swsusp_save
  122. 5: .long swsusp_arch_regs_cpu0
  123. 6: .long SWSUSP_ARCH_REGS_SIZE
  124. 7: .long save_low_regs
  125. 8: .long save_regs