unknown changes from android-tegra-nv-3.4
[linux-3.10.git] / arch / arm / mach-tegra / sleep.S
1 /*
2  * arch/arm/mach-tegra/sleep.S
3  *
4  * Copyright (c) 2010-2011, NVIDIA Corporation.
5  * Copyright (c) 2011, Google, Inc.
6  *
7  * Author: Colin Cross <ccross@android.com>
8  *         Gary King <gking@nvidia.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23  */
24
25 #include <linux/const.h>
26 #include <linux/init.h>
27 #include <linux/linkage.h>
28
29 #include <asm/assembler.h>
30 #include <asm/cache.h>
31 #include <asm/domain.h>
32 #include <asm/memory.h>
33 #include <asm/page.h>
34 #include <asm/ptrace.h>
35 #include <asm/asm-offsets.h>
36 #include <asm/glue-cache.h>
37 #include <asm/glue-proc.h>
38 #include <asm/cp15.h>
39
40 #include "iomap.h"
41
42 #include "sleep.h"
43 #include "flowctrl.h"
44
45 #define CLK_RESET_CCLK_BURST            0x20
46 #define CLK_RESET_CCLK_DIVIDER          0x24
47
48 #define TEGRA_PMC_VIRT          (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
49
50 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
51                                         + IO_PPSB_VIRT)
52
53 /*
54  * tegra_pen_lock
55  *
56  * spinlock implementation with no atomic test-and-set and no coherence
57  * using Peterson's algorithm on strongly-ordered registers
58  * used to synchronize a cpu waking up from wfi with entering lp2 on idle
59  *
60  * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
61  * on cpu 0:
62  * SCRATCH38 = r2 = flag[0]
63  * SCRATCH39 = r3 = flag[1]
64  * on cpu1:
65  * SCRATCH39 = r2 = flag[1]
66  * SCRATCH38 = r3 = flag[0]
67  *
68  * must be called with MMU on
69  * corrupts r0-r3, r12
70  */
71 ENTRY(tegra_pen_lock)
72         mov32   r3, TEGRA_PMC_VIRT
73         cpu_id  r0
74         add     r1, r3, #PMC_SCRATCH37
75         cmp     r0, #0
76         addeq   r2, r3, #PMC_SCRATCH38
77         addeq   r3, r3, #PMC_SCRATCH39
78         addne   r2, r3, #PMC_SCRATCH39
79         addne   r3, r3, #PMC_SCRATCH38
80
81         mov     r12, #1
82         str     r12, [r2]               @ flag[cpu] = 1
83         dsb
84         str     r12, [r1]               @ !turn = cpu
85 1:      dsb
86         ldr     r12, [r3]
87         cmp     r12, #1                 @ flag[!cpu] == 1?
88         ldreq   r12, [r1]
89         cmpeq   r12, r0                 @ !turn == cpu?
90         beq     1b                      @ while !turn == cpu && flag[!cpu] == 1
91
92         mov     pc, lr                  @ locked
93 ENDPROC(tegra_pen_lock)
94
95 ENTRY(tegra_pen_unlock)
96         dsb
97         mov32   r3, TEGRA_PMC_VIRT
98         cpu_id  r0
99         cmp     r0, #0
100         addeq   r2, r3, #PMC_SCRATCH38
101         addne   r2, r3, #PMC_SCRATCH39
102         mov     r12, #0
103         str     r12, [r2]
104         mov     pc, lr
105 ENDPROC(tegra_pen_unlock)
106
107
108 /*
109  * tegra_cpu_exit_coherency
110  *
111  * Exits SMP coherency.
112  * corrupts r4-r5
113  */
114 ENTRY(tegra_cpu_exit_coherency)
115         exit_smp r4, r5
116         mov     pc, lr
117 ENDPROC(tegra_cpu_exit_coherency)
118
119 #ifdef CONFIG_PM_SLEEP
120 /*
121  * tegra_sleep_cpu_finish(unsigned long int)
122  *
123  * enters suspend in LP2 by turning off the mmu and jumping to
124  * tegra?_tear_down_cpu
125  */
126 ENTRY(tegra_sleep_cpu_finish)
127         bl      tegra_cpu_exit_coherency
128
129 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
130         mov32   r1, tegra2_tear_down_cpu
131 #else
132         mov32   r1, tegra3_tear_down_cpu
133 #endif
134         add     r1, r1, r0
135         b       tegra_turn_off_mmu
136 ENDPROC(tegra_sleep_cpu_finish)
137
138 /*
139  * tegra_turn_off_mmu
140  *
141  * r0 = v2p
142  * r1 = physical address to jump to with mmu off
143  */
144 ENTRY(tegra_turn_off_mmu)
145         /*
146          * change page table pointer to tegra_pgd_phys, so that IRAM
147          * and MMU shut-off will be mapped virtual == physical
148          */
149         mrc     p15, 0, r2, c2, c0, 0   @ TTB 0
150         mov32   r3, ~PAGE_MASK
151         and     r2, r2, r3
152         ldr     r3, tegra_pgd_phys_address
153         ldr     r3, [r3]
154         orr     r3, r3, r2
155         mov     r2, #0
156         mcr     p15, 0, r2, c13, c0, 1  @ reserved context
157         isb
158         mcr     p15, 0, r3, c2, c0, 0   @ TTB 0
159         isb
160
161         mov     r2, #0
162         mcr     p15, 0, r2, c8, c3, 0   @ invalidate TLB
163         mcr     p15, 0, r2, c7, c5, 6   @ flush BTAC
164         mcr     p15, 0, r2, c7, c5, 0   @ flush instruction cache
165
166         mov32   r3, tegra_shut_off_mmu
167         add     r3, r3, r0
168         mov     r0, r1
169         mov     pc, r3
170 ENDPROC(tegra_turn_off_mmu)
171
172 tegra_pgd_phys_address:
173         .word   tegra_pgd_phys
174
175 /*
176  * tegra_shut_off_mmu
177  *
178  * r0 = physical address to jump to with mmu off
179  *
180  * called with VA=PA mapping
181  * turns off MMU, icache, dcache and branch prediction
182  */
183         .align  L1_CACHE_SHIFT
184 tegra_shut_off_mmu:
185         mrc     p15, 0, r3, c1, c0, 0
186         movw    r2, #CR_I | CR_Z | CR_C | CR_M
187         bic     r3, r3, r2
188         dsb
189         mcr     p15, 0, r3, c1, c0, 0
190         isb
191         mov     pc, r0
192
193 /*
194  * tegra_cpu_clk32k
195  *
196  * In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
197  */
198 ENTRY(tegra_cpu_pllp)
199         /* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
200         mov32   r5, TEGRA_CLK_RESET_BASE
201         mov     r0, #(2 << 28)                  @ burst policy = run mode
202         orr     r0, r0, #(4 << 4)               @ use PLLP in run mode burst
203         str     r0, [r5, #CLK_RESET_CCLK_BURST]
204         mov     r0, #0
205         str     r0, [r5, #CLK_RESET_CCLK_DIVIDER]
206         mov     pc, lr
207 ENDPROC(tegra_cpu_pllp)
208 #endif
209
210 #ifdef CONFIG_TRUSTED_FOUNDATIONS
211 /*
212  * tegra_generic_smc
213  *
214  * r0 = smc type
215  * r1 = smc subtype
216  * r2 = argument passed to smc
217  *
218  * issues SMC (secure monitor call) instruction with
219  * the specified parameters.
220  */
221 ENTRY(tegra_generic_smc)
222         adr     r3, __tegra_smc_stack
223         stmia   r3, {r4-r12, lr}
224         mov     r3, #0
225         mov     r4, #0
226         dsb
227         smc     #0
228         adr     r3, __tegra_smc_stack
229         ldmia   r3, {r4-r12, pc}
230 ENDPROC(tegra_generic_smc)
231         .type   __tegra_smc_stack, %object
232 __tegra_smc_stack:
233         .long   0, 0, 0, 0, 0, 0, 0, 0, 0, 0
234         .size   __tegra_smc_stack, . - __tegra_smc_stack
235 #endif