sleep.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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