suspend-asm.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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 /* 8 SPRGs */
  28. #define SS_DBAT 0xa0 /* 8 DBATs */
  29. #define SS_IBAT 0xe0 /* 8 IBATs */
  30. #define SS_TB 0x120
  31. #define SS_CR 0x128
  32. #define SS_GPREG 0x12c /* r12-r31 */
  33. #define STATE_SAVE_SIZE 0x17c
  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_SPRG4
  90. mfspr r5, SPRN_SPRG5
  91. mfspr r6, SPRN_SPRG6
  92. mfspr r7, SPRN_SPRG7
  93. stw r4, SS_SPRG+16(r3)
  94. stw r5, SS_SPRG+20(r3)
  95. stw r6, SS_SPRG+24(r3)
  96. stw r7, SS_SPRG+28(r3)
  97. mfspr r4, SPRN_DBAT0U
  98. mfspr r5, SPRN_DBAT0L
  99. mfspr r6, SPRN_DBAT1U
  100. mfspr r7, SPRN_DBAT1L
  101. stw r4, SS_DBAT+0x00(r3)
  102. stw r5, SS_DBAT+0x04(r3)
  103. stw r6, SS_DBAT+0x08(r3)
  104. stw r7, SS_DBAT+0x0c(r3)
  105. mfspr r4, SPRN_DBAT2U
  106. mfspr r5, SPRN_DBAT2L
  107. mfspr r6, SPRN_DBAT3U
  108. mfspr r7, SPRN_DBAT3L
  109. stw r4, SS_DBAT+0x10(r3)
  110. stw r5, SS_DBAT+0x14(r3)
  111. stw r6, SS_DBAT+0x18(r3)
  112. stw r7, SS_DBAT+0x1c(r3)
  113. mfspr r4, SPRN_DBAT4U
  114. mfspr r5, SPRN_DBAT4L
  115. mfspr r6, SPRN_DBAT5U
  116. mfspr r7, SPRN_DBAT5L
  117. stw r4, SS_DBAT+0x20(r3)
  118. stw r5, SS_DBAT+0x24(r3)
  119. stw r6, SS_DBAT+0x28(r3)
  120. stw r7, SS_DBAT+0x2c(r3)
  121. mfspr r4, SPRN_DBAT6U
  122. mfspr r5, SPRN_DBAT6L
  123. mfspr r6, SPRN_DBAT7U
  124. mfspr r7, SPRN_DBAT7L
  125. stw r4, SS_DBAT+0x30(r3)
  126. stw r5, SS_DBAT+0x34(r3)
  127. stw r6, SS_DBAT+0x38(r3)
  128. stw r7, SS_DBAT+0x3c(r3)
  129. mfspr r4, SPRN_IBAT0U
  130. mfspr r5, SPRN_IBAT0L
  131. mfspr r6, SPRN_IBAT1U
  132. mfspr r7, SPRN_IBAT1L
  133. stw r4, SS_IBAT+0x00(r3)
  134. stw r5, SS_IBAT+0x04(r3)
  135. stw r6, SS_IBAT+0x08(r3)
  136. stw r7, SS_IBAT+0x0c(r3)
  137. mfspr r4, SPRN_IBAT2U
  138. mfspr r5, SPRN_IBAT2L
  139. mfspr r6, SPRN_IBAT3U
  140. mfspr r7, SPRN_IBAT3L
  141. stw r4, SS_IBAT+0x10(r3)
  142. stw r5, SS_IBAT+0x14(r3)
  143. stw r6, SS_IBAT+0x18(r3)
  144. stw r7, SS_IBAT+0x1c(r3)
  145. mfspr r4, SPRN_IBAT4U
  146. mfspr r5, SPRN_IBAT4L
  147. mfspr r6, SPRN_IBAT5U
  148. mfspr r7, SPRN_IBAT5L
  149. stw r4, SS_IBAT+0x20(r3)
  150. stw r5, SS_IBAT+0x24(r3)
  151. stw r6, SS_IBAT+0x28(r3)
  152. stw r7, SS_IBAT+0x2c(r3)
  153. mfspr r4, SPRN_IBAT6U
  154. mfspr r5, SPRN_IBAT6L
  155. mfspr r6, SPRN_IBAT7U
  156. mfspr r7, SPRN_IBAT7L
  157. stw r4, SS_IBAT+0x30(r3)
  158. stw r5, SS_IBAT+0x34(r3)
  159. stw r6, SS_IBAT+0x38(r3)
  160. stw r7, SS_IBAT+0x3c(r3)
  161. mfmsr r4
  162. mflr r5
  163. mfcr r6
  164. stw r4, SS_MSR(r3)
  165. stw r5, SS_LR(r3)
  166. stw r6, SS_CR(r3)
  167. stw r1, SS_SP(r3)
  168. stw r2, SS_R2(r3)
  169. 1: mftbu r4
  170. mftb r5
  171. mftbu r6
  172. cmpw r4, r6
  173. bne 1b
  174. stw r4, SS_TB+0(r3)
  175. stw r5, SS_TB+4(r3)
  176. stmw r12, SS_GPREG(r3)
  177. li r4, 0
  178. addi r6, r3, SS_SR-4
  179. 1: mfsrin r5, r4
  180. stwu r5, 4(r6)
  181. addis r4, r4, 0x1000
  182. cmpwi r4, 0
  183. bne 1b
  184. /* Disable machine checks and critical exceptions */
  185. mfmsr r4
  186. rlwinm r4, r4, 0, ~MSR_CE
  187. rlwinm r4, r4, 0, ~MSR_ME
  188. mtmsr r4
  189. isync
  190. #define TMP_VIRT_IMMR 0xf0000000
  191. #define DEFAULT_IMMR_VALUE 0xff400000
  192. #define IMMRBAR_BASE 0x0000
  193. lis r4, immrbase@ha
  194. lwz r4, immrbase@l(r4)
  195. /* Use DBAT0 to address the current IMMR space */
  196. ori r4, r4, 0x002a
  197. mtspr SPRN_DBAT0L, r4
  198. lis r8, TMP_VIRT_IMMR@h
  199. ori r4, r8, 0x001e /* 1 MByte accessible from Kernel Space only */
  200. mtspr SPRN_DBAT0U, r4
  201. isync
  202. /* Use DBAT1 to address the original IMMR space */
  203. lis r4, DEFAULT_IMMR_VALUE@h
  204. ori r4, r4, 0x002a
  205. mtspr SPRN_DBAT1L, r4
  206. lis r9, (TMP_VIRT_IMMR + 0x01000000)@h
  207. ori r4, r9, 0x001e /* 1 MByte accessible from Kernel Space only */
  208. mtspr SPRN_DBAT1U, r4
  209. isync
  210. /* Use DBAT2 to address the beginning of RAM. This isn't done
  211. * using the normal virtual mapping, because with page debugging
  212. * enabled it will be read-only.
  213. */
  214. li r4, 0x0002
  215. mtspr SPRN_DBAT2L, r4
  216. lis r4, KERNELBASE@h
  217. ori r4, r4, 0x001e /* 1 MByte accessible from Kernel Space only */
  218. mtspr SPRN_DBAT2U, r4
  219. isync
  220. /* Flush the cache with our BAT, as there will be TLB misses
  221. * otherwise if page debugging is enabled, and these misses
  222. * will disturb the PLRU algorithm.
  223. */
  224. bl __flush_disable_L1
  225. /* Keep the i-cache enabled, so the hack below for low-boot
  226. * flash will work.
  227. */
  228. mfspr r3, SPRN_HID0
  229. ori r3, r3, HID0_ICE
  230. mtspr SPRN_HID0, r3
  231. isync
  232. lis r6, 0xf515
  233. ori r6, r6, 0x3ae5
  234. lis r7, mpc83xx_deep_resume@h
  235. ori r7, r7, mpc83xx_deep_resume@l
  236. tophys(r7, r7)
  237. lis r5, KERNELBASE@h
  238. stw r6, 0(r5)
  239. stw r7, 4(r5)
  240. /* Reset BARs */
  241. li r4, 0
  242. stw r4, 0x0024(r8)
  243. stw r4, 0x002c(r8)
  244. stw r4, 0x0034(r8)
  245. stw r4, 0x003c(r8)
  246. stw r4, 0x0064(r8)
  247. stw r4, 0x006c(r8)
  248. /* Rev 1 of the 8313 has problems with wakeup events that are
  249. * pending during the transition to deep sleep state (such as if
  250. * the PCI host sets the state to D3 and then D0 in rapid
  251. * succession). This check shrinks the race window somewhat.
  252. *
  253. * See erratum PCI23, though the problem is not limited
  254. * to PCI.
  255. */
  256. lwz r3, 0x0b04(r8)
  257. andi. r3, r3, 1
  258. bne- mpc83xx_deep_resume
  259. /* Move IMMR back to the default location, following the
  260. * procedure specified in the MPC8313 manual.
  261. */
  262. lwz r4, IMMRBAR_BASE(r8)
  263. isync
  264. lis r4, DEFAULT_IMMR_VALUE@h
  265. stw r4, IMMRBAR_BASE(r8)
  266. lis r4, KERNELBASE@h
  267. lwz r4, 0(r4)
  268. isync
  269. lwz r4, IMMRBAR_BASE(r9)
  270. mr r8, r9
  271. isync
  272. /* Check the Reset Configuration Word to see whether flash needs
  273. * to be mapped at a low address or a high address.
  274. */
  275. lwz r4, 0x0904(r8)
  276. andis. r4, r4, 0x0400
  277. li r4, 0
  278. beq boot_low
  279. lis r4, 0xff80
  280. boot_low:
  281. stw r4, 0x0020(r8)
  282. lis r7, 0x8000
  283. ori r7, r7, 0x0016
  284. mfspr r5, SPRN_HID0
  285. rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
  286. oris r5, r5, HID0_SLEEP@h
  287. mtspr SPRN_HID0, r5
  288. isync
  289. mfmsr r5
  290. oris r5, r5, MSR_POW@h
  291. /* Enable the flash mapping at the appropriate address. This
  292. * mapping will override the RAM mapping if booting low, so there's
  293. * no need to disable the latter. This must be done inside the same
  294. * cache line as setting MSR_POW, so that no instruction fetches
  295. * from RAM happen after the flash mapping is turned on.
  296. */
  297. .align 5
  298. stw r7, 0x0024(r8)
  299. sync
  300. isync
  301. mtmsr r5
  302. isync
  303. 1: b 1b
  304. mpc83xx_deep_resume:
  305. lis r4, 1f@h
  306. ori r4, r4, 1f@l
  307. tophys(r4, r4)
  308. mtsrr0 r4
  309. mfmsr r4
  310. rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR)
  311. mtsrr1 r4
  312. rfi
  313. 1: tlbia
  314. bl __inval_enable_L1
  315. lis r3, mpc83xx_sleep_save_area@h
  316. ori r3, r3, mpc83xx_sleep_save_area@l
  317. tophys(r3, r3)
  318. lwz r5, SS_MEMSAVE+0(r3)
  319. lwz r6, SS_MEMSAVE+4(r3)
  320. stw r5, 0(0)
  321. stw r6, 4(0)
  322. lwz r5, SS_HID+0(r3)
  323. lwz r6, SS_HID+4(r3)
  324. lwz r7, SS_HID+8(r3)
  325. mtspr SPRN_HID0, r5
  326. mtspr SPRN_HID1, r6
  327. mtspr SPRN_HID2, r7
  328. lwz r4, SS_IABR+0(r3)
  329. lwz r5, SS_IABR+4(r3)
  330. lwz r6, SS_IBCR(r3)
  331. lwz r7, SS_DABR+0(r3)
  332. lwz r8, SS_DABR+4(r3)
  333. lwz r9, SS_DBCR(r3)
  334. mtspr SPRN_IABR, r4
  335. mtspr SPRN_IABR2, r5
  336. mtspr SPRN_IBCR, r6
  337. mtspr SPRN_DABR, r7
  338. mtspr SPRN_DABR2, r8
  339. mtspr SPRN_DBCR, r9
  340. li r4, 0
  341. addi r6, r3, SS_SR-4
  342. 1: lwzu r5, 4(r6)
  343. mtsrin r5, r4
  344. addis r4, r4, 0x1000
  345. cmpwi r4, 0
  346. bne 1b
  347. lwz r4, SS_DBAT+0x00(r3)
  348. lwz r5, SS_DBAT+0x04(r3)
  349. lwz r6, SS_DBAT+0x08(r3)
  350. lwz r7, SS_DBAT+0x0c(r3)
  351. mtspr SPRN_DBAT0U, r4
  352. mtspr SPRN_DBAT0L, r5
  353. mtspr SPRN_DBAT1U, r6
  354. mtspr SPRN_DBAT1L, r7
  355. lwz r4, SS_DBAT+0x10(r3)
  356. lwz r5, SS_DBAT+0x14(r3)
  357. lwz r6, SS_DBAT+0x18(r3)
  358. lwz r7, SS_DBAT+0x1c(r3)
  359. mtspr SPRN_DBAT2U, r4
  360. mtspr SPRN_DBAT2L, r5
  361. mtspr SPRN_DBAT3U, r6
  362. mtspr SPRN_DBAT3L, r7
  363. lwz r4, SS_DBAT+0x20(r3)
  364. lwz r5, SS_DBAT+0x24(r3)
  365. lwz r6, SS_DBAT+0x28(r3)
  366. lwz r7, SS_DBAT+0x2c(r3)
  367. mtspr SPRN_DBAT4U, r4
  368. mtspr SPRN_DBAT4L, r5
  369. mtspr SPRN_DBAT5U, r6
  370. mtspr SPRN_DBAT5L, r7
  371. lwz r4, SS_DBAT+0x30(r3)
  372. lwz r5, SS_DBAT+0x34(r3)
  373. lwz r6, SS_DBAT+0x38(r3)
  374. lwz r7, SS_DBAT+0x3c(r3)
  375. mtspr SPRN_DBAT6U, r4
  376. mtspr SPRN_DBAT6L, r5
  377. mtspr SPRN_DBAT7U, r6
  378. mtspr SPRN_DBAT7L, r7
  379. lwz r4, SS_IBAT+0x00(r3)
  380. lwz r5, SS_IBAT+0x04(r3)
  381. lwz r6, SS_IBAT+0x08(r3)
  382. lwz r7, SS_IBAT+0x0c(r3)
  383. mtspr SPRN_IBAT0U, r4
  384. mtspr SPRN_IBAT0L, r5
  385. mtspr SPRN_IBAT1U, r6
  386. mtspr SPRN_IBAT1L, r7
  387. lwz r4, SS_IBAT+0x10(r3)
  388. lwz r5, SS_IBAT+0x14(r3)
  389. lwz r6, SS_IBAT+0x18(r3)
  390. lwz r7, SS_IBAT+0x1c(r3)
  391. mtspr SPRN_IBAT2U, r4
  392. mtspr SPRN_IBAT2L, r5
  393. mtspr SPRN_IBAT3U, r6
  394. mtspr SPRN_IBAT3L, r7
  395. lwz r4, SS_IBAT+0x20(r3)
  396. lwz r5, SS_IBAT+0x24(r3)
  397. lwz r6, SS_IBAT+0x28(r3)
  398. lwz r7, SS_IBAT+0x2c(r3)
  399. mtspr SPRN_IBAT4U, r4
  400. mtspr SPRN_IBAT4L, r5
  401. mtspr SPRN_IBAT5U, r6
  402. mtspr SPRN_IBAT5L, r7
  403. lwz r4, SS_IBAT+0x30(r3)
  404. lwz r5, SS_IBAT+0x34(r3)
  405. lwz r6, SS_IBAT+0x38(r3)
  406. lwz r7, SS_IBAT+0x3c(r3)
  407. mtspr SPRN_IBAT6U, r4
  408. mtspr SPRN_IBAT6L, r5
  409. mtspr SPRN_IBAT7U, r6
  410. mtspr SPRN_IBAT7L, r7
  411. lwz r4, SS_SPRG+16(r3)
  412. lwz r5, SS_SPRG+20(r3)
  413. lwz r6, SS_SPRG+24(r3)
  414. lwz r7, SS_SPRG+28(r3)
  415. mtspr SPRN_SPRG4, r4
  416. mtspr SPRN_SPRG5, r5
  417. mtspr SPRN_SPRG6, r6
  418. mtspr SPRN_SPRG7, r7
  419. lwz r4, SS_SPRG+0(r3)
  420. lwz r5, SS_SPRG+4(r3)
  421. lwz r6, SS_SPRG+8(r3)
  422. lwz r7, SS_SPRG+12(r3)
  423. lwz r8, SS_SDR1(r3)
  424. mtspr SPRN_SPRG0, r4
  425. mtspr SPRN_SPRG1, r5
  426. mtspr SPRN_SPRG2, r6
  427. mtspr SPRN_SPRG3, r7
  428. mtsdr1 r8
  429. lwz r4, SS_MSR(r3)
  430. lwz r5, SS_LR(r3)
  431. lwz r6, SS_CR(r3)
  432. lwz r1, SS_SP(r3)
  433. lwz r2, SS_R2(r3)
  434. mtsrr1 r4
  435. mtsrr0 r5
  436. mtcr r6
  437. li r4, 0
  438. mtspr SPRN_TBWL, r4
  439. lwz r4, SS_TB+0(r3)
  440. lwz r5, SS_TB+4(r3)
  441. mtspr SPRN_TBWU, r4
  442. mtspr SPRN_TBWL, r5
  443. lmw r12, SS_GPREG(r3)
  444. /* Kick decrementer */
  445. li r0, 1
  446. mtdec r0
  447. rfi