]>
Commit | Line | Data |
---|---|---|
2f78eae5 YS |
1 | /* |
2 | * (C) Copyright 2014 Freescale Semiconductor | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | * | |
6 | * Extracted from armv8/start.S | |
7 | */ | |
8 | ||
9 | #include <config.h> | |
10 | #include <linux/linkage.h> | |
40f8dec5 | 11 | #include <asm/gic.h> |
2f78eae5 | 12 | #include <asm/macro.h> |
40f8dec5 | 13 | #include "mp.h" |
2f78eae5 YS |
14 | |
15 | ENTRY(lowlevel_init) | |
16 | mov x29, lr /* Save LR */ | |
17 | ||
18 | /* Set the SMMU page size in the sACR register */ | |
19 | ldr x1, =SMMU_BASE | |
20 | ldr w0, [x1, #0x10] | |
21 | orr w0, w0, #1 << 16 /* set sACR.pagesize to indicate 64K page */ | |
22 | str w0, [x1, #0x10] | |
23 | ||
24 | /* Initialize GIC Secure Bank Status */ | |
25 | #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) | |
26 | branch_if_slave x0, 1f | |
27 | ldr x0, =GICD_BASE | |
28 | bl gic_init_secure | |
29 | 1: | |
30 | #ifdef CONFIG_GICV3 | |
31 | ldr x0, =GICR_BASE | |
32 | bl gic_init_secure_percpu | |
33 | #elif defined(CONFIG_GICV2) | |
34 | ldr x0, =GICD_BASE | |
35 | ldr x1, =GICC_BASE | |
36 | bl gic_init_secure_percpu | |
37 | #endif | |
38 | #endif | |
39 | ||
40f8dec5 | 40 | branch_if_master x0, x1, 2f |
2f78eae5 | 41 | |
40f8dec5 YS |
42 | ldr x0, =secondary_boot_func |
43 | blr x0 | |
44 | 2: | |
9c66ce66 BS |
45 | |
46 | #ifdef CONFIG_FSL_TZPC_BP147 | |
47 | /* Set Non Secure access for all devices protected via TZPC */ | |
48 | ldr x1, =TZPCDECPROT_0_SET_BASE /* Decode Protection-0 Set Reg */ | |
49 | orr w0, w0, #1 << 3 /* DCFG_RESET is accessible from NS world */ | |
50 | str w0, [x1] | |
51 | ||
52 | isb | |
53 | dsb sy | |
54 | #endif | |
55 | ||
56 | #ifdef CONFIG_FSL_TZASC_400 | |
57 | /* Set TZASC so that: | |
58 | * a. We use only Region0 whose global secure write/read is EN | |
59 | * b. We use only Region0 whose NSAID write/read is EN | |
60 | * | |
61 | * NOTE: As per the CCSR map doc, TZASC 3 and TZASC 4 are just | |
62 | * placeholders. | |
63 | */ | |
64 | ldr x1, =TZASC_GATE_KEEPER(0) | |
65 | ldr x0, [x1] /* Filter 0 Gate Keeper Register */ | |
66 | orr x0, x0, #1 << 0 /* Set open_request for Filter 0 */ | |
67 | str x0, [x1] | |
68 | ||
69 | ldr x1, =TZASC_GATE_KEEPER(1) | |
70 | ldr x0, [x1] /* Filter 0 Gate Keeper Register */ | |
71 | orr x0, x0, #1 << 0 /* Set open_request for Filter 0 */ | |
72 | str x0, [x1] | |
73 | ||
74 | ldr x1, =TZASC_REGION_ATTRIBUTES_0(0) | |
75 | ldr x0, [x1] /* Region-0 Attributes Register */ | |
76 | orr x0, x0, #1 << 31 /* Set Sec global write en, Bit[31] */ | |
77 | orr x0, x0, #1 << 30 /* Set Sec global read en, Bit[30] */ | |
78 | str x0, [x1] | |
79 | ||
80 | ldr x1, =TZASC_REGION_ATTRIBUTES_0(1) | |
81 | ldr x0, [x1] /* Region-1 Attributes Register */ | |
82 | orr x0, x0, #1 << 31 /* Set Sec global write en, Bit[31] */ | |
83 | orr x0, x0, #1 << 30 /* Set Sec global read en, Bit[30] */ | |
84 | str x0, [x1] | |
85 | ||
86 | ldr x1, =TZASC_REGION_ID_ACCESS_0(0) | |
87 | ldr w0, [x1] /* Region-0 Access Register */ | |
88 | mov w0, #0xFFFFFFFF /* Set nsaid_wr_en and nsaid_rd_en */ | |
89 | str w0, [x1] | |
90 | ||
91 | ldr x1, =TZASC_REGION_ID_ACCESS_0(1) | |
92 | ldr w0, [x1] /* Region-1 Attributes Register */ | |
93 | mov w0, #0xFFFFFFFF /* Set nsaid_wr_en and nsaid_rd_en */ | |
94 | str w0, [x1] | |
95 | ||
96 | isb | |
97 | dsb sy | |
98 | #endif | |
40f8dec5 YS |
99 | mov lr, x29 /* Restore LR */ |
100 | ret | |
101 | ENDPROC(lowlevel_init) | |
102 | ||
103 | /* Keep literals not used by the secondary boot code outside it */ | |
104 | .ltorg | |
105 | ||
106 | /* Using 64 bit alignment since the spin table is accessed as data */ | |
107 | .align 4 | |
108 | .global secondary_boot_code | |
109 | /* Secondary Boot Code starts here */ | |
110 | secondary_boot_code: | |
111 | .global __spin_table | |
112 | __spin_table: | |
113 | .space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE | |
114 | ||
115 | .align 2 | |
116 | ENTRY(secondary_boot_func) | |
2f78eae5 | 117 | /* |
40f8dec5 YS |
118 | * MPIDR_EL1 Fields: |
119 | * MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1) | |
120 | * MPIDR[7:2] = AFF0_RES | |
121 | * MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3) | |
122 | * MPIDR[23:16] = AFF2_CLUSTERID | |
123 | * MPIDR[24] = MT | |
124 | * MPIDR[29:25] = RES0 | |
125 | * MPIDR[30] = U | |
126 | * MPIDR[31] = ME | |
127 | * MPIDR[39:32] = AFF3 | |
128 | * | |
129 | * Linear Processor ID (LPID) calculation from MPIDR_EL1: | |
130 | * (We only use AFF0_CPUID and AFF1_CLUSTERID for now | |
131 | * until AFF2_CLUSTERID and AFF3 have non-zero values) | |
132 | * | |
133 | * LPID = MPIDR[15:8] | MPIDR[1:0] | |
2f78eae5 | 134 | */ |
40f8dec5 YS |
135 | mrs x0, mpidr_el1 |
136 | ubfm x1, x0, #8, #15 | |
137 | ubfm x2, x0, #0, #1 | |
138 | orr x10, x2, x1, lsl #2 /* x10 has LPID */ | |
139 | ubfm x9, x0, #0, #15 /* x9 contains MPIDR[15:0] */ | |
2f78eae5 | 140 | /* |
40f8dec5 YS |
141 | * offset of the spin table element for this core from start of spin |
142 | * table (each elem is padded to 64 bytes) | |
2f78eae5 | 143 | */ |
40f8dec5 YS |
144 | lsl x1, x10, #6 |
145 | ldr x0, =__spin_table | |
146 | /* physical address of this cpus spin table element */ | |
147 | add x11, x1, x0 | |
148 | ||
149 | str x9, [x11, #16] /* LPID */ | |
150 | mov x4, #1 | |
151 | str x4, [x11, #8] /* STATUS */ | |
152 | dsb sy | |
153 | #if defined(CONFIG_GICV3) | |
154 | gic_wait_for_interrupt_m x0 | |
155 | #elif defined(CONFIG_GICV2) | |
156 | ldr x0, =GICC_BASE | |
157 | gic_wait_for_interrupt_m x0, w1 | |
158 | #endif | |
159 | ||
160 | bl secondary_switch_to_el2 | |
2f78eae5 | 161 | #ifdef CONFIG_ARMV8_SWITCH_TO_EL1 |
40f8dec5 | 162 | bl secondary_switch_to_el1 |
2f78eae5 | 163 | #endif |
2f78eae5 | 164 | |
40f8dec5 YS |
165 | slave_cpu: |
166 | wfe | |
167 | ldr x0, [x11] | |
168 | cbz x0, slave_cpu | |
169 | #ifndef CONFIG_ARMV8_SWITCH_TO_EL1 | |
170 | mrs x1, sctlr_el2 | |
171 | #else | |
172 | mrs x1, sctlr_el1 | |
173 | #endif | |
174 | tbz x1, #25, cpu_is_le | |
175 | rev x0, x0 /* BE to LE conversion */ | |
176 | cpu_is_le: | |
177 | br x0 /* branch to the given address */ | |
178 | ENDPROC(secondary_boot_func) | |
179 | ||
180 | ENTRY(secondary_switch_to_el2) | |
181 | switch_el x0, 1f, 0f, 0f | |
182 | 0: ret | |
183 | 1: armv8_switch_to_el2_m x0 | |
184 | ENDPROC(secondary_switch_to_el2) | |
185 | ||
186 | ENTRY(secondary_switch_to_el1) | |
187 | switch_el x0, 0f, 1f, 0f | |
188 | 0: ret | |
189 | 1: armv8_switch_to_el1_m x0, x1 | |
190 | ENDPROC(secondary_switch_to_el1) | |
191 | ||
192 | /* Ensure that the literals used by the secondary boot code are | |
193 | * assembled within it (this is required so that we can protect | |
194 | * this area with a single memreserve region | |
195 | */ | |
196 | .ltorg | |
197 | ||
198 | /* 64 bit alignment for elements accessed as data */ | |
199 | .align 4 | |
200 | .globl __secondary_boot_code_size | |
201 | .type __secondary_boot_code_size, %object | |
202 | /* Secondary Boot Code ends here */ | |
203 | __secondary_boot_code_size: | |
204 | .quad .-secondary_boot_code |