ARM: tegra: power: Use CPU LP mode for Tegra3 deep sleep
Alex Frid [Fri, 13 May 2011 05:51:34 +0000 (22:51 -0700)]
Original-Change-Id: If23b48fb414332f5dd25307a098569a5474283c6
Reviewed-on: http://git-master/r/31471
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

Rebase-Id: R6ba9ce7c7b355da4148ce0ebc9bc357bf5fc0b13

arch/arm/mach-tegra/pm-t3.c
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.h

index 57cbc4c..acfa65d 100644 (file)
@@ -280,6 +280,7 @@ int tegra_cluster_control(unsigned int us, unsigned int flags)
        unsigned int current_cluster = is_lp_cluster()
                                        ? TEGRA_POWER_CLUSTER_LP
                                        : TEGRA_POWER_CLUSTER_G;
+       unsigned long irq_flags;
 
        if ((target_cluster == TEGRA_POWER_CLUSTER_MASK) || !target_cluster)
                return -EINVAL;
@@ -306,7 +307,7 @@ int tegra_cluster_control(unsigned int us, unsigned int flags)
                (flags & TEGRA_POWER_CLUSTER_FORCE) ? "force" : "",
                us));
 
-       local_irq_disable();
+       local_irq_save(irq_flags);
        if (flags & TEGRA_POWER_SDRAM_SELFREFRESH) {
                if (us)
                        tegra_lp2_set_trigger(us);
@@ -322,7 +323,7 @@ int tegra_cluster_control(unsigned int us, unsigned int flags)
                cpu_pm_exit();
                tegra_clear_cpu_in_lp2(0);
        }
-       local_irq_enable();
+       local_irq_restore(irq_flags);
 
        DEBUG_CLUSTER(("%s: %s\r\n", __func__, is_lp_cluster() ? "LP" : "G"));
 
@@ -348,4 +349,19 @@ void tegra_lp0_resume_mc(void)
        writel(mc_reserved_rsv, mc + MC_RESERVED_RSV);
        writel(mc_emem_arb_override, mc + MC_EMEM_ARB_OVERRIDE);
 }
+
+void tegra_lp0_cpu_mode(bool enter)
+{
+       static bool entered_on_g = false;
+       unsigned int flags;
+
+       if (enter)
+               entered_on_g = !is_lp_cluster();
+
+       if (entered_on_g) {
+               flags = enter ? TEGRA_POWER_CLUSTER_LP : TEGRA_POWER_CLUSTER_G;
+               flags |= TEGRA_POWER_CLUSTER_IMMEDIATE;
+               tegra_cluster_control(0, flags);
+       }
+}
 #endif
index d5115ad..3e14860 100644 (file)
@@ -738,8 +738,10 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode)
        cpu_pm_enter();
        cpu_cluster_pm_enter();
 
-       if (mode == TEGRA_SUSPEND_LP0)
+       if (mode == TEGRA_SUSPEND_LP0) {
+               tegra_lp0_cpu_mode(true);
                tegra_lp0_suspend_mc();
+       }
 
        suspend_cpu_complex(0);
        flush_cache_all();
@@ -753,8 +755,10 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode)
 
        tegra_init_cache();
 
-       if (mode == TEGRA_SUSPEND_LP0)
+       if (mode == TEGRA_SUSPEND_LP0) {
                tegra_lp0_resume_mc();
+               tegra_lp0_cpu_mode(false);
+       }
 
        restore_cpu_complex(0);
 
index e888538..0c6c55d 100644 (file)
@@ -103,6 +103,7 @@ void tegra_cluster_switch_prolog(unsigned int flags);
 void tegra_cluster_switch_epilog(unsigned int flags);
 void tegra_lp0_suspend_mc(void);
 void tegra_lp0_resume_mc(void);
+void tegra_lp0_cpu_mode(bool enter);
 #else
 static inline int tegra_cluster_control(unsigned int us, unsigned int flags)
 #define INSTRUMENT_CLUSTER_SWITCH 0    /* Must be zero for ARCH_TEGRA_2x_SOC */
@@ -115,6 +116,7 @@ static inline void tegra_cluster_switch_prolog(unsigned int flags) {}
 static inline void tegra_cluster_switch_epilog(unsigned int flags) {}
 static inline void tegra_lp0_suspend_mc(void) {}
 static inline void tegra_lp0_resume_mc(void) {}
+static inline void tegra_lp0_cpu_mode(bool enter) {}
 #endif
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC