c2837876b1617dfad139e82ee4f23724b208a7be
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / fsl-lsch3 / lowlevel.S
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>
11 #include <asm/gic.h>
12 #include <asm/macro.h>
13 #include "mp.h"
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
40         branch_if_master x0, x1, 2f
41
42         ldr     x0, =secondary_boot_func
43         blr     x0
44 2:
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
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)
117         /*
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]
134          */
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] */
140         /*
141          * offset of the spin table element for this core from start of spin
142          * table (each elem is padded to 64 bytes)
143          */
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
161 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
162         bl secondary_switch_to_el1
163 #endif
164
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