Merge branch 'master' of git://git.denx.de/u-boot-samsung
[platform/kernel/u-boot.git] / arch / arm / mach-exynos / sec_boot.S
1 /*
2  * Copyright (C) 2013 Samsung Electronics
3  * Akshay Saraswat <akshay.s@samsung.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <config.h>
9 #include <asm/arch/cpu.h>
10
11         .globl relocate_wait_code
12 relocate_wait_code:
13         adr     r0, code_base           @ r0: source address (start)
14         adr     r1, code_end            @ r1: source address (end)
15         ldr     r2, =0x02073000         @ r2: target address
16 1:
17         ldmia   r0!, {r3-r6}
18         stmia   r2!, {r3-r6}
19         cmp     r0, r1
20         blt     1b
21         b       code_end
22         .ltorg
23 /*
24  * Secondary core waits here until Primary wake it up.
25  * Below code is copied to CONFIG_EXYNOS_RELOCATE_CODE_BASE.
26  * This is a workaround code which is supposed to act as a
27  * substitute/supplement to the iROM code.
28  *
29  * This workaround code is relocated to the address 0x02073000
30  * because that comes out to be the last 4KB of the iRAM
31  * (Base Address - 0x02020000, Limit Address - 0x020740000).
32  *
33  * U-boot and kernel are aware of this code and flags by the simple
34  * fact that we are implementing a workaround in the last 4KB
35  * of the iRAM and we have already defined these flag and address
36  * values in both kernel and U-boot for our use.
37  */
38 code_base:
39         b        1f
40 /*
41  * These addresses are being used as flags in u-boot and kernel.
42  *
43  * Jump address for resume and flag to check for resume/reset:
44  * Resume address - 0x2073008
45  * Resume flag - 0x207300C
46  *
47  * Jump address for cluster switching:
48  * Switch address - 0x2073018
49  *
50  * Jump address for core hotplug:
51  * Hotplug address - 0x207301C
52  *
53  * Jump address for C2 state (Reserved for future not being used right now):
54  * C2 address - 0x2073024
55  *
56  * Managed per core status for the active cluster:
57  * CPU0 state - 0x2073028
58  * CPU1 state - 0x207302C
59  * CPU2 state - 0x2073030
60  * CPU3 state - 0x2073034
61  *
62  * Managed per core GIC status for the active cluster:
63  * CPU0 gic state - 0x2073038
64  * CPU1 gic state - 0x207303C
65  * CPU2 gic state - 0x2073040
66  * CPU3 gic state - 0x2073044
67  *
68  * Logic of the code:
69  * Step-1: Read current CPU status.
70  * Step-2: If it's a resume then continue, else jump to step 4.
71  * Step-3: Clear inform1 PMU register and jump to inform0 value.
72  * Step-4: If it's a switch, C2 or reset, get the hotplug address.
73  * Step-5: If address is not available, enter WFE.
74  * Step-6: If address is available, jump to that address.
75  */
76         nop                          @ for backward compatibility
77         .word   0x0                  @ REG0: RESUME_ADDR
78         .word   0x0                  @ REG1: RESUME_FLAG
79         .word   0x0                  @ REG2
80         .word   0x0                  @ REG3
81 _switch_addr:
82         .word   0x0                  @ REG4: SWITCH_ADDR
83 _hotplug_addr:
84         .word   0x0                  @ REG5: CPU1_BOOT_REG
85         .word   0x0                  @ REG6
86 _c2_addr:
87         .word   0x0                  @ REG7: REG_C2_ADDR
88 _cpu_state:
89         .word   0x1                  @ CPU0_STATE : RESET
90         .word   0x2                  @ CPU1_STATE : SECONDARY RESET
91         .word   0x2                  @ CPU2_STATE : SECONDARY RESET
92         .word   0x2                  @ CPU3_STATE : SECONDARY RESET
93 _gic_state:
94         .word   0x0                  @ CPU0 - GICD_IGROUPR0
95         .word   0x0                  @ CPU1 - GICD_IGROUPR0
96         .word   0x0                  @ CPU2 - GICD_IGROUPR0
97         .word   0x0                  @ CPU3 - GICD_IGROUPR0
98 1:
99         adr     r0, _cpu_state
100         mrc     p15, 0, r7, c0, c0, 5   @ read MPIDR
101         and     r7, r7, #0xf        @ r7 = cpu id
102 /* Read the current cpu state */
103         ldr     r10, [r0, r7, lsl #2]
104 svc_entry:
105         tst     r10, #(1 << 4)
106         adrne   r0, _switch_addr
107         bne     wait_for_addr
108 /* Clear INFORM1 */
109         ldr     r0, =(0x10040000 + 0x804)
110         ldr     r1, [r0]
111         cmp     r1, #0x0
112         movne   r1, #0x0
113         strne   r1, [r0]
114 /* Get INFORM0 */
115         ldrne   r1, =(0x10040000 + 0x800)
116         ldrne   pc, [r1]
117         tst     r10, #(1 << 0)
118         ldrne   pc, =0x23e00000
119         adr     r0, _hotplug_addr
120 wait_for_addr:
121         ldr     r1, [r0]
122         cmp     r1, #0x0
123         bxne    r1
124         wfe
125         b        wait_for_addr
126         .ltorg
127 code_end:
128         mov     pc, lr