ARM: tegra: power: Update CPU complex resume
Alex Frid [Thu, 29 Dec 2011 04:41:00 +0000 (20:41 -0800)]
- Completely removed PLLP restoration from CPU complex resume on
Tegra3 platforms (too late: if necessary PLLP is restored by LPx
exit code on Tegra3, and attempt to restore it again does not do
any good).

- Restored PLLX only if it is not already used as CPU source
(it is dangerous to restore PLL in use).

- Restore burst policy on exit from LPx states, but preserve it
after cluster switch, as it maybe different for LP and G clusters.

Reviewed-on: http://git-master/r/72535

Change-Id: Ia5ff24d22a2135494bc3442f92bebcc1953c7f08
Signed-off-by: Alex Frid <afrid@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/78702
Reviewed-by: Automatic_Commit_Validation_User

Rebase-Id: R6385ac062bf2b7ca6bf1fbe6f79d96de70f6b585

arch/arm/mach-tegra/pm.c

index df340ec..5856836 100644 (file)
@@ -158,6 +158,10 @@ struct suspend_context tegra_sctx;
 #define CLK_RESET_SOURCE_CSITE 0x1d4
 
 #define CLK_RESET_CCLK_BURST_POLICY_SHIFT 28
+#define CLK_RESET_CCLK_RUN_POLICY_SHIFT    4
+#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT   0
+#define CLK_RESET_CCLK_IDLE_POLICY        1
+#define CLK_RESET_CCLK_RUN_POLICY         2
 #define CLK_RESET_CCLK_BURST_POLICY_PLLM   3
 #define CLK_RESET_CCLK_BURST_POLICY_PLLX   8
 
@@ -359,44 +363,56 @@ static void set_power_timers(unsigned long us_on, unsigned long us_off,
 static void restore_cpu_complex(u32 mode)
 {
        int cpu = smp_processor_id();
-       unsigned int reg;
+       unsigned int reg, policy;
 
        BUG_ON(cpu != 0);
 
        /* restore original PLL settings */
-       writel(tegra_sctx.pllx_misc, clk_rst + CLK_RESET_PLLX_MISC);
-       writel(tegra_sctx.pllx_base, clk_rst + CLK_RESET_PLLX_BASE);
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
        writel(tegra_sctx.pllp_misc, clk_rst + CLK_RESET_PLLP_MISC);
        writel(tegra_sctx.pllp_base, clk_rst + CLK_RESET_PLLP_BASE);
+#endif
        writel(tegra_sctx.pllp_outa, clk_rst + CLK_RESET_PLLP_OUTA);
        writel(tegra_sctx.pllp_outb, clk_rst + CLK_RESET_PLLP_OUTB);
 
        /* Is CPU complex already running on PLLX? */
        reg = readl(clk_rst + CLK_RESET_CCLK_BURST);
-       reg &= 0xF;
-       if (reg != 0x8) {
-               /* restore original burst policy setting; PLLX state restored
-                * by CPU boot-up code - wait for PLL stabilization if PLLX
-                * was enabled */
+       policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF;
 
-               reg = readl(clk_rst + CLK_RESET_PLLX_BASE);
-               /* mask out bit 27 - not to check PLL lock bit */
-               BUG_ON((reg & (~(1 << 27))) !=
-                               (tegra_sctx.pllx_base & (~(1 << 27))));
+       if (policy == CLK_RESET_CCLK_IDLE_POLICY)
+               reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF;
+       else if (policy == CLK_RESET_CCLK_RUN_POLICY)
+               reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF;
+       else
+               BUG();
 
+       if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) {
+               /* restore PLLX settings if CPU is on different PLL */
+               writel(tegra_sctx.pllx_misc, clk_rst + CLK_RESET_PLLX_MISC);
+               writel(tegra_sctx.pllx_base, clk_rst + CLK_RESET_PLLX_BASE);
+
+               /* wait for PLL stabilization if PLLX was enabled */
                if (tegra_sctx.pllx_base & (1<<30)) {
 #if USE_PLL_LOCK_BITS
                        /* Enable lock detector */
                        reg = readl(clk_rst + CLK_RESET_PLLX_MISC);
                        reg |= 1<<18;
                        writel(reg, clk_rst + CLK_RESET_PLLX_MISC);
-                       while (!(readl(clk_rst + CLK_RESET_PLLX_BASE) &&
+                       while (!(readl(clk_rst + CLK_RESET_PLLX_BASE) &
                                 (1<<27)))
                                cpu_relax();
+
+                       udelay(PLL_POST_LOCK_DELAY);
 #else
                        udelay(300);
 #endif
                }
+       }
+
+       /* Restore original burst policy setting for calls resulting from CPU
+          LP2 in idle or system suspend; keep cluster switch prolog setting
+          intact. */
+       if (!(mode & TEGRA_POWER_CLUSTER_MASK)) {
                writel(tegra_sctx.cclk_divider, clk_rst +
                       CLK_RESET_CCLK_DIVIDER);
                writel(tegra_sctx.cpu_burst, clk_rst +