From a78b6e4de0623337c26447bf045084217af426eb Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Fri, 11 Feb 2011 14:37:19 -0800 Subject: 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 Reviewed-by: Aleksandr Frid Reviewed-by: Scott Williams Original-Change-Id: Id0a7e5ad62df4d1638518fe00715aac60e4efea9 Rebase-Id: Re39a0fedb7bb0e2518cfd56d46c6565d4a6c2ef4 --- arch/arm/mach-tegra/cpu-tegra3.c | 9 +++++++-- arch/arm/mach-tegra/platsmp.c | 6 +----- arch/arm/mach-tegra/pm-t3.c | 15 ++++----------- arch/arm/mach-tegra/pm.h | 36 ++++++++++++++++++++++++++++++------ arch/arm/mach-tegra/sysfs-cluster.c | 3 --- 5 files changed, 42 insertions(+), 27 deletions(-) (limited to 'arch') 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; -- cgit v1.2.3