diff options
Diffstat (limited to 'arch/arm/mach-tegra/reset.c')
-rw-r--r-- | arch/arm/mach-tegra/reset.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index 568f5bbf979d..146fe8e0ae7c 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <asm/hardware/cache-l2x0.h> | 23 | #include <asm/hardware/cache-l2x0.h> |
24 | #include <asm/firmware.h> | ||
24 | 25 | ||
25 | #include "iomap.h" | 26 | #include "iomap.h" |
26 | #include "irammap.h" | 27 | #include "irammap.h" |
@@ -33,26 +34,18 @@ | |||
33 | 34 | ||
34 | static bool is_enabled; | 35 | static bool is_enabled; |
35 | 36 | ||
36 | static void __init tegra_cpu_reset_handler_enable(void) | 37 | static void __init tegra_cpu_reset_handler_set(const u32 reset_address) |
37 | { | 38 | { |
38 | void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); | ||
39 | void __iomem *evp_cpu_reset = | 39 | void __iomem *evp_cpu_reset = |
40 | IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); | 40 | IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); |
41 | void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); | 41 | void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); |
42 | u32 reg; | 42 | u32 reg; |
43 | 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 | /* | 44 | /* |
51 | * NOTE: This must be the one and only write to the EVP CPU reset | 45 | * NOTE: This must be the one and only write to the EVP CPU reset |
52 | * vector in the entire system. | 46 | * vector in the entire system. |
53 | */ | 47 | */ |
54 | writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset, | 48 | writel(reset_address, evp_cpu_reset); |
55 | evp_cpu_reset); | ||
56 | wmb(); | 49 | wmb(); |
57 | reg = readl(evp_cpu_reset); | 50 | reg = readl(evp_cpu_reset); |
58 | 51 | ||
@@ -66,8 +59,33 @@ static void __init tegra_cpu_reset_handler_enable(void) | |||
66 | writel(reg, sb_ctrl); | 59 | writel(reg, sb_ctrl); |
67 | wmb(); | 60 | wmb(); |
68 | } | 61 | } |
62 | } | ||
63 | |||
64 | static void __init tegra_cpu_reset_handler_enable(void) | ||
65 | { | ||
66 | void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); | ||
67 | const u32 reset_address = TEGRA_IRAM_RESET_BASE + | ||
68 | tegra_cpu_reset_handler_offset; | ||
69 | int err; | ||
70 | |||
71 | BUG_ON(is_enabled); | ||
72 | BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); | ||
69 | 73 | ||
70 | is_enabled = true; | 74 | memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, |
75 | tegra_cpu_reset_handler_size); | ||
76 | |||
77 | err = call_firmware_op(set_cpu_boot_addr, 0, reset_address); | ||
78 | switch (err) { | ||
79 | case -ENOSYS: | ||
80 | tegra_cpu_reset_handler_set(reset_address); | ||
81 | /* pass-through */ | ||
82 | case 0: | ||
83 | is_enabled = true; | ||
84 | break; | ||
85 | default: | ||
86 | pr_crit("Cannot set CPU reset handler: %d\n", err); | ||
87 | BUG(); | ||
88 | } | ||
71 | } | 89 | } |
72 | 90 | ||
73 | void __init tegra_cpu_reset_handler_init(void) | 91 | void __init tegra_cpu_reset_handler_init(void) |