pmac_sleep.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  * This file contains sleep low-level functions for PowerBook G3.
  6.  *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
  7.  *    and Paul Mackerras (paulus@samba.org).
  8.  *
  9.  * This program is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU General Public License
  11.  * as published by the Free Software Foundation; either version
  12.  * 2 of the License, or (at your option) any later version.
  13.  *
  14.  */
  15. #include <linux/config.h>
  16. #include <asm/processor.h>
  17. #include <asm/page.h>
  18. #include <asm/ppc_asm.h>
  19. #include <asm/cputable.h>
  20. #include <asm/ppc_asm.h>
  21. #include "../kernel/ppc_defs.h" // DAMMIT !
  22. #define MAGIC 0x4c617273 /* 'Lars' */
  23. /*
  24.  * Structure for storing CPU registers on the stack.
  25.  */
  26. #define SL_SP 0
  27. #define SL_PC 4
  28. #define SL_MSR 8
  29. #define SL_SDR1 0xc
  30. #define SL_SPRG0 0x10 /* 4 sprg's */
  31. #define SL_DBAT0 0x20
  32. #define SL_IBAT0 0x28
  33. #define SL_DBAT1 0x30
  34. #define SL_IBAT1 0x38
  35. #define SL_DBAT2 0x40
  36. #define SL_IBAT2 0x48
  37. #define SL_DBAT3 0x50
  38. #define SL_IBAT3 0x58
  39. #define SL_TB 0x60
  40. #define SL_HID0 0x68
  41. #define SL_HID1 0x6c
  42. #define SL_MSSCR0 0x70
  43. #define SL_MSSSR0 0x74
  44. #define SL_ICTRL 0x78
  45. #define SL_LDSTCR 0x7c
  46. #define SL_LDSTDB 0x80
  47. #define SL_R2 0x84
  48. #define SL_CR 0x88
  49. #define SL_R12 0x8c /* r12 to r31 */
  50. #define SL_SIZE (SL_R12 + 80)
  51. .text
  52. .align 5
  53. #if defined(CONFIG_PMAC_PBOOK)
  54. /* This gets called by via-pmu.c late during the sleep process.
  55.  * The PMU was already send the sleep command and will shut us down
  56.  * soon. We need to save all that is needed and setup the wakeup
  57.  * vector that will be called by the ROM on wakeup
  58.  */
  59. _GLOBAL(low_sleep_handler)
  60. mflr r0
  61. stw r0,4(r1)
  62. stwu r1,-SL_SIZE(r1)
  63. mfcr r0
  64. stw r0,SL_CR(r1)
  65. stw r2,SL_R2(r1)
  66. stmw r12,SL_R12(r1)
  67. /* Save MSR & SDR1 */
  68. mfmsr r4
  69. stw r4,SL_MSR(r1)
  70. mfsdr1 r4
  71. stw r4,SL_SDR1(r1)
  72. /* Get a stable timebase and save it */
  73. 1: mftbu r4
  74. stw r4,SL_TB(r1)
  75. mftb r5
  76. stw r5,SL_TB+4(r1)
  77. mftbu r3
  78. cmpw r3,r4
  79. bne 1b
  80. /* Save SPRGs */
  81. mfsprg r4,0
  82. stw r4,SL_SPRG0(r1)
  83. mfsprg r4,1
  84. stw r4,SL_SPRG0+4(r1)
  85. mfsprg r4,2
  86. stw r4,SL_SPRG0+8(r1)
  87. mfsprg r4,3
  88. stw r4,SL_SPRG0+12(r1)
  89. /* Save BATs */
  90. mfdbatu r4,0
  91. stw r4,SL_DBAT0(r1)
  92. mfdbatl r4,0
  93. stw r4,SL_DBAT0+4(r1)
  94. mfdbatu r4,1
  95. stw r4,SL_DBAT1(r1)
  96. mfdbatl r4,1
  97. stw r4,SL_DBAT1+4(r1)
  98. mfdbatu r4,2
  99. stw r4,SL_DBAT2(r1)
  100. mfdbatl r4,2
  101. stw r4,SL_DBAT2+4(r1)
  102. mfdbatu r4,3
  103. stw r4,SL_DBAT3(r1)
  104. mfdbatl r4,3
  105. stw r4,SL_DBAT3+4(r1)
  106. mfibatu r4,0
  107. stw r4,SL_IBAT0(r1)
  108. mfibatl r4,0
  109. stw r4,SL_IBAT0+4(r1)
  110. mfibatu r4,1
  111. stw r4,SL_IBAT1(r1)
  112. mfibatl r4,1
  113. stw r4,SL_IBAT1+4(r1)
  114. mfibatu r4,2
  115. stw r4,SL_IBAT2(r1)
  116. mfibatl r4,2
  117. stw r4,SL_IBAT2+4(r1)
  118. mfibatu r4,3
  119. stw r4,SL_IBAT3(r1)
  120. mfibatl r4,3
  121. stw r4,SL_IBAT3+4(r1)
  122. /* Save HID0 */
  123. mfspr r4,HID0
  124. stw r4,SL_HID0(r1)
  125. /* Save 7400/7410/7450 specific registers */
  126. mfspr r3,PVR
  127. srwi r3,r3,16
  128. cmpli cr0,r3,0x8000 /* 7450 */
  129. cmpli cr1,r3,0x000c /* 7400 */
  130. cmpli cr2,r3,0x800c /* 7410 */
  131. cmpli cr3,r3,0x8001 /* 7455 */
  132. cmpli cr4,r3,0x7000 /* 750FX */
  133. cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
  134. cror 4*cr0+eq,4*cr0+eq,4*cr3+eq
  135. cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
  136. bne 1f
  137. mfspr r4,SPRN_MSSCR0
  138. stw r4,SL_MSSCR0(r1)
  139. mfspr r4,SPRN_MSSSR0
  140. stw r4,SL_MSSSR0(r1)
  141. /* Save 7450/7455 specific registers */
  142. beq cr1,1f
  143. mfspr r4,HID1
  144. stw r4,SL_HID1(r1)
  145. mfspr r4,SPRN_ICTRL
  146. stw r4,SL_ICTRL(r1)
  147. mfspr r4,SPRN_LDSTCR
  148. stw r4,SL_LDSTCR(r1)
  149. mfspr r4,SPRN_LDSTDB
  150. stw r4,SL_LDSTDB(r1)
  151. 1:
  152. /* Save 750FX specific registers */
  153. bne cr4,1f
  154. mfspr r4,HID1
  155. stw r4,SL_HID1(r1)
  156. 1:
  157. /* The ROM can wake us up via 2 different vectors:
  158.  *  - On wallstreet & lombard, we must write a magic
  159.  *    value 'Lars' at address 4 and a pointer to a
  160.  *    memory location containing the PC to resume from
  161.  *    at address 0.
  162.  *  - On Core99, we must store the wakeup vector at
  163.  *    address 0x80 and eventually it's parameters
  164.  *    at address 0x84. I've have some trouble with those
  165.  *    parameters however and I no longer use them.
  166.  */
  167. lis r5,grackle_wake_up@ha
  168. addi r5,r5,grackle_wake_up@l
  169. tophys(r5,r5)
  170. stw r5,SL_PC(r1)
  171. lis r4,KERNELBASE@h
  172. tophys(r5,r1)
  173. addi r5,r5,SL_PC
  174. lis r6,MAGIC@ha
  175. addi r6,r6,MAGIC@l
  176. stw r5,0(r4)
  177. stw r6,4(r4)
  178. /* Setup stuffs at 0x80-0x84 for Core99 */
  179. lis r3,core99_wake_up@ha
  180. addi r3,r3,core99_wake_up@l
  181. tophys(r3,r3)
  182. stw r3,0x80(r4)
  183. stw r5,0x84(r4)
  184. /* Store a pointer to our backup storage into
  185.  * a kernel global
  186.  */
  187. lis r3,sleep_storage@ha
  188. addi r3,r3,sleep_storage@l
  189. stw r5,0(r3)
  190. BEGIN_FTR_SECTION
  191. DSSALL
  192. sync
  193. END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
  194. /*
  195.  * Flush the L1 data cache by reading the first 128kB of RAM
  196.  * and then flushing the same area with the dcbf instruction.
  197.  * The L2 cache has already been disabled.
  198.  */
  199. li r4,0x1000 /* 128kB / 32B */
  200. mtctr r4
  201. lis r4,KERNELBASE@h
  202. 1:
  203. lwz r0,0(r4)
  204. addi r4,r4,0x0020 /* Go to start of next cache line */
  205. bdnz 1b
  206. sync
  207. li r4,0x1000 /* 128kB / 32B */
  208. mtctr r4
  209. lis r4,KERNELBASE@h
  210. 1:
  211. dcbf r0,r4
  212. addi r4,r4,0x0020 /* Go to start of next cache line */
  213. bdnz 1b
  214. sync
  215. /*
  216.  * Set the HID0 and MSR for sleep.
  217.  */
  218. mfspr r2,HID0
  219. rlwinm r2,r2,0,10,7 /* clear doze, nap */
  220. oris r2,r2,HID0_SLEEP@h
  221. sync
  222. mtspr HID0,r2
  223. sync
  224. /* This loop puts us back to sleep in case we have a spurrious
  225.  * wakeup so that the host bridge properly stays asleep. The
  226.  * CPU will be turned off, either after a known time (about 1
  227.  * second) on wallstreet & lombard, or as soon as the CPU enters
  228.  * SLEEP mode on core99
  229.  */
  230. mfmsr r2
  231. oris r2,r2,MSR_POW@h
  232. 1: sync
  233. mtmsr r2
  234. isync
  235. b 1b
  236. /* 
  237.  * Here is the resume code.
  238.  */
  239. /*
  240.  * Core99 machines resume here
  241.  * r4 has the physical address of SL_PC(sp) (unused)
  242.  */
  243. _GLOBAL(core99_wake_up)
  244. /* Make sure HID0 no longer contains any sleep bit */
  245. mfspr r3,HID0
  246. rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */
  247. mtspr HID0,r3
  248. sync
  249. isync
  250. /* Won't that cause problems on CPU that doesn't support it ? */
  251. lis r3, 0
  252. mtspr SPRN_MMCR0, r3
  253. /* sanitize MSR */
  254. mfmsr r3
  255. ori r3,r3,MSR_EE|MSR_IP
  256. xori r3,r3,MSR_EE|MSR_IP
  257. sync
  258. isync
  259. mtmsr r3
  260. sync
  261. isync
  262. /* Recover sleep storage */
  263. lis r3,sleep_storage@ha
  264. addi r3,r3,sleep_storage@l
  265. tophys(r3,r3)
  266. lwz r1,0(r3)
  267. /* Pass thru to older resume code ... */
  268. /* 
  269.  * Here is the resume code for older machines.
  270.  * r1 has the physical address of SL_PC(sp).
  271.  */
  272. grackle_wake_up:
  273. /* Enable and then Flash inval the instruction & data cache */
  274. mfspr r3,HID0
  275. ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI
  276. sync
  277. isync
  278. mtspr HID0,r3
  279. xori r3,r3, HID0_ICFI|HID0_DCI
  280. mtspr HID0,r3
  281. sync
  282. /* Restore the kernel's segment registers before
  283.  * we do any r1 memory access as we are not sure they
  284.  * are in a sane state above the first 256Mb region
  285.  */
  286. li r0,16 /* load up segment register values */
  287. mtctr r0 /* for context 0 */
  288. lis r3,0x2000 /* Ku = 1, VSID = 0 */
  289. li r4,0
  290. 3: mtsrin r3,r4
  291. addi r3,r3,0x111 /* increment VSID */
  292. addis r4,r4,0x1000 /* address of next segment */
  293. bdnz 3b
  294. /* Restore the remaining bits of the HID0 register. */
  295. subi r1,r1,SL_PC
  296. lwz r3,SL_HID0(r1)
  297. sync
  298. isync
  299. mtspr HID0,r3
  300. sync
  301. isync
  302. /* Restore 7400/7410/7450 specific registers */
  303. mfspr r3,PVR
  304. srwi r3,r3,16
  305. cmpli cr0,r3,0x8000 /* 7450 */
  306. cmpli cr1,r3,0x000c /* 7400 */
  307. cmpli cr2,r3,0x800c /* 7410 */
  308. cmpli cr3,r3,0x8001 /* 7455 */
  309. cmpli cr4,r3,0x7000 /* 750FX */
  310. cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
  311. cror 4*cr0+eq,4*cr0+eq,4*cr3+eq
  312. cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
  313. bne 1f
  314. lwz r4,SL_MSSCR0(r1)
  315. sync
  316. mtspr SPRN_MSSCR0,r4
  317. sync
  318. isync
  319. lwz r4,SL_MSSSR0(r1)
  320. sync
  321. mtspr SPRN_MSSSR0,r4
  322. sync
  323. isync
  324. bne cr2,1f
  325. li r4,0
  326. mtspr SPRN_L2CR2,r4
  327. /* Restore 7450/7455 specific registers */
  328. beq cr1,1f
  329. lwz r4,SL_HID1(r1)
  330. sync
  331. mtspr HID1,r4
  332. isync
  333. sync
  334. lwz r4,SPRN_ICTRL(r1)
  335. sync
  336. mtspr SPRN_ICTRL,r4
  337. isync
  338. sync
  339. lwz r4,SPRN_LDSTCR(r1)
  340. sync
  341. mtspr SPRN_LDSTCR,r4
  342. isync
  343. sync
  344. lwz r4,SL_LDSTDB(r1)
  345. sync
  346. mtspr SPRN_LDSTDB,r4
  347. isync
  348. sync
  349. 1:
  350. /* Restore 750FX specific registers */
  351. bne cr4,1f
  352. /* Read PLL config & switch to PLL 0 */
  353. lwz r4,SL_HID1(r1)
  354. rlwinm  r5,r4,0,16,14
  355. mtspr SPRN_HID1,r5
  356. /* Wait for PLL to stabilize */
  357. mftbl r5
  358. 2: mftbl r6
  359. sub r6,r6,r5
  360. cmpli cr0,r6,10000
  361. ble 2b
  362. /* Setup final PLL */
  363. mtspr SPRN_HID1,r4
  364. 1:
  365. /* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
  366. lwz r4,SL_SDR1(r1)
  367. mtsdr1 r4
  368. lwz r4,SL_SPRG0(r1)
  369. mtsprg 0,r4
  370. lwz r4,SL_SPRG0+4(r1)
  371. mtsprg 1,r4
  372. lwz r4,SL_SPRG0+8(r1)
  373. mtsprg 2,r4
  374. lwz r4,SL_SPRG0+12(r1)
  375. mtsprg 3,r4
  376. lwz r4,SL_DBAT0(r1)
  377. mtdbatu 0,r4
  378. lwz r4,SL_DBAT0+4(r1)
  379. mtdbatl 0,r4
  380. lwz r4,SL_DBAT1(r1)
  381. mtdbatu 1,r4
  382. lwz r4,SL_DBAT1+4(r1)
  383. mtdbatl 1,r4
  384. lwz r4,SL_DBAT2(r1)
  385. mtdbatu 2,r4
  386. lwz r4,SL_DBAT2+4(r1)
  387. mtdbatl 2,r4
  388. lwz r4,SL_DBAT3(r1)
  389. mtdbatu 3,r4
  390. lwz r4,SL_DBAT3+4(r1)
  391. mtdbatl 3,r4
  392. lwz r4,SL_IBAT0(r1)
  393. mtibatu 0,r4
  394. lwz r4,SL_IBAT0+4(r1)
  395. mtibatl 0,r4
  396. lwz r4,SL_IBAT1(r1)
  397. mtibatu 1,r4
  398. lwz r4,SL_IBAT1+4(r1)
  399. mtibatl 1,r4
  400. lwz r4,SL_IBAT2(r1)
  401. mtibatu 2,r4
  402. lwz r4,SL_IBAT2+4(r1)
  403. mtibatl 2,r4
  404. lwz r4,SL_IBAT3(r1)
  405. mtibatu 3,r4
  406. lwz r4,SL_IBAT3+4(r1)
  407. mtibatl 3,r4
  408. /* Flush all TLBs */
  409. lis r4,0x1000
  410. 1: addic. r4,r4,-0x1000
  411. tlbie r4
  412. blt 1b
  413. sync
  414. /* restore the MSR and turn on the MMU */
  415. lwz r3,SL_MSR(r1)
  416. bl turn_on_mmu
  417. /* get back the stack pointer */
  418. tovirt(r1,r1)
  419. /* Restore TB */
  420. li r3,0
  421. mttbl r3
  422. lwz r3,SL_TB(r1)
  423. lwz r4,SL_TB+4(r1)
  424. mttbu r3
  425. mttbl r4
  426. /* Restore the callee-saved registers and return */
  427. lwz r0,SL_CR(r1)
  428. mtcr r0
  429. lwz r2,SL_R2(r1)
  430. lmw r12,SL_R12(r1)
  431. addi r1,r1,SL_SIZE
  432. lwz r0,4(r1)
  433. mtlr r0
  434. blr
  435. turn_on_mmu:
  436. mflr r4
  437. tovirt(r4,r4)
  438. mtsrr0 r4
  439. mtsrr1 r3
  440. sync
  441. isync
  442. rfi
  443. #endif /* defined(CONFIG_PMAC_PBOOK) */
  444. .data
  445. .globl sleep_storage
  446. sleep_storage:
  447. .long 0