/arch/ppc/platforms/pmac_sleep.S

https://bitbucket.org/evzijst/gittest · Assembly · 390 lines · 269 code · 40 blank · 81 comment · 1 complexity · c2bc355c0e9fb6f3f9d9cd9197dba1e5 MD5 · raw file

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