]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/microblaze/cpu/start.S
armv8/ls1043aqds: add QSPI boot support
[people/ms/u-boot.git] / arch / microblaze / cpu / start.S
1 /*
2 * (C) Copyright 2007 Michal Simek
3 * (C) Copyright 2004 Atmark Techno, Inc.
4 *
5 * Michal SIMEK <monstr@monstr.eu>
6 * Yasushi SHOJI <yashi@atmark-techno.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11 #include <asm-offsets.h>
12 #include <config.h>
13
14 .text
15 .global _start
16 _start:
17 /*
18 * reserve registers:
19 * r10: Stores little/big endian offset for vectors
20 * r2: Stores imm opcode
21 * r3: Stores brai opcode
22 */
23
24 mts rmsr, r0 /* disable cache */
25
26 addi r8, r0, __end
27 mts rslr, r8
28 /* TODO: Redo this code to call board_init_f_*() */
29 #if defined(CONFIG_SPL_BUILD)
30 addi r1, r0, CONFIG_SPL_STACK_ADDR
31 mts rshr, r1
32 addi r1, r1, -4 /* Decrement SP to top of memory */
33 #else
34 #if defined(CONFIG_SYS_MALLOC_F_LEN)
35 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
36 #else
37 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
38 #endif
39 mts rshr, r1
40 addi r1, r1, -4 /* Decrement SP to top of memory */
41
42 /* Find-out if u-boot is running on BIG/LITTLE endian platform
43 * There are some steps which is necessary to keep in mind:
44 * 1. Setup offset value to r6
45 * 2. Store word offset value to address 0x0
46 * 3. Load just byte from address 0x0
47 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
48 * value that's why is on address 0x0
49 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
50 */
51 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
52 lwi r7, r0, 0x28
53 swi r6, r0, 0x28 /* used first unused MB vector */
54 lbui r10, r0, 0x28 /* used first unused MB vector */
55 swi r7, r0, 0x28
56
57 /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
58 addi r2, r0, 0xb0000000 /* hex b000 opcode imm */
59 addi r3, r0, 0xb8080000 /* hew b808 opcode brai */
60
61 #ifdef CONFIG_SYS_RESET_ADDRESS
62 /* reset address */
63 swi r2, r0, 0x0 /* reset address - imm opcode */
64 swi r3, r0, 0x4 /* reset address - brai opcode */
65
66 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
67 sw r6, r1, r0
68 lhu r7, r1, r10
69 rsubi r8, r10, 0x2
70 sh r7, r0, r8
71 rsubi r8, r10, 0x6
72 sh r6, r0, r8
73 #endif
74
75 #ifdef CONFIG_SYS_USR_EXCEP
76 /* user_vector_exception */
77 swi r2, r0, 0x8 /* user vector exception - imm opcode */
78 swi r3, r0, 0xC /* user vector exception - brai opcode */
79
80 addik r6, r0, _exception_handler
81 sw r6, r1, r0
82 /*
83 * BIG ENDIAN memory map for user exception
84 * 0x8: 0xB000XXXX
85 * 0xC: 0xB808XXXX
86 *
87 * then it is necessary to count address for storing the most significant
88 * 16bits from _exception_handler address and copy it to
89 * 0xa address. Big endian use offset in r10=0 that's why is it just
90 * 0xa address. The same is done for the least significant 16 bits
91 * for 0xe address.
92 *
93 * LITTLE ENDIAN memory map for user exception
94 * 0x8: 0xXXXX00B0
95 * 0xC: 0xXXXX08B8
96 *
97 * Offset is for little endian setup to 0x2. rsubi instruction decrease
98 * address value to ensure that points to proper place which is
99 * 0x8 for the most significant 16 bits and
100 * 0xC for the least significant 16 bits
101 */
102 lhu r7, r1, r10
103 rsubi r8, r10, 0xa
104 sh r7, r0, r8
105 rsubi r8, r10, 0xe
106 sh r6, r0, r8
107 #endif
108
109 /* interrupt_handler */
110 swi r2, r0, 0x10 /* interrupt - imm opcode */
111 swi r3, r0, 0x14 /* interrupt - brai opcode */
112
113 addik r6, r0, _interrupt_handler
114 sw r6, r1, r0
115 lhu r7, r1, r10
116 rsubi r8, r10, 0x12
117 sh r7, r0, r8
118 rsubi r8, r10, 0x16
119 sh r6, r0, r8
120
121 /* hardware exception */
122 swi r2, r0, 0x20 /* hardware exception - imm opcode */
123 swi r3, r0, 0x24 /* hardware exception - brai opcode */
124
125 addik r6, r0, _hw_exception_handler
126 sw r6, r1, r0
127 lhu r7, r1, r10
128 rsubi r8, r10, 0x22
129 sh r7, r0, r8
130 rsubi r8, r10, 0x26
131 sh r6, r0, r8
132 #endif /* BUILD_SPL */
133
134 /* Flush cache before enable cache */
135 addik r5, r0, 0
136 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
137 bralid r15, flush_cache
138 nop
139
140 /* enable instruction and data cache */
141 mfs r12, rmsr
142 ori r12, r12, 0x1a0
143 mts rmsr, r12
144
145 /* TODO: Redo this code to call board_init_f_*() */
146 clear_bss:
147 /* clear BSS segments */
148 addi r5, r0, __bss_start
149 addi r4, r0, __bss_end
150 cmp r6, r5, r4
151 beqi r6, 3f
152 2:
153 swi r0, r5, 0 /* write zero to loc */
154 addi r5, r5, 4 /* increment to next loc */
155 cmp r6, r5, r4 /* check if we have reach the end */
156 bnei r6, 2b
157 3: /* jumping to board_init */
158 #ifndef CONFIG_SPL_BUILD
159 or r5, r0, r0 /* flags - empty */
160 addi r31, r0, _gd
161 #if defined(CONFIG_SYS_MALLOC_F_LEN)
162 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
163 swi r6, r31, GD_MALLOC_BASE
164 #endif
165 brai board_init_f
166 #else
167 addi r31, r0, _gd
168 #if defined(CONFIG_SYS_MALLOC_F_LEN)
169 addi r6, r0, CONFIG_SPL_STACK_ADDR
170 swi r6, r31, GD_MALLOC_BASE
171 #endif
172 brai board_init_r
173 #endif
174 1: bri 1b
175
176 .section .bss
177 .align 4
178 _gd:
179 .space GENERATED_GBL_DATA_SIZE
180
181 #ifndef CONFIG_SPL_BUILD
182 /*
183 * Read 16bit little endian
184 */
185 .text
186 .global in16
187 .ent in16
188 .align 2
189 in16: lhu r3, r0, r5
190 bslli r4, r3, 8
191 bsrli r3, r3, 8
192 andi r4, r4, 0xffff
193 or r3, r3, r4
194 rtsd r15, 8
195 sext16 r3, r3
196 .end in16
197
198 /*
199 * Write 16bit little endian
200 * first parameter(r5) - address, second(r6) - short value
201 */
202 .text
203 .global out16
204 .ent out16
205 .align 2
206 out16: bslli r3, r6, 8
207 bsrli r6, r6, 8
208 andi r3, r3, 0xffff
209 or r3, r3, r6
210 sh r3, r0, r5
211 rtsd r15, 8
212 or r0, r0, r0
213 .end out16
214
215 /*
216 * Relocate u-boot
217 */
218 .text
219 .global relocate_code
220 .ent relocate_code
221 .align 2
222 relocate_code:
223 /*
224 * r5 - start_addr_sp
225 * r6 - new_gd
226 * r7 - reloc_addr
227 */
228 addi r1, r5, 0 /* Start to use new SP */
229 addi r31, r6, 0 /* Start to use new GD */
230
231 add r23, r0, r7 /* Move reloc addr to r23 */
232 /* Relocate text and data - r12 temp value */
233 addi r21, r0, _start
234 addi r22, r0, __end - 4 /* Include BSS too */
235
236 rsub r6, r21, r22
237 or r5, r0, r0
238 1: lw r12, r21, r5 /* Load u-boot data */
239 sw r12, r23, r5 /* Write zero to loc */
240 cmp r12, r5, r6 /* Check if we have reach the end */
241 bneid r12, 1b
242 addi r5, r5, 4 /* Increment to next loc - relocate code */
243
244 /* R23 points to the base address. */
245 add r23, r0, r7 /* Move reloc addr to r23 */
246 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
247 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
248
249 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
250 lwi r7, r0, 0x28
251 swi r6, r0, 0x28 /* used first unused MB vector */
252 lbui r10, r0, 0x28 /* used first unused MB vector */
253 swi r7, r0, 0x28
254
255 #ifdef CONFIG_SYS_USR_EXCEP
256 addik r6, r0, _exception_handler
257 addk r6, r6, r23 /* add offset */
258 sw r6, r1, r0
259 lhu r7, r1, r10
260 rsubi r8, r10, 0xa
261 sh r7, r0, r8
262 rsubi r8, r10, 0xe
263 sh r6, r0, r8
264 #endif
265 addik r6, r0, _hw_exception_handler
266 addk r6, r6, r23 /* add offset */
267 sw r6, r1, r0
268 lhu r7, r1, r10
269 rsubi r8, r10, 0x22
270 sh r7, r0, r8
271 rsubi r8, r10, 0x26
272 sh r6, r0, r8
273
274 addik r6, r0, _interrupt_handler
275 addk r6, r6, r23 /* add offset */
276 sw r6, r1, r0
277 lhu r7, r1, r10
278 rsubi r8, r10, 0x12
279 sh r7, r0, r8
280 rsubi r8, r10, 0x16
281 sh r6, r0, r8
282
283 /* Check if GOT exist */
284 addik r21, r23, _got_start
285 addik r22, r23, _got_end
286 cmpu r12, r21, r22
287 beqi r12, 2f /* No GOT table - jump over */
288
289 /* Skip last 3 entries plus 1 because of loop boundary below */
290 addik r22, r22, -0x10
291
292 /* Relocate the GOT. */
293 3: lw r12, r21, r0 /* Load entry */
294 addk r12, r12, r23 /* Add reloc offset */
295 sw r12, r21, r0 /* Save entry back */
296
297 cmpu r12, r21, r22 /* Check if this cross boundary */
298 bneid r12, 3b
299 addik r21. r21, 4
300
301 /* Update pointer to GOT */
302 mfs r20, rpc
303 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
304 addk r20, r20, r23
305
306 /* Flush caches to ensure consistency */
307 addik r5, r0, 0
308 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
309 bralid r15, flush_cache
310 nop
311
312 2: addi r5, r31, 0 /* gd is initialized in board_r.c */
313 addi r6, r0, CONFIG_SYS_TEXT_BASE
314 addi r12, r23, board_init_r
315 bra r12 /* Jump to relocated code */
316
317 .end relocate_code
318 #endif