Commit 16bb08d1 authored by Stephen Warren's avatar Stephen Warren Committed by Tom Warren

ARM: tegra: implement WAR for Tegra114 CPU reset vector

A Tegra114 HW bug prevents the main CPU vector from being modified under
certain circumstances. Tegra114 A01P and later with a patched boot ROM
set the CPU reset vector to 0x4003fffc (end of IRAM). This allows placing
an arbitrary jump instruction at that location, in order to redirect to
the desired reset vector location. Modify Tegra114's start_cpu() to make
use of this feature. This allows CPUs with the patched boot ROM to boot.

Based-on-work-by: Jimmy Zhang <jimmzhang@nvidia.com>.
Signed-off-by: default avatarStephen Warren <swarren@nvidia.com>
Signed-off-by: default avatarTom Warren <twarren@nvidia.com>
parent 527519ae
...@@ -270,6 +270,8 @@ void powerup_cpus(void) ...@@ -270,6 +270,8 @@ void powerup_cpus(void)
void start_cpu(u32 reset_vector) void start_cpu(u32 reset_vector)
{ {
u32 imme, inst;
debug("start_cpu entry, reset_vector = %x\n", reset_vector); debug("start_cpu entry, reset_vector = %x\n", reset_vector);
t114_init_clocks(); t114_init_clocks();
...@@ -286,12 +288,38 @@ void start_cpu(u32 reset_vector) ...@@ -286,12 +288,38 @@ void start_cpu(u32 reset_vector)
/* Take CPU(s) out of reset */ /* Take CPU(s) out of reset */
remove_cpu_resets(); remove_cpu_resets();
/* Set the entry point for CPU execution from reset */
/* /*
* Set the entry point for CPU execution from reset, * A01P with patched boot ROM; vector hard-coded to 0x4003fffc.
* if it's a non-zero value. * See nvbug 1193357 for details.
*/ */
if (reset_vector)
writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); /* mov r0, #lsb(reset_vector) */
imme = reset_vector & 0xffff;
inst = imme & 0xfff;
inst |= ((imme >> 12) << 16);
inst |= 0xe3000000;
writel(inst, 0x4003fff0);
/* movt r0, #msb(reset_vector) */
imme = (reset_vector >> 16) & 0xffff;
inst = imme & 0xfff;
inst |= ((imme >> 12) << 16);
inst |= 0xe3400000;
writel(inst, 0x4003fff4);
/* bx r0 */
writel(0xe12fff10, 0x4003fff8);
/* b -12 */
imme = (u32)-20;
inst = (imme >> 2) & 0xffffff;
inst |= 0xea000000;
writel(inst, 0x4003fffc);
/* Write to orignal location for compatibility */
writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
/* If the CPU(s) don't already have power, power 'em up */ /* If the CPU(s) don't already have power, power 'em up */
powerup_cpus(); powerup_cpus();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment