1 /* SPDX-License-Identifier: GPL-2.0-only */
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
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.
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.
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
31 * int tz_init_wrapper(int, int, void *);
33 ENTRY(tz_init_wrapper)
34 .global tz_init_wrapper
44 * r0, r1, r2, r3, r12 can be clobbered
45 * r4, r5, r6, r7, r8, r9, r10, r11 have to be preserved
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
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)
58 * SP -> | LR | (Lower address)
64 * | . | (Higher address)
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 */
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 */
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)