While actually switching to non-secure state is one thing, the
more important part of this process is to make sure that we still
have full access to the interrupt controller (GIC).
The GIC is fully aware of secure vs. non-secure state, some
registers are banked, others may be configured to be accessible from
secure state only.
To be as generic as possible, we get the GIC memory mapped address
based on the PERIPHBASE register. We check explicitly for
ARM Cortex-A7 and A15 cores, assuming an A9 otherwise, as for those
cores we know the offsets for the GIC CPU interface from the
PERIPHBASE content. Other cores could be added as needed.

With the GIC accessible, we:
a) allow private interrupts to be delivered to the core
   (GICD_IGROUPR0 = 0xFFFFFFFF)
b) enable the CPU interface (GICC_CTLR[0] = 1)
c) set the priority filter to allow non-secure interrupts
   (GICC_PMR = 0x80)

After having switched to non-secure state, we also enable the
non-secure GIC CPU interface, since this register is banked.

Also we allow access to all coprocessor interfaces from non-secure
state by writing the appropriate bits in the NSACR register.

For reasons obvious later we only use caller saved registers r0-r3.

Signed-off-by: Andre Przywara <andre.przyw...@linaro.org>
---
 arch/arm/cpu/armv7/start.S | 47 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index da48b36..e63e892 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -572,3 +572,50 @@ fiq:
 
 #endif /* CONFIG_USE_IRQ */
 #endif /* CONFIG_SPL_BUILD */
+
+#ifdef CONFIG_ARMV7_VIRT
+/* Routine to initialize GIC CPU interface and switch to nonsecure state.
+ */
+.globl _nonsec_gic_switch
+_nonsec_gic_switch:
+       mrc     p15, 4, r2, c15, c0, 0          @ r2 = PERIPHBASE
+       add     r3, r2, #0x1000                 @ GIC dist i/f offset
+       mvn     r1, #0
+       str     r1, [r3, #0x80]                 @ allow private interrupts
+
+       mrc     p15, 0, r0, c0, c0, 0           @ MIDR
+       bfc     r0, #16, #8                     @ mask out variant, arch
+       bfc     r0, #0, #4                      @ and revision
+       movw    r1, #0xc070
+       movt    r1, #0x4100
+       cmp     r0, r1                          @ check for Cortex-A7
+       orr     r1, #0xf0
+       cmpne   r0, r1                          @ check for Cortex-A15
+       movne   r1, #0x100                      @ GIC CPU offset for A9
+       moveq   r1, #0x2000                     @ GIC CPU offset for A15/A7
+       add     r3, r2, r1                      @ r3 = GIC CPU i/f addr
+
+       mov     r1, #1
+       str     r1, [r3, #0]                    @ set GICC_CTLR[enable]
+       mov     r1, #0x80
+       str     r1, [r3, #4]                    @ set GICC_PIMR[7]
+
+       movw    r1, #0x3fff
+       movt    r1, #0x0006
+       mcr     p15, 0, r1, c1, c1, 2           @ NSACR = all copros to non-sec
+
+       ldr     r1, =_start
+       mcr     p15, 0, r1, c12, c0, 0          @ set VBAR
+       mcr     p15, 0, r1, c12, c0, 1          @ set MVBAR
+
+       isb
+       smc     #0                              @ call into MONITOR mode
+       isb                                     @ clobbers r0 and r1
+
+       mov     r1, #1
+       str     r1, [r3, #0]                    @ set GICC_CTLR[enable]
+       add     r2, r2, #0x1000                 @ GIC dist i/f offset
+       str     r1, [r2]                        @ allow private interrupts
+
+       mov     pc, lr
+#endif /* CONFIG_ARMV7_VIRT */
-- 
1.7.12.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to