Merge tag 'fsl-qoriq-for-v2019.01-rc2' of git://git.denx.de/u-boot-fsl-qoriq
[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
18 #ifdef CONFIG_32BIT
19 #define LREG                    lw
20 #define SREG                    sw
21 #define REGBYTES                4
22 #define RELOC_TYPE              R_RISCV_32
23 #define SYM_INDEX               0x8
24 #define SYM_SIZE                0x10
25 #else
26 #define LREG                    ld
27 #define SREG                    sd
28 #define REGBYTES                8
29 #define RELOC_TYPE              R_RISCV_64
30 #define SYM_INDEX               0x20
31 #define SYM_SIZE                0x18
32 #endif
33
34 .section .text
35 .globl _start
36 _start:
37         /* save hart id and dtb pointer */
38         mv      s0, a0
39         mv      s1, a1
40
41         la      t0, trap_entry
42         csrw    MODE_PREFIX(tvec), t0
43
44         /* mask all interrupts */
45         csrw    MODE_PREFIX(ie), zero
46
47         /* Enable cache */
48         jal     icache_enable
49         jal     dcache_enable
50
51 /*
52  * Set stackpointer in internal/ex RAM to call board_init_f
53  */
54 call_board_init_f:
55         li      t0, -16
56         li      t1, CONFIG_SYS_INIT_SP_ADDR
57         and     sp, t1, t0              /* force 16 byte alignment */
58
59 #ifdef CONFIG_DEBUG_UART
60         jal     debug_uart_init
61 #endif
62
63 call_board_init_f_0:
64         mv      a0, sp
65         jal     board_init_f_alloc_reserve
66         mv      sp, a0
67
68         la      t0, prior_stage_fdt_address
69         SREG    s1, 0(t0)
70
71         jal     board_init_f_init_reserve
72
73         mv      a0, zero                /* a0 <-- boot_flags = 0 */
74         la      t5, board_init_f
75         jr      t5                      /* jump to board_init_f() */
76
77 /*
78  * void relocate_code (addr_sp, gd, addr_moni)
79  *
80  * This "function" does not return, instead it continues in RAM
81  * after relocating the monitor code.
82  *
83  */
84 .globl relocate_code
85 relocate_code:
86         mv      s2, a0                  /* save addr_sp */
87         mv      s3, a1                  /* save addr of gd */
88         mv      s4, a2                  /* save addr of destination */
89
90 /*
91  *Set up the stack
92  */
93 stack_setup:
94         mv      sp, s2
95         la      t0, _start
96         sub     t6, s4, t0              /* t6 <- relocation offset */
97         beq     t0, s4, clear_bss       /* skip relocation */
98
99         mv      t1, s4                  /* t1 <- scratch for copy_loop */
100         la      t3, __bss_start
101         sub     t3, t3, t0              /* t3 <- __bss_start_ofs */
102         add     t2, t0, t3              /* t2 <- source end address */
103
104 copy_loop:
105         LREG    t5, 0(t0)
106         addi    t0, t0, REGBYTES
107         SREG    t5, 0(t1)
108         addi    t1, t1, REGBYTES
109         blt     t0, t2, copy_loop
110
111 /*
112  * Update dynamic relocations after board_init_f
113  */
114 fix_rela_dyn:
115         la      t1, __rel_dyn_start
116         la      t2, __rel_dyn_end
117         beq     t1, t2, clear_bss
118         add     t1, t1, t6              /* t1 <- rela_dyn_start in RAM */
119         add     t2, t2, t6              /* t2 <- rela_dyn_end in RAM */
120
121 /*
122  * skip first reserved entry: address, type, addend
123  */
124         bne     t1, t2, 7f
125
126 6:
127         LREG    t5, -(REGBYTES*2)(t1)   /* t5 <-- relocation info:type */
128         li      t3, R_RISCV_RELATIVE    /* reloc type R_RISCV_RELATIVE */
129         bne     t5, t3, 8f              /* skip non-RISCV_RELOC entries */
130         LREG    t3, -(REGBYTES*3)(t1)
131         LREG    t5, -(REGBYTES)(t1)     /* t5 <-- addend */
132         add     t5, t5, t6              /* t5 <-- location to fix up in RAM */
133         add     t3, t3, t6              /* t3 <-- location to fix up in RAM */
134         SREG    t5, 0(t3)
135 7:
136         addi    t1, t1, (REGBYTES*3)
137         ble     t1, t2, 6b
138
139 8:
140         la      t4, __dyn_sym_start
141         add     t4, t4, t6
142
143 9:
144         LREG    t5, -(REGBYTES*2)(t1)   /* t5 <-- relocation info:type */
145         srli    t0, t5, SYM_INDEX       /* t0 <--- sym table index */
146         andi    t5, t5, 0xFF            /* t5 <--- relocation type */
147         li      t3, RELOC_TYPE
148         bne     t5, t3, 10f             /* skip non-addned entries */
149
150         LREG    t3, -(REGBYTES*3)(t1)
151         li      t5, SYM_SIZE
152         mul     t0, t0, t5
153         add     s5, t4, t0
154         LREG    t5, REGBYTES(s5)
155         add     t5, t5, t6              /* t5 <-- location to fix up in RAM */
156         add     t3, t3, t6              /* t3 <-- location to fix up in RAM */
157         SREG    t5, 0(t3)
158 10:
159         addi    t1, t1, (REGBYTES*3)
160         ble     t1, t2, 9b
161
162 /*
163  * trap update
164 */
165         la      t0, trap_entry
166         add     t0, t0, t6
167         csrw    MODE_PREFIX(tvec), t0
168
169 clear_bss:
170         la      t0, __bss_start         /* t0 <- rel __bss_start in FLASH */
171         add     t0, t0, t6              /* t0 <- rel __bss_start in RAM */
172         la      t1, __bss_end           /* t1 <- rel __bss_end in FLASH */
173         add     t1, t1, t6              /* t1 <- rel __bss_end in RAM */
174         beq     t0, t1, call_board_init_r
175
176 clbss_l:
177         SREG    zero, 0(t0)             /* clear loop... */
178         addi    t0, t0, REGBYTES
179         bne     t0, t1, clbss_l
180
181 /*
182  * We are done. Do not return, instead branch to second part of board
183  * initialization, now running from RAM.
184  */
185 call_board_init_r:
186         jal     invalidate_icache_all
187         jal     flush_dcache_all
188         la      t0, board_init_r
189         mv      t4, t0                  /* offset of board_init_r() */
190         add     t4, t4, t6              /* real address of board_init_r() */
191 /*
192  * setup parameters for board_init_r
193  */
194         mv      a0, s3                  /* gd_t */
195         mv      a1, s4                  /* dest_addr */
196
197 /*
198  * jump to it ...
199  */
200         jr      t4                      /* jump to board_init_r() */
201
202 /*
203  * trap entry
204  */
205 .align 2
206 trap_entry:
207         addi    sp, sp, -32*REGBYTES
208         SREG    x1, 1*REGBYTES(sp)
209         SREG    x2, 2*REGBYTES(sp)
210         SREG    x3, 3*REGBYTES(sp)
211         SREG    x4, 4*REGBYTES(sp)
212         SREG    x5, 5*REGBYTES(sp)
213         SREG    x6, 6*REGBYTES(sp)
214         SREG    x7, 7*REGBYTES(sp)
215         SREG    x8, 8*REGBYTES(sp)
216         SREG    x9, 9*REGBYTES(sp)
217         SREG    x10, 10*REGBYTES(sp)
218         SREG    x11, 11*REGBYTES(sp)
219         SREG    x12, 12*REGBYTES(sp)
220         SREG    x13, 13*REGBYTES(sp)
221         SREG    x14, 14*REGBYTES(sp)
222         SREG    x15, 15*REGBYTES(sp)
223         SREG    x16, 16*REGBYTES(sp)
224         SREG    x17, 17*REGBYTES(sp)
225         SREG    x18, 18*REGBYTES(sp)
226         SREG    x19, 19*REGBYTES(sp)
227         SREG    x20, 20*REGBYTES(sp)
228         SREG    x21, 21*REGBYTES(sp)
229         SREG    x22, 22*REGBYTES(sp)
230         SREG    x23, 23*REGBYTES(sp)
231         SREG    x24, 24*REGBYTES(sp)
232         SREG    x25, 25*REGBYTES(sp)
233         SREG    x26, 26*REGBYTES(sp)
234         SREG    x27, 27*REGBYTES(sp)
235         SREG    x28, 28*REGBYTES(sp)
236         SREG    x29, 29*REGBYTES(sp)
237         SREG    x30, 30*REGBYTES(sp)
238         SREG    x31, 31*REGBYTES(sp)
239         csrr    a0, MODE_PREFIX(cause)
240         csrr    a1, MODE_PREFIX(epc)
241         mv      a2, sp
242         jal     handle_trap
243         csrw    MODE_PREFIX(epc), a0
244
245 #ifdef CONFIG_RISCV_SMODE
246 /*
247  * Remain in S-mode after sret
248  */
249         li      t0, SSTATUS_SPP
250 #else
251 /*
252  * Remain in M-mode after mret
253  */
254         li      t0, MSTATUS_MPP
255 #endif
256         csrs    MODE_PREFIX(status), t0
257         LREG    x1, 1*REGBYTES(sp)
258         LREG    x2, 2*REGBYTES(sp)
259         LREG    x3, 3*REGBYTES(sp)
260         LREG    x4, 4*REGBYTES(sp)
261         LREG    x5, 5*REGBYTES(sp)
262         LREG    x6, 6*REGBYTES(sp)
263         LREG    x7, 7*REGBYTES(sp)
264         LREG    x8, 8*REGBYTES(sp)
265         LREG    x9, 9*REGBYTES(sp)
266         LREG    x10, 10*REGBYTES(sp)
267         LREG    x11, 11*REGBYTES(sp)
268         LREG    x12, 12*REGBYTES(sp)
269         LREG    x13, 13*REGBYTES(sp)
270         LREG    x14, 14*REGBYTES(sp)
271         LREG    x15, 15*REGBYTES(sp)
272         LREG    x16, 16*REGBYTES(sp)
273         LREG    x17, 17*REGBYTES(sp)
274         LREG    x18, 18*REGBYTES(sp)
275         LREG    x19, 19*REGBYTES(sp)
276         LREG    x20, 20*REGBYTES(sp)
277         LREG    x21, 21*REGBYTES(sp)
278         LREG    x22, 22*REGBYTES(sp)
279         LREG    x23, 23*REGBYTES(sp)
280         LREG    x24, 24*REGBYTES(sp)
281         LREG    x25, 25*REGBYTES(sp)
282         LREG    x26, 26*REGBYTES(sp)
283         LREG    x27, 27*REGBYTES(sp)
284         LREG    x28, 28*REGBYTES(sp)
285         LREG    x29, 29*REGBYTES(sp)
286         LREG    x30, 30*REGBYTES(sp)
287         LREG    x31, 31*REGBYTES(sp)
288         addi    sp, sp, 32*REGBYTES
289         MODE_PREFIX(ret)