aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/nvidia/tegra132/Makefile.inc1
-rw-r--r--src/soc/nvidia/tegra132/soc.c64
-rw-r--r--src/soc/nvidia/tegra132/spintable.S38
3 files changed, 102 insertions, 1 deletions
diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index 447963970c..261e570f73 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -69,6 +69,7 @@ ramstage-y += ../tegra/gpio.c
ramstage-y += ../tegra/i2c.c
ramstage-y += ../tegra/pinmux.c
ramstage-y += ramstage.c
+ramstage-y += spintable.S
ramstage-y += mmu_operations.c
ramstage-$(CONFIG_DRIVERS_UART) += uart.c
ramstage-y += ../tegra/usb.c
diff --git a/src/soc/nvidia/tegra132/soc.c b/src/soc/nvidia/tegra132/soc.c
index 024fd805da..16001f9fb3 100644
--- a/src/soc/nvidia/tegra132/soc.c
+++ b/src/soc/nvidia/tegra132/soc.c
@@ -18,10 +18,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <string.h>
#include <console/console.h>
#include <device/device.h>
#include <arch/io.h>
#include <arch/cpu.h>
+#include <arch/cache.h>
+#include <cbmem.h>
#include <timer.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <soc/addressmap.h>
@@ -62,12 +65,69 @@ static void soc_read_resources(device_t dev)
static volatile int secondary_cpu_up;
+static void *spintable_entry;
+static uint64_t * const spintable_magic = (void *)(uintptr_t)0x80000008;
+
+static void spintable_init(void)
+{
+ extern void __wait_for_spin_table_request(void);
+ const size_t spintable_entry_size = 4096;
+
+ spintable_entry =
+ cbmem_add(0x11111111, spintable_entry_size);
+
+ memcpy(spintable_entry, __wait_for_spin_table_request,
+ spintable_entry_size);
+
+ /* Ensure the memory location is zero'd out. */
+ *spintable_magic = 0;
+
+ dcache_clean_invalidate_by_mva(spintable_magic,
+ sizeof(*spintable_magic));
+ dcache_clean_invalidate_by_mva(&spintable_entry,
+ sizeof(spintable_entry));
+ dcache_clean_invalidate_by_mva(spintable_entry, spintable_entry_size);
+ dsb();
+}
+
+static void spintable_wait(void)
+{
+ uint32_t sctlr_el2;
+ uint32_t spsr_el3;
+ uint32_t scr_el3;
+
+ sctlr_el2 = raw_read_sctlr_el2();
+ /* Make sure EL2 is in little endian without any caching enabled. */
+ sctlr_el2 &= ~(1 << 25);
+ sctlr_el2 &= ~(1 << 19);
+ sctlr_el2 &= ~(1 << 12);
+ sctlr_el2 &= ~0xf;
+ raw_write_sctlr_el2(sctlr_el2);
+ /* Ensure enter into EL2t with interrupts disabled. */
+ spsr_el3 = (1 << 9) | (0xf << 6) | (1 << 3);
+ raw_write_spsr_el3(spsr_el3);
+ raw_write_elr_el3((uintptr_t)spintable_entry);
+ /*
+ * Lower exception level is 64 bit. HVC and SMC allowed. EL0 and EL1
+ * in non-secure mode. No interrupts routed to EL3.
+ */
+ scr_el3 = raw_read_scr_el3();
+ scr_el3 |= (1 << 10) | (1 << 8) | (0x3 << 4) | (1 << 0);
+ scr_el3 &= ~((0x7 << 1) | (1 << 7) | (1 << 9) | (1 << 13) | (1 << 12));
+ raw_write_scr_el3(scr_el3);
+ isb();
+ asm volatile(
+ "mov x0, %0\n\t"
+ "eret\n\t" : : "r" (spintable_magic) : "x0" );
+}
+
void soc_secondary_cpu_init(void)
{
printk(BIOS_INFO, "CPU%d is up!\n", smp_processor_id());
gic_init();
dmb();
secondary_cpu_up = 1;
+ spintable_wait();
}
static void start_secondary_cpu(void)
@@ -104,8 +164,10 @@ static void soc_init(device_t dev)
clock_init_arm_generic_timer();
gic_init();
- if (config->bring_up_secondary_cpu)
+ if (config->bring_up_secondary_cpu) {
+ spintable_init();
start_secondary_cpu();
+ }
}
static void soc_noop(device_t dev)
diff --git a/src/soc/nvidia/tegra132/spintable.S b/src/soc/nvidia/tegra132/spintable.S
new file mode 100644
index 0000000000..3066b7e679
--- /dev/null
+++ b/src/soc/nvidia/tegra132/spintable.S
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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
+ */
+
+#include <arch/asm.h>
+
+ENTRY(__wait_for_spin_table_request)
+ /* Entry here is in EL2 with the magic address in x0. */
+ mov x28, x0
+1:
+ ldr x27, [x28]
+ cmp x27, xzr
+ b.ne 2f
+ wfe
+ b 1b
+2:
+ /* Entry into the kernel. */
+ mov x0, xzr
+ mov x1, xzr
+ mov x2, xzr
+ mov x3, xzr
+ br x27
+ENDPROC(__wait_for_spin_table_request)