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