xref: /openbmc/u-boot/arch/riscv/cpu/start.S (revision 8bfa231cc6e1df1848273ed423a105890fd8b902)
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	csrwi	mstatus, 0
42	csrwi	mie, 0
43
44/*
45 * Set stackpointer in internal/ex RAM to call board_init_f
46 */
47call_board_init_f:
48	li	t0, -16
49	li	t1, CONFIG_SYS_INIT_SP_ADDR
50	and	sp, t1, t0		/* force 16 byte alignment */
51
52#ifdef CONFIG_DEBUG_UART
53	jal	debug_uart_init
54#endif
55
56call_board_init_f_0:
57	mv	a0, sp
58	jal	board_init_f_alloc_reserve
59	mv	sp, a0
60	jal	board_init_f_init_reserve
61
62	mv	a0, zero		/* a0 <-- boot_flags = 0 */
63	la	t5, board_init_f
64	jr	t5			/* jump to board_init_f() */
65
66/*
67 * void relocate_code (addr_sp, gd, addr_moni)
68 *
69 * This "function" does not return, instead it continues in RAM
70 * after relocating the monitor code.
71 *
72 */
73.globl relocate_code
74relocate_code:
75	mv	s2, a0			/* save addr_sp */
76	mv	s3, a1			/* save addr of gd */
77	mv	s4, a2			/* save addr of destination */
78
79/*
80 *Set up the stack
81 */
82stack_setup:
83	mv	sp, s2
84	la	t0, _start
85	sub	t6, s4, t0		/* t6 <- relocation offset */
86	beq	t0, s4, clear_bss	/* skip relocation */
87
88	mv	t1, s4			/* t1 <- scratch for copy_loop */
89	la	t3, __bss_start
90	sub	t3, t3, t0		/* t3 <- __bss_start_ofs */
91	add	t2, t0, t3		/* t2 <- source end address */
92
93copy_loop:
94	LREG	t5, 0(t0)
95	addi	t0, t0, REGBYTES
96	SREG	t5, 0(t1)
97	addi	t1, t1, REGBYTES
98	blt	t0, t2, copy_loop
99
100/*
101 * Update dynamic relocations after board_init_f
102 */
103fix_rela_dyn:
104	la	t1, __rel_dyn_start
105	la	t2, __rel_dyn_end
106	beq	t1, t2, clear_bss
107	add	t1, t1, t6		/* t1 <- rela_dyn_start in RAM */
108	add	t2, t2, t6		/* t2 <- rela_dyn_end in RAM */
109
110/*
111 * skip first reserved entry: address, type, addend
112 */
113	bne	t1, t2, 7f
114
1156:
116	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
117	li	t3, R_RISCV_RELATIVE	/* reloc type R_RISCV_RELATIVE */
118	bne	t5, t3, 8f		/* skip non-RISCV_RELOC entries */
119	LREG	t3, -(REGBYTES*3)(t1)
120	LREG	t5, -(REGBYTES)(t1)	/* t5 <-- addend */
121	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
122	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
123	SREG	t5, 0(t3)
1247:
125	addi	t1, t1, (REGBYTES*3)
126	ble	t1, t2, 6b
127
1288:
129	la	t4, __dyn_sym_start
130	add	t4, t4, t6
131
1329:
133	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
134	srli	t0, t5, SYM_INDEX	/* t0 <--- sym table index */
135	andi	t5, t5, 0xFF		/* t5 <--- relocation type */
136	li	t3, RELOC_TYPE
137	bne	t5, t3, 10f		/* skip non-addned entries */
138
139	LREG	t3, -(REGBYTES*3)(t1)
140	li	t5, SYM_SIZE
141	mul	t0, t0, t5
142	add	s1, t4, t0
143	LREG	t5, REGBYTES(s1)
144	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
145	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
146	SREG	t5, 0(t3)
14710:
148	addi	t1, t1, (REGBYTES*3)
149	ble	t1, t2, 9b
150
151/*
152 * trap update
153*/
154	la	t0, trap_entry
155	add	t0, t0, t6
156	csrw	mtvec, t0
157
158clear_bss:
159	la	t0, __bss_start		/* t0 <- rel __bss_start in FLASH */
160	add	t0, t0, t6		/* t0 <- rel __bss_start in RAM */
161	la	t1, __bss_end		/* t1 <- rel __bss_end in FLASH */
162	add	t1, t1, t6		/* t1 <- rel __bss_end in RAM */
163	li	t2, 0x00000000		/* clear */
164	beq	t0, t1, call_board_init_r
165
166clbss_l:
167	SREG	t2, 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 */
175call_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
194trap_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
271