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