aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/sleep-t3.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/sleep-t3.S')
-rw-r--r--arch/arm/mach-tegra/sleep-t3.S715
1 files changed, 715 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/sleep-t3.S b/arch/arm/mach-tegra/sleep-t3.S
new file mode 100644
index 00000000000..5ea7334c45f
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t3.S
@@ -0,0 +1,715 @@
1/*
2 * arch/arm/mach-tegra/include/mach/sleep-t3.S
3 *
4 * Copyright (c) 2010-2011, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include <linux/const.h>
22#include <linux/init.h>
23#include <linux/linkage.h>
24
25#include <asm/assembler.h>
26#include <asm/cache.h>
27#include <asm/domain.h>
28#include <asm/memory.h>
29#include <asm/page.h>
30#include <asm/ptrace.h>
31#include <asm/asm-offsets.h>
32#include <asm/glue-cache.h>
33#include <asm/glue-proc.h>
34#include <asm/system.h>
35
36#include <mach/iomap.h>
37#include <mach/io.h>
38
39#include "asm_macros.h"
40#include "sleep.h"
41#include "clock.h"
42
43#define EMC_CFG 0xc
44#define EMC_ADR_CFG 0x10
45#define EMC_TIMING_CONTROL 0x28
46#define EMC_REFRESH 0x70
47#define EMC_NOP 0xdc
48#define EMC_SELF_REF 0xe0
49#define EMC_MRW 0xe8
50#define EMC_REQ_CTRL 0x2b0
51#define EMC_EMC_STATUS 0x2b4
52#define EMC_FBIO_CFG5 0x104
53#define EMC_AUTO_CAL_CONFIG 0x2a4
54#define EMC_AUTO_CAL_INTERVAL 0x2a8
55#define EMC_AUTO_CAL_STATUS 0x2ac
56#define EMC_CFG_DIG_DLL 0x2bc
57#define EMC_ZCAL_INTERVAL 0x2e0
58#define EMC_ZQ_CAL 0x2ec
59#define EMC_XM2VTTGENPADCTRL 0x310
60#define EMC_XM2VTTGENPADCTRL2 0x314
61
62#define PMC_CTRL 0x0
63#define PMC_CTRL_SIDE_EFFECT_LP0 (1 << 14) /* enter LP0 when CPU pwr gated */
64
65#define PMC_PWRGATE_TOGGLE 0x30
66#define PMC_REMOVE_CLAMPING_CMD 0x34
67#define PMC_PWRGATE_STATUS 0x38
68
69#define PMC_PWRGATE_PARTID_L2C (0x5)
70
71#define PMC_IO_DPD_REQ 0x1b8
72#define PMC_IO_DPD_STATUS 0x1bc
73
74#define CLK_RESET_CCLK_BURST 0x20
75#define CLK_RESET_CCLK_DIVIDER 0x24
76#define CLK_RESET_SCLK_BURST 0x28
77#define CLK_RESET_SCLK_DIVIDER 0x2c
78
79#define CLK_RESET_PLLC_BASE 0x80
80#define CLK_RESET_PLLM_BASE 0x90
81#define CLK_RESET_PLLP_BASE 0xa0
82#define CLK_RESET_PLLA_BASE 0xb0
83#define CLK_RESET_PLLX_BASE 0xe0
84
85#define CLK_RESET_PLLC_MISC 0x8c
86#define CLK_RESET_PLLM_MISC 0x9c
87#define CLK_RESET_PLLP_MISC 0xac
88#define CLK_RESET_PLLA_MISC 0xbc
89#define CLK_RESET_PLLX_MISC 0xe4
90
91#define CLK_RESET_PLLP_OUTA 0xa4
92#define CLK_RESET_PLLP_OUTB 0xa8
93
94#define PMC_PLLP_WB0_OVERRIDE 0xf8
95
96#define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4
97
98#define MSELECT_CLKM (0x3 << 30)
99
100#if USE_PLL_LOCK_BITS
101#define LOCK_DELAY PLL_POST_LOCK_DELAY
102#else
103#define LOCK_DELAY 0xff /* 255uS delay for PLL stabilization */
104#endif
105
106#define USE_PLLP_ON_SLEEP_ENTRY 0
107
108.macro emc_device_mask, rd, base
109 ldr \rd, [\base, #EMC_ADR_CFG]
110 tst \rd, #0x1
111 moveq \rd, #(0x1<<8) @ just 1 device
112 movne \rd, #(0x3<<8) @ 2 devices
113.endm
114
115.macro emc_timing_update, rd, base
116 mov \rd, #1
117 str \rd, [\base, #EMC_TIMING_CONTROL]
1181001:
119 ldr \rd, [\base, #EMC_EMC_STATUS]
120 tst \rd, #(0x1<<23) @ wait until EMC_STATUS_TIMING_UPDATE_STALLED is clear
121 bne 1001b
122.endm
123
124#ifdef CONFIG_HOTPLUG_CPU
125/*
126 * tegra3_hotplug_shutdown(void)
127 *
128 * Powergates the current CPU.
129 * Should never return.
130 */
131ENTRY(tegra3_hotplug_shutdown)
132 mov r6, lr
133 bl tegra_cpu_exit_coherency
134
135 /* Powergate this CPU. */
136 mov r0, #TEGRA_POWER_HOTPLUG_SHUTDOWN
137 bl tegra3_cpu_reset
138 mov pc, r6 @ should never get here
139ENDPROC(tegra3_hotplug_shutdown)
140#endif
141
142#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
143/*
144 * tegra3_cpu_reset(unsigned long flags)
145 *
146 * Puts the current CPU in wait-for-event mode on the flow controller
147 * and powergates it -- flags (in R0) indicate the request type.
148 * Must never be called for CPU 0.
149 *
150 * corrupts r0-r4, r12
151 */
152ENTRY(tegra3_cpu_reset)
153 cpu_id r3
154 cmp r3, #0
155 moveq pc, lr @ Must never be called for CPU 0
156
157 mov32 r12, TEGRA_FLOW_CTRL_VIRT
158 cpu_to_csr_reg r1, r3
159 add r1, r1, r12 @ virtual CSR address for this CPU
160 cpu_to_halt_reg r2, r3
161 add r2, r2, r12 @ virtual HALT_EVENTS address for this CPU
162
163 /* Clear this CPU's "event" and "interrupt" flags and power gate
164 it when halting but not before it is in the "WFE" state. */
165 movw r12, FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | FLOW_CTRL_CSR_ENABLE
166 mov r4, #(1 << 4)
167 orr r12, r12, r4, lsl r3
168 str r12, [r1]
169
170 /* Halt this CPU. */
171 mov r3, #0x400
172delay_1:
173 subs r3, r3, #1 @ delay as a part of wfe war.
174 bge delay_1;
175 cpsid a @ disable imprecise aborts.
176 ldr r3, [r1] @ read CSR
177 str r3, [r1] @ clear CSR
178 tst r0, #TEGRA_POWER_HOTPLUG_SHUTDOWN
179 moveq r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT @ For LP2
180 movne r3, #FLOW_CTRL_WAITEVENT @ For hotplug
181 str r3, [r2]
182 ldr r0, [r2]
183 b wfe_war
184
185__cpu_reset_again:
186 dsb
187 .align 5
188 wfe @ CPU should be power gated here
189wfe_war:
190 b __cpu_reset_again
191
192 /* 38 nop's, which fills reset of wfe cache line and 4 more cachelines with nop*/
193 .rept 38
194 nop
195 .endr
196 b . @ should never get here
197
198ENDPROC(tegra3_cpu_reset)
199#endif
200
201#ifdef CONFIG_PM_SLEEP
202
203/*
204 * tegra3_sleep_core(unsigned long v2p)
205 *
206 * enters suspend in LP0 or LP1 by turning off the mmu and jumping to
207 * tegra3_tear_down_core in IRAM
208 */
209ENTRY(tegra3_sleep_core)
210 mov r12, pc @ return here is via r12
211 b tegra_cpu_save
212
213 /* preload all the address literals that are needed for the
214 * CPU power-gating process, to avoid loads from SDRAM (which are
215 * not supported once SDRAM is put into self-refresh.
216 * LP0 / LP1 use physical address, since the MMU needs to be
217 * disabled before putting SDRAM into self-refresh to avoid
218 * memory access due to page table walks */
219 mov32 r4, TEGRA_PMC_BASE
220 mov32 r5, TEGRA_CLK_RESET_BASE
221 mov32 r6, TEGRA_FLOW_CTRL_BASE
222 mov32 r7, TEGRA_TMRUS_BASE
223
224 mov32 r1, tegra3_tear_down_core
225 mov32 r2, tegra3_iram_start
226 sub r1, r1, r2
227 mov32 r2, TEGRA_IRAM_CODE_AREA
228 add r1, r1, r2
229 b tegra_turn_off_mmu
230ENDPROC(tegra3_sleep_core)
231
232/*
233 * tegra3_sleep_cpu_secondary(unsigned long v2p)
234 *
235 * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
236 */
237ENTRY(tegra3_sleep_cpu_secondary)
238 mov r12, pc @ return here is via r12
239 b tegra_cpu_save
240
241 /* Powergate this CPU. */
242 mov r0, #0 @ power mode flags (!hotplug)
243 bl tegra3_cpu_reset
244 b . @ should never get here
245ENDPROC(tegra3_sleep_cpu_secondary)
246
247/*
248 * tegra3_tear_down_cpu
249 *
250 * Switches the CPU cluster to PLL-P and enters sleep.
251 */
252ENTRY(tegra3_tear_down_cpu)
253 mov32 r4, TEGRA_PMC_BASE
254 mov32 r5, TEGRA_CLK_RESET_BASE
255 mov32 r6, TEGRA_FLOW_CTRL_BASE
256 mov32 r7, TEGRA_TMRUS_BASE
257#if USE_PLLP_ON_SLEEP_ENTRY
258 bl tegra_cpu_pllp
259#endif
260 b tegra3_enter_sleep
261ENDPROC(tegra3_tear_down_cpu)
262
263/* START OF ROUTINES COPIED TO IRAM */
264 .align L1_CACHE_SHIFT
265 .globl tegra3_iram_start
266tegra3_iram_start:
267
268/*
269 * tegra3_lp1_reset
270 *
271 * reset vector for LP1 restore; copied into IRAM during suspend.
272 * brings the system back up to a safe starting point (SDRAM out of
273 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
274 * system clock running on the same PLL that it suspended at), and
275 * jumps to tegra_lp2_startup to restore PLLX and virtual addressing.
276 * physical address of tegra_lp2_startup expected to be stored in
277 * PMC_SCRATCH41
278 *
279 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA AND MUST BE FIRST.
280 */
281.macro pll_enable, rd, car, base, misc
282 ldr \rd, [\car, #\base]
283 tst \rd, #(1<<30)
284 orreq \rd, \rd, #(1<<30)
285 streq \rd, [\car, #\base]
286#if USE_PLL_LOCK_BITS
287 ldr \rd, [\car, #\misc]
288 orr \rd, \rd, #(1<<18)
289 str \rd, [\car, #\misc]
290#endif
291.endm
292
293.macro pll_locked, rd, car, base
294#if USE_PLL_LOCK_BITS
2951:
296 ldr \rd, [\car, #\base]
297 tst \rd, #(1<<27)
298 beq 1b
299#endif
300.endm
301
302ENTRY(tegra3_lp1_reset)
303 /* the CPU and system bus are running at 32KHz and executing from
304 * IRAM when this code is executed; immediately switch to CLKM and
305 * enable PLLP, PLLM, PLLC, PLLA and PLLX. */
306 mov32 r0, TEGRA_CLK_RESET_BASE
307#ifndef CONFIG_TRUSTED_FOUNDATIONS
308 /* secure code handles 32KHz to CLKM/OSC clock switch */
309 mov r1, #(1<<28)
310 str r1, [r0, #CLK_RESET_SCLK_BURST]
311 str r1, [r0, #CLK_RESET_CCLK_BURST]
312 mov r1, #0
313 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
314 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
315#endif
316 /* enable PLLM via PMC */
317 mov32 r2, TEGRA_PMC_BASE
318 ldr r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
319 orr r1, r1, #(1<<12)
320 str r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
321
322 pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC
323 pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC
324 pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC
325 pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC
326 pll_enable r1, r0, CLK_RESET_PLLX_BASE, CLK_RESET_PLLX_MISC
327
328 pll_locked r1, r0, CLK_RESET_PLLM_BASE
329 pll_locked r1, r0, CLK_RESET_PLLP_BASE
330 pll_locked r1, r0, CLK_RESET_PLLA_BASE
331 pll_locked r1, r0, CLK_RESET_PLLC_BASE
332 pll_locked r1, r0, CLK_RESET_PLLX_BASE
333
334 mov32 r7, TEGRA_TMRUS_BASE
335 ldr r1, [r7]
336 add r1, r1, #LOCK_DELAY
337 wait_until r1, r7, r3
338
339 add r5, pc, #tegra3_sdram_pad_save-(.+8) @ r5 reserved for pad base
340
341 ldr r4, [r5, #0x18]
342 str r4, [r0, #CLK_RESET_CLK_SOURCE_MSELECT]
343
344 ldr r4, [r5, #0x1C]
345 str r4, [r0, #CLK_RESET_SCLK_BURST]
346
347 mov32 r4, ((1<<28) | (8)) @ burst policy is PLLX
348 str r4, [r0, #CLK_RESET_CCLK_BURST]
349
350#if defined (CONFIG_CACHE_L2X0)
351 /* power up L2 */
352 ldr r0, [r2, #PMC_PWRGATE_STATUS]
353 tst r0, #(1<<PMC_PWRGATE_PARTID_L2C)
354 bne powerup_l2_done
355 movw r0, #(1<<8) | PMC_PWRGATE_PARTID_L2C
356 str r0, [r2, #PMC_PWRGATE_TOGGLE]
357powerup_l2_wait:
358 ldr r0, [r2, #PMC_PWRGATE_STATUS]
359 tst r0, #(1<<PMC_PWRGATE_PARTID_L2C)
360 beq powerup_l2_wait
361powerup_l2_done:
362 mov r0, #PMC_PWRGATE_PARTID_L2C
363 str r0, [r2, #PMC_REMOVE_CLAMPING_CMD]
364#endif
365
366 mov32 r0, TEGRA_EMC_BASE @ r0 reserved for emc base
367
368 ldr r1, [r5, #0x14] @ PMC_IO_DPD_STATUS
369 mvn r1, r1
370 bic r1, r1, #(0x1<<31)
371 orr r1, r1, #(0x1<<30)
372 str r1, [r2, #PMC_IO_DPD_REQ]
373 ldr r1, [r5, #0xC]
374 str r1, [r0, #EMC_XM2VTTGENPADCTRL]
375 ldr r1, [r5, #0x10]
376 str r1, [r0, #EMC_XM2VTTGENPADCTRL2]
377 ldr r1, [r5, #0x8]
378 str r1, [r0, #EMC_AUTO_CAL_INTERVAL]
379
380 ldr r1, [r0, #EMC_CFG_DIG_DLL]
381 orr r1, r1, #(0x1<<30) @ set DLL_RESET
382 str r1, [r0, #EMC_CFG_DIG_DLL]
383
384 emc_timing_update r1, r0
385
386 ldr r1, [r0, #EMC_AUTO_CAL_CONFIG]
387 orr r1, r1, #(0x1<<31) @ set AUTO_CAL_ACTIVE
388 str r1, [r0, #EMC_AUTO_CAL_CONFIG]
389
390emc_wait_audo_cal_onetime:
391 ldr r1, [r0, #EMC_AUTO_CAL_STATUS]
392 tst r1, #(0x1<<31) @ wait until AUTO_CAL_ACTIVE is clear
393 bne emc_wait_audo_cal_onetime
394
395 ldr r1, [r0, #EMC_CFG]
396 bic r1, r1, #(1<<31) @ disable DRAM_CLK_STOP
397 str r1, [r0, #EMC_CFG]
398
399 mov r1, #0
400 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
401 mov r1, #1
402 str r1, [r0, #EMC_NOP]
403 str r1, [r0, #EMC_NOP]
404 str r1, [r0, #EMC_REFRESH]
405
406 emc_device_mask r1, r0
407
408exit_selfrefresh_loop:
409 ldr r2, [r0, #EMC_EMC_STATUS]
410 ands r2, r2, r1
411 bne exit_selfrefresh_loop
412
413 lsr r1, r1, #8 @ devSel, bit0:dev0 bit1:dev1
414
415 mov32 r7, TEGRA_TMRUS_BASE
416 ldr r2, [r0, #EMC_FBIO_CFG5]
417
418 and r2, r2, #3
419 cmp r2, #2
420 beq emc_lpddr2
421
422 mov32 r2, 0x80000011
423 str r2, [r0, #EMC_ZQ_CAL]
424 ldr r2, [r7]
425 add r2, r2, #10
426 wait_until r2, r7, r3
427
428 tst r1, #2
429 beq zcal_done
430
431 mov32 r2, 0x40000011
432 str r2, [r0, #EMC_ZQ_CAL]
433 ldr r2, [r7]
434 add r2, r2, #10
435 wait_until r2, r7, r3
436 b zcal_done
437
438emc_lpddr2:
439
440 mov32 r2, 0x800A00AB
441 str r2, [r0, #EMC_MRW]
442 ldr r2, [r7]
443 add r2, r2, #1
444 wait_until r2, r7, r3
445
446 tst r1, #2
447 beq zcal_done
448
449 mov32 r2, 0x400A00AB
450 str r2, [r0, #EMC_MRW]
451 ldr r2, [r7]
452 add r2, r2, #1
453 wait_until r2, r7, r3
454
455zcal_done:
456
457 mov r1, #0
458 str r1, [r0, #EMC_REQ_CTRL]
459 ldr r1, [r5, #0x4]
460 str r1, [r0, #EMC_ZCAL_INTERVAL]
461 ldr r1, [r5, #0x0]
462 str r1, [r0, #EMC_CFG]
463
464 mov32 r0, TEGRA_PMC_BASE
465 ldr r0, [r0, #PMC_SCRATCH41]
466 mov pc, r0
467ENDPROC(tegra3_lp1_reset)
468
469 .align L1_CACHE_SHIFT
470 .type tegra3_sdram_pad_save, %object
471tegra3_sdram_pad_save:
472 .word 0
473 .word 0
474 .word 0
475 .word 0
476 .word 0
477 .word 0
478 .word 0
479 .word 0
480
481tegra3_sdram_pad_address:
482 .word TEGRA_EMC_BASE + EMC_CFG @0x0
483 .word TEGRA_EMC_BASE + EMC_ZCAL_INTERVAL @0x4
484 .word TEGRA_EMC_BASE + EMC_AUTO_CAL_INTERVAL @0x8
485 .word TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL @0xc
486 .word TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL2 @0x10
487 .word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14
488 .word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18
489 .word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c
490
491tegra3_sdram_pad_size:
492 .word tegra3_sdram_pad_address - tegra3_sdram_pad_save
493
494/*
495 * tegra3_tear_down_core
496 *
497 * copied into and executed from IRAM
498 * puts memory in self-refresh for LP0 and LP1
499 */
500tegra3_tear_down_core:
501 bl tegra3_sdram_self_refresh
502 bl tegra3_cpu_clk32k
503 b tegra3_enter_sleep
504
505/*
506 * tegra3_cpu_clk32k
507 *
508 * In LP0 and LP1 all plls will be turned off. Switch the CPU and system clock
509 * to the 32khz clock (clks)
510 * r4 = TEGRA_PMC_BASE
511 * r5 = TEGRA_CLK_RESET_BASE
512 * r6 = TEGRA_FLOW_CTRL_BASE
513 * r7 = TEGRA_TMRUS_BASE
514 */
515tegra3_cpu_clk32k:
516 ldr r0, [r4, #PMC_CTRL]
517 tst r0, #PMC_CTRL_SIDE_EFFECT_LP0
518 beq lp1_clocks_prepare
519
520 /* enable PLLM via PMC in LP0 */
521 ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
522 orr r0, r0, #((1<<12) | (1 << 11))
523 str r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
524 mov pc, lr
525
526 /* start by jumping to clkm to safely disable PLLs, then jump
527 * to clks */
528lp1_clocks_prepare:
529 mov r0, #(1 << 28)
530 str r0, [r5, #CLK_RESET_SCLK_BURST]
531 str r0, [r5, #CLK_RESET_CCLK_BURST]
532 mov r0, #0
533 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
534 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
535
536 /* switch the clock source for mselect to be CLK_M */
537 ldr r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT]
538 orr r0, r0, #MSELECT_CLKM
539 str r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT]
540
541 /* 2 us delay between changing sclk and disabling PLLs */
542 wait_for_us r1, r7, r9
543 add r1, r1, #2
544 wait_until r1, r7, r9
545
546#if 1
547 /* switch to CLKS */
548 mov r0, #0 /* burst policy = 32KHz */
549 str r0, [r5, #CLK_RESET_SCLK_BURST]
550#endif
551
552 /* disable PLLM via PMC in LP1 */
553 ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
554 bic r0, r0, #(1<<12)
555 str r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
556 b powerdown_pll_pcx
557
558powerdown_pll_pcx:
559 /* disable PLLP, PLLA, PLLC, and PLLX in LP0 and LP1 states */
560 ldr r0, [r4, #PMC_CTRL]
561 tst r0, #PMC_CTRL_SIDE_EFFECT_LP0
562 beq powerdown_pll_cx
563 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
564 bic r0, r0, #(1<<30)
565 str r0, [r5, #CLK_RESET_PLLP_BASE]
566 ldr r0, [r5, #CLK_RESET_PLLA_BASE]
567 bic r0, r0, #(1<<30)
568 str r0, [r5, #CLK_RESET_PLLA_BASE]
569powerdown_pll_cx:
570 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
571 bic r0, r0, #(1<<30)
572 str r0, [r5, #CLK_RESET_PLLC_BASE]
573 ldr r0, [r5, #CLK_RESET_PLLX_BASE]
574 bic r0, r0, #(1<<30)
575 str r0, [r5, #CLK_RESET_PLLX_BASE]
576
577 mov pc, lr
578
579/*
580 * tegra3_enter_sleep
581 *
582 * uses flow controller to enter sleep state
583 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
584 * executes from SDRAM with target state is LP2
585 * r4 = TEGRA_PMC_BASE
586 * r5 = TEGRA_CLK_RESET_BASE
587 * r6 = TEGRA_FLOW_CTRL_BASE
588 * r7 = TEGRA_TMRUS_BASE
589 */
590tegra3_enter_sleep:
591 ldr r1, [r7]
592 str r1, [r4, #PMC_SCRATCH38]
593 dsb
594 cpu_id r1
595
596 cpu_to_csr_reg r2, r1
597 ldr r0, [r6, r2]
598 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
599 orr r0, r0, #FLOW_CTRL_CSR_ENABLE
600 str r0, [r6, r2]
601
602 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
603 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
604 cpu_to_halt_reg r2, r1
605 str r0, [r6, r2]
606 dsb
607 ldr r0, [r6, r2] /* memory barrier */
608
609halted:
610 isb
611 dsb
612 wfi /* CPU should be power gated here */
613
614 /* !!!FIXME!!! Implement halt failure handler */
615 b halted
616
617/*
618 * tegra3_sdram_self_refresh
619 *
620 * called with MMU off and caches disabled
621 /* puts sdram in self refresh
622 * must execute from IRAM
623 * r4 = TEGRA_PMC_BASE
624 * r5 = TEGRA_CLK_RESET_BASE
625 * r6 = TEGRA_FLOW_CTRL_BASE
626 * r7 = TEGRA_TMRUS_BASE
627 */
628
629tegra3_sdram_self_refresh:
630
631 adr r2, tegra3_sdram_pad_address
632 adr r8, tegra3_sdram_pad_save
633 mov r9, #0
634
635padsave:
636 ldr r0, [r2, r9] @ r0 is emc register address
637
638 ldr r1, [r0]
639 str r1, [r8, r9] @ save emc register
640
641 add r9, r9, #4
642 ldr r0, tegra3_sdram_pad_size
643 cmp r0, r9
644 bne padsave
645padsave_done:
646
647 dsb
648
649 mov32 r0, TEGRA_EMC_BASE @ r0 reserved for emc base
650
651 mov r1, #0
652 str r1, [r0, #EMC_ZCAL_INTERVAL]
653 str r1, [r0, #EMC_AUTO_CAL_INTERVAL]
654 ldr r1, [r0, #EMC_CFG]
655 bic r1, r1, #(1<<28)
656 str r1, [r0, #EMC_CFG] @ disable DYN_SELF_REF
657
658 emc_timing_update r1, r0
659
660 ldr r1, [r7]
661 add r1, r1, #5
662 wait_until r1, r7, r2
663
664emc_wait_audo_cal:
665 ldr r1, [r0, #EMC_AUTO_CAL_STATUS]
666 tst r1, #(0x1<<31) @ wait until AUTO_CAL_ACTIVE is clear
667 bne emc_wait_audo_cal
668
669 mov r1, #3
670 str r1, [r0, #EMC_REQ_CTRL] @ stall incoming DRAM requests
671
672emcidle:
673 ldr r1, [r0, #EMC_EMC_STATUS]
674 tst r1, #4
675 beq emcidle
676
677 mov r1, #1
678 str r1, [r0, #EMC_SELF_REF]
679
680 emc_device_mask r1, r0
681
682emcself:
683 ldr r2, [r0, #EMC_EMC_STATUS]
684 and r2, r2, r1
685 cmp r2, r1
686 bne emcself @ loop until DDR in self-refresh
687
688 ldr r1, [r0, #EMC_XM2VTTGENPADCTRL]
689 mov32 r2, 0xF8F8FFFF @ clear XM2VTTGEN_DRVUP and XM2VTTGEN_DRVDN
690 and r1, r1, r2
691 str r1, [r0, #EMC_XM2VTTGENPADCTRL]
692 ldr r1, [r0, #EMC_XM2VTTGENPADCTRL2]
693 orr r1, r1, #7 @ set E_NO_VTTGEN
694 str r1, [r0, #EMC_XM2VTTGENPADCTRL2]
695
696 emc_timing_update r1, r0
697
698 ldr r1, [r4, #PMC_CTRL]
699 tst r1, #PMC_CTRL_SIDE_EFFECT_LP0
700 bne pmc_io_dpd_skip
701 mov32 r1, 0x8EC00000
702 str r1, [r4, #PMC_IO_DPD_REQ]
703pmc_io_dpd_skip:
704
705 dsb
706
707 mov pc, lr
708
709 .ltorg
710/* dummy symbol for end of IRAM */
711 .align L1_CACHE_SHIFT
712 .globl tegra3_iram_end
713tegra3_iram_end:
714 b .
715#endif