aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2013-01-03 02:31:31 -0500
committerStephen Warren <swarren@nvidia.com>2013-01-28 12:21:41 -0500
commit130bfed72c75a36c76ecc82d73818c6fccd2a468 (patch)
tree3f193d9e84f0520c649372e152ac00c58cbd6b63 /arch/arm/mach-tegra
parentc26cefd08990e3a393cc1592efc3f097f608015f (diff)
ARM: tegra30: fix power up sequence for boot_secondary
The power up sequence is different on the cold boot CPU and the CPU that resumed from the hotplug. For the cold boot CPU, it was been power gated as default. To power up the cold boot CPU, the power should be un-gated by un toggling the power gate register manually. For the CPU that resumed from the hotplug, after un-halted the CPU. The flow controller will un-gate the power of the CPU. No need to manually control, just wait the power be resumed and continue the power up sequence after the CPU power is ready. Based on the work by: Varun Wadekar <vwadekar@nvidia.com> Signed-off-by: Joseph Lo <josephl@nvidia.com> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/platsmp.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1b926df99c4b..40f8c37c8178 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -23,6 +23,7 @@
23#include <asm/hardware/gic.h> 23#include <asm/hardware/gic.h>
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25#include <asm/smp_scu.h> 25#include <asm/smp_scu.h>
26#include <asm/smp_plat.h>
26 27
27#include <mach/powergate.h> 28#include <mach/powergate.h>
28 29
@@ -36,6 +37,7 @@
36 37
37extern void tegra_secondary_startup(void); 38extern void tegra_secondary_startup(void);
38 39
40static cpumask_t tegra_cpu_init_mask;
39static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); 41static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
40 42
41#define EVP_CPU_RESET_VECTOR \ 43#define EVP_CPU_RESET_VECTOR \
@@ -50,6 +52,7 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)
50 */ 52 */
51 gic_secondary_init(0); 53 gic_secondary_init(0);
52 54
55 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
53} 56}
54 57
55static int tegra20_power_up_cpu(unsigned int cpu) 58static int tegra20_power_up_cpu(unsigned int cpu)
@@ -72,7 +75,35 @@ static int tegra30_power_up_cpu(unsigned int cpu)
72 if (pwrgateid < 0) 75 if (pwrgateid < 0)
73 return pwrgateid; 76 return pwrgateid;
74 77
75 /* If this is the first boot, toggle powergates directly. */ 78 /*
79 * The power up sequence of cold boot CPU and warm boot CPU
80 * was different.
81 *
82 * For warm boot CPU that was resumed from CPU hotplug, the
83 * power will be resumed automatically after un-halting the
84 * flow controller of the warm boot CPU. We need to wait for
85 * the confirmaiton that the CPU is powered then removing
86 * the IO clamps.
87 * For cold boot CPU, do not wait. After the cold boot CPU be
88 * booted, it will run to tegra_secondary_init() and set
89 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
90 * next time around.
91 */
92 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
93 timeout = jiffies + 5*HZ;
94 do {
95 if (!tegra_powergate_is_powered(pwrgateid))
96 goto remove_clamps;
97 udelay(10);
98 } while (time_before(jiffies, timeout));
99 }
100
101 /*
102 * The power status of the cold boot CPU is power gated as
103 * default. To power up the cold boot CPU, the power should
104 * be un-gated by un-toggling the power gate register
105 * manually.
106 */
76 if (!tegra_powergate_is_powered(pwrgateid)) { 107 if (!tegra_powergate_is_powered(pwrgateid)) {
77 ret = tegra_powergate_power_on(pwrgateid); 108 ret = tegra_powergate_power_on(pwrgateid);
78 if (ret) 109 if (ret)
@@ -87,6 +118,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
87 } 118 }
88 } 119 }
89 120
121remove_clamps:
90 /* CPU partition is powered. Enable the CPU clock. */ 122 /* CPU partition is powered. Enable the CPU clock. */
91 tegra_enable_cpu_clock(cpu); 123 tegra_enable_cpu_clock(cpu);
92 udelay(10); 124 udelay(10);
@@ -105,6 +137,8 @@ static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *
105{ 137{
106 int status; 138 int status;
107 139
140 cpu = cpu_logical_map(cpu);
141
108 /* 142 /*
109 * Force the CPU into reset. The CPU must remain in reset when the 143 * Force the CPU into reset. The CPU must remain in reset when the
110 * flow controller state is cleared (which will cause the flow 144 * flow controller state is cleared (which will cause the flow
@@ -165,6 +199,9 @@ static void __init tegra_smp_init_cpus(void)
165 199
166static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) 200static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
167{ 201{
202 /* Always mark the boot CPU (CPU0) as initialized. */
203 cpumask_set_cpu(0, &tegra_cpu_init_mask);
204
168 tegra_cpu_reset_handler_init(); 205 tegra_cpu_reset_handler_init();
169 scu_enable(scu_base); 206 scu_enable(scu_base);
170} 207}