ARM: Tegra: Add CONFIG_TEGRA_USE_SECURE_KERNEL
[linux-3.10.git] / arch / arm / mach-tegra / sleep.S
1 /*
2  * arch/arm/mach-tegra/sleep.S
3  *
4  * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
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 #include <asm/hardware/cache-l2x0.h>
40
41 #include "iomap.h"
42
43 #include "sleep.h"
44 #include "flowctrl.h"
45 #include "reset.h"
46
47 #define CLK_RESET_CCLK_BURST            0x20
48 #define CLK_RESET_CCLK_DIVIDER          0x24
49
50 #define TEGRA_PMC_VIRT          (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
51
52 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
53                                         + IO_PPSB_VIRT)
54
55 /*
56  * tegra_pen_lock
57  *
58  * spinlock implementation with no atomic test-and-set and no coherence
59  * using Peterson's algorithm on strongly-ordered registers
60  * used to synchronize a cpu waking up from wfi with entering lp2 on idle
61  *
62  * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
63  * on cpu 0:
64  * SCRATCH38 = r2 = flag[0]
65  * SCRATCH39 = r3 = flag[1]
66  * on cpu1:
67  * SCRATCH39 = r2 = flag[1]
68  * SCRATCH38 = r3 = flag[0]
69  *
70  * must be called with MMU on
71  * corrupts r0-r3, r12
72  */
73 ENTRY(tegra_pen_lock)
74         mov32   r3, TEGRA_PMC_VIRT
75         cpu_id  r0
76         add     r1, r3, #PMC_SCRATCH37
77         cmp     r0, #0
78         addeq   r2, r3, #PMC_SCRATCH38
79         addeq   r3, r3, #PMC_SCRATCH39
80         addne   r2, r3, #PMC_SCRATCH39
81         addne   r3, r3, #PMC_SCRATCH38
82
83         mov     r12, #1
84         str     r12, [r2]               @ flag[cpu] = 1
85         dsb
86         str     r12, [r1]               @ !turn = cpu
87 1:      dsb
88         ldr     r12, [r3]
89         cmp     r12, #1                 @ flag[!cpu] == 1?
90         ldreq   r12, [r1]
91         cmpeq   r12, r0                 @ !turn == cpu?
92         beq     1b                      @ while !turn == cpu && flag[!cpu] == 1
93
94         mov     pc, lr                  @ locked
95 ENDPROC(tegra_pen_lock)
96
97 ENTRY(tegra_pen_unlock)
98         dsb
99         mov32   r3, TEGRA_PMC_VIRT
100         cpu_id  r0
101         cmp     r0, #0
102         addeq   r2, r3, #PMC_SCRATCH38
103         addne   r2, r3, #PMC_SCRATCH39
104         mov     r12, #0
105         str     r12, [r2]
106         mov     pc, lr
107 ENDPROC(tegra_pen_unlock)
108
109 /*
110  * tegra_cpu_exit_coherency
111  *
112  * Exits SMP coherency.
113  * corrupts r4-r5
114  */
115 ENTRY(tegra_cpu_exit_coherency)
116         exit_smp r4, r5
117         mov     pc, lr
118 ENDPROC(tegra_cpu_exit_coherency)
119
120 /*
121  * tegra_flush_cache
122  *
123  * clean & invalidate inner cache
124  *
125  * Disable is needed before flush to prevent allocations during flush
126  * When cache is disabled, we cannot push to stack.
127  */
128 ENTRY(tegra_flush_cache)
129         stmfd   sp!, {r4-r5, r7, r9-r11, lr}
130         dmb                                     @ ensure ordering
131
132         /* Disable the data cache */
133         mrc     p15, 0, r2, c1, c0, 0
134         bic     r2, r2, #CR_C
135         dsb
136         mcr     p15, 0, r2, c1, c0, 0
137
138         bl      v7_flush_dcache_all
139
140         ldmfd   sp!, {r4-r5, r7, r9-r11, lr}
141         mov     pc, lr
142 ENDPROC(tegra_flush_cache)
143
144 /*
145  * tegra_flush_l1_cache
146  *
147  * clean & invalidate the L1 cache
148  *
149  * The flush_cache_all flushes all caches within level of coherence, this
150  * may not be desired if all we need is to flush L1 only. Therefore this
151  * function is implemented to flush the L1 cache only.
152  *
153  * Disable is needed before flush to prevent allocations during flush
154  * When cache is disabled, we cannot push to stack.
155  *
156  * Corrupted registers: r0-r7, r9-r11
157  */
158 ENTRY(tegra_flush_l1_cache)
159         stmfd   sp!, {r4-r5, r7, r9-r11, lr}
160         dmb                                     @ ensure ordering with previous memory accesses
161
162         /* Disable the data cache */
163         mrc     p15, 0, r2, c1, c0, 0
164         bic     r2, r2, #CR_C
165         dsb
166         mcr     p15, 0, r2, c1, c0, 0
167
168         mov     r10, #0
169 #ifdef CONFIG_PREEMPT
170         save_and_disable_irqs_notrace r9
171 #endif
172         mcr     p15, 2, r10, c0, c0, 0          @ select cache level 0
173         isb
174         mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
175 #ifdef CONFIG_PREEMPT
176         restore_irqs_notrace r9
177 #endif
178         and     r2, r1, #7                                      @ extract the length of the cache lines
179         add     r2, r2, #4                                      @ add 4 (line length offset)
180         ldr     r4, =0x3ff
181         ands    r4, r4, r1, lsr #3              @ find maximum number on the way size
182         clz     r5, r4                                          @ find bit position of way size increment
183         ldr     r7, =0x7fff
184         ands    r7, r7, r1, lsr #13             @ extract max number of the index size
185 1001:
186         mov     r9, r4                                          @ create working copy of max way size
187 1002:
188         orr     r11, r10, r9, lsl r5            @ factor way and cache number into r11
189         orr     r11, r11, r7, lsl r2            @ factor index number into r11
190         mcr     p15, 0, r11, c7, c14, 2         @ op=c10/c14, clean/flush by set/way
191         subs    r9, r9, #1                              @ decrement the way
192         bge     1002b
193         subs    r7, r7, #1                              @ decrement the index
194         bge     1001b
195         mcr     p15, 2, r10, c0, c0, 0          @ restore cache level 0
196         isb
197         dsb
198         ldmfd   sp!, {r4-r5, r7, r9-r11, lr}
199         mov     pc, lr
200 ENDPROC(tegra_flush_l1_cache)
201
202 #ifdef CONFIG_PM_SLEEP
203 /*
204  * tegra_sleep_cpu_finish(unsigned long int)
205  *
206  * enters suspend in LP2 by turning off the mmu and jumping to
207  * tegra?_tear_down_cpu
208  */
209 ENTRY(tegra_sleep_cpu_finish)
210         mov     r4, r0
211 #if defined(CONFIG_TEGRA_USE_SECURE_KERNEL)
212         ldr     r0, =0xFFFFFFFC
213         ldr     r1, =0xFFFFFFE4
214         ldr     r2, =TEGRA_RESET_HANDLER_BASE
215         bl      tegra_generic_smc
216 #else
217         bl      tegra_flush_cache
218 #endif
219
220         mov     r0, r4
221         bl      tegra_cpu_exit_coherency
222
223 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
224         mov32   r1, tegra2_tear_down_cpu
225 #else
226         mov32   r1, tegra3_tear_down_cpu
227 #endif
228         add     r1, r1, r0
229         mov     r11, #1
230         b       tegra_turn_off_mmu
231 ENDPROC(tegra_sleep_cpu_finish)
232
233 /*
234  * tegra_turn_off_mmu
235  *
236  * r0 = v2p
237  * r1 = physical address to jump to with mmu off
238  * r11 = L2 disable/flush
239  */
240 ENTRY(tegra_turn_off_mmu)
241         /*
242          * change page table pointer to tegra_pgd_phys, so that IRAM
243          * and MMU shut-off will be mapped virtual == physical
244          */
245         mrc     p15, 0, r2, c2, c0, 0   @ TTB 0
246         mov32   r3, ~PAGE_MASK
247         and     r2, r2, r3
248         ldr     r3, tegra_pgd_phys_address
249         ldr     r3, [r3]
250         orr     r3, r3, r2
251         mov     r2, #0
252         mcr     p15, 0, r2, c13, c0, 1  @ reserved context
253         isb
254         mcr     p15, 0, r3, c2, c0, 0   @ TTB 0
255         isb
256
257         mcr     p15, 0, r2, c8, c3, 0   @ invalidate TLB
258         mcr     p15, 0, r2, c7, c5, 6   @ flush BTAC
259         mcr     p15, 0, r2, c7, c5, 0   @ flush instruction cache
260         dsb
261         isb
262
263         mov32   r3, tegra_shut_off_mmu
264         add     r3, r3, r0
265         mov     r0, r1
266         mov     pc, r3
267 ENDPROC(tegra_turn_off_mmu)
268
269 tegra_pgd_phys_address:
270         .word   tegra_pgd_phys
271
272 /*
273  * tegra_shut_off_mmu
274  *
275  * r0 = physical address to jump to with mmu off
276  * r11 = L2 disable/flush
277  *
278  * called with VA=PA mapping
279  * turns off MMU, icache, dcache and branch prediction
280  */
281         .align  L1_CACHE_SHIFT
282 tegra_shut_off_mmu:
283         mrc     p15, 0, r3, c1, c0, 0
284         movw    r2, #CR_I | CR_Z | CR_C | CR_M
285         bic     r3, r3, r2
286         dsb
287         mcr     p15, 0, r3, c1, c0, 0
288         isb
289 #if defined(CONFIG_CACHE_L2X0) && \
290                 !defined(CONFIG_TEGRA_USE_SECURE_KERNEL)
291         tst     r11, #1
292         beq     2f
293         mov32   r1, TEGRA_ARM_PL310_BASE
294 #ifdef CONFIG_ARCH_TEGRA_14x_SOC
295         /* need to flush the L2 */
296         ldr     r2, [r1, #L2X0_AUX_CTRL]
297         tst     r2, #(1 << 16)                  @ associativity
298         mov     r2, #0xff
299         orrne   r2, #0xff00
300         str     r2, [r1, #L2X0_CLEAN_INV_WAY]
301 1:      ldr     r3, [r1, #L2X0_CLEAN_INV_WAY]
302         tst     r3, r2
303         bne     1b
304 #endif /* CONFIG_ARCH_TEGRA_14x_SOC */
305         /* Sync and disable L2 */
306         mov     r2, #0
307         str     r2, [r1, #L2X0_CACHE_SYNC]
308         str     r2, [r1, #L2X0_CTRL]
309 #endif /* CONFIG_CACHE_L2X0 && !CONFIG_TEGRA_USE_SECURE_KERNEL */
310 2:      mov     pc, r0
311
312 /*
313  * tegra_cpu_clk32k
314  *
315  * In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
316  */
317 ENTRY(tegra_cpu_pllp)
318         /* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
319         mov32   r5, TEGRA_CLK_RESET_BASE
320         mov     r0, #(2 << 28)                  @ burst policy = run mode
321         orr     r0, r0, #(4 << 4)               @ use PLLP in run mode burst
322         str     r0, [r5, #CLK_RESET_CCLK_BURST]
323         mov     r0, #0
324         str     r0, [r5, #CLK_RESET_CCLK_DIVIDER]
325         mov     pc, lr
326 ENDPROC(tegra_cpu_pllp)
327 #endif
328
329 #if defined(CONFIG_TEGRA_USE_SECURE_KERNEL)
330 /*
331  * tegra_generic_smc
332  *
333  * r0 = smc type
334  * r1 = smc subtype
335  * r2 = argument passed to smc
336  *
337  * issues SMC (secure monitor call) instruction with
338  * the specified parameters.
339  */
340 ENTRY(tegra_generic_smc)
341         adr     r3, __tegra_smc_stack
342         stmia   r3, {r4-r12, lr}
343         mov     r3, #0
344         mov     r4, #0
345         dsb
346         smc     #0
347         adr     r3, __tegra_smc_stack
348         ldmia   r3, {r4-r12, pc}
349 ENDPROC(tegra_generic_smc)
350         .type   __tegra_smc_stack, %object
351 __tegra_smc_stack:
352         .long   0, 0, 0, 0, 0, 0, 0, 0, 0, 0
353         .size   __tegra_smc_stack, . - __tegra_smc_stack
354 #endif