summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/sleep.h
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2010-11-28 22:36:08 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:34:22 -0800
commit8e437c201dbd10bdfc7532f40f7bbf35ffacda7b (patch)
treedf734899391fcd0aa2cf40bf7655b878548b976f /arch/arm/mach-tegra/sleep.h
parentbc2b6b4c1dd531e9c204ac20ca2b790b5182de4d (diff)
ARM: tegra: Add suspend support
Tegra supports three low power modes that involve powering down the CPU. LP2 powers down both CPU cores and the GICs, but leaves the core peripherals, including the memory controller and the legacy interrupt controller, enabled. The legacy interrupt controller is used as the wakeup source, and any interrupt can wake the device. LP2 can be used in idle. LP1 is the same as LP2, but in addition turns off the memory controller and puts the DDR memory in self-refresh. Any interrupt can wake the device. LP1 could be used in idle if no peripherals are doing DMA. LP0 turns off everything in the SoC except the RTC and a power management controller, both of which run off a 32 kHz clock. The power management controller has 32 wake sources, all other interrupts can not be used to wake from LP0. These low power modes power-gate the main CPU complex, requiring a full processor state save and restore from a reset vector. Platform-specific data (power good times, PMU capabilities, etc.) must be specified when registering the suspend operations to ensure that platform power sequencing restrictions are maintained. In both LP0 and LP1, SDRAM is placed into self-refresh. in order to safely perform this transition, the final shutdown procedure responsible for * turning off the MMU and L1 data cache * putting memory into self-refresh * setting the DDR pads to the lowest power state * and turning off PLLs is copied into IRAM (at the address TEGRA_IRAM_BASE + SZ_4K) at the start of the suspend process. In LP1 mode (like LP2), the CPU is reset and executes the code specified at the EVP reset vector. Since SDRAM is in self-refresh, this code must also be located in IRAM, and it must re-enable DRAM before restoring the full context. In this implementation, it enables the CPU on PLLP, enables PLLC and PLLM, restores the SCLK burst policy, and jumps to the LP2 reset vector to restore the rest of the system (MMU, PLLX, coresite, etc.). The LP2 reset vector is expected to be found in PMC_SCRATCH1, and is initialized during system-bootup. In LP0 mode, the core voltage domain is also shutoff. As a result, all of the volatile state in the core voltage domain (e.g., pinmux registers, clock registers, etc.) must be saved to memory so that it can be restored after the system resumes. A limited set of wakeups are available from LP0, and the correct levels for the wakeups must be programmed into the PMC wakepad configuration register prior to system shutdown. On resume, the system resets into the boot ROM, and the boot ROM restores SDRAM and other system state using values saved during kernel initialization in the PMC scratch registers. Resuming from LP0 requires the boot ROM to supply a signed recovery codeblob to the kernel; the kernel expects that the length and address of this blob is supplied with the lp0_vec= command line argument; if not present, suspend- to-LP0 will be disabled For simplicity, the outer cache is shutdown for both LP0 and LP1; it is possible to optimize the LP1 routine to bypass outer cache shutdown and restart. Includes fixes from: Scott Williams <scwilliams@nvidia.com> Aleksandr Frid <afrid@nvidia.com> Vik Kasivajhula <tkasivajhula@nvidia.com> Bharat Nihalani <Kbnihalani@nvidia.com> James Wylder <james.wylder@motorola.com> Allen Martin <amartin@nvidia.com> Change-Id: I9e4e61c2fbb8c7bb5a29b1832ea38e7ea0524c52 Original-author: Gary King <gking@nvidia.com> Signed-off-by: Gary King <gking@nvidia.com> Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/mach-tegra/sleep.h')
-rw-r--r--arch/arm/mach-tegra/sleep.h64
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
new file mode 100644
index 000000000000..0c007139b483
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep.h
@@ -0,0 +1,64 @@
+/*
+ * arch/arm/mach-tegra/power.h
+ *
+ * Declarations for power state transition code
+ *
+ * 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_TEGRA_POWER_H
+#define __MACH_TEGRA_POWER_H
+
+#include <mach/iomap.h>
+
+#define TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K)
+
+/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock in idle */
+#define PMC_SCRATCH37 0x130
+#define PMC_SCRATCH38 0x134
+/* PMC_SCRATCH39 stores the reset vector of the AVP (always 0) after LP0 */
+#define PMC_SCRATCH39 0x138
+/* PMC_SCRATCH41 stores the reset vector of the CPU after LP0 and LP1 */
+#define PMC_SCRATCH41 0x140
+
+#define CPU_RESETTABLE 2
+#define CPU_RESETTABLE_SOON 1
+#define CPU_NOT_RESETTABLE 0
+
+#ifndef __ASSEMBLY__
+/* assembly routines implemented in sleep.S */
+void tegra_pen_lock(void);
+void tegra_pen_unlock(void);
+void tegra_cpu_wfi(void);
+void tegra_cpu_reset(int cpu);
+void tegra_cpu_set_resettable_soon(void);
+int tegra_cpu_is_resettable_soon(void);
+
+extern void tegra_lp1_reset;
+extern void tegra_iram_start;
+extern void tegra_iram_end;
+
+void tegra_sleep_reset(void);
+void tegra_sleep_wfi(unsigned long v2p);
+void tegra_sleep_cpu(unsigned long v2p);
+void tegra_sleep_core(unsigned long v2p);
+void tegra_resume(void);
+void tegra_secondary_resume(void);
+
+#endif
+
+#endif