| Peter De Schrijver | b36ab97 | 2012-02-10 01:47:45 +0200 | [diff] [blame] | 1 | /* | 
 | 2 |  * arch/arm/mach-tegra/reset.c | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2011,2012 NVIDIA Corporation. | 
 | 5 |  * | 
 | 6 |  * This software is licensed under the terms of the GNU General Public | 
 | 7 |  * License version 2, as published by the Free Software Foundation, and | 
 | 8 |  * may be copied, distributed, and modified under those terms. | 
 | 9 |  * | 
 | 10 |  * This program is distributed in the hope that it will be useful, | 
 | 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | 13 |  * GNU General Public License for more details. | 
 | 14 |  * | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include <linux/init.h> | 
 | 18 | #include <linux/io.h> | 
 | 19 | #include <linux/cpumask.h> | 
 | 20 | #include <linux/bitops.h> | 
 | 21 |  | 
 | 22 | #include <asm/cacheflush.h> | 
 | 23 | #include <asm/hardware/cache-l2x0.h> | 
 | 24 |  | 
| Stephen Warren | 2be39c0 | 2012-10-04 14:24:09 -0600 | [diff] [blame] | 25 | #include "iomap.h" | 
| Stephen Warren | bb1de88 | 2012-10-04 14:16:59 -0600 | [diff] [blame] | 26 | #include "irammap.h" | 
| Peter De Schrijver | b36ab97 | 2012-02-10 01:47:45 +0200 | [diff] [blame] | 27 | #include "reset.h" | 
| Joseph Lo | d3f2936 | 2012-10-31 17:41:16 +0800 | [diff] [blame] | 28 | #include "sleep.h" | 
| Peter De Schrijver | b36ab97 | 2012-02-10 01:47:45 +0200 | [diff] [blame] | 29 | #include "fuse.h" | 
 | 30 |  | 
 | 31 | #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ | 
 | 32 | 				TEGRA_IRAM_RESET_HANDLER_OFFSET) | 
 | 33 |  | 
 | 34 | static bool is_enabled; | 
 | 35 |  | 
| Stephen Warren | 6355f25 | 2012-06-18 15:01:50 -0600 | [diff] [blame] | 36 | static void __init tegra_cpu_reset_handler_enable(void) | 
| Peter De Schrijver | b36ab97 | 2012-02-10 01:47:45 +0200 | [diff] [blame] | 37 | { | 
 | 38 | 	void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); | 
 | 39 | 	void __iomem *evp_cpu_reset = | 
 | 40 | 		IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); | 
 | 41 | 	void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); | 
 | 42 | 	u32 reg; | 
 | 43 |  | 
 | 44 | 	BUG_ON(is_enabled); | 
 | 45 | 	BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); | 
 | 46 |  | 
 | 47 | 	memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, | 
 | 48 | 			tegra_cpu_reset_handler_size); | 
 | 49 |  | 
 | 50 | 	/* | 
 | 51 | 	 * NOTE: This must be the one and only write to the EVP CPU reset | 
 | 52 | 	 *       vector in the entire system. | 
 | 53 | 	 */ | 
 | 54 | 	writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset, | 
 | 55 | 			evp_cpu_reset); | 
 | 56 | 	wmb(); | 
 | 57 | 	reg = readl(evp_cpu_reset); | 
 | 58 |  | 
 | 59 | 	/* | 
 | 60 | 	 * Prevent further modifications to the physical reset vector. | 
 | 61 | 	 *  NOTE: Has no effect on chips prior to Tegra30. | 
 | 62 | 	 */ | 
 | 63 | 	if (tegra_chip_id != TEGRA20) { | 
 | 64 | 		reg = readl(sb_ctrl); | 
 | 65 | 		reg |= 2; | 
 | 66 | 		writel(reg, sb_ctrl); | 
 | 67 | 		wmb(); | 
 | 68 | 	} | 
 | 69 |  | 
 | 70 | 	is_enabled = true; | 
 | 71 | } | 
 | 72 |  | 
 | 73 | void __init tegra_cpu_reset_handler_init(void) | 
 | 74 | { | 
 | 75 |  | 
 | 76 | #ifdef CONFIG_SMP | 
 | 77 | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] = | 
| Joseph Lo | 9e32366 | 2013-01-04 17:32:22 +0800 | [diff] [blame] | 78 | 		*((u32 *)cpu_possible_mask); | 
| Peter De Schrijver | b36ab97 | 2012-02-10 01:47:45 +0200 | [diff] [blame] | 79 | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] = | 
 | 80 | 		virt_to_phys((void *)tegra_secondary_startup); | 
 | 81 | #endif | 
 | 82 |  | 
| Joseph Lo | d3f2936 | 2012-10-31 17:41:16 +0800 | [diff] [blame] | 83 | #ifdef CONFIG_PM_SLEEP | 
 | 84 | 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] = | 
 | 85 | 		virt_to_phys((void *)tegra_resume); | 
 | 86 | #endif | 
 | 87 |  | 
| Peter De Schrijver | b36ab97 | 2012-02-10 01:47:45 +0200 | [diff] [blame] | 88 | 	tegra_cpu_reset_handler_enable(); | 
 | 89 | } |