summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/platsmp.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-02-11 18:17:28 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:42:21 -0800
commit2cb26eeefc5f4ce61046451a62eaf2ef68bf99b0 (patch)
tree788441ff869e285d346f395474cac949d80dea63 /arch/arm/mach-tegra/platsmp.c
parente7a52cfec6f819c7c8255f13c9665f1fd5a0e935 (diff)
ARM: tegra: Update secondary CPU power up procedure
- Wait for power up status confirmation after secondary CPU was un-gated by flow controller (instead of directly UN-gating CPU again if the 1st status check failed). - Enable CPU clock only after power up is confirmed. - Insert propagation delays before and after removing clamps. Original-Change-Id: I81cd1479bdb49163eeb9a369fc165cede49eb71a Reviewed-on: http://git-master/r/19372 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Original-Change-Id: I061738a5c5f46299cccfcb264d9b5bd838694305 Rebase-Id: R8f3d1364c016aaf4d9856add97612dc7ac77aa6e
Diffstat (limited to 'arch/arm/mach-tegra/platsmp.c')
-rw-r--r--arch/arm/mach-tegra/platsmp.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1f91d4d08584..e903da701bfb 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -76,7 +76,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
int boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- u32 reg;
int status;
if (is_lp_cluster()) {
@@ -113,16 +112,20 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle)
is now driving reset. */
flowctrl_writel(0, FLOW_CTRL_HALT_CPU(cpu));
- /* enable cpu clock on cpu */
- reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
- writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
- dmb();
-
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ {
+ /* enable cpu clock on cpu */
+ u32 reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+ writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+ dmb();
+ }
+#endif
status = power_up_cpu(cpu);
if (status)
goto done;
dmb();
+ udelay(10); /* power up delay */
writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
done:
@@ -168,11 +171,24 @@ static bool is_cpu_powered(unsigned int cpu)
static int power_up_cpu(unsigned int cpu)
{
int ret;
+ u32 reg;
unsigned long timeout;
BUG_ON(cpu == smp_processor_id());
BUG_ON(is_lp_cluster());
+ /* This function is entered after CPU has been already un-gated by
+ flow controller. Wait for confirmation that cpu is powered and
+ remove clamps. */
+ timeout = jiffies + HZ;
+ do {
+ if (is_cpu_powered(cpu))
+ goto remove_clamps;
+ udelay(10);
+ } while (time_before(jiffies, timeout));
+
+ /* Flow controller did not work as expected - try directly toggle
+ power gates. Bail out if direct power on also failed */
if (!is_cpu_powered(cpu))
{
ret = tegra_powergate_power_on(TEGRA_CPU_POWERGATE_ID(cpu));
@@ -192,6 +208,13 @@ static int power_up_cpu(unsigned int cpu)
}
remove_clamps:
+ /* now CPU is up: enable clock, propagate reset, and remove clamps */
+ reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+ writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+ barrier();
+ reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+
+ udelay(10);
ret = tegra_powergate_remove_clamping(TEGRA_CPU_POWERGATE_ID(cpu));
fail:
return ret;