ARM: tegra11: CPU rail power up sequence
Bo Yan [Mon, 7 May 2012 21:24:20 +0000 (14:24 -0700)]
It is necessary to disable RAM repair bypass when CPU rail is
powered up.  This needs to be done even in case of HW controlled
CPU rail power-on.

This change also enables cluster switch to use "power_gate" flag
defined in sysfs to control the power gating mode. For LP0 entry
case, rail-gating is set to default.

Set default power gating mode for cluster switch to rail gating.
For chips that doesn't support symmetric power gating, "0" is
the default value which will trigger rail-gating.

Change-Id: Ia7ccb023118bbfba4fa53dc263bdfda59e29f089
Signed-off-by: Bo Yan <byan@nvidia.com>
Reviewed-on: http://git-master/r/101045
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

Rebase-Id: R50b64bfc236a664028edc822219af0d30d1af043

arch/arm/mach-tegra/pm-t3.c
arch/arm/mach-tegra/pm.h
arch/arm/mach-tegra/sleep.h
arch/arm/mach-tegra/sysfs-cluster.c
arch/arm/mach-tegra/tegra11_clocks.c

index 595e405..700ab96 100644 (file)
@@ -211,6 +211,14 @@ void tegra_cluster_switch_prolog(unsigned int flags)
        if (!target_cluster)
                goto done;
 
+#if defined(CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE)
+       reg &= ~FLOW_CTRL_CPU_CSR_ENABLE_EXT_MASK;
+       if (flags & TEGRA_POWER_CLUSTER_PART_CRAIL)
+               reg |= FLOW_CTRL_CPU_CSR_ENABLE_EXT_CRAIL;
+       if (flags & TEGRA_POWER_CLUSTER_PART_NONCPU)
+               reg |= FLOW_CTRL_CPU_CSR_ENABLE_EXT_NCPU;
+#endif
+
        if ((current_cluster != target_cluster) ||
                (flags & TEGRA_POWER_CLUSTER_FORCE)) {
                if (current_cluster != target_cluster) {
@@ -296,6 +304,9 @@ void tegra_cluster_switch_epilog(unsigned int flags)
        reg = readl(FLOW_CTRL_CPU_CSR(0));
        reg &= ~(FLOW_CTRL_CPU_CSR_IMMEDIATE_WAKE |
                 FLOW_CTRL_CPU_CSR_SWITCH_CLUSTER);
+#if defined(CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE)
+       reg &= ~FLOW_CTRL_CPU_CSR_ENABLE_EXT_MASK;
+#endif
        writel(reg, FLOW_CTRL_CPU_CSR(0));
 
        /* Perform post-switch LP=>G clean-up */
@@ -359,10 +370,22 @@ int tegra_cluster_control(unsigned int us, unsigned int flags)
                if (target_cluster == TEGRA_POWER_CLUSTER_G) {
                        s64 t = ktime_to_us(ktime_sub(now, last_g2lp));
                        s64 t_off = tegra_cpu_power_off_time();
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+                       u32 reg;
+#endif
                        if (t_off > t)
                                udelay((unsigned int)(t_off - t));
 
                        tegra_dvfs_rail_on(tegra_cpu_rail, now);
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+                       reg = readl(FLOW_CTRL_RAM_REPAIR);
+                       reg &= ~FLOW_CTRL_RAM_REPAIR_BYPASS_EN;
+                       writel(reg, FLOW_CTRL_RAM_REPAIR);
+                       /* power up C rail */
+                       reg = readl(FLOW_CTRL_CPU_PWR_CSR);
+                       reg |= FLOW_CTRL_CPU_PWR_CSR_RAIL_ENABLE;
+                       writel(reg, FLOW_CTRL_CPU_PWR_CSR);
+#endif
 
                } else {
                        last_g2lp = now;
@@ -428,6 +451,9 @@ void tegra_lp0_cpu_mode(bool enter)
        if (entered_on_g) {
                flags = enter ? TEGRA_POWER_CLUSTER_LP : TEGRA_POWER_CLUSTER_G;
                flags |= TEGRA_POWER_CLUSTER_IMMEDIATE;
+#if defined(CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE)
+               flags |= TEGRA_POWER_CLUSTER_PART_DEFAULT;
+#endif
                tegra_cluster_control(0, flags);
                pr_info("Tegra: switched to %s cluster\n", enter ? "LP" : "G");
        }
index fe685d4..a5b7ce7 100644 (file)
@@ -84,9 +84,22 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags);
 
 #define FLOW_CTRL_CLUSTER_CONTROL \
        (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x2c)
+#define FLOW_CTRL_CPU_CSR_ENABLE_EXT_CRAIL     (1<<13)
+#define FLOW_CTRL_CPU_CSR_ENABLE_EXT_NCPU      (1<<12)
+#define FLOW_CTRL_CPU_CSR_ENABLE_EXT_MASK      ( \
+       FLOW_CTRL_CPU_CSR_ENABLE_EXT_NCPU | \
+       FLOW_CTRL_CPU_CSR_ENABLE_EXT_CRAIL )
 #define FLOW_CTRL_CPU_CSR_IMMEDIATE_WAKE       (1<<3)
 #define FLOW_CTRL_CPU_CSR_SWITCH_CLUSTER       (1<<2)
 
+#define FLOW_CTRL_CPU_PWR_CSR \
+       (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x38)
+#define FLOW_CTRL_CPU_PWR_CSR_RAIL_ENABLE      1
+
+#define FLOW_CTRL_RAM_REPAIR \
+       (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x40)
+#define FLOW_CTRL_RAM_REPAIR_BYPASS_EN (1<<2)
+
 #define FUSE_SKU_DIRECT_CONFIG \
        (IO_ADDRESS(TEGRA_FUSE_BASE) + 0x1F4)
 #define FUSE_SKU_DISABLE_ALL_CPUS      (1<<5)
index 3a9d6f6..757c4d4 100644 (file)
@@ -34,6 +34,9 @@
 #define TEGRA_POWER_CLUSTER_PART_NONCPU        (1 << 25) /* Power gate CxNC partition */
 #define TEGRA_POWER_CLUSTER_PART_MASK  (TEGRA_POWER_CLUSTER_PART_CRAIL | \
                                                TEGRA_POWER_CLUSTER_PART_NONCPU)
