sleep.S 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * This file contains sleep low-level functions for PowerBook G3.
  4. * Copyright (C) 1999 Benjamin Herrenschmidt ([email protected])
  5. * and Paul Mackerras ([email protected]).
  6. */
  7. #include <asm/processor.h>
  8. #include <asm/page.h>
  9. #include <asm/ppc_asm.h>
  10. #include <asm/cputable.h>
  11. #include <asm/cache.h>
  12. #include <asm/thread_info.h>
  13. #include <asm/asm-offsets.h>
  14. #include <asm/mmu.h>
  15. #include <asm/feature-fixups.h>
  16. #define MAGIC 0x4c617273 /* 'Lars' */
  17. /*
  18. * Structure for storing CPU registers on the stack.
  19. */
  20. #define SL_SP 0
  21. #define SL_PC 4
  22. #define SL_MSR 8
  23. #define SL_SDR1 0xc
  24. #define SL_SPRG0 0x10 /* 4 sprg's */
  25. #define SL_DBAT0 0x20
  26. #define SL_IBAT0 0x28
  27. #define SL_DBAT1 0x30
  28. #define SL_IBAT1 0x38
  29. #define SL_DBAT2 0x40
  30. #define SL_IBAT2 0x48
  31. #define SL_DBAT3 0x50
  32. #define SL_IBAT3 0x58
  33. #define SL_DBAT4 0x60
  34. #define SL_IBAT4 0x68
  35. #define SL_DBAT5 0x70
  36. #define SL_IBAT5 0x78
  37. #define SL_DBAT6 0x80
  38. #define SL_IBAT6 0x88
  39. #define SL_DBAT7 0x90
  40. #define SL_IBAT7 0x98
  41. #define SL_TB 0xa0
  42. #define SL_R2 0xa8
  43. #define SL_CR 0xac
  44. #define SL_LR 0xb0
  45. #define SL_R12 0xb4 /* r12 to r31 */
  46. #define SL_SIZE (SL_R12 + 80)
  47. .section .text
  48. .align 5
  49. #if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \
  50. (defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32))
  51. /* This gets called by via-pmu.c late during the sleep process.
  52. * The PMU was already send the sleep command and will shut us down
  53. * soon. We need to save all that is needed and setup the wakeup
  54. * vector that will be called by the ROM on wakeup
  55. */
  56. _GLOBAL(low_sleep_handler)
  57. #ifndef CONFIG_PPC_BOOK3S_32
  58. blr
  59. #else
  60. mflr r0
  61. lis r11,sleep_storage@ha
  62. addi r11,r11,sleep_storage@l
  63. stw r0,SL_LR(r11)
  64. mfcr r0
  65. stw r0,SL_CR(r11)
  66. stw r1,SL_SP(r11)
  67. stw r2,SL_R2(r11)
  68. stmw r12,SL_R12(r11)
  69. /* Save MSR & SDR1 */
  70. mfmsr r4
  71. stw r4,SL_MSR(r11)
  72. mfsdr1 r4
  73. stw r4,SL_SDR1(r11)
  74. /* Get a stable timebase and save it */
  75. 1: mftbu r4
  76. stw r4,SL_TB(r11)
  77. mftb r5
  78. stw r5,SL_TB+4(r11)
  79. mftbu r3
  80. cmpw r3,r4
  81. bne 1b
  82. /* Save SPRGs */
  83. mfsprg r4,0
  84. stw r4,SL_SPRG0(r11)
  85. mfsprg r4,1
  86. stw r4,SL_SPRG0+4(r11)
  87. mfsprg r4,2
  88. stw r4,SL_SPRG0+8(r11)
  89. mfsprg r4,3
  90. stw r4,SL_SPRG0+12(r11)
  91. /* Save BATs */
  92. mfdbatu r4,0
  93. stw r4,SL_DBAT0(r11)
  94. mfdbatl r4,0
  95. stw r4,SL_DBAT0+4(r11)
  96. mfdbatu r4,1
  97. stw r4,SL_DBAT1(r11)
  98. mfdbatl r4,1
  99. stw r4,SL_DBAT1+4(r11)
  100. mfdbatu r4,2
  101. stw r4,SL_DBAT2(r11)
  102. mfdbatl r4,2
  103. stw r4,SL_DBAT2+4(r11)
  104. mfdbatu r4,3
  105. stw r4,SL_DBAT3(r11)
  106. mfdbatl r4,3
  107. stw r4,SL_DBAT3+4(r11)
  108. mfibatu r4,0
  109. stw r4,SL_IBAT0(r11)
  110. mfibatl r4,0
  111. stw r4,SL_IBAT0+4(r11)
  112. mfibatu r4,1
  113. stw r4,SL_IBAT1(r11)
  114. mfibatl r4,1
  115. stw r4,SL_IBAT1+4(r11)
  116. mfibatu r4,2
  117. stw r4,SL_IBAT2(r11)
  118. mfibatl r4,2
  119. stw r4,SL_IBAT2+4(r11)
  120. mfibatu r4,3
  121. stw r4,SL_IBAT3(r11)
  122. mfibatl r4,3
  123. stw r4,SL_IBAT3+4(r11)
  124. BEGIN_MMU_FTR_SECTION
  125. mfspr r4,SPRN_DBAT4U
  126. stw r4,SL_DBAT4(r11)
  127. mfspr r4,SPRN_DBAT4L
  128. stw r4,SL_DBAT4+4(r11)
  129. mfspr r4,SPRN_DBAT5U
  130. stw r4,SL_DBAT5(r11)
  131. mfspr r4,SPRN_DBAT5L
  132. stw r4,SL_DBAT5+4(r11)
  133. mfspr r4,SPRN_DBAT6U
  134. stw r4,SL_DBAT6(r11)
  135. mfspr r4,SPRN_DBAT6L
  136. stw r4,SL_DBAT6+4(r11)
  137. mfspr r4,SPRN_DBAT7U
  138. stw r4,SL_DBAT7(r11)
  139. mfspr r4,SPRN_DBAT7L
  140. stw r4,SL_DBAT7+4(r11)
  141. mfspr r4,SPRN_IBAT4U
  142. stw r4,SL_IBAT4(r11)
  143. mfspr r4,SPRN_IBAT4L
  144. stw r4,SL_IBAT4+4(r11)
  145. mfspr r4,SPRN_IBAT5U
  146. stw r4,SL_IBAT5(r11)
  147. mfspr r4,SPRN_IBAT5L
  148. stw r4,SL_IBAT5+4(r11)
  149. mfspr r4,SPRN_IBAT6U
  150. stw r4,SL_IBAT6(r11)
  151. mfspr r4,SPRN_IBAT6L
  152. stw r4,SL_IBAT6+4(r11)
  153. mfspr r4,SPRN_IBAT7U
  154. stw r4,SL_IBAT7(r11)
  155. mfspr r4,SPRN_IBAT7L
  156. stw r4,SL_IBAT7+4(r11)
  157. END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
  158. /* Backup various CPU config stuffs */
  159. bl __save_cpu_setup
  160. /* The ROM can wake us up via 2 different vectors:
  161. * - On wallstreet & lombard, we must write a magic
  162. * value 'Lars' at address 4 and a pointer to a
  163. * memory location containing the PC to resume from
  164. * at address 0.
  165. * - On Core99, we must store the wakeup vector at
  166. * address 0x80 and eventually it's parameters
  167. * at address 0x84. I've have some trouble with those
  168. * parameters however and I no longer use them.
  169. */
  170. lis r5,grackle_wake_up@ha
  171. addi r5,r5,grackle_wake_up@l
  172. tophys(r5,r5)
  173. stw r5,SL_PC(r11)
  174. lis r4,KERNELBASE@h
  175. tophys(r5,r11)
  176. addi r5,r5,SL_PC
  177. lis r6,MAGIC@ha
  178. addi r6,r6,MAGIC@l
  179. stw r5,0(r4)
  180. stw r6,4(r4)
  181. /* Setup stuffs at 0x80-0x84 for Core99 */
  182. lis r3,core99_wake_up@ha
  183. addi r3,r3,core99_wake_up@l
  184. tophys(r3,r3)
  185. stw r3,0x80(r4)
  186. stw r5,0x84(r4)
  187. .globl low_cpu_offline_self
  188. low_cpu_offline_self:
  189. /* Flush & disable all caches */
  190. bl flush_disable_caches
  191. /* Turn off data relocation. */
  192. mfmsr r3 /* Save MSR in r7 */
  193. rlwinm r3,r3,0,28,26 /* Turn off DR bit */
  194. sync
  195. mtmsr r3
  196. isync
  197. BEGIN_FTR_SECTION
  198. /* Flush any pending L2 data prefetches to work around HW bug */
  199. sync
  200. lis r3,0xfff0
  201. lwz r0,0(r3) /* perform cache-inhibited load to ROM */
  202. sync /* (caches are disabled at this point) */
  203. END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
  204. /*
  205. * Set the HID0 and MSR for sleep.
  206. */
  207. mfspr r2,SPRN_HID0
  208. rlwinm r2,r2,0,10,7 /* clear doze, nap */
  209. oris r2,r2,HID0_SLEEP@h
  210. sync
  211. isync
  212. mtspr SPRN_HID0,r2
  213. sync
  214. /* This loop puts us back to sleep in case we have a spurrious
  215. * wakeup so that the host bridge properly stays asleep. The
  216. * CPU will be turned off, either after a known time (about 1
  217. * second) on wallstreet & lombard, or as soon as the CPU enters
  218. * SLEEP mode on core99
  219. */
  220. mfmsr r2
  221. oris r2,r2,MSR_POW@h
  222. 1: sync
  223. mtmsr r2
  224. isync
  225. b 1b
  226. _ASM_NOKPROBE_SYMBOL(low_cpu_offline_self)
  227. /*
  228. * Here is the resume code.
  229. */
  230. /*
  231. * Core99 machines resume here
  232. * r4 has the physical address of SL_PC(sp) (unused)
  233. */
  234. _GLOBAL(core99_wake_up)
  235. /* Make sure HID0 no longer contains any sleep bit and that data cache
  236. * is disabled
  237. */
  238. mfspr r3,SPRN_HID0
  239. rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */
  240. rlwinm 3,r3,0,18,15 /* clear DCE, ICE */
  241. mtspr SPRN_HID0,r3
  242. sync
  243. isync
  244. /* sanitize MSR */
  245. mfmsr r3
  246. ori r3,r3,MSR_EE|MSR_IP
  247. xori r3,r3,MSR_EE|MSR_IP
  248. sync
  249. isync
  250. mtmsr r3
  251. sync
  252. isync
  253. /* Recover sleep storage */
  254. lis r3,sleep_storage@ha
  255. addi r3,r3,sleep_storage@l
  256. tophys(r3,r3)
  257. addi r1,r3,SL_PC
  258. /* Pass thru to older resume code ... */
  259. _ASM_NOKPROBE_SYMBOL(core99_wake_up)
  260. /*
  261. * Here is the resume code for older machines.
  262. * r1 has the physical address of SL_PC(sp).
  263. */
  264. grackle_wake_up:
  265. /* Restore the kernel's segment registers before
  266. * we do any r1 memory access as we are not sure they
  267. * are in a sane state above the first 256Mb region
  268. */
  269. bl load_segment_registers
  270. sync
  271. isync
  272. subi r1,r1,SL_PC
  273. /* Restore various CPU config stuffs */
  274. bl __restore_cpu_setup
  275. /* Make sure all FPRs have been initialized */
  276. bl reloc_offset
  277. bl __init_fpu_registers
  278. /* Invalidate & enable L1 cache, we don't care about
  279. * whatever the ROM may have tried to write to memory
  280. */
  281. bl __inval_enable_L1
  282. /* Restore the BATs, and SDR1. Then we can turn on the MMU. */
  283. lwz r4,SL_SDR1(r1)
  284. mtsdr1 r4
  285. lwz r4,SL_SPRG0(r1)
  286. mtsprg 0,r4
  287. lwz r4,SL_SPRG0+4(r1)
  288. mtsprg 1,r4
  289. lwz r4,SL_SPRG0+8(r1)
  290. mtsprg 2,r4
  291. lwz r4,SL_SPRG0+12(r1)
  292. mtsprg 3,r4
  293. lwz r4,SL_DBAT0(r1)
  294. mtdbatu 0,r4
  295. lwz r4,SL_DBAT0+4(r1)
  296. mtdbatl 0,r4
  297. lwz r4,SL_DBAT1(r1)
  298. mtdbatu 1,r4
  299. lwz r4,SL_DBAT1+4(r1)
  300. mtdbatl 1,r4
  301. lwz r4,SL_DBAT2(r1)
  302. mtdbatu 2,r4
  303. lwz r4,SL_DBAT2+4(r1)
  304. mtdbatl 2,r4
  305. lwz r4,SL_DBAT3(r1)
  306. mtdbatu 3,r4
  307. lwz r4,SL_DBAT3+4(r1)
  308. mtdbatl 3,r4
  309. lwz r4,SL_IBAT0(r1)
  310. mtibatu 0,r4
  311. lwz r4,SL_IBAT0+4(r1)
  312. mtibatl 0,r4
  313. lwz r4,SL_IBAT1(r1)
  314. mtibatu 1,r4
  315. lwz r4,SL_IBAT1+4(r1)
  316. mtibatl 1,r4
  317. lwz r4,SL_IBAT2(r1)
  318. mtibatu 2,r4
  319. lwz r4,SL_IBAT2+4(r1)
  320. mtibatl 2,r4
  321. lwz r4,SL_IBAT3(r1)
  322. mtibatu 3,r4
  323. lwz r4,SL_IBAT3+4(r1)
  324. mtibatl 3,r4
  325. BEGIN_MMU_FTR_SECTION
  326. lwz r4,SL_DBAT4(r1)
  327. mtspr SPRN_DBAT4U,r4
  328. lwz r4,SL_DBAT4+4(r1)
  329. mtspr SPRN_DBAT4L,r4
  330. lwz r4,SL_DBAT5(r1)
  331. mtspr SPRN_DBAT5U,r4
  332. lwz r4,SL_DBAT5+4(r1)
  333. mtspr SPRN_DBAT5L,r4
  334. lwz r4,SL_DBAT6(r1)
  335. mtspr SPRN_DBAT6U,r4
  336. lwz r4,SL_DBAT6+4(r1)
  337. mtspr SPRN_DBAT6L,r4
  338. lwz r4,SL_DBAT7(r1)
  339. mtspr SPRN_DBAT7U,r4
  340. lwz r4,SL_DBAT7+4(r1)
  341. mtspr SPRN_DBAT7L,r4
  342. lwz r4,SL_IBAT4(r1)
  343. mtspr SPRN_IBAT4U,r4
  344. lwz r4,SL_IBAT4+4(r1)
  345. mtspr SPRN_IBAT4L,r4
  346. lwz r4,SL_IBAT5(r1)
  347. mtspr SPRN_IBAT5U,r4
  348. lwz r4,SL_IBAT5+4(r1)
  349. mtspr SPRN_IBAT5L,r4
  350. lwz r4,SL_IBAT6(r1)
  351. mtspr SPRN_IBAT6U,r4
  352. lwz r4,SL_IBAT6+4(r1)
  353. mtspr SPRN_IBAT6L,r4
  354. lwz r4,SL_IBAT7(r1)
  355. mtspr SPRN_IBAT7U,r4
  356. lwz r4,SL_IBAT7+4(r1)
  357. mtspr SPRN_IBAT7L,r4
  358. END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
  359. /* Flush all TLBs */
  360. lis r4,0x1000
  361. 1: addic. r4,r4,-0x1000
  362. tlbie r4
  363. blt 1b
  364. sync
  365. /* Restore TB */
  366. li r3,0
  367. mttbl r3
  368. lwz r3,SL_TB(r1)
  369. lwz r4,SL_TB+4(r1)
  370. mttbu r3
  371. mttbl r4
  372. /* Restore the callee-saved registers and return */
  373. lwz r0,SL_CR(r1)
  374. mtcr r0
  375. lwz r2,SL_R2(r1)
  376. lmw r12,SL_R12(r1)
  377. /* restore the MSR and SP and turn on the MMU and return */
  378. lwz r3,SL_MSR(r1)
  379. lwz r4,SL_LR(r1)
  380. lwz r1,SL_SP(r1)
  381. mtsrr0 r4
  382. mtsrr1 r3
  383. sync
  384. isync
  385. rfi
  386. _ASM_NOKPROBE_SYMBOL(grackle_wake_up)
  387. #endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
  388. .section .bss
  389. .balign L1_CACHE_BYTES
  390. sleep_storage:
  391. .space SL_SIZE
  392. .balign L1_CACHE_BYTES, 0
  393. #endif /* CONFIG_PPC_BOOK3S_32 */
  394. .section .text