Merge tag 'signed-efi-2019.01' of git://github.com/agraf/u-boot
[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 #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  */
55 call_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
64 call_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
89 relocate_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  */
97 stack_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
108 copy_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  */
118 fix_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
130 6:
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)
139 7:
140         addi    t1, t1, (REGBYTES*3)
141         ble     t1, t2, 6b
142
143 8:
144         la      t4, __dyn_sym_start
145         add     t4, t4, t6
146
147 9:
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)
162 10:
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
173 clear_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
180 clbss_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  */
189 call_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() */