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