diff options
author | Colin Cross <ccross@android.com> | 2011-04-03 00:57:28 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:34:22 -0800 |
commit | a1c4cc2df7fc4f286763514de76a2b5396a4c58e (patch) | |
tree | 8120f8b50b2233d5f00520a879f01a8d10f5805e /arch/arm/mach-tegra/hotplug.c | |
parent | c00ce39eeac1324289f2e849409e78c739917bc0 (diff) |
ARM: tegra: add hotplug support
Hotplug uses the same CPU wfi code as cpuidle to put either cpu
into a slightly lower power mode (clock gated, but still powered).
If the remaining cpu enters LP2, the hotplugged cpu will be power
gated until the remaining cpu is active.
Change-Id: Ib7428709043415dc759136cf91668f6f63fe5a5c
Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/mach-tegra/hotplug.c')
-rw-r--r-- | arch/arm/mach-tegra/hotplug.c | 122 |
1 files changed, 33 insertions, 89 deletions
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c index f3294040d357..97d9746cee25 100644 --- a/arch/arm/mach-tegra/hotplug.c +++ b/arch/arm/mach-tegra/hotplug.c @@ -1,119 +1,63 @@ /* - * linux/arch/arm/mach-realview/hotplug.c + * linux/arch/arm/mach-tegra/hotplug.c * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved + * Copyright (C) 2010 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/kernel.h> -#include <linux/errno.h> +#include <linux/io.h> #include <linux/smp.h> -#include <asm/cacheflush.h> +#include <asm/cpu_pm.h> -static inline void cpu_enter_lowpower(void) -{ - unsigned int v; +#include <mach/iomap.h> - flush_cache_all(); - asm volatile( - " mcr p15, 0, %1, c7, c5, 0\n" - " mcr p15, 0, %1, c7, c10, 4\n" - /* - * Turn off coherency - */ - " mrc p15, 0, %0, c1, c0, 1\n" - " bic %0, %0, #0x20\n" - " mcr p15, 0, %0, c1, c0, 1\n" - " mrc p15, 0, %0, c1, c0, 0\n" - " bic %0, %0, %2\n" - " mcr p15, 0, %0, c1, c0, 0\n" - : "=&r" (v) - : "r" (0), "Ir" (CR_C) - : "cc"); -} +#include "sleep.h" -static inline void cpu_leave_lowpower(void) -{ - unsigned int v; +#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \ + (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c) +#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \ + (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340) +#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \ + (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344) - asm volatile( - "mrc p15, 0, %0, c1, c0, 0\n" - " orr %0, %0, %1\n" - " mcr p15, 0, %0, c1, c0, 0\n" - " mrc p15, 0, %0, c1, c0, 1\n" - " orr %0, %0, #0x20\n" - " mcr p15, 0, %0, c1, c0, 1\n" - : "=&r" (v) - : "Ir" (CR_C) - : "cc"); -} - -static inline void platform_do_lowpower(unsigned int cpu, int *spurious) +int platform_cpu_kill(unsigned int cpu) { - /* - * there is no power-control hardware on this platform, so all - * we can do is put the core into WFI; this is safe as the calling - * code will have already disabled interrupts - */ - for (;;) { - /* - * here's the WFI - */ - asm(".word 0xe320f003\n" - : - : - : "memory", "cc"); + unsigned int reg; - /*if (pen_release == cpu) {*/ - /* - * OK, proper wakeup, we're done - */ - break; - /*}*/ + do { + reg = readl(CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + cpu_relax(); + } while (!(reg & (1<<cpu))); - /* - * Getting here, means that we have come out of WFI without - * having been woken up - this shouldn't happen - * - * Just note it happening - when we're woken, we can report - * its occurrence. - */ - (*spurious)++; - } -} + reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + writel(reg | (1<<(8+cpu)), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); -int platform_cpu_kill(unsigned int cpu) -{ return 1; } -/* - * platform-specific code to shutdown a CPU - * - * Called with IRQs disabled - */ void platform_cpu_die(unsigned int cpu) { - int spurious = 0; +#ifdef DEBUG + unsigned int this_cpu = hard_smp_processor_id(); - /* - * we're ready for shutdown now, so do it - */ - cpu_enter_lowpower(); - platform_do_lowpower(cpu, &spurious); + if (cpu != this_cpu) { + printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + this_cpu, cpu); + BUG(); + } +#endif + + tegra_sleep_reset(); /* - * bring this CPU back into the world of cache - * coherency, and then restore interrupts + * tegra_cpu_suspend can return through tegra_cpu_resume, but that + * should never happen for a hotplugged cpu */ - cpu_leave_lowpower(); - - if (spurious) - pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); + BUG(); } int platform_cpu_disable(unsigned int cpu) |