blob: a30f6f7194772c46e158c016a1e0b7d71a004d52 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Rick Chene8e39592017-12-26 13:55:48 +08002/*
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>
Rick Chene8e39592017-12-26 13:55:48 +080010 */
11
12#include <asm-offsets.h>
13#include <config.h>
14#include <common.h>
15#include <elf.h>
16#include <asm/encoding.h>
Bin Meng51ab4572018-12-12 06:12:45 -080017#include <generated/asm-offsets.h>
Rick Chene8e39592017-12-26 13:55:48 +080018
19#ifdef CONFIG_32BIT
Lukas Auerc55309c2018-11-22 11:26:24 +010020#define LREG lw
21#define SREG sw
22#define REGBYTES 4
Rick Chene8e39592017-12-26 13:55:48 +080023#define RELOC_TYPE R_RISCV_32
24#define SYM_INDEX 0x8
25#define SYM_SIZE 0x10
26#else
Lukas Auerc55309c2018-11-22 11:26:24 +010027#define LREG ld
28#define SREG sd
29#define REGBYTES 8
Rick Chene8e39592017-12-26 13:55:48 +080030#define RELOC_TYPE R_RISCV_64
31#define SYM_INDEX 0x20
32#define SYM_SIZE 0x18
33#endif
34
Lukas Auerc55309c2018-11-22 11:26:24 +010035.section .text
Rick Chene8e39592017-12-26 13:55:48 +080036.globl _start
37_start:
Lukas Auer5d8b2e72018-11-22 11:26:29 +010038 /* save hart id and dtb pointer */
39 mv s0, a0
40 mv s1, a1
41
Lukas Auerc55309c2018-11-22 11:26:24 +010042 la t0, trap_entry
Anup Pateld2db2a82018-12-03 10:57:40 +053043 csrw MODE_PREFIX(tvec), t0
Lukas Auer31f90582018-11-22 11:26:28 +010044
45 /* mask all interrupts */
Anup Pateld2db2a82018-12-03 10:57:40 +053046 csrw MODE_PREFIX(ie), zero
Rick Chene8e39592017-12-26 13:55:48 +080047
48/*
Rick Chene8e39592017-12-26 13:55:48 +080049 * Set stackpointer in internal/ex RAM to call board_init_f
50 */
51call_board_init_f:
Lukas Auerc55309c2018-11-22 11:26:24 +010052 li t0, -16
53 li t1, CONFIG_SYS_INIT_SP_ADDR
54 and sp, t1, t0 /* force 16 byte alignment */
Rick Chene8e39592017-12-26 13:55:48 +080055
Rick Chene8e39592017-12-26 13:55:48 +080056call_board_init_f_0:
57 mv a0, sp
58 jal board_init_f_alloc_reserve
59 mv sp, a0
Lukas Auer5d8b2e72018-11-22 11:26:29 +010060
61 la t0, prior_stage_fdt_address
62 SREG s1, 0(t0)
63
Rick Chene8e39592017-12-26 13:55:48 +080064 jal board_init_f_init_reserve
65
Bin Meng51ab4572018-12-12 06:12:45 -080066 /* save the boot hart id to global_data */
67 SREG s0, GD_BOOT_HART(gp)
68
Lukas Auer2503ccc2019-03-17 19:28:35 +010069 /* Enable cache */
70 jal icache_enable
71 jal dcache_enable
72
73#ifdef CONFIG_DEBUG_UART
74 jal debug_uart_init
75#endif
76
Lukas Auerc55309c2018-11-22 11:26:24 +010077 mv a0, zero /* a0 <-- boot_flags = 0 */
78 la t5, board_init_f
79 jr t5 /* jump to board_init_f() */
Rick Chene8e39592017-12-26 13:55:48 +080080
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:
Lukas Auerc55309c2018-11-22 11:26:24 +010090 mv s2, a0 /* save addr_sp */
91 mv s3, a1 /* save addr of gd */
92 mv s4, a2 /* save addr of destination */
Rick Chene8e39592017-12-26 13:55:48 +080093
94/*
95 *Set up the stack
96 */
97stack_setup:
Lukas Auerc55309c2018-11-22 11:26:24 +010098 mv sp, s2
99 la t0, _start
100 sub t6, s4, t0 /* t6 <- relocation offset */
101 beq t0, s4, clear_bss /* skip relocation */
Rick Chene8e39592017-12-26 13:55:48 +0800102
Lukas Auerc55309c2018-11-22 11:26:24 +0100103 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 */
Rick Chene8e39592017-12-26 13:55:48 +0800107
108copy_loop:
Lukas Auerc55309c2018-11-22 11:26:24 +0100109 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
Rick Chene8e39592017-12-26 13:55:48 +0800114
115/*
116 * Update dynamic relocations after board_init_f
117 */
118fix_rela_dyn:
Lukas Auerc55309c2018-11-22 11:26:24 +0100119 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 */
Rick Chene8e39592017-12-26 13:55:48 +0800124
125/*
126 * skip first reserved entry: address, type, addend
127 */
Lukas Auerc55309c2018-11-22 11:26:24 +0100128 bne t1, t2, 7f
Rick Chene8e39592017-12-26 13:55:48 +0800129
1306:
Lukas Auerc55309c2018-11-22 11:26:24 +0100131 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)
Rick Chene8e39592017-12-26 13:55:48 +08001397:
Lukas Auerc55309c2018-11-22 11:26:24 +0100140 addi t1, t1, (REGBYTES*3)
141 ble t1, t2, 6b
Rick Chene8e39592017-12-26 13:55:48 +0800142
1438:
Lukas Auerc55309c2018-11-22 11:26:24 +0100144 la t4, __dyn_sym_start
145 add t4, t4, t6
Rick Chene8e39592017-12-26 13:55:48 +0800146
1479:
Lukas Auerc55309c2018-11-22 11:26:24 +0100148 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 */
Rick Chene8e39592017-12-26 13:55:48 +0800153
Lukas Auerc55309c2018-11-22 11:26:24 +0100154 LREG t3, -(REGBYTES*3)(t1)
155 li t5, SYM_SIZE
156 mul t0, t0, t5
Lukas Auer5d8b2e72018-11-22 11:26:29 +0100157 add s5, t4, t0
158 LREG t5, REGBYTES(s5)
Lukas Auerc55309c2018-11-22 11:26:24 +0100159 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)
Rick Chene8e39592017-12-26 13:55:48 +080016210:
Lukas Auerc55309c2018-11-22 11:26:24 +0100163 addi t1, t1, (REGBYTES*3)
164 ble t1, t2, 9b
Rick Chene8e39592017-12-26 13:55:48 +0800165
166/*
167 * trap update
168*/
Lukas Auerc55309c2018-11-22 11:26:24 +0100169 la t0, trap_entry
170 add t0, t0, t6
Anup Pateld2db2a82018-12-03 10:57:40 +0530171 csrw MODE_PREFIX(tvec), t0
Rick Chene8e39592017-12-26 13:55:48 +0800172
173clear_bss:
Lukas Auerc55309c2018-11-22 11:26:24 +0100174 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 */
Lukas Auerc55309c2018-11-22 11:26:24 +0100178 beq t0, t1, call_board_init_r
Rick Chene8e39592017-12-26 13:55:48 +0800179
180clbss_l:
Lukas Auer31f90582018-11-22 11:26:28 +0100181 SREG zero, 0(t0) /* clear loop... */
Lukas Auerc55309c2018-11-22 11:26:24 +0100182 addi t0, t0, REGBYTES
183 bne t0, t1, clbss_l
Rick Chene8e39592017-12-26 13:55:48 +0800184
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:
Rick Chen52923c62018-11-07 09:34:06 +0800190 jal invalidate_icache_all
191 jal flush_dcache_all
Lukas Auerc55309c2018-11-22 11:26:24 +0100192 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() */
Rick Chene8e39592017-12-26 13:55:48 +0800195/*
196 * setup parameters for board_init_r
197 */
Lukas Auerc55309c2018-11-22 11:26:24 +0100198 mv a0, s3 /* gd_t */
199 mv a1, s4 /* dest_addr */
Rick Chene8e39592017-12-26 13:55:48 +0800200
201/*
202 * jump to it ...
203 */
Lukas Auerc55309c2018-11-22 11:26:24 +0100204 jr t4 /* jump to board_init_r() */