arm64: initialize SCR_EL3 on all CPUs

Provide SCR_EL3 initialization on all CPUs. This settings were
chosen in such a way that nothing would need to be done if EL3
is abandoned after transitioning to EL2 or EL1. If persistent
EL3 program is used those SCR policies can be updated within
that program.

BUG=chrome-os-partner:31634
BRANCH=None
TEST=Built and booted through kernel. Printed out SCR setting for
     each CPU.

Change-Id: Ib44acd8ae40dbca590740340632f5b72998e9dd8
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: f77b903afbafad7d439ec50fc48f1eaa37827d90
Original-Change-Id: Id659f0a98360fe8bbc80e5a623eba1526e81b400
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/218300
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9078
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/src/arch/arm64/cpu.c b/src/arch/arm64/cpu.c
index 0f9e874..396c5b7 100644
--- a/src/arch/arm64/cpu.c
+++ b/src/arch/arm64/cpu.c
@@ -84,6 +84,43 @@
 	return 0;
 }
 
+/* Set up default SCR values. */
+static void el3_init(void)
+{
+	uint32_t scr;
+
+	if (get_current_el() != EL3)
+		return;
+
+	scr = raw_read_scr_el3();
+	/* Default to non-secure EL1 and EL0. */
+	scr &= ~(SCR_NS_MASK);
+	scr |= SCR_NS_ENABLE;
+	/* Disable IRQ, FIQ, and external abort interrupt routing. */
+	scr &= ~(SCR_IRQ_MASK | SCR_FIQ_MASK | SCR_EA_MASK);
+	scr |= SCR_IRQ_DISABLE | SCR_FIQ_DISABLE | SCR_EA_DISABLE;
+	/* Enable HVC */
+	scr &= ~(SCR_HVC_MASK);
+	scr |= SCR_HVC_ENABLE;
+	/* Disable SMC */
+	scr &= ~(SCR_SMC_MASK);
+	scr |= SCR_SMC_DISABLE;
+	/* Disable secure instruction fetches. */
+	scr &= ~(SCR_SIF_MASK);
+	scr |= SCR_SIF_DISABLE;
+	/* All lower exception levels 64-bit by default. */
+	scr &= ~(SCR_RW_MASK);
+	scr |= SCR_LOWER_AARCH64;
+	/* Disable secure EL1 access to secure timer. */
+	scr &= ~(SCR_ST_MASK);
+	scr |= SCR_ST_DISABLE;
+	/* Don't trap on WFE or WFI instructions. */
+	scr &= ~(SCR_TWI_MASK | SCR_TWE_MASK);
+	scr |= SCR_TWI_DISABLE | SCR_TWE_DISABLE;
+	raw_write_scr_el3(scr);
+	isb();
+}
+
 static void init_this_cpu(void *arg)
 {
 	struct cpu_info *ci = arg;
@@ -91,6 +128,8 @@
 
 	cpu_set_device_operations(dev);
 
+	el3_init();
+
 	/* Initialize the GIC. */
 	gic_init();