From e142b9572a89f43fe984c4fc87e3203f380ff4de Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 16 Oct 2013 23:53:19 -0700 Subject: [PATCH] tegra124: Add an assembly stub which is run first on the main CPUs. When starting the main CPUs, their register state hasn't been initialized in any way. This is different from how the ROM stage typically starts since it usually follows the bootblock on the same CPU, and is usually entered with a branch, link and exchange instruction generated as part of the stage_exit function. If we were to jump directly into code on the newly enabled CPUs, especially thumb code, things will go badly. To fix that, this change adds a small assembly stub which sets the stack pointer to be the start of the stack used in the bootblock, zeroes out the link register, and then uses a branch and exchange instruction, bx, to jump to the actual first instruction. The stub is compiled using the compiler flags of the bootblock, but that's ok for two reasons. First, since it's already in assembly, the compiler doesn't have much choice as far as what to emit. Second, all of the instructions used are available on both an ARMv4 and ARMv7 CPU and so will assemble correctly for the AVP and run correctly on the main CPUs. BUG=None TEST=Built and booted into the ROM stage and then RAM stage on nyan. BRANCH=None Change-Id: Idac59d76d44d2dd00f142382de2068f4d3e4aec8 Signed-off-by: Gabe Black Reviewed-on: https://chromium-review.googlesource.com/173541 Reviewed-by: Ronald Minnich Tested-by: Ronald Minnich Commit-Queue: Ronald Minnich --- src/soc/nvidia/tegra124/Makefile.inc | 1 + src/soc/nvidia/tegra124/clock.c | 8 +++-- src/soc/nvidia/tegra124/cpug.S | 47 ++++++++++++++++++++++++++++ src/soc/nvidia/tegra124/cpug.h | 29 +++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/soc/nvidia/tegra124/cpug.S create mode 100644 src/soc/nvidia/tegra124/cpug.h diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc index 8a8ef67286..e34fc1c7be 100644 --- a/src/soc/nvidia/tegra124/Makefile.inc +++ b/src/soc/nvidia/tegra124/Makefile.inc @@ -4,6 +4,7 @@ bootblock-y += bootblock.c bootblock-y += bootblock_asm.S bootblock-y += cbfs.c bootblock-y += clock.c +bootblock-y += cpug.S bootblock-y += dma.c bootblock-y += i2c.c bootblock-y += dma.c diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c index e1484b3d1d..919b641bd3 100644 --- a/src/soc/nvidia/tegra124/clock.c +++ b/src/soc/nvidia/tegra124/clock.c @@ -19,6 +19,7 @@ #include #include "clk_rst.h" #include "clock.h" +#include "cpug.h" #include "flow.h" #include "pmc.h" @@ -173,8 +174,11 @@ void clock_uart_config(void) void clock_cpu0_config_and_reset(void *entry) { - void *evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100; - write32((uintptr_t)entry, evp_cpu_reset); + void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100; + + write32(CONFIG_STACK_TOP, &cpug_stack_pointer); + write32((uintptr_t)entry, &cpug_entry_point); + write32((uintptr_t)&cpug_setup, evp_cpu_reset); // Wait for PLLX to lock. while (!(readl(&clk_rst->pllx_base) & (0x1 << 27))) diff --git a/src/soc/nvidia/tegra124/cpug.S b/src/soc/nvidia/tegra124/cpug.S new file mode 100644 index 0000000000..eceb66baf7 --- /dev/null +++ b/src/soc/nvidia/tegra124/cpug.S @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + .align 6 + .arm + + .global cpug_stack_pointer +cpug_stack_pointer: + .word 0 + + .global cpug_entry_point +cpug_entry_point: + .word 0 + + .global cpug_setup + .type cpug_setup, function + cpug_setup: + ldr sp, cpug_stack_pointer + eor lr, lr + ldr r0, cpug_entry_point + bx r0 diff --git a/src/soc/nvidia/tegra124/cpug.h b/src/soc/nvidia/tegra124/cpug.h new file mode 100644 index 0000000000..842843a65b --- /dev/null +++ b/src/soc/nvidia/tegra124/cpug.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_CPUG_H__ +#define __SOC_NVIDIA_TEGRA124_CPUG_H__ + +#include + +extern u32 cpug_stack_pointer; +extern u32 cpug_entry_point; +void cpug_setup(void); + +#endif /* __SOC_NVIDIA_TEGRA124_CPUG_H__ */