sleep-tegra20.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
  3. * Copyright (c) 2011, Google, Inc.
  4. *
  5. * Author: Colin Cross <ccross@android.com>
  6. * Gary King <gking@nvidia.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms and conditions of the GNU General Public License,
  10. * version 2, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  15. * more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <linux/linkage.h>
  21. #include <asm/assembler.h>
  22. #include <asm/proc-fns.h>
  23. #include <asm/cp15.h>
  24. #include "sleep.h"
  25. #include "flowctrl.h"
  26. #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
  27. /*
  28. * tegra20_hotplug_shutdown(void)
  29. *
  30. * puts the current cpu in reset
  31. * should never return
  32. */
  33. ENTRY(tegra20_hotplug_shutdown)
  34. /* Put this CPU down */
  35. cpu_id r0
  36. bl tegra20_cpu_shutdown
  37. mov pc, lr @ should never get here
  38. ENDPROC(tegra20_hotplug_shutdown)
  39. /*
  40. * tegra20_cpu_shutdown(int cpu)
  41. *
  42. * r0 is cpu to reset
  43. *
  44. * puts the specified CPU in wait-for-event mode on the flow controller
  45. * and puts the CPU in reset
  46. * can be called on the current cpu or another cpu
  47. * if called on the current cpu, does not return
  48. * MUST NOT BE CALLED FOR CPU 0.
  49. *
  50. * corrupts r0-r3, r12
  51. */
  52. ENTRY(tegra20_cpu_shutdown)
  53. cmp r0, #0
  54. moveq pc, lr @ must not be called for CPU 0
  55. cpu_to_halt_reg r1, r0
  56. ldr r3, =TEGRA_FLOW_CTRL_VIRT
  57. mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
  58. str r2, [r3, r1] @ put flow controller in wait event mode
  59. ldr r2, [r3, r1]
  60. isb
  61. dsb
  62. movw r1, 0x1011
  63. mov r1, r1, lsl r0
  64. ldr r3, =TEGRA_CLK_RESET_VIRT
  65. str r1, [r3, #0x340] @ put slave CPU in reset
  66. isb
  67. dsb
  68. cpu_id r3
  69. cmp r3, r0
  70. beq .
  71. mov pc, lr
  72. ENDPROC(tegra20_cpu_shutdown)
  73. #endif
  74. #ifdef CONFIG_PM_SLEEP
  75. /*
  76. * tegra_pen_lock
  77. *
  78. * spinlock implementation with no atomic test-and-set and no coherence
  79. * using Peterson's algorithm on strongly-ordered registers
  80. * used to synchronize a cpu waking up from wfi with entering lp2 on idle
  81. *
  82. * The reference link of Peterson's algorithm:
  83. * http://en.wikipedia.org/wiki/Peterson's_algorithm
  84. *
  85. * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
  86. * on cpu 0:
  87. * r2 = flag[0] (in SCRATCH38)
  88. * r3 = flag[1] (in SCRATCH39)
  89. * on cpu1:
  90. * r2 = flag[1] (in SCRATCH39)
  91. * r3 = flag[0] (in SCRATCH38)
  92. *
  93. * must be called with MMU on
  94. * corrupts r0-r3, r12
  95. */
  96. ENTRY(tegra_pen_lock)
  97. mov32 r3, TEGRA_PMC_VIRT
  98. cpu_id r0
  99. add r1, r3, #PMC_SCRATCH37
  100. cmp r0, #0
  101. addeq r2, r3, #PMC_SCRATCH38
  102. addeq r3, r3, #PMC_SCRATCH39
  103. addne r2, r3, #PMC_SCRATCH39
  104. addne r3, r3, #PMC_SCRATCH38
  105. mov r12, #1
  106. str r12, [r2] @ flag[cpu] = 1
  107. dsb
  108. str r12, [r1] @ !turn = cpu
  109. 1: dsb
  110. ldr r12, [r3]
  111. cmp r12, #1 @ flag[!cpu] == 1?
  112. ldreq r12, [r1]
  113. cmpeq r12, r0 @ !turn == cpu?
  114. beq 1b @ while !turn == cpu && flag[!cpu] == 1
  115. mov pc, lr @ locked
  116. ENDPROC(tegra_pen_lock)
  117. ENTRY(tegra_pen_unlock)
  118. dsb
  119. mov32 r3, TEGRA_PMC_VIRT
  120. cpu_id r0
  121. cmp r0, #0
  122. addeq r2, r3, #PMC_SCRATCH38
  123. addne r2, r3, #PMC_SCRATCH39
  124. mov r12, #0
  125. str r12, [r2]
  126. mov pc, lr
  127. ENDPROC(tegra_pen_unlock)
  128. /*
  129. * tegra20_cpu_clear_resettable(void)
  130. *
  131. * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when
  132. * it is expected that the secondary CPU will be idle soon.
  133. */
  134. ENTRY(tegra20_cpu_clear_resettable)
  135. mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
  136. mov r12, #CPU_NOT_RESETTABLE
  137. str r12, [r1]
  138. mov pc, lr
  139. ENDPROC(tegra20_cpu_clear_resettable)
  140. /*
  141. * tegra20_cpu_set_resettable_soon(void)
  142. *
  143. * Called to set the "resettable soon" flag in PMC_SCRATCH41 when
  144. * it is expected that the secondary CPU will be idle soon.
  145. */
  146. ENTRY(tegra20_cpu_set_resettable_soon)
  147. mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
  148. mov r12, #CPU_RESETTABLE_SOON
  149. str r12, [r1]
  150. mov pc, lr
  151. ENDPROC(tegra20_cpu_set_resettable_soon)
  152. /*
  153. * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
  154. *
  155. * Enters WFI on secondary CPU by exiting coherency.
  156. */
  157. ENTRY(tegra20_sleep_cpu_secondary_finish)
  158. stmfd sp!, {r4-r11, lr}
  159. mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency
  160. /* Flush and disable the L1 data cache */
  161. bl tegra_disable_clean_inv_dcache
  162. mov32 r0, TEGRA_PMC_VIRT + PMC_SCRATCH41
  163. mov r3, #CPU_RESETTABLE
  164. str r3, [r0]
  165. bl cpu_do_idle
  166. /*
  167. * cpu may be reset while in wfi, which will return through
  168. * tegra_resume to cpu_resume
  169. * or interrupt may wake wfi, which will return here
  170. * cpu state is unchanged - MMU is on, cache is on, coherency
  171. * is off, and the data cache is off
  172. *
  173. * r11 contains the original actlr
  174. */
  175. bl tegra_pen_lock
  176. mov32 r3, TEGRA_PMC_VIRT
  177. add r0, r3, #PMC_SCRATCH41
  178. mov r3, #CPU_NOT_RESETTABLE
  179. str r3, [r0]
  180. bl tegra_pen_unlock
  181. /* Re-enable the data cache */
  182. mrc p15, 0, r10, c1, c0, 0
  183. orr r10, r10, #CR_C
  184. mcr p15, 0, r10, c1, c0, 0
  185. isb
  186. mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
  187. /* Invalidate the TLBs & BTAC */
  188. mov r1, #0
  189. mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
  190. mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
  191. dsb
  192. isb
  193. /* the cpu was running with coherency disabled,
  194. * caches may be out of date */
  195. bl v7_flush_kern_cache_louis
  196. ldmfd sp!, {r4 - r11, pc}
  197. ENDPROC(tegra20_sleep_cpu_secondary_finish)
  198. #endif