summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/common.c1
-rw-r--r--arch/arm/mach-tegra/hotplug.c8
-rw-r--r--arch/arm/mach-tegra/sleep-t20.S82
-rw-r--r--arch/arm/mach-tegra/sleep.h4
5 files changed, 96 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index efb2f90a8f77..84d21f514418 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -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
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 06520564d815..0560538bf598 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -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
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index be92d4c07606..d02a35476135 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -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
index 000000000000..a36ae413e2b8
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t20.S
@@ -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
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 0f047eb3ca2e..e25a7cd703d9 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -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 */
@@ -72,8 +74,10 @@
#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