sleep.S 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /* sleep.S: power saving mode entry
  2. *
  3. * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Woodhouse (dwmw2@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. *
  11. */
  12. #include <linux/sys.h>
  13. #include <linux/config.h>
  14. #include <linux/linkage.h>
  15. #include <asm/setup.h>
  16. #include <asm/segment.h>
  17. #include <asm/page.h>
  18. #include <asm/ptrace.h>
  19. #include <asm/errno.h>
  20. #include <asm/cache.h>
  21. #include <asm/spr-regs.h>
  22. #define __addr_MASK 0xfeff9820 /* interrupt controller mask */
  23. #define __addr_FR55X_DRCN 0xfeff0218 /* Address of DRCN register */
  24. #define FR55X_DSTS_OFFSET -4 /* Offset from DRCN to DSTS */
  25. #define FR55X_SDRAMC_DSTS_SSI 0x00000002 /* indicates that the SDRAM is in self-refresh mode */
  26. #define __addr_FR4XX_DRCN 0xfe000430 /* Address of DRCN register */
  27. #define FR4XX_DSTS_OFFSET -8 /* Offset from DRCN to DSTS */
  28. #define FR4XX_SDRAMC_DSTS_SSI 0x00000001 /* indicates that the SDRAM is in self-refresh mode */
  29. #define SDRAMC_DRCN_SR 0x00000001 /* transition SDRAM into self-refresh mode */
  30. .section .bss
  31. .balign 8
  32. .globl __sleep_save_area
  33. __sleep_save_area:
  34. .space 16
  35. .text
  36. .balign 4
  37. .macro li v r
  38. sethi.p %hi(\v),\r
  39. setlo %lo(\v),\r
  40. .endm
  41. #ifdef CONFIG_PM
  42. ###############################################################################
  43. #
  44. # CPU suspension routine
  45. # - void frv_cpu_suspend(unsigned long pdm_mode)
  46. #
  47. ###############################################################################
  48. .globl frv_cpu_suspend
  49. .type frv_cpu_suspend,@function
  50. frv_cpu_suspend:
  51. #----------------------------------------------------
  52. # save hsr0, psr, isr, and lr for resume code
  53. #----------------------------------------------------
  54. li __sleep_save_area,gr11
  55. movsg hsr0,gr4
  56. movsg psr,gr5
  57. movsg isr,gr6
  58. movsg lr,gr7
  59. stdi gr4,@(gr11,#0)
  60. stdi gr6,@(gr11,#8)
  61. # store the return address from sleep in GR14, and its complement in GR13 as a check
  62. li __ramboot_resume,gr14
  63. #ifdef CONFIG_MMU
  64. # Resume via RAMBOOT# will turn MMU off, so bootloader needs a physical address.
  65. sethi.p %hi(__page_offset),gr13
  66. setlo %lo(__page_offset),gr13
  67. sub gr14,gr13,gr14
  68. #endif
  69. not gr14,gr13
  70. #----------------------------------------------------
  71. # preload and lock into icache that code which may have to run
  72. # when dram is in self-refresh state.
  73. #----------------------------------------------------
  74. movsg hsr0, gr3
  75. li HSR0_ICE,gr4
  76. or gr3,gr4,gr3
  77. movgs gr3,hsr0
  78. or gr3,gr8,gr7 // add the sleep bits for later
  79. li #__icache_lock_start,gr3
  80. li #__icache_lock_end,gr4
  81. 1: icpl gr3,gr0,#1
  82. addi gr3,#L1_CACHE_BYTES,gr3
  83. cmp gr4,gr3,icc0
  84. bhi icc0,#0,1b
  85. # disable exceptions
  86. movsg psr,gr8
  87. andi.p gr8,#~PSR_PIL,gr8
  88. andi gr8,~PSR_ET,gr8
  89. movgs gr8,psr
  90. ori gr8,#PSR_ET,gr8
  91. srli gr8,#28,gr4
  92. subicc gr4,#3,gr0,icc0
  93. beq icc0,#0,1f
  94. # FR4xx
  95. li __addr_FR4XX_DRCN,gr4
  96. li FR4XX_SDRAMC_DSTS_SSI,gr5
  97. li FR4XX_DSTS_OFFSET,gr6
  98. bra __icache_lock_start
  99. 1:
  100. # FR5xx
  101. li __addr_FR55X_DRCN,gr4
  102. li FR55X_SDRAMC_DSTS_SSI,gr5
  103. li FR55X_DSTS_OFFSET,gr6
  104. bra __icache_lock_start
  105. .size frv_cpu_suspend, .-frv_cpu_suspend
  106. #
  107. # the final part of the sleep sequence...
  108. # - we want it to be be cacheline aligned so we can lock it into the icache easily
  109. # On entry: gr7 holds desired hsr0 sleep value
  110. # gr8 holds desired psr sleep value
  111. #
  112. .balign L1_CACHE_BYTES
  113. .type __icache_lock_start,@function
  114. __icache_lock_start:
  115. #----------------------------------------------------
  116. # put SDRAM in self-refresh mode
  117. #----------------------------------------------------
  118. # Flush all data in the cache using the DCEF instruction.
  119. dcef @(gr0,gr0),#1
  120. # Stop DMAC transfer
  121. # Execute dummy load from SDRAM
  122. ldi @(gr11,#0),gr11
  123. # put the SDRAM into self-refresh mode
  124. ld @(gr4,gr0),gr11
  125. ori gr11,#SDRAMC_DRCN_SR,gr11
  126. st gr11,@(gr4,gr0)
  127. membar
  128. # wait for SDRAM to reach self-refresh mode
  129. 1: ld @(gr4,gr6),gr11
  130. andcc gr11,gr5,gr11,icc0
  131. beq icc0,#0,1b
  132. # Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
  133. # Set the clock mode (CLKC register) as required.
  134. # - At this time, also set the CLKC register P0 bit.
  135. # Set the HSR0 register PDM field.
  136. movgs gr7,hsr0
  137. # Execute NOP 32 times.
  138. .rept 32
  139. nop
  140. .endr
  141. #if 0 // Fujitsu recommend to skip this and will update docs.
  142. # Release the interrupt mask setting of the MASK register of the
  143. # interrupt controller if necessary.
  144. sti gr10,@(gr9,#0)
  145. membar
  146. #endif
  147. # Set the PSR register ET bit to 1 to enable interrupts.
  148. movgs gr8,psr
  149. ###################################################
  150. # this is only reached if waking up via interrupt
  151. ###################################################
  152. # Execute NOP 32 times.
  153. .rept 32
  154. nop
  155. .endr
  156. #----------------------------------------------------
  157. # wake SDRAM from self-refresh mode
  158. #----------------------------------------------------
  159. ld @(gr4,gr0),gr11
  160. andi gr11,#~SDRAMC_DRCN_SR,gr11
  161. st gr11,@(gr4,gr0)
  162. membar
  163. 2:
  164. ld @(gr4,gr6),gr11 // Wait for it to come back...
  165. andcc gr11,gr5,gr0,icc0
  166. bne icc0,0,2b
  167. # wait for the SDRAM to stabilise
  168. li 0x0100000,gr3
  169. 3: subicc gr3,#1,gr3,icc0
  170. bne icc0,#0,3b
  171. # now that DRAM is back, this is the end of the code which gets
  172. # locked in icache.
  173. __icache_lock_end:
  174. .size __icache_lock_start, .-__icache_lock_start
  175. # Fall-through to the RAMBOOT# wakeup path
  176. ###############################################################################
  177. #
  178. # resume from suspend re-entry point reached via RAMBOOT# and bootloader
  179. #
  180. ###############################################################################
  181. __ramboot_resume:
  182. #----------------------------------------------------
  183. # restore hsr0, psr, isr, and leave saved lr in gr7
  184. #----------------------------------------------------
  185. li __sleep_save_area,gr11
  186. #ifdef CONFIG_MMU
  187. movsg hsr0,gr4
  188. sethi.p %hi(HSR0_EXMMU),gr3
  189. setlo %lo(HSR0_EXMMU),gr3
  190. andcc gr3,gr4,gr0,icc0
  191. bne icc0,#0,2f
  192. # need to use physical address
  193. sethi.p %hi(__page_offset),gr3
  194. setlo %lo(__page_offset),gr3
  195. sub gr11,gr3,gr11
  196. # flush all tlb entries
  197. setlos #64,gr4
  198. setlos.p #PAGE_SIZE,gr5
  199. setlos #0,gr6
  200. 1:
  201. tlbpr gr6,gr0,#6,#0
  202. subicc.p gr4,#1,gr4,icc0
  203. add gr6,gr5,gr6
  204. bne icc0,#2,1b
  205. # need a temporary mapping for the current physical address we are
  206. # using between time MMU is enabled and jump to virtual address is
  207. # made.
  208. sethi.p %hi(0x00000000),gr4
  209. setlo %lo(0x00000000),gr4 ; physical address
  210. setlos #xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5
  211. or gr4,gr5,gr5
  212. movsg cxnr,gr13
  213. or gr4,gr13,gr4
  214. movgs gr4,iamlr1 ; mapped from real address 0
  215. movgs gr5,iampr1 ; cached kernel memory at 0x00000000
  216. 2:
  217. #endif
  218. lddi @(gr11,#0),gr4 ; hsr0, psr
  219. lddi @(gr11,#8),gr6 ; isr, lr
  220. movgs gr4,hsr0
  221. bar
  222. #ifdef CONFIG_MMU
  223. sethi.p %hi(1f),gr11
  224. setlo %lo(1f),gr11
  225. jmpl @(gr11,gr0)
  226. 1:
  227. movgs gr0,iampr1 ; get rid of temporary mapping
  228. #endif
  229. movgs gr5,psr
  230. movgs gr6,isr
  231. #----------------------------------------------------
  232. # unlock the icache which was locked before going to sleep
  233. #----------------------------------------------------
  234. li __icache_lock_start,gr3
  235. li __icache_lock_end,gr4
  236. 1: icul gr3
  237. addi gr3,#L1_CACHE_BYTES,gr3
  238. cmp gr4,gr3,icc0
  239. bhi icc0,#0,1b
  240. #----------------------------------------------------
  241. # back to business as usual
  242. #----------------------------------------------------
  243. jmpl @(gr7,gr0) ;
  244. #endif /* CONFIG_PM */
  245. ###############################################################################
  246. #
  247. # CPU core sleep mode routine
  248. #
  249. ###############################################################################
  250. .globl frv_cpu_core_sleep
  251. .type frv_cpu_core_sleep,@function
  252. frv_cpu_core_sleep:
  253. # Preload into icache.
  254. li #__core_sleep_icache_lock_start,gr3
  255. li #__core_sleep_icache_lock_end,gr4
  256. 1: icpl gr3,gr0,#1
  257. addi gr3,#L1_CACHE_BYTES,gr3
  258. cmp gr4,gr3,icc0
  259. bhi icc0,#0,1b
  260. bra __core_sleep_icache_lock_start
  261. .balign L1_CACHE_BYTES
  262. __core_sleep_icache_lock_start:
  263. # (1) Set the PSR register ET bit to 0 to disable interrupts.
  264. movsg psr,gr8
  265. andi.p gr8,#~(PSR_PIL),gr8
  266. andi gr8,#~(PSR_ET),gr4
  267. movgs gr4,psr
  268. #if 0 // Fujitsu recommend to skip this and will update docs.
  269. # (2) Set '1' to all bits in the MASK register of the interrupt
  270. # controller and mask interrupts.
  271. sethi.p %hi(__addr_MASK),gr9
  272. setlo %lo(__addr_MASK),gr9
  273. sethi.p %hi(0xffff0000),gr4
  274. setlo %lo(0xffff0000),gr4
  275. ldi @(gr9,#0),gr10
  276. sti gr4,@(gr9,#0)
  277. #endif
  278. # (3) Flush all data in the cache using the DCEF instruction.
  279. dcef @(gr0,gr0),#1
  280. # (4) Execute the memory barrier instruction
  281. membar
  282. # (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
  283. # (6) Set the clock mode (CLKC register) as required.
  284. # - At this time, also set the CLKC register P0 bit.
  285. # (7) Set the HSR0 register PDM field to 001 .
  286. movsg hsr0,gr4
  287. ori gr4,HSR0_PDM_CORE_SLEEP,gr4
  288. movgs gr4,hsr0
  289. # (8) Execute NOP 32 times.
  290. .rept 32
  291. nop
  292. .endr
  293. #if 0 // Fujitsu recommend to skip this and will update docs.
  294. # (9) Release the interrupt mask setting of the MASK register of the
  295. # interrupt controller if necessary.
  296. sti gr10,@(gr9,#0)
  297. membar
  298. #endif
  299. # (10) Set the PSR register ET bit to 1 to enable interrupts.
  300. movgs gr8,psr
  301. __core_sleep_icache_lock_end:
  302. # Unlock from icache
  303. li __core_sleep_icache_lock_start,gr3
  304. li __core_sleep_icache_lock_end,gr4
  305. 1: icul gr3
  306. addi gr3,#L1_CACHE_BYTES,gr3
  307. cmp gr4,gr3,icc0
  308. bhi icc0,#0,1b
  309. bralr
  310. .size frv_cpu_core_sleep, .-frv_cpu_core_sleep