armv8: Initialize CNTFRQ if at highest exception level

CNTFRQ_EL0 is only writable from the highest supported exception
level on the platform. For Armv8-A, this is typically EL3, but
technically EL2 and EL3 are optional so it may need to be
initialized at EL2 or EL1. For Armv8-R, the highest exception
level is always EL2.

This patch moves the initialization outside of the switch_el
block and uses a new macro branch_if_not_highest_el which
dynamically detects whether it is at the highest supported
exception level.

Linux's docs state that CNTFRQ_EL0 should be initialized by the
bootloader. If not set, the the U-Boot prompt countdown hangs.

Signed-off-by: Peter Hoyes <Peter.Hoyes@arm.com>
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index 9e9c614..b3eef70 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -127,10 +127,6 @@
 	orr	x0, x0, #0xf			/* SCR_EL3.NS|IRQ|FIQ|EA */
 	msr	scr_el3, x0
 	msr	cptr_el3, xzr			/* Enable FP/SIMD */
-#ifdef COUNTER_FREQUENCY
-	ldr	x0, =COUNTER_FREQUENCY
-	msr	cntfrq_el0, x0			/* Initialize CNTFRQ */
-#endif
 	b	0f
 2:	mrs	x1, hcr_el2
 	tbnz	x1, #34, 1f			/* HCR_EL2.E2H */
@@ -142,7 +138,14 @@
 	mov	x0, #3 << 20
 	msr	cpacr_el1, x0			/* Enable FP/SIMD */
 0:
-	isb
+
+#ifdef COUNTER_FREQUENCY
+	branch_if_not_highest_el x0, 4f
+	ldr	x0, =COUNTER_FREQUENCY
+	msr	cntfrq_el0, x0			/* Initialize CNTFRQ */
+#endif
+
+4:	isb
 
 	/*
 	 * Enable SMPEN bit for coherency.