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