treewide: replace GPLv2 long form headers with SPDX header
[coreboot.git] / src / soc / qualcomm / ipq806x / tz_wrapper.S
blobfab220417deca5941083d8db4fcde05967def8fc
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /*
4  * TZ expects the ARM core to be in 'ARM' mode. However, coreboot seems
5  * to be compiled in mixed thumb/arm mode. Hence create a glue function
6  * to invoke TZ.
7  */
9 #include <arch/asm.h>
12  * Force ARM mode. Else this gets assembled with mixed ARM and
13  * Thumb instructions. We set up everything and jump to TZBSP
14  * using the 'blx' instruction. For 'blx' if the last bit of the
15  * destination address is zero, it switches to ARM mode. Since,
16  * we are already in ARM mode, nothing to switch as such.
17  *
18  * However, when TZBSP returns, the CPU is still in ARM mode.
19  * If the assembler inserts Thumb instructions between the point
20  * of return from TZBSP to the 'bx' instruction we are hosed.
21  * Hence forcing ARM mode.
22  *
23  * Rest of the code can be compiled in mixed ARM/Thumb mode.
24  * Since tz_init_wrapper is being forced as an ARM symbol,
25  * callers will use 'blx' to come here forcing a switch to
26  * ARM mode. The wrapper does its job and returns back to the
27  * Thumb caller.
28  */
29 .arm
31  * int tz_init_wrapper(int, int, void *);
32  */
33 ENTRY(tz_init_wrapper)
34         .global tz_init_wrapper
36         /*
37          *      r0 = tz_arg1
38          *      r1 = tz_arg2
39          *      r2 = tz_load_addr
40          */
42         /*
43          * Per the AAPCS
44          *      r0, r1, r2, r3, r12 can be clobbered
45          *      r4, r5, r6, r7, r8, r9, r10, r11 have to be preserved
46          *
47          * Following code clobbers
48          *      r0 - Setting return value to zero
49          *      r1 - For doing a thumb return
50          *      r3 - Passing 'SP' from current mode to 'svc' mode
51          *      r4 - To save & restore CPSR
52          *
53          * Per AAPCS, save and restore r4, rest are 'clobberable' :)
54          * The invoked code takes care of saving and restoring the other
55          * preserved registers (i.e. r5 - r11)
56          *
57          * Stack Usage:
58          *      SP ->   | LR    |       (Lower address)
59          *              | r4    |
60          *              | CPSR  |
61          *              |-------|
62          *              |   .   |
63          *              |   .   |
64          *              |   .   |       (Higher address)
65          */
67         sub     sp, sp, #12     /* Allocate stack frame */
68         str     lr, [sp]        /* Save return address */
69         str     r4, [sp, #4]    /* Use r4 to hold the new CPSR value */
71         mov     r3, sp          /* Get current stack pointer */
73         mrs     r4, CPSR        /* save CPSR */
74         str     r4, [sp, #8]
76         bic     r4, r4, 0x1f    /* Clear mode bits */
77         orr     r4, r4, 0x13    /* 'svc' mode */
78         msr     cpsr_cxf, r4    /* Switch to Supervisor mode. */
79         mov     sp, r3          /* Use the same stack as the previous mode */
81         blx     r2              /* Jump to TZ in ARM mode */
83         nop                     /* back from TZ, in ARM mode */
85         ldr     r4, [sp, #8]    /* restore CPSR */
86         msr     cpsr_cxf, r4
88         ldr     r4, [sp, #4]    /* restore r4 */
90         ldr     lr, [sp]        /* saved return address */
91         add     sp, sp, #12     /* free stack frame */
93         bx      lr              /* back to thumb caller */
95 ENDPROC(tz_init_wrapper)