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 39nmi_vector: 40 j nmi_vector 41 42trap_vector: 43 j trap_entry 44 45.global trap_entry 46handle_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 */ 65call_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 74call_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 92relocate_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 */ 100stack_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 111copy_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 */ 121fix_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 1336: 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) 1427: 143 addi t1, t1, (REGBYTES*3) 144 ble t1, t2, 6b 145 1468: 147 la t4, __dyn_sym_start 148 add t4, t4, t6 149 1509: 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) 16510: 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 176clear_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 184clbss_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 */ 193call_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 */ 211trap_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 290cpu_init_crit: 291 ret 292#endif 293