ARM: tegra11: Select partitions for power gating
Bo Yan [Sat, 19 May 2012 02:47:34 +0000 (19:47 -0700)]
Select power gating partitions based on flag. With this change,
Rail-gating is used as the default power gating option for CPU0
on cluster 0, non-CPU gating is the default power gating option
for CPU0 on cluster 1.

Also fixed  power gating flags by using control macros instead of
CSR field macros.

Change-Id: I971a34cc01f0216314f4bdbafc9aa070ca0dd708
Signed-off-by: Bo Yan <byan@nvidia.com>
Reviewed-on: http://git-master/r/103477
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Seshendra Gadagottu <sgadagottu@nvidia.com>

Rebase-Id: R90ff171fb99007996ac159955095bed568960000

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

index d93bcfd..a027036 100644 (file)
@@ -205,6 +205,7 @@ static bool tegra3_idle_enter_lp2_cpu_0(struct cpuidle_device *dev,
        bool sleep_completed = false;
        bool multi_cpu_entry = false;
        int bin;
+       unsigned int flag = 0;
        s64 sleep_time;
 
        /* LP2 entry time */
@@ -286,7 +287,10 @@ static bool tegra3_idle_enter_lp2_cpu_0(struct cpuidle_device *dev,
                        tegra_clk_cfg_ex(dfll, TEGRA_CLK_DFLL_LOCK, 0);
        }
 
-       if (tegra_idle_lp2_last(sleep_time, 0) == 0)
+#if defined(CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE)
+       flag = get_power_gating_partition();
+#endif
+       if (tegra_idle_lp2_last(sleep_time, flag) == 0)
                sleep_completed = true;
        else {
                int irq = tegra_gic_pending_interrupt();
index f6b568e..fcae16c 100644 (file)
@@ -160,7 +160,7 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev,
 #define        POWER_GATING_OPTION_LEN 8
 static char power_gating_option[8] __read_mostly =
                                                                                        {'c', 'r', 'a', 'i', 'l', '\0'};
-static int power_gating_mode = FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+static int power_gating_mode = TEGRA_POWER_CLUSTER_PART_CRAIL;
 static struct kparam_string power_gating __read_mostly = {
        .maxlen = POWER_GATING_OPTION_LEN,
        .string = power_gating_option,
@@ -178,12 +178,12 @@ static int power_gating_set(const char *buffer, const struct kernel_param *kp)
        }
 
        if (!strncmp(buffer, "noncpu", 6))
-               mode = FLOW_CTRL_CSR_ENABLE_EXT_NCPU;
+               mode = TEGRA_POWER_CLUSTER_PART_NONCPU;
        else if (!strncmp(buffer, "crail", 5))
-               mode = FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+               mode = TEGRA_POWER_CLUSTER_PART_CRAIL;
        else if (!strncmp(buffer, "emu", 3))
-               mode = FLOW_CTRL_CSR_ENABLE_EXT_MASK;
-       else if (!strncmp(buffer, "cpu", 3))
+               mode = TEGRA_POWER_CLUSTER_PART_MASK;
+       else if (!strncmp(buffer, "none", 4))
                mode = 0;
 
        if (mode >= 0) {
index ef8ecd2..3492943 100644 (file)
@@ -518,20 +518,20 @@ static inline void tegra_sleep_cpu(unsigned long v2p)
 
 unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
 {
-       u32 mode;       /* hardware + software power mode flags */
+       u32 reg;
        unsigned int remain;
        pgd_t *pgd;
 
        /* Only the last cpu down does the final suspend steps */
-       mode = readl(pmc + PMC_CTRL);
-       mode |= TEGRA_POWER_CPU_PWRREQ_OE;
+       reg = readl(pmc + PMC_CTRL);
+       reg |= TEGRA_POWER_CPU_PWRREQ_OE;
        if (pdata->combined_req)
-               mode &= ~TEGRA_POWER_PWRREQ_OE;
+               reg &= ~TEGRA_POWER_PWRREQ_OE;
        else
-               mode |= TEGRA_POWER_PWRREQ_OE;
-       mode &= ~TEGRA_POWER_EFFECT_LP0;
-       writel(mode, pmc + PMC_CTRL);
-       mode |= flags;
+               reg |= TEGRA_POWER_PWRREQ_OE;
+
+       reg &= ~TEGRA_POWER_EFFECT_LP0;
+       writel(reg, pmc + PMC_CTRL);
 
        tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_start);
 
@@ -553,17 +553,36 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
                                writel(UN_PWRGATE_CPU,
                                       pmc + PMC_PWRGATE_TOGGLE);
                }
-               tegra_cluster_switch_prolog(mode);
+               tegra_cluster_switch_prolog(flags);
        } else {
                set_power_timers(pdata->cpu_timer, pdata->cpu_off_timer,
                        clk_get_rate_all_locked(tegra_pclk));
+#if defined(CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE)
+               reg = readl(FLOW_CTRL_CPU_CSR(0));
+               reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
+               if (is_lp_cluster()) {
+                       /* for LP cluster, there is no option for rail gating */
+                       if ((flags & TEGRA_POWER_CLUSTER_PART_MASK) ==
+                                               TEGRA_POWER_CLUSTER_PART_MASK)
+                               reg |= FLOW_CTRL_CSR_ENABLE_EXT_EMU;
+                       else if (flags)
+                               reg |= FLOW_CTRL_CSR_ENABLE_EXT_NCPU;
+               }
+               else {
+                       if (flags & TEGRA_POWER_CLUSTER_PART_CRAIL)
+                               reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+                       if (flags & TEGRA_POWER_CLUSTER_PART_NONCPU)
+                               reg |= FLOW_CTRL_CSR_ENABLE_EXT_NCPU;
+               }
+               writel(reg, FLOW_CTRL_CPU_CSR(0));
+#endif
        }
 
        if (sleep_time)
                tegra_lp2_set_trigger(sleep_time);
 
        cpu_cluster_pm_enter();
-       suspend_cpu_complex(mode);
+       suspend_cpu_complex(flags);
        tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_prolog);
        flush_cache_all();
        /*
@@ -580,7 +599,7 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
 
        tegra_init_cache(false);
        tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_switch);
-       restore_cpu_complex(mode);
+       restore_cpu_complex(flags);
        cpu_cluster_pm_exit();
 
        remain = tegra_lp2_timer_remain();
@@ -588,7 +607,7 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
                tegra_lp2_set_trigger(0);
 
        if (flags & TEGRA_POWER_CLUSTER_MASK) {
-               tegra_cluster_switch_epilog(mode);
+               tegra_cluster_switch_epilog(flags);
                trace_cpu_cluster(POWER_CPU_CLUSTER_DONE);
        }
        tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_epilog);