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