summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/sleep.S
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-07-18 15:20:56 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:46:48 -0800
commit07e32729adeff79693e0da4f64ade4a64f52b024 (patch)
tree1dad1a27668df6e24bb91bbb854d472644e2406e /arch/arm/mach-tegra/sleep.S
parenta30f93203f93896205fc7de4956a05b285846c62 (diff)
ARM: tegra: Split sleep.S for Tegra2
Change-Id: I22bbfe62c6fed753a6852b12246f4a1f2414a96f Signed-off-by: Scott Williams <scwilliams@nvidia.com> DW: Split into logical changes Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com> Rebase-Id: R2d7985afe7ffafac651d747205e528331f5f993e
Diffstat (limited to 'arch/arm/mach-tegra/sleep.S')
-rw-r--r--arch/arm/mach-tegra/sleep.S476
1 files changed, 13 insertions, 463 deletions
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 11e38f2aaa34..dd3fcc3571fa 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -1,4 +1,6 @@
/*
+ * arch/arm/mach-tegra/sleep.S
+ *
* Copyright (c) 2010-2011, NVIDIA Corporation.
* Copyright (c) 2011, Google, Inc.
*
@@ -41,40 +43,11 @@
#include "asm_macros.h"
#include "sleep.h"
-#define EMC_CFG 0xc
-#define EMC_ADR_CFG 0x10
-#define EMC_REFRESH 0x70
-#define EMC_NOP 0xdc
-#define EMC_SELF_REF 0xe0
-#define EMC_REQ_CTRL 0x2b0
-#define EMC_EMC_STATUS 0x2b4
-
#define CLK_RESET_CCLK_BURST 0x20
#define CLK_RESET_CCLK_DIVIDER 0x24
-#define CLK_RESET_SCLK_BURST 0x28
-#define CLK_RESET_SCLK_DIVIDER 0x2c
-
-#define CLK_RESET_PLLC_BASE 0x80
-#define CLK_RESET_PLLM_BASE 0x90
-#define CLK_RESET_PLLP_BASE 0xa0
-#define CLK_RESET_PLLP_OUTA 0xa4
-#define CLK_RESET_PLLP_OUTB 0xa8
-#define CLK_RESET_PLLP_MISC 0xac
-#define CLK_RESET_PLLX_BASE 0xe0
-#define CLK_RESET_PLLX_MISC 0xe4
-
-#define FLOW_CTRL_WAITEVENT (2 << 29)
-#define FLOW_CTRL_STOP_UNTIL_IRQ (4 << 29)
-#define FLOW_CTRL_JTAG_RESUME (1 << 28)
-#define FLOW_CTRL_IRQ_RESUME (1 << 10)
-#define FLOW_CTRL_FIQ_RESUME (1 << 8)
-
-#define FLOW_CTRL_CSR_INTR_FLAG (1<<15)
-#define FLOW_CTRL_CSR_EVENT_FLAG (1<<14)
#define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
#define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS + IO_CPU_VIRT)
-#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS + IO_PPSB_VIRT)
#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS + IO_PPSB_VIRT)
/*
@@ -131,24 +104,6 @@ ENTRY(tegra_pen_unlock)
mov pc, lr
ENDPROC(tegra_pen_unlock)
-ENTRY(tegra_cpu_set_resettable_soon)
- mov32 r3, TEGRA_PMC_VIRT
- add r1, r3, #PMC_SCRATCH41
- mov r12, #CPU_RESETTABLE_SOON
- str r12, [r1]
- mov pc, lr
-ENDPROC(tegra_cpu_set_resettable_soon)
-
-ENTRY(tegra_cpu_is_resettable_soon)
- mov32 r3, TEGRA_PMC_VIRT
- add r1, r3, #PMC_SCRATCH41
- ldr r12, [r1]
- cmp r12, #CPU_RESETTABLE_SOON
- moveq r0, #1
- movne r0, #0
- mov pc, lr
-ENDPROC(tegra_cpu_is_resettable_soon)
-
/*
* tegra_cpu_save
*
@@ -219,108 +174,26 @@ ENTRY(tegra_cpu_wfi)
mov pc, lr
ENDPROC(tegra_cpu_wfi)
-/*
- * tegra_sleep_reset(unsigned long v2p)
- *
- * puts the current cpu in reset
- * uses tegra_cpu_save to take the cpu out of coherence
- * should never return
- */
-ENTRY(tegra_sleep_reset)
- bl tegra_cpu_save
- cpu_id r0
- bl tegra_cpu_reset
- mov pc, lr
-ENDPROC(tegra_sleep_reset)
-
-/*
- * tegra_sleep_core(unsigned long v2p)
- *
- * enters suspend in LP0 or LP1 by turning off the mmu and jumping to
- * tegra_tear_down_core in IRAM
- */
-ENTRY(tegra_sleep_core)
- mov r3, lr @ set resume address to lr
- bl tegra_cpu_save
-
- mov32 r1, tegra_tear_down_core
- mov32 r2, tegra_iram_start
- sub r1, r1, r2
- mov32 r2, TEGRA_IRAM_CODE_AREA
- add r1, r1, r2
- b tegra_turn_off_mmu
-ENDPROC(tegra_sleep_core)
-
.word
/*
* tegra_sleep_cpu(unsigned long v2p)
*
* enters suspend in LP2 by turning off the mmu and jumping to
- * tegra_tear_down_cpu
+ * tegra?_tear_down_cpu
*/
ENTRY(tegra_sleep_cpu)
mov r3, lr @ set resume address to lr
bl tegra_cpu_save
- mov32 r1, tegra_tear_down_cpu
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ mov32 r1, tegra2_tear_down_cpu
+#endif
add r1, r1, r0
b tegra_turn_off_mmu
ENDPROC(tegra_sleep_cpu)
/*
- * tegra_sleep_wfi(unsigned long v2p)
- */
-ENTRY(tegra_sleep_wfi)
- mov r3, lr @ set resume address to lr
- mrc p15, 0, r2, c1, c0, 1 @ save actlr before exiting coherency
- bl tegra_cpu_save
-
- mov r11, r2
-
- mov32 r3, TEGRA_PMC_VIRT
- add r0, r3, #PMC_SCRATCH41
- mov r3, #CPU_RESETTABLE
- str r3, [r0]
-
- bl tegra_cpu_wfi
-
- /*
- * cpu may be reset while in wfi, which will return through
- * tegra_secondary_resume to cpu_resume to tegra_cpu_resume
- * or interrupt may wake wfi, which will return here
- * cpu state is unchanged - MMU is on, cache is on, coherency is off
- *
- * r11 contains the original actlr
- */
-
- bl tegra_pen_lock
-
- mov32 r3, TEGRA_PMC_VIRT
- add r0, r3, #PMC_SCRATCH41
- mov r3, #CPU_NOT_RESETTABLE
- str r3, [r0]
-
- bl tegra_pen_unlock
-
- mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
-
- @ the cpu was running with coherency disabled, caches may be out of date
- mov r0, #0
- mcr p15, 0, r0, c8, c3, 0 @ invalidate TLB
- mcr p15, 0, r0, c7, c5, 6 @ flush BTAC
-#ifdef MULTI_CACHE
- mov32 r10, cpu_cache
- mov lr, pc
- ldr pc, [r10, #CACHE_FLUSH_KERN_ALL]
-#else
- bl __cpuc_flush_kern_all
-#endif
-
- b tegra_cpu_sleep_abort
-ENDPROC(tegra_sleep_wfi)
-
-/*
* tegra_cpu_resume
*
* reloads the volatile CPU state from the context area
@@ -335,9 +208,8 @@ tegra_cpu_resume:
dsb
isb
- bl cpu_init
+ bl cpu_init
-tegra_cpu_sleep_abort:
ldmfd sp!, {r4}
mcr p15, 0, r4, c15, c0, 1 @ write diagnostic register
ldmfd sp!, {lr}
@@ -345,49 +217,12 @@ tegra_cpu_sleep_abort:
mov pc, lr
/*
- * tegra_cpu_reset
- *
- * r0 is cpu to reset
- *
- * puts the specified CPU in wait-for-event mode on the flow controller
- * and puts the CPU in reset
- * can be called on the current cpu or another cpu
- * if called on the current cpu, does not return
- *
- * corrupts r0-r3, r12
- */
-ENTRY(tegra_cpu_reset)
- mov32 r3, TEGRA_PMC_VIRT
- add r1, r3, #PMC_SCRATCH41
- mov r12, #CPU_RESETTABLE
- str r12, [r1]
-
- cpu_to_halt_reg r1, r0
- mov32 r3, TEGRA_FLOW_CTRL_VIRT
- mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
- str r2, [r3, r1] @ put flow controller in wait event mode
- ldr r2, [r3, r1]
- isb
- dsb
- movw r1, 0x1011
- mov r1, r1, lsl r0
- mov32 r3, TEGRA_CLK_RESET_VIRT
- str r1, [r3, #0x340] @ put slave CPU in reset
- isb
- dsb
- cpu_id r3
- cmp r3, r0
- beq .
- mov pc, lr
-ENDPROC(tegra_cpu_reset)
-
-/*
* tegra_turn_off_mmu
*
* r0 = v2p
* r1 = physical address to jump to with mmu off
*/
-tegra_turn_off_mmu:
+ENTRY(tegra_turn_off_mmu)
/*
* change page table pointer to tegra_pgd_phys, so that IRAM
* and MMU shut-off will be mapped virtual == physical
@@ -413,6 +248,7 @@ tegra_turn_off_mmu:
add r3, r3, r0
mov r0, r1
mov pc, r3
+ENDPROC(tegra_turn_off_mmu)
tegra_pgd_phys_address:
.word tegra_pgd_phys
@@ -434,305 +270,19 @@ tegra_shut_off_mmu:
isb
mov pc, r0
- .ltorg
-
/*
* tegra_cpu_clk32k
*
* In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
*/
- tegra_cpu_pllp:
+ENTRY(tegra_cpu_pllp)
/* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
mov32 r5, TEGRA_CLK_RESET_BASE
- mov r0, #(2 << 28) /* burst policy = run mode */
- orr r0, r0, #(4 << 4) /* use PLLP in run mode burst */
- str r0, [r5, #CLK_RESET_CCLK_BURST]
- mov r0, #0
- str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
- mov pc, lr
-
-tegra_tear_down_cpu:
- bl tegra_cpu_pllp
- b tegra_enter_sleep
-
-/* START OF ROUTINES COPIED TO IRAM */
- .align L1_CACHE_SHIFT
- .globl tegra_iram_start
-tegra_iram_start:
-
-/*
- * tegra_tear_down_core
- *
- * copied into and executed from IRAM
- * puts memory in self-refresh for LP0 and LP1
- */
-tegra_tear_down_core:
- bl tegra_sdram_self_refresh
- bl tegra_cpu_clk32k
- b tegra_enter_sleep
-
-/*
- * tegra_cpu_clk32k
- *
- * In LP0 and LP1 all plls will be turned off. Switch the CPU and system clock
- * to the 32khz clock (clks)
- */
-tegra_cpu_clk32k:
- /* start by jumping to clkm to safely disable PLLs, then jump
- * to clks */
- mov r0, #(1 << 28)
- str r0, [r5, #CLK_RESET_SCLK_BURST]
+ mov r0, #(2 << 28) @ burst policy = run mode
+ orr r0, r0, #(4 << 4) @ use PLLP in run mode burst
str r0, [r5, #CLK_RESET_CCLK_BURST]
mov r0, #0
str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
- str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
-
- /* 2 us delay between changing sclk and disabling PLLs */
- mov32 r7, TEGRA_TMRUS_BASE
- ldr r1, [r7]
- add r1, r1, #3
-
-1: ldr r0, [r7]
- cmp r0, r1
- dmb
- bmi 1b
-
- /* switch to CLKS */
- mov r0, #0 /* burst policy = 32KHz */
- str r0, [r5, #CLK_RESET_SCLK_BURST]
-
- /* disable PLLP, PLLM, PLLC in LP0 and LP1 states */
- ldr r0, [r5, #CLK_RESET_PLLM_BASE]
- bic r0, r0, #(1 << 30)
- str r0, [r5, #CLK_RESET_PLLM_BASE]
- ldr r0, [r5, #CLK_RESET_PLLP_BASE]
- bic r0, r0, #(1 << 30)
- str r0, [r5, #CLK_RESET_PLLP_BASE]
- ldr r0, [r5, #CLK_RESET_PLLC_BASE]
- bic r0, r0, #(1 << 30)
- str r0, [r5, #CLK_RESET_PLLC_BASE]
- mov pc, lr
-
-/*
- * tegra_enter_sleep
- *
- * uses flow controller to enter sleep state
- * executes from IRAM with SDRAM in selfrefresh when target state is LP0 and LP1
- * executes from SDRAM with target state is LP2
- */
-tegra_enter_sleep:
- mov32 r7, TEGRA_TMRUS_BASE
- ldr r1, [r7]
- mov32 r4, TEGRA_PMC_BASE
- str r1, [r4, #PMC_SCRATCH38]
- dsb
- mov32 r6, TEGRA_FLOW_CTRL_BASE
-
- mov r0, #FLOW_CTRL_STOP_UNTIL_IRQ
- orr r0, r0, #FLOW_CTRL_IRQ_RESUME | FLOW_CTRL_FIQ_RESUME
- cpu_id r1
- cpu_to_halt_reg r1, r1
- str r0, [r6, r1]
- dsb
- ldr r0, [r6, r1] /* memory barrier */
-
-halted: dsb
- wfe /* CPU should be power gated here */
- isb
- b halted
-
-/*
- * tegra_lp1_reset
- *
- * reset vector for LP1 restore; copied into IRAM during suspend.
- * brings the system back up to a safe starting point (SDRAM out of
- * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
- * system clock running on the same PLL that it suspended at), and
- * jumps to tegra_lp2_startup to restore PLLX and virtual addressing.
- * physical address of tegra_lp2_startup expected to be stored in
- * PMC_SCRATCH41
- */
-ENTRY(tegra_lp1_reset)
- /*
- * the CPU and system bus are running at 32KHz and executing from
- * IRAM when this code is executed; immediately switch to CLKM and
- * enable PLLP.
- */
- mov32 r0, TEGRA_CLK_RESET_BASE
- mov r1, #(1 << 28)
- str r1, [r0, #CLK_RESET_SCLK_BURST]
- str r1, [r0, #CLK_RESET_CCLK_BURST]
- mov r1, #0
- str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
- str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
-
- ldr r1, [r0, #CLK_RESET_PLLM_BASE]
- tst r1, #(1 << 30)
- orreq r1, r1, #(1 << 30)
- streq r1, [r0, #CLK_RESET_PLLM_BASE]
- ldr r1, [r0, #CLK_RESET_PLLP_BASE]
- tst r1, #(1 << 30)
- orreq r1, r1, #(1 << 30)
- streq r1, [r0, #CLK_RESET_PLLP_BASE]
- ldr r1, [r0, #CLK_RESET_PLLC_BASE]
- tst r1, #(1 << 30)
- orreq r1, r1, #(1 << 30)
- streq r1, [r0, #CLK_RESET_PLLC_BASE]
-
- adr r2, tegra_sdram_pad_address
- adr r4, tegra_sdram_pad_save
- mov r5, #0
-
-padload:
- ldr r0, [r2, r5] @ r0 is emc register address
-
- ldr r1, [r4, r5]
- str r1, [r0] @ set emc register to safe vals
-
- add r5, r5, #4
- ldr r0, tegra_sdram_pad_size
- cmp r0, r5
- bne padload
-
-padload_done:
- mov32 r7, TEGRA_TMRUS_BASE
- ldr r1, [r7]
- add r1, r1, #0xff @ 255uS delay for PLL stabilization
-
-1: ldr r0, [r7]
- cmp r0, r1
- dmb
- bmi 1b
-
- adr r4, tegra_sclk_save
- ldr r4, [r4]
- mov32 r0, TEGRA_CLK_RESET_BASE
- str r4, [r0, #CLK_RESET_SCLK_BURST]
- ldr r4, =((1 << 28) | (4)) @ burst policy is PLLP
- str r4, [r0, #CLK_RESET_CCLK_BURST]
-
- mov32 r0, TEGRA_EMC_BASE
- ldr r1, [r0, #EMC_CFG]
- bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
- str r1, [r0, #EMC_CFG]
-
- mov r1, #0
- str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
- mov r1, #1
- str r1, [r0, #EMC_NOP]
- str r1, [r0, #EMC_NOP]
- str r1, [r0, #EMC_REFRESH]
-
- ldr r1, [r0, #EMC_ADR_CFG]
- tst r1, #(0x3 << 24)
- moveq r1, #(0x1 << 8) @ just 1 device
- movne r1, #(0x3 << 8) @ 2 devices
-
-exit_selfrefresh_loop:
- ldr r2, [r0, #EMC_EMC_STATUS]
- ands r2, r2, r1
- bne exit_selfrefresh_loop
-
- mov r1, #0
- str r1, [r0, #EMC_REQ_CTRL]
-
- mov32 r0, TEGRA_PMC_BASE
- ldr r0, [r0, #PMC_SCRATCH41]
- mov pc, r0
-ENDPROC(tegra_lp1_reset)
-
-/*
- * tegra_sdram_self_refresh
- *
- * called with MMU off and caches disabled
- * puts sdram in self refresh
- * must execute from IRAM
- */
-tegra_sdram_self_refresh:
- mov32 r1, TEGRA_EMC_BASE
- mov r2, #3
- str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
-
-emcidle:ldr r2, [r1, #EMC_EMC_STATUS]
- tst r2, #4
- beq emcidle
-
- mov r2, #1
- str r2, [r1, #EMC_SELF_REF]
-
- ldr r2, [r1, #EMC_ADR_CFG]
- tst r2, #(0x3 << 24)
- moveq r2, #(0x1 << 8) @ just 1 device
- movne r2, #(0x3 << 8) @ 2 devices
-
-emcself:ldr r3, [r1, #EMC_EMC_STATUS]
- and r3, r3, r2
- cmp r3, r2
- bne emcself @ loop until DDR in self-refresh
-
- adr r2, tegra_sdram_pad_address
- adr r3, tegra_sdram_pad_safe
- adr r4, tegra_sdram_pad_save
- mov r5, #0
-
-padsave:
- ldr r0, [r2, r5] @ r0 is emc register address
-
- ldr r1, [r0]
- str r1, [r4, r5] @ save emc register
-
- ldr r1, [r3, r5]
- str r1, [r0] @ set emc register to safe vals
-
- add r5, r5, #4
- ldr r0, tegra_sdram_pad_size
- cmp r0, r5
- bne padsave
-padsave_done:
-
- mov32 r5, TEGRA_CLK_RESET_BASE
- ldr r0, [r5, #CLK_RESET_SCLK_BURST]
- adr r2, tegra_sclk_save
- str r0, [r2]
- dsb
mov pc, lr
+ENDPROC(tegra_cpu_pllp)
-tegra_sdram_pad_address:
- .word TEGRA_APB_MISC_BASE + 0x8c8 /* XM2CFGCPADCTRL */
- .word TEGRA_APB_MISC_BASE + 0x8cc /* XM2CFGDPADCTRL */
- .word TEGRA_APB_MISC_BASE + 0x8d0 /* XM2CLKCFGPADCTRL */
- .word TEGRA_APB_MISC_BASE + 0x8d4 /* XM2COMPPADCTRL */
- .word TEGRA_APB_MISC_BASE + 0x8d8 /* XM2VTTGENPADCTRL */
- .word TEGRA_APB_MISC_BASE + 0x8e4 /* XM2CFGCPADCTRL2 */
- .word TEGRA_APB_MISC_BASE + 0x8e8 /* XM2CFGDPADCTRL2 */
-
-tegra_sdram_pad_size:
- .word tegra_sdram_pad_size - tegra_sdram_pad_address
-
-tegra_sdram_pad_safe:
- .word 0x8
- .word 0x8
- .word 0x0
- .word 0x8
- .word 0x5500
- .word 0x08080040
- .word 0x0
-
-tegra_sclk_save:
- .word 0x0
-
-tegra_sdram_pad_save:
- .word 0
- .word 0
- .word 0
- .word 0
- .word 0
- .word 0
- .word 0
-
- .ltorg
-/* dummy symbol for end of IRAM */
- .align L1_CACHE_SHIFT
- .globl tegra_iram_end
-tegra_iram_end:
- b .