aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/hotplug.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/hotplug.c')
-rw-r--r--arch/arm/mach-tegra/hotplug.c140
1 files changed, 31 insertions, 109 deletions
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index 8e7f115aa21..ff26af26bd0 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,100 +1,32 @@
/*
- * linux/arch/arm/mach-realview/hotplug.c
- *
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
+ * Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.
*
* 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/smp.h>
-#include <linux/completion.h>
-
-#include <asm/cacheflush.h>
+#include <linux/clk/tegra.h>
-static DECLARE_COMPLETION(cpu_killed);
+#include <asm/smp_plat.h>
-static inline void cpu_enter_lowpower(void)
-{
- unsigned int v;
+#include "fuse.h"
+#include "sleep.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, #0x04\n"
- " mcr p15, 0, %0, c1, c0, 0\n"
- : "=&r" (v)
- : "r" (0)
- : "cc");
-}
+static void (*tegra_hotplug_shutdown)(void);
-static inline void cpu_leave_lowpower(void)
+int tegra_cpu_kill(unsigned cpu)
{
- unsigned int v;
+ cpu = cpu_logical_map(cpu);
- asm volatile(
- "mrc p15, 0, %0, c1, c0, 0\n"
- " orr %0, %0, #0x04\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)
- :
- : "cc");
-}
-
-static inline void platform_do_lowpower(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");
+ /* Clock gate the CPU */
+ tegra_wait_cpu_in_reset(cpu);
+ tegra_disable_cpu_clock(cpu);
- /*if (pen_release == cpu) {*/
- /*
- * OK, proper wakeup, we're done
- */
- break;
- /*}*/
-
- /*
- * getting here, means that we have come out of WFI without
- * having been woken up - this shouldn't happen
- *
- * The trouble is, letting people know about this is not really
- * possible, since we are currently running incoherently, and
- * therefore cannot safely call printk() or anything else
- */
-#ifdef DEBUG
- printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
- }
-}
-
-int platform_cpu_kill(unsigned int cpu)
-{
- return wait_for_completion_timeout(&cpu_killed, 5000);
+ return 1;
}
/*
@@ -102,39 +34,29 @@ int platform_cpu_kill(unsigned int cpu)
*
* Called with IRQs disabled
*/
-void platform_cpu_die(unsigned int cpu)
+void __ref tegra_cpu_die(unsigned int cpu)
{
-#ifdef DEBUG
- unsigned int this_cpu = hard_smp_processor_id();
-
- if (cpu != this_cpu) {
- printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
- this_cpu, cpu);
- BUG();
- }
-#endif
-
- printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
- complete(&cpu_killed);
+ /* Clean L1 data cache */
+ tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
- /*
- * we're ready for shutdown now, so do it
- */
- cpu_enter_lowpower();
- platform_do_lowpower(cpu);
+ /* Shut down the current CPU. */
+ tegra_hotplug_shutdown();
- /*
- * bring this CPU back into the world of cache
- * coherency, and then restore interrupts
- */
- cpu_leave_lowpower();
+ /* Should never return here. */
+ BUG();
}
-int platform_cpu_disable(unsigned int cpu)
+void __init tegra_hotplug_init(void)
{
- /*
- * we don't allow CPU 0 to be shutdown (it is still too special
- * e.g. clock tick interrupts)
- */
- return cpu == 0 ? -EPERM : 0;
+ if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+ return;
+
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+ tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
}