From dc87b8c1df7df88ec6c97cc3ac57a73e475c821f Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 5 Jul 2011 18:05:26 -0700 Subject: 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 DW: Split into logical changes Signed-off-by: Dan Willemsen Rebase-Id: R7b9859a83717e76c3c083bdde724bd5fef9ce089 --- arch/arm/mach-tegra/reset.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-tegra/reset.c') 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(); } -- cgit v1.2.3