ARM: Tegra: Utilize burst policy for LP1 wakeup
Martin Chi [Thu, 12 Dec 2013 05:18:02 +0000 (13:18 +0800)]
Running SCLK from CLKS makes LP1 wakeup latencies horrible.
However, we can utilize IRQ bursting to switch automatically
to CLKM upon LP1 wakeup IRQ. This maintains low power for LP1
but improves wakeup latencies significantly.

Bug 1423099

Change-Id: I9231d736c5d330a1c36a38a4e2ad1d0b29a4c158
Signed-off-by: Martin Chi <mchi@nvidia.com>
Reviewed-on: http://git-master/r/344607
Reviewed-on: http://git-master/r/350636
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit

arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/sleep-t3.S

index 5bca895..e7056dd 100644 (file)
@@ -200,6 +200,7 @@ static struct pm_qos_request awake_cpu_freq_req;
 static struct clk *tegra_dfll;
 #endif
 static struct clk *tegra_pclk;
+static struct clk *tegra_clk_m;
 static const struct tegra_suspend_platform_data *pdata;
 static enum tegra_suspend_mode current_suspend_mode = TEGRA_SUSPEND_NONE;
 
@@ -890,6 +891,7 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
        case TEGRA_SUSPEND_LP1:
                __raw_writel(virt_to_phys(tegra_resume), pmc + PMC_SCRATCH41);
                wmb();
+               rate = clk_get_rate(tegra_clk_m);
                break;
        case TEGRA_SUSPEND_LP2:
                rate = clk_get_rate(tegra_pclk);
@@ -1278,6 +1280,8 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat)
 #endif
        tegra_pclk = clk_get_sys(NULL, "pclk");
        BUG_ON(IS_ERR(tegra_pclk));
+       tegra_clk_m = clk_get_sys(NULL, "clk_m");
+
        pdata = plat;
        (void)reg;
        (void)mode;
index 6eb6080..c1b02ca 100644 (file)
@@ -439,9 +439,10 @@ tegra3_iram_start:
 .endm
 
 ENTRY(tegra3_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, PLLM, PLLC, and PLLX. */
+       /* the CPU and system bus are running from CLKM and executing from
+       * IRAM when this code is executed
+       * switch all SCLK/CCLK clocks to CLKM and set non STDBY clock source
+       * enable PLLP, PLLM, PLLC, and PLLX. */
        mov32   r0, TEGRA_CLK_RESET_BASE
 #ifndef CONFIG_TRUSTED_FOUNDATIONS
        /* secure code handles 32KHz to CLKM/OSC clock switch */
@@ -761,8 +762,8 @@ tegra3_tear_down_core:
 /*
  * tegra3_cpu_clk32k
  *
- * In LP0 and LP1 all plls will be turned off.  Switch the CPU and system clock
- * to the 32khz clock (clks)
+ * In LP0 and LP1 all plls will be turned off. Switch the system clock
+ * to the 32khz clock (clks) and CPU to clkm.
  * r4 = TEGRA_PMC_BASE
  * r5 = TEGRA_CLK_RESET_BASE
  * r6 = TEGRA_FLOW_CTRL_BASE
@@ -863,6 +864,14 @@ powerdown_pll_cx:
         */
        pll_iddq_entry r1, r5, CLK_RESET_PLLX_MISC3, CLK_RESET_PLLX_MISC3_IDDQ
 #endif
+       /*
+       * Switch to STDBY clock (CLKS), bits 28:31 == 0
+       * Enable burst on CPU IRQ (bit 24)
+       * Set clock sources to CLKM (clock source 0)
+       */
+       mov     r0, #(1 << 24)
+       str     r0, [r5, #CLK_RESET_SCLK_BURST]
+       mov     pc, lr
 
        /* switch to CLKS */
        mov     r0, #0  /* burst policy = 32KHz */