diff options
author | Alex Frid <afrid@nvidia.com> | 2011-02-11 18:17:28 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:42:21 -0800 |
commit | 2cb26eeefc5f4ce61046451a62eaf2ef68bf99b0 (patch) | |
tree | 788441ff869e285d346f395474cac949d80dea63 /arch/arm/mach-tegra/platsmp.c | |
parent | e7a52cfec6f819c7c8255f13c9665f1fd5a0e935 (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.c | 35 |
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; |