diff options
author | Prashant Malani <pmalani@nvidia.com> | 2012-11-01 11:50:57 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 12:59:01 -0700 |
commit | 87ab5f7626913409ffd0f41100de7dc6e1d2b9cc (patch) | |
tree | 20906e0ea3615fee8f4381584aeede743161ab1e /arch/arm/mach-tegra/sleep-t30.S | |
parent | cd66120f98823789d0ccc4cfebc16eba5201d23d (diff) |
ARM: tegra14x: add BB checking in pm code
Add condition checks to query IPC registers
and conditionally branch to LP0 or LP1BB.
Bug 1160000
Change-Id: I3a7e151a5523a338cef7e83302af460e12323c14
Signed-off-by: Prashant Malani <pmalani@nvidia.com>
Reviewed-on: http://git-master/r/195637
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bo Yan <byan@nvidia.com>
Tested-by: Seshendra Gadagottu <sgadagottu@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Seshendra Gadagottu <sgadagottu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/sleep-t30.S')
-rw-r--r-- | arch/arm/mach-tegra/sleep-t30.S | 143 |
1 files changed, 140 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-t30.S index 38017e5a3302..aed80d4efdd4 100644 --- a/arch/arm/mach-tegra/sleep-t30.S +++ b/arch/arm/mach-tegra/sleep-t30.S @@ -107,6 +107,8 @@ #define MSELECT_CLKM (0x3 << 30) +#define TEGRA_RTC_MSEC 0x10 + #if USE_PLL_LOCK_BITS #define LOCK_DELAY PLL_POST_LOCK_DELAY #else @@ -701,18 +703,151 @@ lp1_register_core_highvolt: .word 0 #endif -/* - * tegra3_tear_down_core +/* tegra3_tear_down_core + * + * LP0 entry check conditions w.r.t BB take place here + */ +tegra3_tear_down_core: +#if defined(CONFIG_ARCH_TEGRA_14x_SOC) + /* Checking for BB-idle or Paging case */ + ldr r0, [r4, #PMC_IPC_STS] + ldr r3, [r4, #PMC_SCRATCH37] + + tst r0, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON + moveq r0, #0 + beq tegra148_lp0_entry + andnes r3, r3, #TEGRA_POWER_LP1_AUDIO + bne lp1bb_entry + +/* lp0_delayed_entry + * + * If BB has a paging request, a 30msec timeout has to be done before the + * PMC_IPC_STS register is queried again + */ +lp0_delayed_entry: + /* Use RTC MS timer + */ + mov32 r8, TEGRA_RTC_BASE + ldr r0, [r8, #TEGRA_RTC_MSEC] + add r0, r0, #30 +timer_loop: + ldr r1, [r8, #TEGRA_RTC_MSEC] + subs r1,r1, r0 + ble timer_loop + ldr r0, [r4, #PMC_IPC_STS] + tst r0, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON + moveq r0, #1 + bne lp1bb_entry + +/* R0 contains info whether delay timeout has already taken place or not */ +tegra148_lp0_entry: + + /* Write PMC_IPC_CLR[mem_sts] = 1 */ + ldr r1, [r4, #PMC_IPC_CLR] + orr r1, r1, #PMC_IPC_CLR_MEM_STS + str r1, [r4, #PMC_IPC_CLR] + + /* Check PMC_IPC_STS[mem_req] and PMC_IPC_STS[mem_req_soon] + * once again. If both 0 then go to LP0 entry + */ + ldr r3, [r4, #PMC_IPC_STS] + tst r3, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON + beq tegra3_lp0_tear_down_core + + /* Check if delay has happened. If yes, then set PMC_IPC_SET[mem_sts] + * and then go to LP1BB, else go to delay */ + cmp r0, #1 + bne lp0_delayed_entry + ldr r1, [r4, #PMC_IPC_SET] + orr r1, r1, #PMC_IPC_SET_MEM_STS + str r1, [r4, #PMC_IPC_SET] + b lp1bb_entry + + +/* lp1bb_entry + * Set up mem_req active low to be a wake event. + * Configure the EVP reset vector. + * Set up LIC to accept pmc wake events as interrupts. + * Clear previously set warmboot and side_effect bits + * Invoke remaining LP routines. + */ +lp1bb_entry: + + /* Clear the PMC_CTRL2_WAKE_DET_EN bit */ + ldr r0, [r4, #PMC_CTRL2] + bic r0, r0, #PMC_CTRL2_WAKE_DET_EN + str r0, [r4, #PMC_CTRL2] + + /* Program the wake_level2 registers */ + ldr r0, [r4, #PMC_WAKE2_LEVEL] + bic r0, r0, #PMC_WAKE2_BB_MEM_REQ + str r0, [r4, #PMC_WAKE2_LEVEL] + + /* Wait for a few ticks for this to stabilize */ + ldr r0, =0x300 +wait_stable: + subs r0, r0, #1 + bne wait_stable + + /* Program the auto_wake_lvl regsiters */ + ldr r0, [r4, #PMC_AUTO_WAKE_LVL] + orr r0, r0, #1 + str r0, [r4, #PMC_AUTO_WAKE_LVL] + + ldr r0, =0x300 +wait_stable2: + subs r0, r0, #1 + bne wait_stable2 + + /* Configure mem_req active low to be wake event */ + ldr r0, [r4, #PMC_WAKE2_MASK] + orr r0, r0, #PMC_WAKE2_BB_MEM_REQ + str r0, [r4, #PMC_WAKE2_MASK] + + ldr r0, [r4, #PMC_CTRL2] + orr r0, r0, #PMC_CTRL2_WAKE_DET_EN + str r0, [r4, #PMC_CTRL2] + + /* Configure the EVP reset vector */ + ldr r0, [r4, #PMC_SCRATCH41] + ldr r8, =TEGRA_EXCEPTION_VECTORS_BASE + str r0, [r8, #0x100] + + /* Set up the LIC to accept pmc_wake events as interrupts */ + ldr r8, =TEGRA_TERTIARY_ICTLR_BASE + ldr r0, =TRI_ICTLR_PMC_WAKE_INT + str r0, [r8, #TRI_ICTLR_CPU_IER_SET] + + bl tegra148_lp1bb_clear_warmboot_flag + bl tegra3_cpu_clk32k + b tegra3_enter_sleep +#endif + +/* tegra3_lp0_tear_down_core * * copied into and executed from IRAM * puts memory in self-refresh for LP0 and LP1 */ -tegra3_tear_down_core: +tegra3_lp0_tear_down_core: bl tegra3_sdram_self_refresh bl tegra3_cpu_clk32k b tegra3_enter_sleep /* + * tegra148_lp1bb_clear_warmboot_flag + * Clears warmboot0 flag, and clears SIDE_EFFECT_BIT. + * Called by lp1bb_entry. + */ +tegra148_lp1bb_clear_warmboot_flag: + ldr r0, [r4, #PMC_SCRATCH0] + bic r0, r0, #1 + str r0, [r4, #PMC_SCRATCH0] + ldr r0, [r4, #PMC_CTRL] + bic r0, r0, #PMC_CTRL_SIDE_EFFECT_LP0 + str r0, [r4, #PMC_CTRL] + mov pc, lr + +/* * tegra3_cpu_clk32k * * In LP0 and LP1 all plls will be turned off. Switch the CPU and system clock @@ -830,10 +965,12 @@ lp1_volt_skip: add r1, r1, #2 wait_until r1, r7, r9 +#if !defined(CONFIG_ARCH_TEGRA_14x_SOC) /* disable PLLM via PMC in LP1 */ ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE] bic r0, r0, #(1 << 12) str r0, [r4, #PMC_PLLP_WB0_OVERRIDE] +#endif b powerdown_pll_pcx powerdown_pll_pcx: |