]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
507bbe3e | 2 | /* |
cfc67116 | 3 | * (C) Copyright 2007 Michal Simek |
507bbe3e WD |
4 | * (C) Copyright 2004 Atmark Techno, Inc. |
5 | * | |
cfc67116 | 6 | * Michal SIMEK <[email protected]> |
507bbe3e | 7 | * Yasushi SHOJI <[email protected]> |
507bbe3e WD |
8 | */ |
9 | ||
25ddd1fb | 10 | #include <asm-offsets.h> |
507bbe3e WD |
11 | #include <config.h> |
12 | ||
d58c0074 MS |
13 | #if defined(CONFIG_STATIC_RELA) |
14 | #define SYM_ADDR(reg, reg_add, symbol) \ | |
15 | mfs r20, rpc; \ | |
16 | addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8; \ | |
17 | lwi reg, r20, symbol@GOT; \ | |
18 | addk reg, reg reg_add; | |
19 | #else | |
07c052be MS |
20 | #define SYM_ADDR(reg, reg_add, symbol) \ |
21 | addi reg, reg_add, symbol | |
d58c0074 | 22 | #endif |
07c052be | 23 | |
507bbe3e WD |
24 | .text |
25 | .global _start | |
26 | _start: | |
cfc67116 | 27 | mts rmsr, r0 /* disable cache */ |
b6fe10af MS |
28 | mfs r20, rpc |
29 | addi r20, r20, -4 | |
9d242745 | 30 | |
16a18471 | 31 | mts rslr, r0 |
b6fe10af | 32 | mts rshr, r20 |
f5d8b1a1 | 33 | |
9d242745 MS |
34 | #if defined(CONFIG_SPL_BUILD) |
35 | addi r1, r0, CONFIG_SPL_STACK_ADDR | |
9d242745 | 36 | #else |
b6fe10af | 37 | add r1, r0, r20 |
d58c0074 MS |
38 | #if defined(CONFIG_STATIC_RELA) |
39 | bri 1f | |
40 | ||
41 | /* Force alignment for easier ASM code below */ | |
42 | #define ALIGNMENT_ADDR 0x20 | |
43 | .align 4 | |
44 | uboot_dyn_start: | |
45 | .word __rel_dyn_start | |
46 | ||
47 | uboot_dyn_end: | |
48 | .word __rel_dyn_end | |
49 | ||
50 | uboot_sym_start: | |
51 | .word __dyn_sym_start | |
52 | 1: | |
53 | ||
54 | addi r5, r20, 0 | |
55 | add r6, r0, r0 | |
56 | ||
57 | lwi r7, r20, ALIGNMENT_ADDR | |
58 | addi r7, r7, -CONFIG_SYS_TEXT_BASE | |
59 | add r7, r7, r5 | |
60 | lwi r8, r20, ALIGNMENT_ADDR + 0x4 | |
61 | addi r8, r8, -CONFIG_SYS_TEXT_BASE | |
62 | add r8, r8, r5 | |
63 | lwi r9, r20, ALIGNMENT_ADDR + 0x8 | |
64 | addi r9, r9, -CONFIG_SYS_TEXT_BASE | |
65 | add r9, r9, r5 | |
66 | addi r10, r0, CONFIG_SYS_TEXT_BASE | |
67 | ||
68 | brlid r15, mb_fix_rela | |
69 | nop | |
70 | #endif | |
405e651d | 71 | #endif |
f5d8b1a1 | 72 | |
17980495 | 73 | addi r1, r1, -4 /* Decrement SP to top of memory */ |
b98cba09 | 74 | |
f5d8b1a1 OP |
75 | /* Call board_init_f_alloc_reserve with the current stack pointer as |
76 | * parameter. */ | |
77 | add r5, r0, r1 | |
7cf236cf | 78 | brlid r15, board_init_f_alloc_reserve |
f5d8b1a1 OP |
79 | nop |
80 | ||
81 | /* board_init_f_alloc_reserve returns a pointer to the allocated area | |
82 | * in r3. Set the new stack pointer below this area. */ | |
83 | add r1, r0, r3 | |
84 | mts rshr, r1 | |
85 | addi r1, r1, -4 | |
86 | ||
87 | /* Call board_init_f_init_reserve with the address returned by | |
88 | * board_init_f_alloc_reserve as parameter. */ | |
89 | add r5, r0, r3 | |
7cf236cf | 90 | brlid r15, board_init_f_init_reserve |
f5d8b1a1 OP |
91 | nop |
92 | ||
93 | #if !defined(CONFIG_SPL_BUILD) | |
627085ea OP |
94 | /* Setup vectors with pre-relocation symbols */ |
95 | or r5, r0, r0 | |
7cf236cf | 96 | brlid r15, __setup_exceptions |
627085ea | 97 | nop |
f5d8b1a1 | 98 | #endif |
627085ea OP |
99 | |
100 | /* Flush cache before enable cache */ | |
b1951349 | 101 | brlid r15, flush_cache_all |
627085ea OP |
102 | nop |
103 | ||
104 | /* enable instruction and data cache */ | |
105 | mfs r12, rmsr | |
106 | ori r12, r12, 0x1a0 | |
107 | mts rmsr, r12 | |
108 | ||
627085ea OP |
109 | clear_bss: |
110 | /* clear BSS segments */ | |
07c052be MS |
111 | SYM_ADDR(r5, r0, __bss_start) |
112 | SYM_ADDR(r4, r0, __bss_end) | |
627085ea OP |
113 | cmp r6, r5, r4 |
114 | beqi r6, 3f | |
115 | 2: | |
116 | swi r0, r5, 0 /* write zero to loc */ | |
117 | addi r5, r5, 4 /* increment to next loc */ | |
118 | cmp r6, r5, r4 /* check if we have reach the end */ | |
119 | bnei r6, 2b | |
120 | 3: /* jumping to board_init */ | |
121 | #ifdef CONFIG_DEBUG_UART | |
7cf236cf | 122 | brlid r15, debug_uart_init |
627085ea OP |
123 | nop |
124 | #endif | |
125 | #ifndef CONFIG_SPL_BUILD | |
126 | or r5, r0, r0 /* flags - empty */ | |
7cf236cf | 127 | bri board_init_f |
627085ea | 128 | #else |
7cf236cf | 129 | bri board_init_r |
627085ea OP |
130 | #endif |
131 | 1: bri 1b | |
132 | ||
627085ea OP |
133 | #ifndef CONFIG_SPL_BUILD |
134 | .text | |
135 | .ent __setup_exceptions | |
136 | .align 2 | |
137 | /* | |
138 | * Set up reset, interrupt, user exception and hardware exception vectors. | |
139 | * | |
140 | * Parameters: | |
141 | * r5 - relocation offset (zero when setting up vectors before | |
142 | * relocation, and gd->reloc_off when setting up vectors after | |
143 | * relocation) | |
144 | * - the relocation offset is added to the _exception_handler, | |
145 | * _interrupt_handler and _hw_exception_handler symbols to reflect the | |
146 | * post-relocation memory addresses | |
147 | * | |
148 | * Reserve registers: | |
149 | * r10: Stores little/big endian offset for vectors | |
150 | * r2: Stores imm opcode | |
151 | * r3: Stores brai opcode | |
f149ee4c | 152 | * r4: Stores the vector base address |
627085ea OP |
153 | */ |
154 | __setup_exceptions: | |
f149ee4c | 155 | addik r1, r1, -32 |
627085ea OP |
156 | swi r2, r1, 4 |
157 | swi r3, r1, 8 | |
f149ee4c OP |
158 | swi r4, r1, 12 |
159 | swi r6, r1, 16 | |
160 | swi r7, r1, 20 | |
161 | swi r8, r1, 24 | |
162 | swi r10, r1, 28 | |
627085ea | 163 | |
b98cba09 MS |
164 | /* Find-out if u-boot is running on BIG/LITTLE endian platform |
165 | * There are some steps which is necessary to keep in mind: | |
166 | * 1. Setup offset value to r6 | |
167 | * 2. Store word offset value to address 0x0 | |
168 | * 3. Load just byte from address 0x0 | |
169 | * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest | |
170 | * value that's why is on address 0x0 | |
171 | * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3 | |
172 | */ | |
173 | addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ | |
48039c33 OP |
174 | sw r6, r1, r0 |
175 | lbu r10, r1, r0 | |
b98cba09 | 176 | |
86c1b2a8 MS |
177 | /* add opcode instruction for 32bit jump - 2 instruction imm & brai */ |
178 | addi r2, r0, 0xb0000000 /* hex b000 opcode imm */ | |
179 | addi r3, r0, 0xb8080000 /* hew b808 opcode brai */ | |
507bbe3e | 180 | |
f149ee4c OP |
181 | /* Store the vector base address in r4 */ |
182 | addi r4, r0, CONFIG_XILINX_MICROBLAZE0_VECTOR_BASE_ADDR | |
183 | ||
cfc67116 | 184 | /* reset address */ |
f149ee4c OP |
185 | swi r2, r4, 0x0 /* reset address - imm opcode */ |
186 | swi r3, r4, 0x4 /* reset address - brai opcode */ | |
86c1b2a8 | 187 | |
07c052be | 188 | SYM_ADDR(r6, r0, _start) |
81169ae6 | 189 | /* Intentionally keep reset vector back to origin u-boot location */ |
cfc67116 | 190 | sw r6, r1, r0 |
5562bcc2 MS |
191 | lhu r7, r1, r10 |
192 | rsubi r8, r10, 0x2 | |
f149ee4c | 193 | sh r7, r4, r8 |
5562bcc2 | 194 | rsubi r8, r10, 0x6 |
f149ee4c | 195 | sh r6, r4, r8 |
cfc67116 | 196 | |
83b175be | 197 | #if CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_USR_EXCEP) |
cfc67116 | 198 | /* user_vector_exception */ |
f149ee4c OP |
199 | swi r2, r4, 0x8 /* user vector exception - imm opcode */ |
200 | swi r3, r4, 0xC /* user vector exception - brai opcode */ | |
86c1b2a8 | 201 | |
07c052be | 202 | SYM_ADDR(r6, r5, _exception_handler) |
cfc67116 | 203 | sw r6, r1, r0 |
b98cba09 MS |
204 | /* |
205 | * BIG ENDIAN memory map for user exception | |
206 | * 0x8: 0xB000XXXX | |
207 | * 0xC: 0xB808XXXX | |
208 | * | |
209 | * then it is necessary to count address for storing the most significant | |
071bc923 | 210 | * 16bits from _exception_handler address and copy it to |
b98cba09 MS |
211 | * 0xa address. Big endian use offset in r10=0 that's why is it just |
212 | * 0xa address. The same is done for the least significant 16 bits | |
213 | * for 0xe address. | |
214 | * | |
215 | * LITTLE ENDIAN memory map for user exception | |
216 | * 0x8: 0xXXXX00B0 | |
217 | * 0xC: 0xXXXX08B8 | |
218 | * | |
219 | * Offset is for little endian setup to 0x2. rsubi instruction decrease | |
220 | * address value to ensure that points to proper place which is | |
221 | * 0x8 for the most significant 16 bits and | |
222 | * 0xC for the least significant 16 bits | |
223 | */ | |
224 | lhu r7, r1, r10 | |
225 | rsubi r8, r10, 0xa | |
f149ee4c | 226 | sh r7, r4, r8 |
b98cba09 | 227 | rsubi r8, r10, 0xe |
f149ee4c | 228 | sh r6, r4, r8 |
cfc67116 MS |
229 | #endif |
230 | ||
cfc67116 | 231 | /* interrupt_handler */ |
f149ee4c OP |
232 | swi r2, r4, 0x10 /* interrupt - imm opcode */ |
233 | swi r3, r4, 0x14 /* interrupt - brai opcode */ | |
86c1b2a8 | 234 | |
07c052be | 235 | SYM_ADDR(r6, r5, _interrupt_handler) |
cfc67116 | 236 | sw r6, r1, r0 |
b98cba09 MS |
237 | lhu r7, r1, r10 |
238 | rsubi r8, r10, 0x12 | |
f149ee4c | 239 | sh r7, r4, r8 |
b98cba09 | 240 | rsubi r8, r10, 0x16 |
f149ee4c | 241 | sh r6, r4, r8 |
507bbe3e | 242 | |
cfc67116 | 243 | /* hardware exception */ |
f149ee4c OP |
244 | swi r2, r4, 0x20 /* hardware exception - imm opcode */ |
245 | swi r3, r4, 0x24 /* hardware exception - brai opcode */ | |
86c1b2a8 | 246 | |
07c052be | 247 | SYM_ADDR(r6, r5, _hw_exception_handler) |
cfc67116 | 248 | sw r6, r1, r0 |
b98cba09 MS |
249 | lhu r7, r1, r10 |
250 | rsubi r8, r10, 0x22 | |
f149ee4c | 251 | sh r7, r4, r8 |
b98cba09 | 252 | rsubi r8, r10, 0x26 |
f149ee4c | 253 | sh r6, r4, r8 |
cfc67116 | 254 | |
f149ee4c OP |
255 | lwi r10, r1, 28 |
256 | lwi r8, r1, 24 | |
257 | lwi r7, r1, 20 | |
258 | lwi r6, r1, 16 | |
259 | lwi r4, r1, 12 | |
627085ea OP |
260 | lwi r3, r1, 8 |
261 | lwi r2, r1, 4 | |
f149ee4c | 262 | addik r1, r1, 32 |
0643631a | 263 | |
627085ea OP |
264 | rtsd r15, 8 |
265 | or r0, r0, r0 | |
266 | .end __setup_exceptions | |
0510b14b | 267 | |
e945f6dc MS |
268 | /* |
269 | * Relocate u-boot | |
270 | */ | |
271 | .text | |
272 | .global relocate_code | |
273 | .ent relocate_code | |
274 | .align 2 | |
275 | relocate_code: | |
276 | /* | |
277 | * r5 - start_addr_sp | |
278 | * r6 - new_gd | |
279 | * r7 - reloc_addr | |
280 | */ | |
281 | addi r1, r5, 0 /* Start to use new SP */ | |
532ad5f8 | 282 | mts rshr, r1 |
e945f6dc MS |
283 | addi r31, r6, 0 /* Start to use new GD */ |
284 | ||
e945f6dc | 285 | /* Relocate text and data - r12 temp value */ |
07c052be MS |
286 | SYM_ADDR(r21, r0, _start) |
287 | SYM_ADDR(r22, r0, _end) /* Include BSS too */ | |
1918c416 | 288 | addi r22, r22, -4 |
7c4dd542 MS |
289 | |
290 | rsub r6, r21, r22 | |
291 | or r5, r0, r0 | |
292 | 1: lw r12, r21, r5 /* Load u-boot data */ | |
3041b512 | 293 | sw r12, r7, r5 /* Write zero to loc */ |
7c4dd542 | 294 | cmp r12, r5, r6 /* Check if we have reach the end */ |
e945f6dc | 295 | bneid r12, 1b |
7c4dd542 | 296 | addi r5, r5, 4 /* Increment to next loc - relocate code */ |
e945f6dc | 297 | |
3ad95ed6 | 298 | /* R23 points to the base address. */ |
3041b512 | 299 | rsub r23, r21, r7 /* keep - this is already here gd->reloc_off */ |
e945f6dc | 300 | |
627085ea OP |
301 | /* Setup vectors with post-relocation symbols */ |
302 | add r5, r0, r23 /* load gd->reloc_off to r5 */ | |
7cf236cf | 303 | brlid r15, __setup_exceptions |
627085ea | 304 | nop |
e945f6dc | 305 | |
d58c0074 MS |
306 | #if defined(CONFIG_STATIC_RELA) |
307 | /* reloc_offset is current location */ | |
308 | SYM_ADDR(r10, r0, _start) | |
309 | ||
310 | /* r5 new address where I should copy code */ | |
311 | add r5, r0, r7 /* Move reloc addr to r5 */ | |
312 | ||
313 | /* Verbose message */ | |
314 | addi r6, r0, 0 | |
315 | ||
316 | SYM_ADDR(r7, r0, __rel_dyn_start) | |
317 | rsub r7, r10, r7 | |
318 | add r7, r7, r5 | |
319 | SYM_ADDR(r8, r0, __rel_dyn_end) | |
320 | rsub r8, r10, r8 | |
321 | add r8, r8, r5 | |
322 | SYM_ADDR(r9, r0, __dyn_sym_start) | |
323 | rsub r9, r10, r9 | |
324 | add r9, r9, r5 | |
325 | brlid r15, mb_fix_rela | |
326 | nop | |
327 | ||
328 | /* end of code which does relocation */ | |
329 | #else | |
e945f6dc MS |
330 | /* Check if GOT exist */ |
331 | addik r21, r23, _got_start | |
332 | addik r22, r23, _got_end | |
333 | cmpu r12, r21, r22 | |
334 | beqi r12, 2f /* No GOT table - jump over */ | |
335 | ||
336 | /* Skip last 3 entries plus 1 because of loop boundary below */ | |
337 | addik r22, r22, -0x10 | |
338 | ||
339 | /* Relocate the GOT. */ | |
340 | 3: lw r12, r21, r0 /* Load entry */ | |
341 | addk r12, r12, r23 /* Add reloc offset */ | |
342 | sw r12, r21, r0 /* Save entry back */ | |
343 | ||
344 | cmpu r12, r21, r22 /* Check if this cross boundary */ | |
345 | bneid r12, 3b | |
346 | addik r21. r21, 4 | |
d58c0074 | 347 | #endif |
e945f6dc | 348 | |
e945f6dc | 349 | /* Flush caches to ensure consistency */ |
b1951349 | 350 | brlid r15, flush_cache_all |
e945f6dc MS |
351 | nop |
352 | ||
353 | 2: addi r5, r31, 0 /* gd is initialized in board_r.c */ | |
07c052be MS |
354 | SYM_ADDR(r6, r0, _start) |
355 | SYM_ADDR(r12, r23, board_init_r) | |
e945f6dc MS |
356 | bra r12 /* Jump to relocated code */ |
357 | ||
358 | .end relocate_code | |
9d242745 | 359 | #endif |