suspend-asm.S 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. * Enter and leave deep sleep state on MPC83xx
  3. *
  4. * Copyright (c) 2006-2008 Freescale Semiconductor, Inc.
  5. * Author: Scott Wood <scottwood@freescale.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published
  9. * by the Free Software Foundation.
  10. */
  11. #include <asm/page.h>
  12. #include <asm/ppc_asm.h>
  13. #include <asm/reg.h>
  14. #include <asm/asm-offsets.h>
  15. #define SS_MEMSAVE 0x00 /* First 8 bytes of RAM */
  16. #define SS_HID 0x08 /* 3 HIDs */
  17. #define SS_IABR 0x14 /* 2 IABRs */
  18. #define SS_IBCR 0x1c
  19. #define SS_DABR 0x20 /* 2 DABRs */
  20. #define SS_DBCR 0x28
  21. #define SS_SP 0x2c
  22. #define SS_SR 0x30 /* 16 segment registers */
  23. #define SS_R2 0x70
  24. #define SS_MSR 0x74
  25. #define SS_SDR1 0x78
  26. #define SS_LR 0x7c
  27. #define SS_SPRG 0x80 /* 4 SPRGs */
  28. #define SS_DBAT 0x90 /* 8 DBATs */
  29. #define SS_IBAT 0xd0 /* 8 IBATs */
  30. #define SS_TB 0x110
  31. #define SS_CR 0x118
  32. #define SS_GPREG 0x11c /* r12-r31 */
  33. #define STATE_SAVE_SIZE 0x16c
  34. .section .data
  35. .align 5
  36. mpc83xx_sleep_save_area:
  37. .space STATE_SAVE_SIZE
  38. immrbase:
  39. .long 0
  40. .section .text
  41. .align 5
  42. /* r3 = physical address of IMMR */
  43. _GLOBAL(mpc83xx_enter_deep_sleep)
  44. lis r4, immrbase@ha
  45. stw r3, immrbase@l(r4)
  46. /* The first 2 words of memory are used to communicate with the
  47. * bootloader, to tell it how to resume.
  48. *
  49. * The first word is the magic number 0xf5153ae5, and the second
  50. * is the pointer to mpc83xx_deep_resume.
  51. *
  52. * The original content of these two words is saved in SS_MEMSAVE.
  53. */
  54. lis r3, mpc83xx_sleep_save_area@h
  55. ori r3, r3, mpc83xx_sleep_save_area@l
  56. lis r4, KERNELBASE@h
  57. lwz r5, 0(r4)
  58. lwz r6, 4(r4)
  59. stw r5, SS_MEMSAVE+0(r3)
  60. stw r6, SS_MEMSAVE+4(r3)
  61. mfspr r5, SPRN_HID0
  62. mfspr r6, SPRN_HID1
  63. mfspr r7, SPRN_HID2
  64. stw r5, SS_HID+0(r3)
  65. stw r6, SS_HID+4(r3)
  66. stw r7, SS_HID+8(r3)
  67. mfspr r4, SPRN_IABR
  68. mfspr r5, SPRN_IABR2
  69. mfspr r6, SPRN_IBCR
  70. mfspr r7, SPRN_DABR
  71. mfspr r8, SPRN_DABR2
  72. mfspr r9, SPRN_DBCR
  73. stw r4, SS_IABR+0(r3)
  74. stw r5, SS_IABR+4(r3)
  75. stw r6, SS_IBCR(r3)
  76. stw r7, SS_DABR+0(r3)
  77. stw r8, SS_DABR+4(r3)
  78. stw r9, SS_DBCR(r3)
  79. mfspr r4, SPRN_SPRG0
  80. mfspr r5, SPRN_SPRG1
  81. mfspr r6, SPRN_SPRG2
  82. mfspr r7, SPRN_SPRG3
  83. mfsdr1 r8
  84. stw r4, SS_SPRG+0(r3)
  85. stw r5, SS_SPRG+4(r3)
  86. stw r6, SS_SPRG+8(r3)
  87. stw r7, SS_SPRG+12(r3)
  88. stw r8, SS_SDR1(r3)
  89. mfspr r4, SPRN_DBAT0U
  90. mfspr r5, SPRN_DBAT0L
  91. mfspr r6, SPRN_DBAT1U
  92. mfspr r7, SPRN_DBAT1L
  93. stw r4, SS_DBAT+0x00(r3)
  94. stw r5, SS_DBAT+0x04(r3)
  95. stw r6, SS_DBAT+0x08(r3)
  96. stw r7, SS_DBAT+0x0c(r3)
  97. mfspr r4, SPRN_DBAT2U
  98. mfspr r5, SPRN_DBAT2L
  99. mfspr r6, SPRN_DBAT3U
  100. mfspr r7, SPRN_DBAT3L
  101. stw r4, SS_DBAT+0x10(r3)
  102. stw r5, SS_DBAT+0x14(r3)
  103. stw r6, SS_DBAT+0x18(r3)
  104. stw r7, SS_DBAT+0x1c(r3)
  105. mfspr r4, SPRN_DBAT4U
  106. mfspr r5, SPRN_DBAT4L
  107. mfspr r6, SPRN_DBAT5U
  108. mfspr r7, SPRN_DBAT5L
  109. stw r4, SS_DBAT+0x20(r3)
  110. stw r5, SS_DBAT+0x24(r3)
  111. stw r6, SS_DBAT+0x28(r3)
  112. stw r7, SS_DBAT+0x2c(r3)
  113. mfspr r4, SPRN_DBAT6U
  114. mfspr r5, SPRN_DBAT6L
  115. mfspr r6, SPRN_DBAT7U
  116. mfspr r7, SPRN_DBAT7L
  117. stw r4, SS_DBAT+0x30(r3)
  118. stw r5, SS_DBAT+0x34(r3)
  119. stw r6, SS_DBAT+0x38(r3)
  120. stw r7, SS_DBAT+0x3c(r3)
  121. mfspr r4, SPRN_IBAT0U
  122. mfspr r5, SPRN_IBAT0L
  123. mfspr r6, SPRN_IBAT1U
  124. mfspr r7, SPRN_IBAT1L
  125. stw r4, SS_IBAT+0x00(r3)
  126. stw r5, SS_IBAT+0x04(r3)
  127. stw r6, SS_IBAT+0x08(r3)
  128. stw r7, SS_IBAT+0x0c(r3)
  129. mfspr r4, SPRN_IBAT2U
  130. mfspr r5, SPRN_IBAT2L
  131. mfspr r6, SPRN_IBAT3U
  132. mfspr r7, SPRN_IBAT3L
  133. stw r4, SS_IBAT+0x10(r3)
  134. stw r5, SS_IBAT+0x14(r3)
  135. stw r6, SS_IBAT+0x18(r3)
  136. stw r7, SS_IBAT+0x1c(r3)
  137. mfspr r4, SPRN_IBAT4U
  138. mfspr r5, SPRN_IBAT4L
  139. mfspr r6, SPRN_IBAT5U
  140. mfspr r7, SPRN_IBAT5L
  141. stw r4, SS_IBAT+0x20(r3)
  142. stw r5, SS_IBAT+0x24(r3)
  143. stw r6, SS_IBAT+0x28(r3)
  144. stw r7, SS_IBAT+0x2c(r3)
  145. mfspr r4, SPRN_IBAT6U
  146. mfspr r5, SPRN_IBAT6L
  147. mfspr r6, SPRN_IBAT7U
  148. mfspr r7, SPRN_IBAT7L
  149. stw r4, SS_IBAT+0x30(r3)
  150. stw r5, SS_IBAT+0x34(r3)
  151. stw r6, SS_IBAT+0x38(r3)
  152. stw r7, SS_IBAT+0x3c(r3)
  153. mfmsr r4
  154. mflr r5
  155. mfcr r6
  156. stw r4, SS_MSR(r3)
  157. stw r5, SS_LR(r3)
  158. stw r6, SS_CR(r3)
  159. stw r1, SS_SP(r3)
  160. stw r2, SS_R2(r3)
  161. 1: mftbu r4
  162. mftb r5
  163. mftbu r6
  164. cmpw r4, r6
  165. bne 1b
  166. stw r4, SS_TB+0(r3)
  167. stw r5, SS_TB+4(r3)
  168. stmw r12, SS_GPREG(r3)
  169. li r4, 0
  170. addi r6, r3, SS_SR-4
  171. 1: mfsrin r5, r4
  172. stwu r5, 4(r6)
  173. addis r4, r4, 0x1000
  174. cmpwi r4, 0
  175. bne 1b
  176. /* Disable machine checks and critical exceptions */
  177. mfmsr r4
  178. rlwinm r4, r4, 0, ~MSR_CE
  179. rlwinm r4, r4, 0, ~MSR_ME
  180. mtmsr r4
  181. isync
  182. #define TMP_VIRT_IMMR 0xf0000000
  183. #define DEFAULT_IMMR_VALUE 0xff400000
  184. #define IMMRBAR_BASE 0x0000
  185. lis r4, immrbase@ha
  186. lwz r4, immrbase@l(r4)
  187. /* Use DBAT0 to address the current IMMR space */
  188. ori r4, r4, 0x002a
  189. mtspr SPRN_DBAT0L, r4
  190. lis r8, TMP_VIRT_IMMR@h
  191. ori r4, r8, 0x001e /* 1 MByte accessible from Kernel Space only */
  192. mtspr SPRN_DBAT0U, r4
  193. isync
  194. /* Use DBAT1 to address the original IMMR space */
  195. lis r4, DEFAULT_IMMR_VALUE@h
  196. ori r4, r4, 0x002a
  197. mtspr SPRN_DBAT1L, r4
  198. lis r9, (TMP_VIRT_IMMR + 0x01000000)@h
  199. ori r4, r9, 0x001e /* 1 MByte accessible from Kernel Space only */
  200. mtspr SPRN_DBAT1U, r4
  201. isync
  202. /* Use DBAT2 to address the beginning of RAM. This isn't done
  203. * using the normal virtual mapping, because with page debugging
  204. * enabled it will be read-only.
  205. */
  206. li r4, 0x0002
  207. mtspr SPRN_DBAT2L, r4
  208. lis r4, KERNELBASE@h
  209. ori r4, r4, 0x001e /* 1 MByte accessible from Kernel Space only */
  210. mtspr SPRN_DBAT2U, r4
  211. isync
  212. /* Flush the cache with our BAT, as there will be TLB misses
  213. * otherwise if page debugging is enabled, and these misses
  214. * will disturb the PLRU algorithm.
  215. */
  216. bl __flush_disable_L1
  217. /* Keep the i-cache enabled, so the hack below for low-boot
  218. * flash will work.
  219. */
  220. mfspr r3, SPRN_HID0
  221. ori r3, r3, HID0_ICE
  222. mtspr SPRN_HID0, r3
  223. isync
  224. lis r6, 0xf515
  225. ori r6, r6, 0x3ae5
  226. lis r7, mpc83xx_deep_resume@h
  227. ori r7, r7, mpc83xx_deep_resume@l
  228. tophys(r7, r7)
  229. lis r5, KERNELBASE@h
  230. stw r6, 0(r5)
  231. stw r7, 4(r5)
  232. /* Reset BARs */
  233. li r4, 0
  234. stw r4, 0x0024(r8)
  235. stw r4, 0x002c(r8)
  236. stw r4, 0x0034(r8)
  237. stw r4, 0x003c(r8)
  238. stw r4, 0x0064(r8)
  239. stw r4, 0x006c(r8)
  240. /* Rev 1 of the 8313 has problems with wakeup events that are
  241. * pending during the transition to deep sleep state (such as if
  242. * the PCI host sets the state to D3 and then D0 in rapid
  243. * succession). This check shrinks the race window somewhat.
  244. *
  245. * See erratum PCI23, though the problem is not limited
  246. * to PCI.
  247. */
  248. lwz r3, 0x0b04(r8)
  249. andi. r3, r3, 1
  250. bne- mpc83xx_deep_resume
  251. /* Move IMMR back to the default location, following the
  252. * procedure specified in the MPC8313 manual.
  253. */
  254. lwz r4, IMMRBAR_BASE(r8)
  255. isync
  256. lis r4, DEFAULT_IMMR_VALUE@h
  257. stw r4, IMMRBAR_BASE(r8)
  258. lis r4, KERNELBASE@h
  259. lwz r4, 0(r4)
  260. isync
  261. lwz r4, IMMRBAR_BASE(r9)
  262. mr r8, r9
  263. isync
  264. /* Check the Reset Configuration Word to see whether flash needs
  265. * to be mapped at a low address or a high address.
  266. */
  267. lwz r4, 0x0904(r8)
  268. andis. r4, r4, 0x0400
  269. li r4, 0
  270. beq boot_low
  271. lis r4, 0xff80
  272. boot_low:
  273. stw r4, 0x0020(r8)
  274. lis r7, 0x8000
  275. ori r7, r7, 0x0016
  276. mfspr r5, SPRN_HID0
  277. rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
  278. oris r5, r5, HID0_SLEEP@h
  279. mtspr SPRN_HID0, r5
  280. isync
  281. mfmsr r5
  282. oris r5, r5, MSR_POW@h
  283. /* Enable the flash mapping at the appropriate address. This
  284. * mapping will override the RAM mapping if booting low, so there's
  285. * no need to disable the latter. This must be done inside the same
  286. * cache line as setting MSR_POW, so that no instruction fetches
  287. * from RAM happen after the flash mapping is turned on.
  288. */
  289. .align 5
  290. stw r7, 0x0024(r8)
  291. sync
  292. isync
  293. mtmsr r5
  294. isync
  295. 1: b 1b
  296. mpc83xx_deep_resume:
  297. lis r4, 1f@h
  298. ori r4, r4, 1f@l
  299. tophys(r4, r4)
  300. mtsrr0 r4
  301. mfmsr r4
  302. rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR)
  303. mtsrr1 r4
  304. rfi
  305. 1: tlbia
  306. bl __inval_enable_L1
  307. lis r3, mpc83xx_sleep_save_area@h
  308. ori r3, r3, mpc83xx_sleep_save_area@l
  309. tophys(r3, r3)
  310. lwz r5, SS_MEMSAVE+0(r3)
  311. lwz r6, SS_MEMSAVE+4(r3)
  312. stw r5, 0(0)
  313. stw r6, 4(0)
  314. lwz r5, SS_HID+0(r3)
  315. lwz r6, SS_HID+4(r3)
  316. lwz r7, SS_HID+8(r3)
  317. mtspr SPRN_HID0, r5
  318. mtspr SPRN_HID1, r6
  319. mtspr SPRN_HID2, r7
  320. lwz r4, SS_IABR+0(r3)
  321. lwz r5, SS_IABR+4(r3)
  322. lwz r6, SS_IBCR(r3)
  323. lwz r7, SS_DABR+0(r3)
  324. lwz r8, SS_DABR+4(r3)
  325. lwz r9, SS_DBCR(r3)
  326. mtspr SPRN_IABR, r4
  327. mtspr SPRN_IABR2, r5
  328. mtspr SPRN_IBCR, r6
  329. mtspr SPRN_DABR, r7
  330. mtspr SPRN_DABR2, r8
  331. mtspr SPRN_DBCR, r9
  332. li r4, 0
  333. addi r6, r3, SS_SR-4
  334. 1: lwzu r5, 4(r6)
  335. mtsrin r5, r4
  336. addis r4, r4, 0x1000
  337. cmpwi r4, 0
  338. bne 1b
  339. lwz r4, SS_DBAT+0x00(r3)
  340. lwz r5, SS_DBAT+0x04(r3)
  341. lwz r6, SS_DBAT+0x08(r3)
  342. lwz r7, SS_DBAT+0x0c(r3)
  343. mtspr SPRN_DBAT0U, r4
  344. mtspr SPRN_DBAT0L, r5
  345. mtspr SPRN_DBAT1U, r6
  346. mtspr SPRN_DBAT1L, r7
  347. lwz r4, SS_DBAT+0x10(r3)
  348. lwz r5, SS_DBAT+0x14(r3)
  349. lwz r6, SS_DBAT+0x18(r3)
  350. lwz r7, SS_DBAT+0x1c(r3)
  351. mtspr SPRN_DBAT2U, r4
  352. mtspr SPRN_DBAT2L, r5
  353. mtspr SPRN_DBAT3U, r6
  354. mtspr SPRN_DBAT3L, r7
  355. lwz r4, SS_DBAT+0x20(r3)
  356. lwz r5, SS_DBAT+0x24(r3)
  357. lwz r6, SS_DBAT+0x28(r3)
  358. lwz r7, SS_DBAT+0x2c(r3)
  359. mtspr SPRN_DBAT4U, r4
  360. mtspr SPRN_DBAT4L, r5
  361. mtspr SPRN_DBAT5U, r6
  362. mtspr SPRN_DBAT5L, r7
  363. lwz r4, SS_DBAT+0x30(r3)
  364. lwz r5, SS_DBAT+0x34(r3)
  365. lwz r6, SS_DBAT+0x38(r3)
  366. lwz r7, SS_DBAT+0x3c(r3)
  367. mtspr SPRN_DBAT6U, r4
  368. mtspr SPRN_DBAT6L, r5
  369. mtspr SPRN_DBAT7U, r6
  370. mtspr SPRN_DBAT7L, r7
  371. lwz r4, SS_IBAT+0x00(r3)
  372. lwz r5, SS_IBAT+0x04(r3)
  373. lwz r6, SS_IBAT+0x08(r3)
  374. lwz r7, SS_IBAT+0x0c(r3)
  375. mtspr SPRN_IBAT0U, r4
  376. mtspr SPRN_IBAT0L, r5
  377. mtspr SPRN_IBAT1U, r6
  378. mtspr SPRN_IBAT1L, r7
  379. lwz r4, SS_IBAT+0x10(r3)
  380. lwz r5, SS_IBAT+0x14(r3)
  381. lwz r6, SS_IBAT+0x18(r3)
  382. lwz r7, SS_IBAT+0x1c(r3)
  383. mtspr SPRN_IBAT2U, r4
  384. mtspr SPRN_IBAT2L, r5
  385. mtspr SPRN_IBAT3U, r6
  386. mtspr SPRN_IBAT3L, r7
  387. lwz r4, SS_IBAT+0x20(r3)
  388. lwz r5, SS_IBAT+0x24(r3)
  389. lwz r6, SS_IBAT+0x28(r3)
  390. lwz r7, SS_IBAT+0x2c(r3)
  391. mtspr SPRN_IBAT4U, r4
  392. mtspr SPRN_IBAT4L, r5
  393. mtspr SPRN_IBAT5U, r6
  394. mtspr SPRN_IBAT5L, r7
  395. lwz r4, SS_IBAT+0x30(r3)
  396. lwz r5, SS_IBAT+0x34(r3)
  397. lwz r6, SS_IBAT+0x38(r3)
  398. lwz r7, SS_IBAT+0x3c(r3)
  399. mtspr SPRN_IBAT6U, r4
  400. mtspr SPRN_IBAT6L, r5
  401. mtspr SPRN_IBAT7U, r6
  402. mtspr SPRN_IBAT7L, r7
  403. lwz r4, SS_SPRG+0(r3)
  404. lwz r5, SS_SPRG+4(r3)
  405. lwz r6, SS_SPRG+8(r3)
  406. lwz r7, SS_SPRG+12(r3)
  407. lwz r8, SS_SDR1(r3)
  408. mtspr SPRN_SPRG0, r4
  409. mtspr SPRN_SPRG1, r5
  410. mtspr SPRN_SPRG2, r6
  411. mtspr SPRN_SPRG3, r7
  412. mtsdr1 r8
  413. lwz r4, SS_MSR(r3)
  414. lwz r5, SS_LR(r3)
  415. lwz r6, SS_CR(r3)
  416. lwz r1, SS_SP(r3)
  417. lwz r2, SS_R2(r3)
  418. mtsrr1 r4
  419. mtsrr0 r5
  420. mtcr r6
  421. li r4, 0
  422. mtspr SPRN_TBWL, r4
  423. lwz r4, SS_TB+0(r3)
  424. lwz r5, SS_TB+4(r3)
  425. mtspr SPRN_TBWU, r4
  426. mtspr SPRN_TBWL, r5
  427. lmw r12, SS_GPREG(r3)
  428. /* Kick decrementer */
  429. li r0, 1
  430. mtdec r0
  431. rfi