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