riscv: Move trap handler codes to mtrap.S
[oweals/u-boot.git] / arch / riscv / cpu / start.S
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  */
54 call_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
63 call_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
85 relocate_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  */
93 stack_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
104 copy_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  */
114 fix_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
126 6:
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)
135 7:
136         addi    t1, t1, (REGBYTES*3)
137         ble     t1, t2, 6b
138
139 8:
140         la      t4, __dyn_sym_start
141         add     t4, t4, t6
142
143 9:
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)
158 10:
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
169 clear_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
176 clbss_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  */
185 call_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() */