aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/sleep-tegra30.S
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2013-08-12 05:40:04 -0400
committerStephen Warren <swarren@nvidia.com>2013-08-12 15:30:11 -0400
commite7a932b1961c3936c7ae5b8d1628f39dc50a746d (patch)
tree757f5862da9fad0e10185382f9a9bbaca4723579 /arch/arm/mach-tegra/sleep-tegra30.S
parent95872f427eca73b19ac9466c25afd9bb876dc1aa (diff)
ARM: tegra: add LP1 suspend support for Tegra30
The LP1 suspend mode will power off the CPU, clock gated the PLLs and put SDRAM to self-refresh mode. Any interrupt can wake up device from LP1. The sequence when LP1 suspending: * tunning off L1 data cache and the MMU * storing some EMC registers, DPD (deep power down) status, clk source of mselect and SCLK burst policy * putting SDRAM into self-refresh * switching CPU to CLK_M (12MHz OSC) * tunning off PLLM, PLLP, PLLA, PLLC and PLLX * switching SCLK to CLK_S (32KHz OSC) * shutting off the CPU rail The sequence of LP1 resuming: * re-enabling PLLM, PLLP, PLLA, PLLC and PLLX * restoring the clk source of mselect and SCLK burst policy * setting up CCLK burst policy to PLLX * restoring DPD status and some EMC registers * resuming SDRAM to normal mode * jumping to the "tegra_resume" from PMC_SCRATCH41 Due to the SDRAM will be put into self-refresh mode, the low level procedures of LP1 suspending and resuming should be copied to TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K) when suspending. Before restoring the CPU context when resuming, the SDRAM needs to be switched back to normal mode. And the PLLs need to be re-enabled, SCLK burst policy be restored, CCLK burst policy be set in PLLX. Then jumping to "tegra_resume" that was expected to be stored in PMC_SCRATCH41 to restore CPU context and back to kernel. Based on the work by: Scott Williams <scwilliams@nvidia.com> Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/sleep-tegra30.S')
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S492
1 files changed, 492 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index ecad4eace941..2be7f70e19cb 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -18,13 +18,102 @@
18 18
19#include <asm/assembler.h> 19#include <asm/assembler.h>
20#include <asm/asm-offsets.h> 20#include <asm/asm-offsets.h>
21#include <asm/cache.h>
21 22
22#include "fuse.h" 23#include "fuse.h"
23#include "sleep.h" 24#include "sleep.h"
24#include "flowctrl.h" 25#include "flowctrl.h"
25 26
27#define EMC_CFG 0xc
28#define EMC_ADR_CFG 0x10
29#define EMC_TIMING_CONTROL 0x28
30#define EMC_REFRESH 0x70
31#define EMC_NOP 0xdc
32#define EMC_SELF_REF 0xe0
33#define EMC_MRW 0xe8
34#define EMC_FBIO_CFG5 0x104
35#define EMC_AUTO_CAL_CONFIG 0x2a4
36#define EMC_AUTO_CAL_INTERVAL 0x2a8
37#define EMC_AUTO_CAL_STATUS 0x2ac
38#define EMC_REQ_CTRL 0x2b0
39#define EMC_CFG_DIG_DLL 0x2bc
40#define EMC_EMC_STATUS 0x2b4
41#define EMC_ZCAL_INTERVAL 0x2e0
42#define EMC_ZQ_CAL 0x2ec
43#define EMC_XM2VTTGENPADCTRL 0x310
44#define EMC_XM2VTTGENPADCTRL2 0x314
45
46#define PMC_CTRL 0x0
47#define PMC_CTRL_SIDE_EFFECT_LP0 (1 << 14) /* enter LP0 when CPU pwr gated */
48
49#define PMC_PLLP_WB0_OVERRIDE 0xf8
50#define PMC_IO_DPD_REQ 0x1b8
51#define PMC_IO_DPD_STATUS 0x1bc
52
53#define CLK_RESET_CCLK_BURST 0x20
54#define CLK_RESET_CCLK_DIVIDER 0x24
55#define CLK_RESET_SCLK_BURST 0x28
56#define CLK_RESET_SCLK_DIVIDER 0x2c
57
58#define CLK_RESET_PLLC_BASE 0x80
59#define CLK_RESET_PLLC_MISC 0x8c
60#define CLK_RESET_PLLM_BASE 0x90
61#define CLK_RESET_PLLM_MISC 0x9c
62#define CLK_RESET_PLLP_BASE 0xa0
63#define CLK_RESET_PLLP_MISC 0xac
64#define CLK_RESET_PLLA_BASE 0xb0
65#define CLK_RESET_PLLA_MISC 0xbc
66#define CLK_RESET_PLLX_BASE 0xe0
67#define CLK_RESET_PLLX_MISC 0xe4
68
69#define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4
70
71#define MSELECT_CLKM (0x3 << 30)
72
73#define LOCK_DELAY 50 /* safety delay after lock is detected */
74
26#define TEGRA30_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */ 75#define TEGRA30_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */
27 76
77.macro emc_device_mask, rd, base
78 ldr \rd, [\base, #EMC_ADR_CFG]
79 tst \rd, #0x1
80 moveq \rd, #(0x1 << 8) @ just 1 device
81 movne \rd, #(0x3 << 8) @ 2 devices
82.endm
83
84.macro emc_timing_update, rd, base
85 mov \rd, #1
86 str \rd, [\base, #EMC_TIMING_CONTROL]
871001:
88 ldr \rd, [\base, #EMC_EMC_STATUS]
89 tst \rd, #(0x1<<23) @ wait EMC_STATUS_TIMING_UPDATE_STALLED is clear
90 bne 1001b
91.endm
92
93.macro pll_enable, rd, r_car_base, pll_base, pll_misc
94 ldr \rd, [\r_car_base, #\pll_base]
95 tst \rd, #(1 << 30)
96 orreq \rd, \rd, #(1 << 30)
97 streq \rd, [\r_car_base, #\pll_base]
98 /* Enable lock detector */
99 .if \pll_misc
100 ldr \rd, [\r_car_base, #\pll_misc]
101 bic \rd, \rd, #(1 << 18)
102 str \rd, [\r_car_base, #\pll_misc]
103 ldr \rd, [\r_car_base, #\pll_misc]
104 ldr \rd, [\r_car_base, #\pll_misc]
105 orr \rd, \rd, #(1 << 18)
106 str \rd, [\r_car_base, #\pll_misc]
107 .endif
108.endm
109
110.macro pll_locked, rd, r_car_base, pll_base
1111:
112 ldr \rd, [\r_car_base, #\pll_base]
113 tst \rd, #(1 << 27)
114 beq 1b
115.endm
116
28#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) 117#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
29/* 118/*
30 * tegra30_hotplug_shutdown(void) 119 * tegra30_hotplug_shutdown(void)
@@ -129,6 +218,41 @@ ENDPROC(tegra30_cpu_shutdown)
129 218
130#ifdef CONFIG_PM_SLEEP 219#ifdef CONFIG_PM_SLEEP
131/* 220/*
221 * tegra30_sleep_core_finish(unsigned long v2p)
222 *
223 * Enters suspend in LP0 or LP1 by turning off the MMU and jumping to
224 * tegra30_tear_down_core in IRAM
225 */
226ENTRY(tegra30_sleep_core_finish)
227 /* Flush, disable the L1 data cache and exit SMP */
228 bl tegra_disable_clean_inv_dcache
229
230 /*
231 * Preload all the address literals that are needed for the
232 * CPU power-gating process, to avoid loading from SDRAM which
233 * are not supported once SDRAM is put into self-refresh.
234 * LP0 / LP1 use physical address, since the MMU needs to be
235 * disabled before putting SDRAM into self-refresh to avoid
236 * memory access due to page table walks.
237 */
238 mov32 r4, TEGRA_PMC_BASE
239 mov32 r5, TEGRA_CLK_RESET_BASE
240 mov32 r6, TEGRA_FLOW_CTRL_BASE
241 mov32 r7, TEGRA_TMRUS_BASE
242
243 mov32 r3, tegra_shut_off_mmu
244 add r3, r3, r0
245
246 mov32 r0, tegra30_tear_down_core
247 mov32 r1, tegra30_iram_start
248 sub r0, r0, r1
249 mov32 r1, TEGRA_IRAM_CODE_AREA
250 add r0, r0, r1
251
252 mov pc, r3
253ENDPROC(tegra30_sleep_core_finish)
254
255/*
132 * tegra30_sleep_cpu_secondary_finish(unsigned long v2p) 256 * tegra30_sleep_cpu_secondary_finish(unsigned long v2p)
133 * 257 *
134 * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU. 258 * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
@@ -158,6 +282,273 @@ ENTRY(tegra30_tear_down_cpu)
158 b tegra30_enter_sleep 282 b tegra30_enter_sleep
159ENDPROC(tegra30_tear_down_cpu) 283ENDPROC(tegra30_tear_down_cpu)
160 284
285/* START OF ROUTINES COPIED TO IRAM */
286 .align L1_CACHE_SHIFT
287 .globl tegra30_iram_start
288tegra30_iram_start:
289
290/*
291 * tegra30_lp1_reset
292 *
293 * reset vector for LP1 restore; copied into IRAM during suspend.
294 * Brings the system back up to a safe staring point (SDRAM out of
295 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLX,
296 * system clock running on the same PLL that it suspended at), and
297 * jumps to tegra_resume to restore virtual addressing.
298 * The physical address of tegra_resume expected to be stored in
299 * PMC_SCRATCH41.
300 *
301 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA.
302 */
303ENTRY(tegra30_lp1_reset)
304 /*
305 * The CPU and system bus are running at 32KHz and executing from
306 * IRAM when this code is executed; immediately switch to CLKM and
307 * enable PLLP, PLLM, PLLC, PLLA and PLLX.
308 */
309 mov32 r0, TEGRA_CLK_RESET_BASE
310
311 mov r1, #(1 << 28)
312 str r1, [r0, #CLK_RESET_SCLK_BURST]
313 str r1, [r0, #CLK_RESET_CCLK_BURST]
314 mov r1, #0
315 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
316 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
317
318 /* enable PLLM via PMC */
319 mov32 r2, TEGRA_PMC_BASE
320 ldr r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
321 orr r1, r1, #(1 << 12)
322 str r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
323
324 pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC
325 pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC
326 pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC
327 pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC
328 pll_enable r1, r0, CLK_RESET_PLLX_BASE, CLK_RESET_PLLX_MISC
329
330 pll_locked r1, r0, CLK_RESET_PLLM_BASE
331 pll_locked r1, r0, CLK_RESET_PLLP_BASE
332 pll_locked r1, r0, CLK_RESET_PLLA_BASE
333 pll_locked r1, r0, CLK_RESET_PLLC_BASE
334 pll_locked r1, r0, CLK_RESET_PLLX_BASE
335
336 mov32 r7, TEGRA_TMRUS_BASE
337 ldr r1, [r7]
338 add r1, r1, #LOCK_DELAY
339 wait_until r1, r7, r3
340
341 adr r5, tegra30_sdram_pad_save
342
343 ldr r4, [r5, #0x18] @ restore CLK_SOURCE_MSELECT
344 str r4, [r0, #CLK_RESET_CLK_SOURCE_MSELECT]
345
346 ldr r4, [r5, #0x1C] @ restore SCLK_BURST
347 str r4, [r0, #CLK_RESET_SCLK_BURST]
348
349 mov32 r4, ((1 << 28) | (0x8)) @ burst policy is PLLX
350 str r4, [r0, #CLK_RESET_CCLK_BURST]
351
352 /* Restore pad power state to normal */
353 ldr r1, [r5, #0x14] @ PMC_IO_DPD_STATUS
354 mvn r1, r1
355 bic r1, r1, #(1 << 31)
356 orr r1, r1, #(1 << 30)
357 str r1, [r2, #PMC_IO_DPD_REQ] @ DPD_OFF
358
359 mov32 r0, TEGRA_EMC_BASE @ r0 reserved for emc base
360
361 ldr r1, [r5, #0xC] @ restore EMC_XM2VTTGENPADCTRL
362 str r1, [r0, #EMC_XM2VTTGENPADCTRL]
363 ldr r1, [r5, #0x10] @ restore EMC_XM2VTTGENPADCTRL2
364 str r1, [r0, #EMC_XM2VTTGENPADCTRL2]
365 ldr r1, [r5, #0x8] @ restore EMC_AUTO_CAL_INTERVAL
366 str r1, [r0, #EMC_AUTO_CAL_INTERVAL]
367
368 /* Relock DLL */
369 ldr r1, [r0, #EMC_CFG_DIG_DLL]
370 orr r1, r1, #(1 << 30) @ set DLL_RESET
371 str r1, [r0, #EMC_CFG_DIG_DLL]
372
373 emc_timing_update r1, r0
374
375 ldr r1, [r0, #EMC_AUTO_CAL_CONFIG]
376 orr r1, r1, #(1 << 31) @ set AUTO_CAL_ACTIVE
377 str r1, [r0, #EMC_AUTO_CAL_CONFIG]
378
379emc_wait_auto_cal_onetime:
380 ldr r1, [r0, #EMC_AUTO_CAL_STATUS]
381 tst r1, #(1 << 31) @ wait until AUTO_CAL_ACTIVE is cleared
382 bne emc_wait_auto_cal_onetime
383
384 ldr r1, [r0, #EMC_CFG]
385 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP_PD
386 str r1, [r0, #EMC_CFG]
387
388 mov r1, #0
389 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
390 mov r1, #1
391 str r1, [r0, #EMC_NOP]
392 str r1, [r0, #EMC_NOP]
393 str r1, [r0, #EMC_REFRESH]
394
395 emc_device_mask r1, r0
396
397exit_selfrefresh_loop:
398 ldr r2, [r0, #EMC_EMC_STATUS]
399 ands r2, r2, r1
400 bne exit_selfrefresh_loop
401
402 lsr r1, r1, #8 @ devSel, bit0:dev0, bit1:dev1
403
404 mov32 r7, TEGRA_TMRUS_BASE
405 ldr r2, [r0, #EMC_FBIO_CFG5]
406
407 and r2, r2, #3 @ check DRAM_TYPE
408 cmp r2, #2
409 beq emc_lpddr2
410
411 /* Issue a ZQ_CAL for dev0 - DDR3 */
412 mov32 r2, 0x80000011 @ DEV_SELECTION=2, LENGTH=LONG, CMD=1
413 str r2, [r0, #EMC_ZQ_CAL]
414 ldr r2, [r7]
415 add r2, r2, #10
416 wait_until r2, r7, r3
417
418 tst r1, #2
419 beq zcal_done
420
421 /* Issue a ZQ_CAL for dev1 - DDR3 */
422 mov32 r2, 0x40000011 @ DEV_SELECTION=1, LENGTH=LONG, CMD=1
423 str r2, [r0, #EMC_ZQ_CAL]
424 ldr r2, [r7]
425 add r2, r2, #10
426 wait_until r2, r7, r3
427 b zcal_done
428
429emc_lpddr2:
430 /* Issue a ZQ_CAL for dev0 - LPDDR2 */
431 mov32 r2, 0x800A00AB @ DEV_SELECTION=2, MA=10, OP=0xAB
432 str r2, [r0, #EMC_MRW]
433 ldr r2, [r7]
434 add r2, r2, #1
435 wait_until r2, r7, r3
436
437 tst r1, #2
438 beq zcal_done
439
440 /* Issue a ZQ_CAL for dev0 - LPDDR2 */
441 mov32 r2, 0x400A00AB @ DEV_SELECTION=1, MA=10, OP=0xAB
442 str r2, [r0, #EMC_MRW]
443 ldr r2, [r7]
444 add r2, r2, #1
445 wait_until r2, r7, r3
446
447zcal_done:
448 mov r1, #0 @ unstall all transactions
449 str r1, [r0, #EMC_REQ_CTRL]
450 ldr r1, [r5, #0x4] @ restore EMC_ZCAL_INTERVAL
451 str r1, [r0, #EMC_ZCAL_INTERVAL]
452 ldr r1, [r5, #0x0] @ restore EMC_CFG
453 str r1, [r0, #EMC_CFG]
454
455 mov32 r0, TEGRA_PMC_BASE
456 ldr r0, [r0, #PMC_SCRATCH41]
457 mov pc, r0 @ jump to tegra_resume
458ENDPROC(tegra30_lp1_reset)
459
460 .align L1_CACHE_SHIFT
461tegra30_sdram_pad_address:
462 .word TEGRA_EMC_BASE + EMC_CFG @0x0
463 .word TEGRA_EMC_BASE + EMC_ZCAL_INTERVAL @0x4
464 .word TEGRA_EMC_BASE + EMC_AUTO_CAL_INTERVAL @0x8
465 .word TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL @0xc
466 .word TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL2 @0x10
467 .word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14
468 .word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18
469 .word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c
470
471tegra30_sdram_pad_size:
472 .word tegra30_sdram_pad_size - tegra30_sdram_pad_address
473
474 .type tegra30_sdram_pad_save, %object
475tegra30_sdram_pad_save:
476 .rept (tegra30_sdram_pad_size - tegra30_sdram_pad_address) / 4
477 .long 0
478 .endr
479
480/*
481 * tegra30_tear_down_core
482 *
483 * copied into and executed from IRAM
484 * puts memory in self-refresh for LP0 and LP1
485 */
486tegra30_tear_down_core:
487 bl tegra30_sdram_self_refresh
488 bl tegra30_switch_cpu_to_clk32k
489 b tegra30_enter_sleep
490
491/*
492 * tegra30_switch_cpu_to_clk32k
493 *
494 * In LP0 and LP1 all PLLs will be turned off. Switching the CPU and System CLK
495 * to the 32KHz clock.
496 * r4 = TEGRA_PMC_BASE
497 * r5 = TEGRA_CLK_RESET_BASE
498 * r6 = TEGRA_FLOW_CTRL_BASE
499 * r7 = TEGRA_TMRUS_BASE
500 */
501tegra30_switch_cpu_to_clk32k:
502 /*
503 * start by jumping to CLKM to safely disable PLLs, then jump to
504 * CLKS.
505 */
506 mov r0, #(1 << 28)
507 str r0, [r5, #CLK_RESET_SCLK_BURST]
508 /* 2uS delay delay between changing SCLK and CCLK */
509 ldr r1, [r7]
510 add r1, r1, #2
511 wait_until r1, r7, r9
512 str r0, [r5, #CLK_RESET_CCLK_BURST]
513 mov r0, #0
514 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
515 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
516
517 /* switch the clock source of mselect to be CLK_M */
518 ldr r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT]
519 orr r0, r0, #MSELECT_CLKM
520 str r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT]
521
522 /* 2uS delay delay between changing SCLK and disabling PLLs */
523 ldr r1, [r7]
524 add r1, r1, #2
525 wait_until r1, r7, r9
526
527 /* disable PLLM via PMC in LP1 */
528 ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
529 bic r0, r0, #(1 << 12)
530 str r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
531
532 /* disable PLLP, PLLA, PLLC and PLLX */
533 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
534 bic r0, r0, #(1 << 30)
535 str r0, [r5, #CLK_RESET_PLLP_BASE]
536 ldr r0, [r5, #CLK_RESET_PLLA_BASE]
537 bic r0, r0, #(1 << 30)
538 str r0, [r5, #CLK_RESET_PLLA_BASE]
539 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
540 bic r0, r0, #(1 << 30)
541 str r0, [r5, #CLK_RESET_PLLC_BASE]
542 ldr r0, [r5, #CLK_RESET_PLLX_BASE]
543 bic r0, r0, #(1 << 30)
544 str r0, [r5, #CLK_RESET_PLLX_BASE]
545
546 /* switch to CLKS */
547 mov r0, #0 /* brust policy = 32KHz */
548 str r0, [r5, #CLK_RESET_SCLK_BURST]
549
550 mov pc, lr
551
161/* 552/*
162 * tegra30_enter_sleep 553 * tegra30_enter_sleep
163 * 554 *
@@ -194,4 +585,105 @@ halted:
194 /* !!!FIXME!!! Implement halt failure handler */ 585 /* !!!FIXME!!! Implement halt failure handler */
195 b halted 586 b halted
196 587
588/*
589 * tegra30_sdram_self_refresh
590 *
591 * called with MMU off and caches disabled
592 * must be executed from IRAM
593 * r4 = TEGRA_PMC_BASE
594 * r5 = TEGRA_CLK_RESET_BASE
595 * r6 = TEGRA_FLOW_CTRL_BASE
596 * r7 = TEGRA_TMRUS_BASE
597 */
598tegra30_sdram_self_refresh:
599
600 adr r2, tegra30_sdram_pad_address
601 adr r8, tegra30_sdram_pad_save
602 mov r9, #0
603
604 ldr r3, tegra30_sdram_pad_size
605padsave:
606 ldr r0, [r2, r9] @ r0 is the addr in the pad_address
607
608 ldr r1, [r0]
609 str r1, [r8, r9] @ save the content of the addr
610
611 add r9, r9, #4
612 cmp r3, r9
613 bne padsave
614padsave_done:
615
616 dsb
617
618 mov32 r0, TEGRA_EMC_BASE @ r0 reserved for emc base addr
619
620 mov r1, #0
621 str r1, [r0, #EMC_ZCAL_INTERVAL]
622 str r1, [r0, #EMC_AUTO_CAL_INTERVAL]
623 ldr r1, [r0, #EMC_CFG]
624 bic r1, r1, #(1 << 28)
625 str r1, [r0, #EMC_CFG] @ disable DYN_SELF_REF
626
627 emc_timing_update r1, r0
628
629 ldr r1, [r7]
630 add r1, r1, #5
631 wait_until r1, r7, r2
632
633emc_wait_auto_cal:
634 ldr r1, [r0, #EMC_AUTO_CAL_STATUS]
635 tst r1, #(1 << 31) @ wait until AUTO_CAL_ACTIVE is cleared
636 bne emc_wait_auto_cal
637
638 mov r1, #3
639 str r1, [r0, #EMC_REQ_CTRL] @ stall incoming DRAM requests
640
641emcidle:
642 ldr r1, [r0, #EMC_EMC_STATUS]
643 tst r1, #4
644 beq emcidle
645
646 mov r1, #1
647 str r1, [r0, #EMC_SELF_REF]
648
649 emc_device_mask r1, r0
650
651emcself:
652 ldr r2, [r0, #EMC_EMC_STATUS]
653 and r2, r2, r1
654 cmp r2, r1
655 bne emcself @ loop until DDR in self-refresh
656
657 /* Put VTTGEN in the lowest power mode */
658 ldr r1, [r0, #EMC_XM2VTTGENPADCTRL]
659 mov32 r2, 0xF8F8FFFF @ clear XM2VTTGEN_DRVUP and XM2VTTGEN_DRVDN
660 and r1, r1, r2
661 str r1, [r0, #EMC_XM2VTTGENPADCTRL]
662 ldr r1, [r0, #EMC_XM2VTTGENPADCTRL2]
663 orr r1, r1, #7 @ set E_NO_VTTGEN
664 str r1, [r0, #EMC_XM2VTTGENPADCTRL2]
665
666 emc_timing_update r1, r0
667
668 ldr r1, [r4, #PMC_CTRL]
669 tst r1, #PMC_CTRL_SIDE_EFFECT_LP0
670 bne pmc_io_dpd_skip
671 /*
672 * Put DDR_DATA, DISC_ADDR_CMD, DDR_ADDR_CMD, POP_ADDR_CMD, POP_CLK
673 * and COMP in the lowest power mode when LP1.
674 */
675 mov32 r1, 0x8EC00000
676 str r1, [r4, #PMC_IO_DPD_REQ]
677pmc_io_dpd_skip:
678
679 dsb
680
681 mov pc, lr
682
683 .ltorg
684/* dummy symbol for end of IRAM */
685 .align L1_CACHE_SHIFT
686 .global tegra30_iram_end
687tegra30_iram_end:
688 b .
197#endif 689#endif