summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/reset.c
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-07-05 18:05:26 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 00:55:38 -0700
commitdc87b8c1df7df88ec6c97cc3ac57a73e475c821f (patch)
tree6b0011729f588f773ee3ef3fd73664e49e62d3d1 /arch/arm/mach-tegra/reset.c
parentde7efe0191222a1fb968cfb740e412c4bda1f703 (diff)
ARM: tegra: Redesign Tegra CPU reset handling
- Add a single unified handler for all CPU resets that is copied to IRAM. - Add state information to direct the flow of execution through the reset handler based on the reason a CPU was reset. - Write the EVP CPU reset vector only once per cold/warm boot session. - Prevent modification of the EVP CPU reset vector in Tegra3. Bug 786290 Bug 790458 Change-Id: Ica6707f3514986ee914e73a2d9766a4e06ce2d29 Signed-off-by: Scott Williams <scwilliams@nvidia.com> DW: Split into logical changes Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com> Rebase-Id: R7b9859a83717e76c3c083bdde724bd5fef9ce089
Diffstat (limited to 'arch/arm/mach-tegra/reset.c')
-rw-r--r--arch/arm/mach-tegra/reset.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index e05da7d10c3b..853edde06b62 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -26,6 +26,7 @@
#include "irammap.h"
#include "reset.h"
#include "fuse.h"
+#include "sleep.h"
#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
TEGRA_IRAM_RESET_HANDLER_OFFSET)
@@ -69,15 +70,52 @@ static void __init tegra_cpu_reset_handler_enable(void)
is_enabled = true;
}
-void __init tegra_cpu_reset_handler_init(void)
+#ifdef CONFIG_PM_SLEEP
+static unsigned long cpu_reset_handler_save[TEGRA_RESET_DATA_SIZE];
+
+void tegra_cpu_reset_handler_save(void)
{
+ unsigned int i;
+ BUG_ON(!is_enabled);
+ for (i = 0; i < TEGRA_RESET_DATA_SIZE; i++)
+ cpu_reset_handler_save[i] =
+ tegra_cpu_reset_handler_ptr[i];
+ is_enabled = false;
+}
+
+void tegra_cpu_reset_handler_restore(void)
+{
+ unsigned int i;
+ BUG_ON(is_enabled);
+ for (i = 0; i < TEGRA_RESET_DATA_SIZE; i++)
+ tegra_cpu_reset_handler_ptr[i] =
+ cpu_reset_handler_save[i];
+ is_enabled = true;
+}
+#endif
+void __init tegra_cpu_reset_handler_init(void)
+{
#ifdef CONFIG_SMP
__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
*((u32 *)cpu_present_mask);
__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
virt_to_phys((void *)tegra_secondary_startup);
#endif
+#ifdef CONFIG_PM_SLEEP
+ __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] =
+ TEGRA_IRAM_CODE_AREA;
+ __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
+ virt_to_phys((void *)tegra_resume);
+#endif
+
+ /* Push all of reset handler data out to the L3 memory system. */
+ __cpuc_coherent_kern_range(
+ (unsigned long)&__tegra_cpu_reset_handler_data[0],
+ (unsigned long)&__tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE]);
+
+ outer_clean_range(__pa(&__tegra_cpu_reset_handler_data[0]),
+ __pa(&__tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE]));
tegra_cpu_reset_handler_enable();
}