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