diff options
Diffstat (limited to 'arch/arm/mach-tegra/reset.c')
| -rw-r--r-- | arch/arm/mach-tegra/reset.c | 42 | 
1 files changed, 30 insertions, 12 deletions
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index fd0bbf8a6c9..146fe8e0ae7 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -21,6 +21,7 @@  #include <asm/cacheflush.h>  #include <asm/hardware/cache-l2x0.h> +#include <asm/firmware.h>  #include "iomap.h"  #include "irammap.h" @@ -33,26 +34,18 @@  static bool is_enabled; -static void __init tegra_cpu_reset_handler_enable(void) +static void __init tegra_cpu_reset_handler_set(const u32 reset_address)  { -	void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);  	void __iomem *evp_cpu_reset =  		IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);  	void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);  	u32 reg; -	BUG_ON(is_enabled); -	BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); - -	memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, -			tegra_cpu_reset_handler_size); -  	/*  	 * NOTE: This must be the one and only write to the EVP CPU reset  	 *       vector in the entire system.  	 */ -	writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset, -			evp_cpu_reset); +	writel(reset_address, evp_cpu_reset);  	wmb();  	reg = readl(evp_cpu_reset); @@ -66,8 +59,33 @@ static void __init tegra_cpu_reset_handler_enable(void)  		writel(reg, sb_ctrl);  		wmb();  	} +} + +static void __init tegra_cpu_reset_handler_enable(void) +{ +	void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); +	const u32 reset_address = TEGRA_IRAM_RESET_BASE + +						tegra_cpu_reset_handler_offset; +	int err; + +	BUG_ON(is_enabled); +	BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); -	is_enabled = true; +	memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, +			tegra_cpu_reset_handler_size); + +	err = call_firmware_op(set_cpu_boot_addr, 0, reset_address); +	switch (err) { +	case -ENOSYS: +		tegra_cpu_reset_handler_set(reset_address); +		/* pass-through */ +	case 0: +		is_enabled = true; +		break; +	default: +		pr_crit("Cannot set CPU reset handler: %d\n", err); +		BUG(); +	}  }  void __init tegra_cpu_reset_handler_init(void) @@ -82,7 +100,7 @@ void __init tegra_cpu_reset_handler_init(void)  #ifdef CONFIG_PM_SLEEP  	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] = -		TEGRA_IRAM_CODE_AREA; +		TEGRA_IRAM_LPx_RESUME_AREA;  	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =  		virt_to_phys((void *)tegra_resume);  #endif  | 
