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