aboutsummaryrefslogtreecommitdiff
path: root/src/soc/nvidia/tegra132/soc.c
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2014-08-28 09:46:10 -0500
committerPatrick Georgi <pgeorgi@google.com>2015-03-27 08:04:14 +0100
commit127f051f86a3f3f1c1df889f2838123481a37b2f (patch)
tree19a8211f8735673573052fe0a58de70d7aa72bac /src/soc/nvidia/tegra132/soc.c
parent79eb2b3ec6c0b38c6aeaf9a78ab3cb2de9cfcee7 (diff)
tegra132: add spin table support
Until PSCI is functional the other core still needs to be brought up in the kernel. The kernel boots these cpus with the spin table which is just an address in memory to monitor a jump location. BUG=chrome-os-partner:31545 BRANCH=None TEST=Built and brought up secondary core in linux. Change-Id: Iaa69110f6a647d8fd4149119d97db4fc45d7da00 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 01ca36685852bc5dd85fd4015c8a1e600e23e7ca Original-Change-Id: Ieaf19cd70aff3e6c8de932e04b1b5aba71822a97 Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/214777 Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: http://review.coreboot.org/9021 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/soc/nvidia/tegra132/soc.c')
-rw-r--r--src/soc/nvidia/tegra132/soc.c64
1 files changed, 63 insertions, 1 deletions
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)