1 /* SPDX-License-Identifier: GPL-2.0+ */
3 * Startup Code for RISC-V Core
5 * Copyright (c) 2017 Microsemi Corporation.
8 * Copyright (C) 2017 Andes Technology Corporation
12 #include <asm-offsets.h>
16 #include <asm/encoding.h>
17 #include <generated/asm-offsets.h>
23 #define RELOC_TYPE R_RISCV_32
30 #define RELOC_TYPE R_RISCV_64
31 #define SYM_INDEX 0x20
38 /* save hart id and dtb pointer */
43 csrw MODE_PREFIX(tvec), t0
45 /* mask all interrupts */
46 csrw MODE_PREFIX(ie), zero
53 * Set stackpointer in internal/ex RAM to call board_init_f
57 li t1, CONFIG_SYS_INIT_SP_ADDR
58 and sp, t1, t0 /* force 16 byte alignment */
60 #ifdef CONFIG_DEBUG_UART
66 jal board_init_f_alloc_reserve
69 la t0, prior_stage_fdt_address
72 jal board_init_f_init_reserve
74 /* save the boot hart id to global_data */
75 SREG s0, GD_BOOT_HART(gp)
77 mv a0, zero /* a0 <-- boot_flags = 0 */
79 jr t5 /* jump to board_init_f() */
82 * void relocate_code (addr_sp, gd, addr_moni)
84 * This "function" does not return, instead it continues in RAM
85 * after relocating the monitor code.
90 mv s2, a0 /* save addr_sp */
91 mv s3, a1 /* save addr of gd */
92 mv s4, a2 /* save addr of destination */
100 sub t6, s4, t0 /* t6 <- relocation offset */
101 beq t0, s4, clear_bss /* skip relocation */
103 mv t1, s4 /* t1 <- scratch for copy_loop */
105 sub t3, t3, t0 /* t3 <- __bss_start_ofs */
106 add t2, t0, t3 /* t2 <- source end address */
110 addi t0, t0, REGBYTES
112 addi t1, t1, REGBYTES
113 blt t0, t2, copy_loop
116 * Update dynamic relocations after board_init_f
119 la t1, __rel_dyn_start
121 beq t1, t2, clear_bss
122 add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */
123 add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */
126 * skip first reserved entry: address, type, addend
131 LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
132 li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
133 bne t5, t3, 8f /* skip non-RISCV_RELOC entries */
134 LREG t3, -(REGBYTES*3)(t1)
135 LREG t5, -(REGBYTES)(t1) /* t5 <-- addend */
136 add t5, t5, t6 /* t5 <-- location to fix up in RAM */
137 add t3, t3, t6 /* t3 <-- location to fix up in RAM */
140 addi t1, t1, (REGBYTES*3)
144 la t4, __dyn_sym_start
148 LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
149 srli t0, t5, SYM_INDEX /* t0 <--- sym table index */
150 andi t5, t5, 0xFF /* t5 <--- relocation type */
152 bne t5, t3, 10f /* skip non-addned entries */
154 LREG t3, -(REGBYTES*3)(t1)
158 LREG t5, REGBYTES(s5)
159 add t5, t5, t6 /* t5 <-- location to fix up in RAM */
160 add t3, t3, t6 /* t3 <-- location to fix up in RAM */
163 addi t1, t1, (REGBYTES*3)
171 csrw MODE_PREFIX(tvec), t0
174 la t0, __bss_start /* t0 <- rel __bss_start in FLASH */
175 add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
176 la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
177 add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
178 beq t0, t1, call_board_init_r
181 SREG zero, 0(t0) /* clear loop... */
182 addi t0, t0, REGBYTES
186 * We are done. Do not return, instead branch to second part of board
187 * initialization, now running from RAM.
190 jal invalidate_icache_all
193 mv t4, t0 /* offset of board_init_r() */
194 add t4, t4, t6 /* real address of board_init_r() */
196 * setup parameters for board_init_r
199 mv a1, s4 /* dest_addr */
204 jr t4 /* jump to board_init_r() */