riscv: Merge unnecessary SMP ifdefs in start.S
[oweals/u-boot.git] / arch / riscv / cpu / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Startup Code for RISC-V Core
4  *
5  * Copyright (c) 2017 Microsemi Corporation.
6  * Copyright (c) 2017 Padmarao Begari <Padmarao.Begari@microsemi.com>
7  *
8  * Copyright (C) 2017 Andes Technology Corporation
9  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
10  */
11
12 #include <asm-offsets.h>
13 #include <config.h>
14 #include <common.h>
15 #include <elf.h>
16 #include <asm/encoding.h>
17 #include <generated/asm-offsets.h>
18
19 #ifdef CONFIG_32BIT
20 #define LREG                    lw
21 #define SREG                    sw
22 #define REGBYTES                4
23 #define RELOC_TYPE              R_RISCV_32
24 #define SYM_INDEX               0x8
25 #define SYM_SIZE                0x10
26 #else
27 #define LREG                    ld
28 #define SREG                    sd
29 #define REGBYTES                8
30 #define RELOC_TYPE              R_RISCV_64
31 #define SYM_INDEX               0x20
32 #define SYM_SIZE                0x18
33 #endif
34
35 .section .data
36 secondary_harts_relocation_error:
37         .ascii "Relocation of secondary harts has failed, error %d\n"
38
39 .section .text
40 .globl _start
41 _start:
42 #if CONFIG_IS_ENABLED(RISCV_MMODE)
43         csrr    a0, CSR_MHARTID
44 #endif
45
46         /* save hart id and dtb pointer */
47         mv      tp, a0
48         mv      s1, a1
49
50         la      t0, trap_entry
51         csrw    MODE_PREFIX(tvec), t0
52
53         /* mask all interrupts */
54         csrw    MODE_PREFIX(ie), zero
55
56 #ifdef CONFIG_SMP
57         /* check if hart is within range */
58         /* tp: hart id */
59         li      t0, CONFIG_NR_CPUS
60         bge     tp, t0, hart_out_of_bounds_loop
61
62         /* set xSIE bit to receive IPIs */
63 #if CONFIG_IS_ENABLED(RISCV_MMODE)
64         li      t0, MIE_MSIE
65 #else
66         li      t0, SIE_SSIE
67 #endif
68         csrs    MODE_PREFIX(ie), t0
69 #endif
70
71 /*
72  * Set stackpointer in internal/ex RAM to call board_init_f
73  */
74 call_board_init_f:
75         li      t0, -16
76 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
77         li      t1, CONFIG_SPL_STACK
78 #else
79         li      t1, CONFIG_SYS_INIT_SP_ADDR
80 #endif
81         and     sp, t1, t0              /* force 16 byte alignment */
82
83 call_board_init_f_0:
84         mv      a0, sp
85         jal     board_init_f_alloc_reserve
86
87         /*
88          * Set global data pointer here for all harts, uninitialized at this
89          * point.
90          */
91         mv      gp, a0
92
93         /* setup stack */
94 #ifdef CONFIG_SMP
95         /* tp: hart id */
96         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
97         sub     sp, a0, t0
98 #else
99         mv      sp, a0
100 #endif
101
102 #ifndef CONFIG_XIP
103         /*
104          * Pick hart to initialize global data and run U-Boot. The other harts
105          * wait for initialization to complete.
106          */
107         la      t0, hart_lottery
108         li      s2, 1
109         amoswap.w s2, t1, 0(t0)
110         bnez    s2, wait_for_gd_init
111 #else
112         bnez    tp, secondary_hart_loop
113 #endif
114
115 #ifdef CONFIG_OF_PRIOR_STAGE
116         la      t0, prior_stage_fdt_address
117         SREG    s1, 0(t0)
118 #endif
119
120         jal     board_init_f_init_reserve
121
122         /* save the boot hart id to global_data */
123         SREG    tp, GD_BOOT_HART(gp)
124
125 #ifndef CONFIG_XIP
126         la      t0, available_harts_lock
127         fence   rw, w
128         amoswap.w zero, zero, 0(t0)
129
130 wait_for_gd_init:
131         la      t0, available_harts_lock
132         li      t1, 1
133 1:      amoswap.w t1, t1, 0(t0)
134         fence   r, rw
135         bnez    t1, 1b
136
137         /* register available harts in the available_harts mask */
138         li      t1, 1
139         sll     t1, t1, tp
140         LREG    t2, GD_AVAILABLE_HARTS(gp)
141         or      t2, t2, t1
142         SREG    t2, GD_AVAILABLE_HARTS(gp)
143
144         fence   rw, w
145         amoswap.w zero, zero, 0(t0)
146
147         /*
148          * Continue on hart lottery winner, others branch to
149          * secondary_hart_loop.
150          */
151         bnez    s2, secondary_hart_loop
152 #endif
153
154         /* Enable cache */
155         jal     icache_enable
156         jal     dcache_enable
157
158 #ifdef CONFIG_DEBUG_UART
159         jal     debug_uart_init
160 #endif
161
162         mv      a0, zero                /* a0 <-- boot_flags = 0 */
163         la      t5, board_init_f
164         jalr    t5                      /* jump to board_init_f() */
165
166 #ifdef CONFIG_SPL_BUILD
167 spl_clear_bss:
168         la      t0, __bss_start
169         la      t1, __bss_end
170         beq     t0, t1, spl_stack_gd_setup
171
172 spl_clear_bss_loop:
173         SREG    zero, 0(t0)
174         addi    t0, t0, REGBYTES
175         blt     t0, t1, spl_clear_bss_loop
176
177 spl_stack_gd_setup:
178         jal     spl_relocate_stack_gd
179
180         /* skip setup if we did not relocate */
181         beqz    a0, spl_call_board_init_r
182         mv      s0, a0
183
184         /* setup stack on main hart */
185 #ifdef CONFIG_SMP
186         /* tp: hart id */
187         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
188         sub     sp, s0, t0
189 #else
190         mv      sp, s0
191 #endif
192
193         /* set new stack and global data pointer on secondary harts */
194 spl_secondary_hart_stack_gd_setup:
195         la      a0, secondary_hart_relocate
196         mv      a1, s0
197         mv      a2, s0
198         mv      a3, zero
199         jal     smp_call_function
200
201         /* hang if relocation of secondary harts has failed */
202         beqz    a0, 1f
203         mv      a1, a0
204         la      a0, secondary_harts_relocation_error
205         jal     printf
206         jal     hang
207
208         /* set new global data pointer on main hart */
209 1:      mv      gp, s0
210
211 spl_call_board_init_r:
212         mv      a0, zero
213         mv      a1, zero
214         jal     board_init_r
215 #endif
216
217 /*
218  * void relocate_code(addr_sp, gd, addr_moni)
219  *
220  * This "function" does not return, instead it continues in RAM
221  * after relocating the monitor code.
222  *
223  */
224 .globl relocate_code
225 relocate_code:
226         mv      s2, a0                  /* save addr_sp */
227         mv      s3, a1                  /* save addr of gd */
228         mv      s4, a2                  /* save addr of destination */
229
230 /*
231  *Set up the stack
232  */
233 stack_setup:
234 #ifdef CONFIG_SMP
235         /* tp: hart id */
236         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
237         sub     sp, s2, t0
238 #else
239         mv      sp, s2
240 #endif
241
242         la      t0, _start
243         sub     t6, s4, t0              /* t6 <- relocation offset */
244         beq     t0, s4, clear_bss       /* skip relocation */
245
246         mv      t1, s4                  /* t1 <- scratch for copy_loop */
247         la      t3, __bss_start
248         sub     t3, t3, t0              /* t3 <- __bss_start_ofs */
249         add     t2, t0, t3              /* t2 <- source end address */
250
251 copy_loop:
252         LREG    t5, 0(t0)
253         addi    t0, t0, REGBYTES
254         SREG    t5, 0(t1)
255         addi    t1, t1, REGBYTES
256         blt     t0, t2, copy_loop
257
258 /*
259  * Update dynamic relocations after board_init_f
260  */
261 fix_rela_dyn:
262         la      t1, __rel_dyn_start
263         la      t2, __rel_dyn_end
264         beq     t1, t2, clear_bss
265         add     t1, t1, t6              /* t1 <- rela_dyn_start in RAM */
266         add     t2, t2, t6              /* t2 <- rela_dyn_end in RAM */
267
268 /*
269  * skip first reserved entry: address, type, addend
270  */
271         j       10f
272
273 6:
274         LREG    t5, -(REGBYTES*2)(t1)   /* t5 <-- relocation info:type */
275         li      t3, R_RISCV_RELATIVE    /* reloc type R_RISCV_RELATIVE */
276         bne     t5, t3, 8f              /* skip non-RISCV_RELOC entries */
277         LREG    t3, -(REGBYTES*3)(t1)
278         LREG    t5, -(REGBYTES)(t1)     /* t5 <-- addend */
279         add     t5, t5, t6              /* t5 <-- location to fix up in RAM */
280         add     t3, t3, t6              /* t3 <-- location to fix up in RAM */
281         SREG    t5, 0(t3)
282         j       10f
283
284 8:
285         la      t4, __dyn_sym_start
286         add     t4, t4, t6
287
288 9:
289         LREG    t5, -(REGBYTES*2)(t1)   /* t5 <-- relocation info:type */
290         srli    t0, t5, SYM_INDEX       /* t0 <--- sym table index */
291         andi    t5, t5, 0xFF            /* t5 <--- relocation type */
292         li      t3, RELOC_TYPE
293         bne     t5, t3, 10f             /* skip non-addned entries */
294
295         LREG    t3, -(REGBYTES*3)(t1)
296         li      t5, SYM_SIZE
297         mul     t0, t0, t5
298         add     s5, t4, t0
299         LREG    t0, -(REGBYTES)(t1)     /* t0 <-- addend */
300         LREG    t5, REGBYTES(s5)
301         add     t5, t5, t0
302         add     t5, t5, t6              /* t5 <-- location to fix up in RAM */
303         add     t3, t3, t6              /* t3 <-- location to fix up in RAM */
304         SREG    t5, 0(t3)
305 10:
306         addi    t1, t1, (REGBYTES*3)
307         ble     t1, t2, 6b
308
309 /*
310  * trap update
311 */
312         la      t0, trap_entry
313         add     t0, t0, t6
314         csrw    MODE_PREFIX(tvec), t0
315
316 clear_bss:
317         la      t0, __bss_start         /* t0 <- rel __bss_start in FLASH */
318         add     t0, t0, t6              /* t0 <- rel __bss_start in RAM */
319         la      t1, __bss_end           /* t1 <- rel __bss_end in FLASH */
320         add     t1, t1, t6              /* t1 <- rel __bss_end in RAM */
321         beq     t0, t1, relocate_secondary_harts
322
323 clbss_l:
324         SREG    zero, 0(t0)             /* clear loop... */
325         addi    t0, t0, REGBYTES
326         blt     t0, t1, clbss_l
327
328 relocate_secondary_harts:
329 #ifdef CONFIG_SMP
330         /* send relocation IPI */
331         la      t0, secondary_hart_relocate
332         add     a0, t0, t6
333
334         /* store relocation offset */
335         mv      s5, t6
336
337         mv      a1, s2
338         mv      a2, s3
339         mv      a3, zero
340         jal     smp_call_function
341
342         /* hang if relocation of secondary harts has failed */
343         beqz    a0, 1f
344         mv      a1, a0
345         la      a0, secondary_harts_relocation_error
346         jal     printf
347         jal     hang
348
349         /* restore relocation offset */
350 1:      mv      t6, s5
351 #endif
352
353 /*
354  * We are done. Do not return, instead branch to second part of board
355  * initialization, now running from RAM.
356  */
357 call_board_init_r:
358         jal     invalidate_icache_all
359         jal     flush_dcache_all
360         la      t0, board_init_r        /* offset of board_init_r() */
361         add     t4, t0, t6              /* real address of board_init_r() */
362 /*
363  * setup parameters for board_init_r
364  */
365         mv      a0, s3                  /* gd_t */
366         mv      a1, s4                  /* dest_addr */
367
368 /*
369  * jump to it ...
370  */
371         jr      t4                      /* jump to board_init_r() */
372
373 #ifdef CONFIG_SMP
374 hart_out_of_bounds_loop:
375         /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
376         wfi
377         j       hart_out_of_bounds_loop
378
379 /* SMP relocation entry */
380 secondary_hart_relocate:
381         /* a1: new sp */
382         /* a2: new gd */
383         /* tp: hart id */
384
385         /* setup stack */
386         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
387         sub     sp, a1, t0
388
389         /* update global data pointer */
390         mv      gp, a2
391 #endif
392
393 secondary_hart_loop:
394         wfi
395
396 #ifdef CONFIG_SMP
397         csrr    t0, MODE_PREFIX(ip)
398 #if CONFIG_IS_ENABLED(RISCV_MMODE)
399         andi    t0, t0, MIE_MSIE
400 #else
401         andi    t0, t0, SIE_SSIE
402 #endif
403         beqz    t0, secondary_hart_loop
404
405         mv      a0, tp
406         jal     handle_ipi
407 #endif
408
409         j       secondary_hart_loop