summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/sleep-t30.S
diff options
context:
space:
mode:
authorPrashant Malani <pmalani@nvidia.com>2012-11-01 11:50:57 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:59:01 -0700
commit87ab5f7626913409ffd0f41100de7dc6e1d2b9cc (patch)
tree20906e0ea3615fee8f4381584aeede743161ab1e /arch/arm/mach-tegra/sleep-t30.S
parentcd66120f98823789d0ccc4cfebc16eba5201d23d (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.S143
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: