| 
									
										
										
										
											2012-02-10 01:47:45 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * arch/arm/mach-tegra/reset.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2011,2012 NVIDIA Corporation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This software is licensed under the terms of the GNU General Public | 
					
						
							|  |  |  |  * License version 2, as published by the Free Software Foundation, and | 
					
						
							|  |  |  |  * may be copied, distributed, and modified under those terms. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/io.h>
 | 
					
						
							|  |  |  | #include <linux/cpumask.h>
 | 
					
						
							|  |  |  | #include <linux/bitops.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/cacheflush.h>
 | 
					
						
							|  |  |  | #include <asm/hardware/cache-l2x0.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-04 14:24:09 -06:00
										 |  |  | #include "iomap.h"
 | 
					
						
							| 
									
										
										
										
											2012-10-04 14:16:59 -06:00
										 |  |  | #include "irammap.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-10 01:47:45 +02:00
										 |  |  | #include "reset.h"
 | 
					
						
							| 
									
										
										
										
											2012-10-31 17:41:16 +08:00
										 |  |  | #include "sleep.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-10 01:47:45 +02:00
										 |  |  | #include "fuse.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
 | 
					
						
							|  |  |  | 				TEGRA_IRAM_RESET_HANDLER_OFFSET) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool is_enabled; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-18 15:01:50 -06:00
										 |  |  | static void __init tegra_cpu_reset_handler_enable(void) | 
					
						
							| 
									
										
										
										
											2012-02-10 01:47:45 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 	wmb(); | 
					
						
							|  |  |  | 	reg = readl(evp_cpu_reset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Prevent further modifications to the physical reset vector. | 
					
						
							|  |  |  | 	 *  NOTE: Has no effect on chips prior to Tegra30. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (tegra_chip_id != TEGRA20) { | 
					
						
							|  |  |  | 		reg = readl(sb_ctrl); | 
					
						
							|  |  |  | 		reg |= 2; | 
					
						
							|  |  |  | 		writel(reg, sb_ctrl); | 
					
						
							|  |  |  | 		wmb(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	is_enabled = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void __init tegra_cpu_reset_handler_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_SMP
 | 
					
						
							|  |  |  | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] = | 
					
						
							| 
									
										
										
										
											2013-01-04 17:32:22 +08:00
										 |  |  | 		*((u32 *)cpu_possible_mask); | 
					
						
							| 
									
										
										
										
											2012-02-10 01:47:45 +02:00
										 |  |  | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] = | 
					
						
							|  |  |  | 		virt_to_phys((void *)tegra_secondary_startup); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-31 17:41:16 +08:00
										 |  |  | #ifdef CONFIG_PM_SLEEP
 | 
					
						
							| 
									
										
										
										
											2013-08-12 17:40:00 +08:00
										 |  |  | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] = | 
					
						
							|  |  |  | 		TEGRA_IRAM_CODE_AREA; | 
					
						
							| 
									
										
										
										
											2012-10-31 17:41:16 +08:00
										 |  |  | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] = | 
					
						
							|  |  |  | 		virt_to_phys((void *)tegra_resume); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 01:47:45 +02:00
										 |  |  | 	tegra_cpu_reset_handler_enable(); | 
					
						
							|  |  |  | } |