]> git.openfabrics.org - ~emulex/infiniband.git/commitdiff
ARM: tegra20: add CPU hotplug support
authorJoseph Lo <josephl@nvidia.com>
Thu, 16 Aug 2012 09:31:52 +0000 (17:31 +0800)
committerStephen Warren <swarren@nvidia.com>
Thu, 13 Sep 2012 17:41:06 +0000 (11:41 -0600)
Hotplug function put CPU in offline or online mode at runtime.
When the CPU been put into offline, it was been clock gated. The
offline CPU can be power gated, when the remaining CPU goes into
LP2.

Based on the worked by:
Colin Cross <ccross@android.com>
Gary King <gking@nvidia.com>

Signed-off-by: Joseph Lo <josephl@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/hotplug.c
arch/arm/mach-tegra/sleep-t20.S [new file with mode: 0644]
arch/arm/mach-tegra/sleep.h

index efb2f90a8f7785dcd5d9f30ee5d58a69f436b6b1..84d21f51441841030a0af4fe75bf0e08984b24c3 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_IDLE)                        += sleep.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += tegra2_emc.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += sleep-t20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += tegra30_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += tegra30_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += sleep-t30.o
index 06520564d8157624d2d58c73cdefff10f58de1d1..0560538bf5983c22b789beef539d3ed954217835 100644 (file)
@@ -136,6 +136,7 @@ void __init tegra20_init_early(void)
        tegra_init_cache(0x331, 0x441);
        tegra_pmc_init();
        tegra_powergate_init();
+       tegra20_hotplug_init();
 }
 #endif
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
index be92d4c07606c21fbf4bfe795bed9df76f1ab80d..d02a354761356d02e0e3e91e9c9b5426ff93a82a 100644 (file)
@@ -56,6 +56,14 @@ int platform_cpu_disable(unsigned int cpu)
        return cpu == 0 ? -EPERM : 0;
 }
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+extern void tegra20_hotplug_shutdown(void);
+void __init tegra20_hotplug_init(void)
+{
+       tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+}
+#endif
+
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 extern void tegra30_hotplug_shutdown(void);
 void __init tegra30_hotplug_init(void)
diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-t20.S
new file mode 100644 (file)
index 0000000..a36ae41
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011, Google, Inc.
+ *
+ * Author: Colin Cross <ccross@android.com>
+ *         Gary King <gking@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra20_hotplug_shutdown(void)
+ *
+ * puts the current cpu in reset
+ * should never return
+ */
+ENTRY(tegra20_hotplug_shutdown)
+       /* Turn off SMP coherency */
+       exit_smp r4, r5
+
+       /* Put this CPU down */
+       cpu_id  r0
+       bl      tegra20_cpu_shutdown
+       mov     pc, lr                  @ should never get here
+ENDPROC(tegra20_hotplug_shutdown)
+
+/*
+ * tegra20_cpu_shutdown(int cpu)
+ *
+ * r0 is cpu to reset
+ *
+ * puts the specified CPU in wait-for-event mode on the flow controller
+ * and puts the CPU in reset
+ * can be called on the current cpu or another cpu
+ * if called on the current cpu, does not return
+ * MUST NOT BE CALLED FOR CPU 0.
+ *
+ * corrupts r0-r3, r12
+ */
+ENTRY(tegra20_cpu_shutdown)
+       cmp     r0, #0
+       moveq   pc, lr                  @ must not be called for CPU 0
+
+       cpu_to_halt_reg r1, r0
+       ldr     r3, =TEGRA_FLOW_CTRL_VIRT
+       mov     r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
+       str     r2, [r3, r1]            @ put flow controller in wait event mode
+       ldr     r2, [r3, r1]
+       isb
+       dsb
+       movw    r1, 0x1011
+       mov     r1, r1, lsl r0
+       ldr     r3, =TEGRA_CLK_RESET_VIRT
+       str     r1, [r3, #0x340]        @ put slave CPU in reset
+       isb
+       dsb
+       cpu_id  r3
+       cmp     r3, r0
+       beq     .
+       mov     pc, lr
+ENDPROC(tegra20_cpu_shutdown)
+#endif
index 0f047eb3ca2efdfac8e778c71dc2256a58ffff5a..e25a7cd703d9cdc852abd9dbd19d80b33d530267 100644 (file)
@@ -23,6 +23,8 @@
                                        + IO_CPU_VIRT)
 #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
                                        + IO_PPSB_VIRT)
+#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
+                                       + IO_PPSB_VIRT)
 
 #ifdef __ASSEMBLY__
 /* returns the offset of the flow controller halt register for a cpu */
 #else
 
 #ifdef CONFIG_HOTPLUG_CPU
+void tegra20_hotplug_init(void);
 void tegra30_hotplug_init(void);
 #else
+static inline void tegra20_hotplug_init(void) {}
 static inline void tegra30_hotplug_init(void) {}
 #endif