Ventana: KBC: Removing the KBC usage on ventana
[linux-2.6.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/system.h>
39
40 #include <mach/iomap.h>
41 #include <mach/io.h>
42
43 #include "asm_macros.h"
44 #include "sleep.h"
45
46 #define CLK_RESET_CCLK_BURST            0x20
47 #define CLK_RESET_CCLK_DIVIDER          0x24
48
49 #define TEGRA_PMC_VIRT          (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
50 #define TEGRA_CLK_RESET_VIRT    (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS + IO_PPSB_VIRT)
51 #define TEGRA_PL310_VIRT        (TEGRA_ARM_PL310_BASE - IO_PPSB_PHYS + 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  * tegra_cpu_wfi
109  *
110  * puts current CPU in clock-gated wfi using the flow controller
111  *
112  * corrupts r0-r3
113  * must be called with MMU on
114  */
115 ENTRY(tegra_cpu_wfi)
116         cpu_id  r0
117         cpu_to_halt_reg r1, r0
118         cpu_to_csr_reg r2, r0
119         mov32   r0, TEGRA_FLOW_CTRL_VIRT
120         mov     r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
121         str     r3, [r0, r2]            @ clear event & interrupt status
122         mov     r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT | FLOW_CTRL_JTAG_RESUME
123         str     r3, [r0, r1]            @ put flow controller in wait irq mode
124         dsb
125         wfi
126         mov     r3, #0
127         str     r3, [r0, r1]            @ clear flow controller halt status
128         mov     r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
129         str     r3, [r0, r2]            @ clear event & interrupt status
130         dsb
131         mov     pc, lr
132 ENDPROC(tegra_cpu_wfi)
133
134 /*
135  * tegra_cpu_exit_coherency
136  *
137  * Exits SMP coherency.
138  * corrupts r4-r5
139  */
140 ENTRY(tegra_cpu_exit_coherency)
141         exit_smp r4, r5
142         mov     pc, lr
143 ENDPROC(tegra_cpu_exit_coherency)
144
145 #ifdef CONFIG_PM_SLEEP
146 /*
147  * Restore CPU state for a suspend
148  *
149  * NOTE: This is a copy of cpu_resume in arch/arm/sleep.S that has been
150  *       modified to work with an L2 cache.
151  */
152         .align  L1_CACHE_SHIFT
153 ENTRY(tegra_cpu_resume_phys)
154 #if USE_TEGRA_CPU_SUSPEND
155 #ifdef CONFIG_SMP
156         adr     r0, tegra_phys_sleep_sp
157         ALT_SMP(mrc p15, 0, r1, c0, c0, 5)
158         ALT_UP(mov r1, #0)
159         and     r1, r1, #15
160         ldr     r0, [r0, r1, lsl #2]            @ stack phys addr
161 #else
162         ldr     r0, tegra_phys_sleep_sp         @ stack phys addr
163 #endif
164         setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
165 #ifdef MULTI_CPU
166         @ load v:p, stack, return fn, resume fn
167   ARM(  ldmia   r0!, {r1, sp, lr, pc}   )
168 THUMB(  ldmia   r0!, {r1, r2, r3, r4}   )
169 THUMB(  mov     sp, r2                  )
170 THUMB(  mov     lr, r3                  )
171 THUMB(  bx      r4                      )
172 #else
173         @ load v:p, stack, return fn
174   ARM(  ldmia   r0!, {r1, sp, lr}       )
175 THUMB(  ldmia   r0!, {r1, r2, lr}       )
176 THUMB(  mov     sp, r2                  )
177         b       cpu_do_resume
178 #endif
179 #else
180         /* Use the standard cpu_resume. */
181         b       cpu_resume
182 #endif
183 ENDPROC(tegra_cpu_resume_phys)
184
185 #if USE_TEGRA_CPU_SUSPEND
186         .align  L1_CACHE_SHIFT
187         .globl  tegra_phys_sleep_sp
188 tegra_phys_sleep_sp:
189         .rept   4
190         .long   0               @ preserve stack phys ptr here
191         .endr
192         .align  L1_CACHE_SHIFT  @ nothing else must be in this cache line
193 #endif
194
195 /*
196  * tegra_cpu_suspend
197  *
198  * Save CPU suspend state
199  * NOTE: This is a copy of cpu_suspend in arch/arm/sleep.S that has been
200  *       modified to work with an L2 cache.
201  *
202  * Input:
203  *      r1 = v:p offset
204  *      r3 = virtual return function
205  * Output:
206  *      sp is decremented to allocate space for CPU state on stack
207  * r0-r3,r8-r10,lr corrupted
208  */
209         .align  L1_CACHE_SHIFT
210 ENTRY(tegra_cpu_suspend)
211 #if USE_TEGRA_CPU_SUSPEND
212         mov     r9, lr
213 #ifdef MULTI_CPU
214         mov32   r10, processor
215         mov     r2, sp                  @ current virtual SP
216         ldr     r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
217         ldr     ip, [r10, #CPU_DO_RESUME] @ virtual resume function
218         sub     sp, sp, r0              @ allocate CPU state on stack
219         mov     r0, sp                  @ save pointer
220         add     ip, ip, r1              @ convert resume fn to phys
221         stmfd   sp!, {r1, r2, r3, ip}   @ save v:p, virt SP, retfn, phys resume fn
222         mov     lr, pc
223         ldr     pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
224 #else
225         mov     r2, sp                  @ current virtual SP
226         mov32   r0, cpu_suspend_size
227         sub     sp, sp, r0              @ allocate CPU state on stack
228         mov     r0, sp                  @ save pointer
229         stmfd   sp!, {r1, r2, r3}       @ save v:p, virt SP, return fn
230         bl      cpu_do_suspend
231 #endif
232         dsb
233
234         /* Disable the data cache */
235         mrc     p15, 0, r10, c1, c0, 0
236         bic     r10, r10, #CR_C
237         dsb
238         mcr     p15, 0, r10, c1, c0, 0
239         isb
240
241         /* Flush data cache */
242 #ifdef MULTI_CACHE
243         mov32   r10, cpu_cache
244         mov     lr, pc
245         ldr     pc, [r10, #CACHE_FLUSH_KERN_ALL]
246 #else
247         bl      __cpuc_flush_kern_all
248 #endif
249 #ifdef CONFIG_CACHE_L2X0
250         /* Issue a PL310 cache sync operation */
251         dsb
252         mov32   r2, TEGRA_PL310_VIRT
253         movw    r1, 0x730               @ cache sync
254         add     r2, r2, r1
255         mov     r1, #0
256         str     r1, [r2]
257 #endif
258
259         /* Invalidate the TLBs & BTAC */
260         mov     r1, #0
261         mcr     p15, 0, r1, c8, c3, 0   @ invalidate shared TLBs
262         mcr     p15, 0, r1, c7, c1, 6   @ invalidate shared BTAC
263         dsb
264         isb
265
266         /* Turn off SMP coherency */
267         exit_smp r1, r2
268
269         /* Convert SP from virtual to physical address. */
270         movw    r1, #0xFFF
271         bic     r2, sp, r1              @ VA & 0xFFFFF000
272         mcr     p15, 0, r2, c7, c8, 0   @ V2PPRPC
273         mrc     p15, 0, r2, c7, c4, 0   @ PAR
274         bic     r2, r2, r1              @ PA & 0xFFFFF000
275         and     r0, sp, r1              @ VA & 0x00000FFF
276         orr     r2, r0, r2              @ (PA & 0xFFFFF000) | (VA & 0x00000FFF)
277
278         mov32   r3, tegra_phys_sleep_sp @ per-CPU phys SP save area
279
280 #ifdef CONFIG_SMP
281         ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
282         ALT_UP(mov lr, #0)
283         and     lr, lr, #15
284 #else
285         mov     lr, #0
286 #endif
287
288         /* Save the normal PRRR value */
289         mrc     p15, 0, r0, c10, c2, 0  @ PRRR
290
291         /* Override all remappings to strongly ordered */
292         mov     r1, #0
293         mcr     p15, 0, r1, c10, c2, 0  @ PRRR
294         mcr     p15, 0, r1, c8, c7, 0   @ invalidate local TLBs
295         dsb
296         isb
297
298         /* Save the physical stack pointer */
299         str     r2, [r3, lr, lsl #2]    @ save phys SP
300
301         /* Restore the regular remappings */
302         mcr     p15, 0, r0, c10, c2, 0  @ PRRR
303         mcr     p15, 0, r1, c8, c7, 0   @ invalidate local TLBs
304         dsb
305         isb
306
307         mov     pc, r9
308 #else
309         /* Use the standard cpu_suspend. */
310         mov     r8, lr
311         bl      cpu_suspend
312         exit_smp r0, r2
313         mov     pc, r8
314 #endif
315 ENDPROC(tegra_cpu_suspend)
316
317 /*
318  * tegra_cpu_save
319  *
320  * Input:
321  *      r0 = v:p offset
322  *      r12 = return to the caller of this function
323  *      lr = resume address
324  * Output:
325  *      r0 = v:p offset
326  *      r7 = SP after saving the registers but before cpu_suspend, suitable
327  *           for restoring an aborted suspend
328  *      sp = SP after tegra_cpu_suspend (the 'real' SP)
329  * Saves r4-r11 on the stack
330  * Corrupts r1, r3-r10
331  */
332
333 ENTRY(tegra_cpu_save)
334         push_ctx_regs r1                @ save context registers
335
336         adr     r3, tegra_cpu_resume
337
338         mov     r7, sp                  @ SP after reg save, before suspend
339
340 #if USE_TEGRA_CPU_SUSPEND
341         cpu_id  r4
342         mov32   r5, tegra_cpu_context   @ address of non-cacheable context page
343         ldr     r5, [r5]                @ non-cacheable context save area
344         mov     r6, #0x400              @ size of one CPU context stack area
345         add     r4, r4, #1
346         smlabb  sp, r6, r4, r5          @ context area for this CPU
347         push_stack_token r4             @ debug check word
348         stmfd   sp!, {r7}               @ save the real stack pointer
349         push_stack_token r4             @ debug check word
350 #endif
351
352         mov     r4, r12
353         mov     r5, r0
354         mov     r6, r2
355         mov     r1, r0
356         bl      tegra_cpu_suspend
357         mov     r0, r5
358         mov     r2, r6
359         mov     pc, r4
360 ENDPROC(tegra_cpu_save)
361
362 /*
363  * tegra_sleep_cpu(unsigned long v2p)
364  *
365  * enters suspend in LP2 by turning off the mmu and jumping to
366  * tegra?_tear_down_cpu
367  */
368 ENTRY(tegra_sleep_cpu)
369         mov     r12, pc                 @ return here is via r12
370         b       tegra_cpu_save
371
372 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
373         mov32   r1, tegra2_tear_down_cpu
374 #else
375         mov32   r1, tegra3_tear_down_cpu
376 #endif
377         add     r1, r1, r0
378         b       tegra_turn_off_mmu
379 ENDPROC(tegra_sleep_cpu)
380
381 /*
382  * tegra_cpu_resume
383  *
384  * reloads the volatile CPU state from the context area
385  * initializes the processor mode stacks
386  * the mmu should be on and the CPU should be coherent before this is called
387  */
388         .align L1_CACHE_SHIFT
389 tegra_cpu_resume:
390         mov     r0, #0
391         mcr     p15, 0, r0, c8, c3, 0   @ invalidate TLB
392         mcr     p15, 0, r0, c7, c5, 6   @ flush BTAC
393         mcr     p15, 0, r0, c7, c5, 0   @ flush instruction cache
394         dsb
395         isb
396
397 #if USE_TEGRA_CPU_SUSPEND
398         pop_stack_token r4, r5          @ check stack debug token
399         ldmfd   sp!, {r0}               @ get the real stack pointer
400         pop_stack_token r4, r5          @ check stack debug token
401         mov     sp, r0                  @ switch to the real stack pointer
402 #endif
403
404         bl      cpu_init
405
406         pop_ctx_regs r1, r2             @ restore context registers
407         mov     pc, lr
408
409 /*
410  * tegra_turn_off_mmu
411  *
412  * r0 = v2p
413  * r1 = physical address to jump to with mmu off
414  */
415 ENTRY(tegra_turn_off_mmu)
416         mov32   r3, tegra_shut_off_mmu
417         add     r3, r3, r0
418         mov     r0, r1
419         mov     pc, r3
420 ENDPROC(tegra_turn_off_mmu)
421
422 tegra_pgd_phys_address:
423         .word   tegra_pgd_phys
424
425 /*
426  * tegra_shut_off_mmu
427  *
428  * r0 = physical address to jump to with mmu off
429  *
430  * called with VA=PA mapping
431  * turns off MMU, icache, dcache and branch prediction
432  */
433         .align  L1_CACHE_SHIFT
434 tegra_shut_off_mmu:
435         mrc     p15, 0, r3, c1, c0, 0
436         movw    r2, #CR_I | CR_Z | CR_C | CR_M
437         bic     r3, r3, r2
438         dsb
439         mcr     p15, 0, r3, c1, c0, 0
440         isb
441         mov     pc, r0
442
443 /*
444  * tegra_cpu_clk32k
445  *
446  * In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
447  */
448 ENTRY(tegra_cpu_pllp)
449         /* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
450         mov32   r5, TEGRA_CLK_RESET_BASE
451         mov     r0, #(2 << 28)                  @ burst policy = run mode
452         orr     r0, r0, #(4 << 4)               @ use PLLP in run mode burst
453         str     r0, [r5, #CLK_RESET_CCLK_BURST]
454         mov     r0, #0
455         str     r0, [r5, #CLK_RESET_CCLK_DIVIDER]
456         mov     pc, lr
457 ENDPROC(tegra_cpu_pllp)
458 #endif