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#include <generated/asm-offsets.h> 18 19#ifdef CONFIG_32BIT 20#define LREG lw 21#define SREG sw 22#define REGBYTES 4 23#define RELOC_TYPE R_RISCV_32 24#define SYM_INDEX 0x8 25#define SYM_SIZE 0x10 26#else 27#define LREG ld 28#define SREG sd 29#define REGBYTES 8 30#define RELOC_TYPE R_RISCV_64 31#define SYM_INDEX 0x20 32#define SYM_SIZE 0x18 33#endif 34 35.section .text 36.globl _start 37_start: 38 /* save hart id and dtb pointer */ 39 mv s0, a0 40 mv s1, a1 41 42 la t0, trap_entry 43 csrw MODE_PREFIX(tvec), t0 44 45 /* mask all interrupts */ 46 csrw MODE_PREFIX(ie), zero 47 48 /* Enable cache */ 49 jal icache_enable 50 jal dcache_enable 51 52/* 53 * Set stackpointer in internal/ex RAM to call board_init_f 54 */ 55call_board_init_f: 56 li t0, -16 57 li t1, CONFIG_SYS_INIT_SP_ADDR 58 and sp, t1, t0 /* force 16 byte alignment */ 59 60#ifdef CONFIG_DEBUG_UART 61 jal debug_uart_init 62#endif 63 64call_board_init_f_0: 65 mv a0, sp 66 jal board_init_f_alloc_reserve 67 mv sp, a0 68 69 la t0, prior_stage_fdt_address 70 SREG s1, 0(t0) 71 72 jal board_init_f_init_reserve 73 74 /* save the boot hart id to global_data */ 75 SREG s0, GD_BOOT_HART(gp) 76 77 mv a0, zero /* a0 <-- boot_flags = 0 */ 78 la t5, board_init_f 79 jr t5 /* jump to board_init_f() */ 80 81/* 82 * void relocate_code (addr_sp, gd, addr_moni) 83 * 84 * This "function" does not return, instead it continues in RAM 85 * after relocating the monitor code. 86 * 87 */ 88.globl relocate_code 89relocate_code: 90 mv s2, a0 /* save addr_sp */ 91 mv s3, a1 /* save addr of gd */ 92 mv s4, a2 /* save addr of destination */ 93 94/* 95 *Set up the stack 96 */ 97stack_setup: 98 mv sp, s2 99 la t0, _start 100 sub t6, s4, t0 /* t6 <- relocation offset */ 101 beq t0, s4, clear_bss /* skip relocation */ 102 103 mv t1, s4 /* t1 <- scratch for copy_loop */ 104 la t3, __bss_start 105 sub t3, t3, t0 /* t3 <- __bss_start_ofs */ 106 add t2, t0, t3 /* t2 <- source end address */ 107 108copy_loop: 109 LREG t5, 0(t0) 110 addi t0, t0, REGBYTES 111 SREG t5, 0(t1) 112 addi t1, t1, REGBYTES 113 blt t0, t2, copy_loop 114 115/* 116 * Update dynamic relocations after board_init_f 117 */ 118fix_rela_dyn: 119 la t1, __rel_dyn_start 120 la t2, __rel_dyn_end 121 beq t1, t2, clear_bss 122 add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */ 123 add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */ 124 125/* 126 * skip first reserved entry: address, type, addend 127 */ 128 bne t1, t2, 7f 129 1306: 131 LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */ 132 li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */ 133 bne t5, t3, 8f /* skip non-RISCV_RELOC entries */ 134 LREG t3, -(REGBYTES*3)(t1) 135 LREG t5, -(REGBYTES)(t1) /* t5 <-- addend */ 136 add t5, t5, t6 /* t5 <-- location to fix up in RAM */ 137 add t3, t3, t6 /* t3 <-- location to fix up in RAM */ 138 SREG t5, 0(t3) 1397: 140 addi t1, t1, (REGBYTES*3) 141 ble t1, t2, 6b 142 1438: 144 la t4, __dyn_sym_start 145 add t4, t4, t6 146 1479: 148 LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */ 149 srli t0, t5, SYM_INDEX /* t0 <--- sym table index */ 150 andi t5, t5, 0xFF /* t5 <--- relocation type */ 151 li t3, RELOC_TYPE 152 bne t5, t3, 10f /* skip non-addned entries */ 153 154 LREG t3, -(REGBYTES*3)(t1) 155 li t5, SYM_SIZE 156 mul t0, t0, t5 157 add s5, t4, t0 158 LREG t5, REGBYTES(s5) 159 add t5, t5, t6 /* t5 <-- location to fix up in RAM */ 160 add t3, t3, t6 /* t3 <-- location to fix up in RAM */ 161 SREG t5, 0(t3) 16210: 163 addi t1, t1, (REGBYTES*3) 164 ble t1, t2, 9b 165 166/* 167 * trap update 168*/ 169 la t0, trap_entry 170 add t0, t0, t6 171 csrw MODE_PREFIX(tvec), t0 172 173clear_bss: 174 la t0, __bss_start /* t0 <- rel __bss_start in FLASH */ 175 add t0, t0, t6 /* t0 <- rel __bss_start in RAM */ 176 la t1, __bss_end /* t1 <- rel __bss_end in FLASH */ 177 add t1, t1, t6 /* t1 <- rel __bss_end in RAM */ 178 beq t0, t1, call_board_init_r 179 180clbss_l: 181 SREG zero, 0(t0) /* clear loop... */ 182 addi t0, t0, REGBYTES 183 bne t0, t1, clbss_l 184 185/* 186 * We are done. Do not return, instead branch to second part of board 187 * initialization, now running from RAM. 188 */ 189call_board_init_r: 190 jal invalidate_icache_all 191 jal flush_dcache_all 192 la t0, board_init_r 193 mv t4, t0 /* offset of board_init_r() */ 194 add t4, t4, t6 /* real address of board_init_r() */ 195/* 196 * setup parameters for board_init_r 197 */ 198 mv a0, s3 /* gd_t */ 199 mv a1, s4 /* dest_addr */ 200 201/* 202 * jump to it ... 203 */ 204 jr t4 /* jump to board_init_r() */ 205