+#define TEGRA_POWER_CLUSTER_PART_DEFAULT TEGRA_POWER_CLUSTER_PART_CRAIL
+#else
+#define TEGRA_POWER_CLUSTER_PART_DEFAULT 0
 #endif
 
 #define TEGRA_POWER_SDRAM_SELFREFRESH  (1 << 26) /* SDRAM is in self-refresh */
index 38accd5..c72b9b5 100644 (file)
@@ -66,7 +66,7 @@
  * power_gate: additional power gate partitions
  *             write:  'none' = no additional partitions
  *                     'noncpu' = CxNC partition
- *                     'crail' = CRAIL partition (implies noncpu also)
+ *                     'crail' = CRAIL partition (implies noncpu also, default)
  *             read: returns the current power_gate value
  *
  * Writing the force, immediate and wake_ms attributes simply updates the
@@ -149,7 +149,7 @@ static struct kobj_attribute cluster_powermode_attr =
 
 #ifdef CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE
 /* Additional partitions to power gate. */
-static unsigned int power_gate;
+static unsigned int power_gate = TEGRA_POWER_CLUSTER_PART_CRAIL;
 static struct kobj_attribute cluster_powergate_attr =
                __ATTR(power_gate, 0640, sysfscluster_show, sysfscluster_store);
 
index 3e1f45d..ad1d2fb 100644 (file)
@@ -1148,6 +1148,7 @@ static int tegra11_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
                        return -ECANCELED;
                }
                flags = TEGRA_POWER_CLUSTER_IMMEDIATE;
+               flags |= TEGRA_POWER_CLUSTER_PART_DEFAULT;
                delay = 0;
        }
        flags |= (p->u.cpu.mode == MODE_LP) ? TEGRA_POWER_CLUSTER_LP :