diff options
author | Scott Williams <scwilliams@nvidia.com> | 2011-02-11 14:37:19 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:42:21 -0800 |
commit | a78b6e4de0623337c26447bf045084217af426eb (patch) | |
tree | a874497bfe8f3057dc7bf5cc3f338b41fe27c6a7 /arch | |
parent | 41d47bdeca1b9eb34fd89fbe875bdab9208fb00c (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.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-tegra/platsmp.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm-t3.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.h | 36 | ||||
-rw-r--r-- | arch/arm/mach-tegra/sysfs-cluster.c | 3 |
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; |