summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-02-11 14:37:19 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:42:21 -0800
commita78b6e4de0623337c26447bf045084217af426eb (patch)
treea874497bfe8f3057dc7bf5cc3f338b41fe27c6a7 /arch
parent41d47bdeca1b9eb34fd89fbe875bdab9208fb00c (diff)
arm: tegra: Fix initial boot to LP cluster
Forbid cluster switch to G cluster if the G cluster doesn't exist. Bug 791057 Original-Change-Id: I215de2581edf5fb3c1feaa00d1c6e0b52b15dc23 Reviewed-on: http://git-master/r/19302 Tested-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Original-Change-Id: Id0a7e5ad62df4d1638518fe00715aac60e4efea9 Rebase-Id: Re39a0fedb7bb0e2518cfd56d46c6565d4a6c2ef4
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/cpu-tegra3.c9
-rw-r--r--arch/arm/mach-tegra/platsmp.c6
-rw-r--r--arch/arm/mach-tegra/pm-t3.c15
-rw-r--r--arch/arm/mach-tegra/pm.h36
-rw-r--r--arch/arm/mach-tegra/sysfs-cluster.c3
5 files changed, 42 insertions, 27 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c
index ac5699599270..895f286daa4c 100644
--- a/arch/arm/mach-tegra/cpu-tegra3.c
+++ b/arch/arm/mach-tegra/cpu-tegra3.c
@@ -195,11 +195,15 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
void tegra_auto_hotplug_governor(unsigned int cpu_freq)
{
+ if (!is_g_cluster_present())
+ return;
+
mutex_lock(&tegra_hp_lock);
if (is_lp_cluster() && (cpu_freq > lpcpu_max_freq)) {
- tegra_cluster_control(0, TEGRA_POWER_CLUSTER_G |
- TEGRA_POWER_CLUSTER_IMMEDIATE);
+ if (tegra_cluster_control(0, TEGRA_POWER_CLUSTER_G |
+ TEGRA_POWER_CLUSTER_IMMEDIATE))
+ goto fail;
hp_stats_update(CONFIG_NR_CPUS, false);
hp_stats_update(0, true);
}
@@ -241,6 +245,7 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq)
__func__, hp_state);
BUG();
}
+fail:
mutex_unlock(&tegra_hp_lock);
}
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 55b06b91a199..1f91d4d08584 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -63,10 +63,6 @@ static int power_up_cpu(unsigned int cpu);
#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS \
(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x470)
-#define FUSE_SKU_DIRECT_CONFIG \
- (IO_ADDRESS(TEGRA_FUSE_BASE) + 0x1F4)
-#define FUSE_SKU_DISABLE_ALL_CPUS (1<<5)
-#define FUSE_SKU_NUM_DISABLED_CPUS(x) (((x) >> 3) & 3)
#endif
extern void tegra_secondary_startup(void);
@@ -159,7 +155,7 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
scu_enable(scu_base);
}
-#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
static bool is_cpu_powered(unsigned int cpu)
{
diff --git a/arch/arm/mach-tegra/pm-t3.c b/arch/arm/mach-tegra/pm-t3.c
index 1ce95412dc2b..c005e67ba370 100644
--- a/arch/arm/mach-tegra/pm-t3.c
+++ b/arch/arm/mach-tegra/pm-t3.c
@@ -84,20 +84,9 @@
#define CPU_CLOCK(cpu) (0x1<<(8+cpu))
#define CPU_RESET(cpu) (0x1111ul<<(cpu))
-#define FLOW_CTRL_CLUSTER_CONTROL \
- (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x2c)
-#define FLOW_CTRL_CPU_CSR_IMMEDIATE_WAKE (1<<3)
-#define FLOW_CTRL_CPU_CSR_SWITCH_CLUSTER (1<<2)
void tegra_suspend_dram(bool lp0_ok, unsigned int flags);
-unsigned int is_lp_cluster(void)
-{
- unsigned int reg;
- reg = readl(FLOW_CTRL_CLUSTER_CONTROL);
- return (reg & 1); /* 0 == G, 1 == LP*/
-}
-
static int cluster_switch_prolog_clock(unsigned int flags)
{
u32 reg;
@@ -314,6 +303,10 @@ int tegra_cluster_control(unsigned int us, unsigned int flags)
&& !(flags & TEGRA_POWER_CLUSTER_FORCE))
return -EEXIST;
+ if (target_cluster == TEGRA_POWER_CLUSTER_G)
+ if (!is_g_cluster_present())
+ return -EPERM;
+
if (flags & TEGRA_POWER_CLUSTER_IMMEDIATE)
us = 0;
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index f5293ea8a85b..e39fda078280 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -50,6 +50,21 @@ unsigned long tegra_cpu_power_off_time(void);
#define TEGRA_POWER_CLUSTER_IMMEDIATE 0x4000 /* Immediate wake */
#define TEGRA_POWER_CLUSTER_FORCE 0x8000 /* Force switch */
+#define FLOW_CTRL_HALT_CPU(cpu) (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + \
+ ((cpu) == 0 ? 0x8 : (0x18 + 8 * ((cpu) - 1))))
+#define FLOW_CTRL_CPU_CSR(cpu) (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + \
+ ((cpu) == 0 ? 0x0 : (0x4 + cpu * 0x10)))
+
+#define FLOW_CTRL_CLUSTER_CONTROL \
+ (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x2c)
+#define FLOW_CTRL_CPU_CSR_IMMEDIATE_WAKE (1<<3)
+#define FLOW_CTRL_CPU_CSR_SWITCH_CLUSTER (1<<2)
+
+#define FUSE_SKU_DIRECT_CONFIG \
+ (IO_ADDRESS(TEGRA_FUSE_BASE) + 0x1F4)
+#define FUSE_SKU_DISABLE_ALL_CPUS (1<<5)
+#define FUSE_SKU_NUM_DISABLED_CPUS(x) (((x) >> 3) & 3)
+
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
void tegra2_lp0_suspend_init(void);
#else
@@ -89,6 +104,8 @@ static inline int tegra_cluster_control(unsigned int us, unsigned int flags)
{ return -EPERM; }
#define tegra_cluster_switch_prolog(flags) do {} while(0)
#define tegra_cluster_switch_epilog(flags) do {} while(0)
+static inline bool is_g_cluster_present(void)
+{ return true; }
static inline unsigned int is_lp_cluster(void)
{ return 0; }
static inline unsigned long tegra_get_lpcpu_max_rate(void)
@@ -99,7 +116,19 @@ static inline unsigned long tegra_get_lpcpu_max_rate(void)
int tegra_cluster_control(unsigned int us, unsigned int flags);
void tegra_cluster_switch_prolog(unsigned int flags);
void tegra_cluster_switch_epilog(unsigned int flags);
-unsigned int is_lp_cluster(void);
+static inline bool is_g_cluster_present(void)
+{
+ u32 fuse_sku = readl(FUSE_SKU_DIRECT_CONFIG);
+ if (fuse_sku & FUSE_SKU_DISABLE_ALL_CPUS)
+ return false;
+ return true;
+}
+static inline unsigned int is_lp_cluster(void)
+{
+ unsigned int reg;
+ reg = readl(FLOW_CTRL_CLUSTER_CONTROL);
+ return (reg & 1); /* 0 == G, 1 == LP*/
+}
unsigned long tegra_get_lpcpu_max_rate(void);
#endif
@@ -110,11 +139,6 @@ extern unsigned int tegra_cluster_debug;
#define DEBUG_CLUSTER(x) do { } while (0)
#endif
-#define FLOW_CTRL_HALT_CPU(cpu) (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + \
- ((cpu) == 0 ? 0x8 : (0x18 + 8 * ((cpu) - 1))))
-#define FLOW_CTRL_CPU_CSR(cpu) (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + \
- ((cpu) == 0 ? 0x0 : (0x4 + cpu * 0x10)))
-
static inline void flowctrl_writel(unsigned long val, void __iomem *addr)
{
writel(val, addr);
diff --git a/arch/arm/mach-tegra/sysfs-cluster.c b/arch/arm/mach-tegra/sysfs-cluster.c
index a16b09c3a236..eaded6c2fc70 100644
--- a/arch/arm/mach-tegra/sysfs-cluster.c
+++ b/arch/arm/mach-tegra/sysfs-cluster.c
@@ -104,9 +104,6 @@
#define PRINT_CLUSTER(x)
#endif
-#define FLOW_CTRL_CLUSTER_CONTROL \
- (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x2c)
-
static struct kobject *cluster_kobj;
static spinlock_t cluster_lock;
static unsigned int flags = 0;