]>
Commit | Line | Data |
---|---|---|
507bbe3e | 1 | /* |
cfc67116 | 2 | * (C) Copyright 2007 Michal Simek |
507bbe3e WD |
3 | * (C) Copyright 2004 Atmark Techno, Inc. |
4 | * | |
cfc67116 | 5 | * Michal SIMEK <monstr@monstr.eu> |
507bbe3e WD |
6 | * Yasushi SHOJI <yashi@atmark-techno.com> |
7 | * | |
1a459660 | 8 | * SPDX-License-Identifier: GPL-2.0+ |
507bbe3e WD |
9 | */ |
10 | ||
25ddd1fb | 11 | #include <asm-offsets.h> |
507bbe3e WD |
12 | #include <config.h> |
13 | ||
14 | .text | |
15 | .global _start | |
16 | _start: | |
86c1b2a8 MS |
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 | ||
cfc67116 | 24 | mts rmsr, r0 /* disable cache */ |
9d242745 | 25 | |
da931af1 MS |
26 | addi r8, r0, __end |
27 | mts rslr, r8 | |
ecc30663 | 28 | /* TODO: Redo this code to call board_init_f_*() */ |
9d242745 MS |
29 | #if defined(CONFIG_SPL_BUILD) |
30 | addi r1, r0, CONFIG_SPL_STACK_ADDR | |
da931af1 | 31 | mts rshr, r1 |
9d242745 | 32 | addi r1, r1, -4 /* Decrement SP to top of memory */ |
405e651d | 33 | #else |
9eea5016 AY |
34 | #if CONFIG_VAL(SYS_MALLOC_F_LEN) |
35 | addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN) | |
9d242745 | 36 | #else |
6d0f6bcf | 37 | addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET |
405e651d | 38 | #endif |
da931af1 | 39 | mts rshr, r1 |
17980495 | 40 | addi r1, r1, -4 /* Decrement SP to top of memory */ |
b98cba09 MS |
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 */ | |
f3090fce MS |
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 | |
b98cba09 | 56 | |
86c1b2a8 MS |
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 */ | |
507bbe3e | 60 | |
6d0f6bcf | 61 | #ifdef CONFIG_SYS_RESET_ADDRESS |
cfc67116 | 62 | /* reset address */ |
86c1b2a8 MS |
63 | swi r2, r0, 0x0 /* reset address - imm opcode */ |
64 | swi r3, r0, 0x4 /* reset address - brai opcode */ | |
65 | ||
6d0f6bcf | 66 | addik r6, r0, CONFIG_SYS_RESET_ADDRESS |
cfc67116 | 67 | sw r6, r1, r0 |
5562bcc2 MS |
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 | |
cfc67116 MS |
73 | #endif |
74 | ||
6d0f6bcf | 75 | #ifdef CONFIG_SYS_USR_EXCEP |
cfc67116 | 76 | /* user_vector_exception */ |
86c1b2a8 MS |
77 | swi r2, r0, 0x8 /* user vector exception - imm opcode */ |
78 | swi r3, r0, 0xC /* user vector exception - brai opcode */ | |
79 | ||
cfc67116 MS |
80 | addik r6, r0, _exception_handler |
81 | sw r6, r1, r0 | |
b98cba09 MS |
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 | |
071bc923 | 88 | * 16bits from _exception_handler address and copy it to |
b98cba09 MS |
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 | |
cfc67116 MS |
107 | #endif |
108 | ||
cfc67116 | 109 | /* interrupt_handler */ |
86c1b2a8 MS |
110 | swi r2, r0, 0x10 /* interrupt - imm opcode */ |
111 | swi r3, r0, 0x14 /* interrupt - brai opcode */ | |
112 | ||
cfc67116 MS |
113 | addik r6, r0, _interrupt_handler |
114 | sw r6, r1, r0 | |
b98cba09 MS |
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 | |
507bbe3e | 120 | |
cfc67116 | 121 | /* hardware exception */ |
86c1b2a8 MS |
122 | swi r2, r0, 0x20 /* hardware exception - imm opcode */ |
123 | swi r3, r0, 0x24 /* hardware exception - brai opcode */ | |
124 | ||
cfc67116 MS |
125 | addik r6, r0, _hw_exception_handler |
126 | sw r6, r1, r0 | |
b98cba09 MS |
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 | |
1d82e2c1 | 132 | #endif /* CONFIG_SPL_BUILD */ |
cfc67116 | 133 | |
5811830f MS |
134 | /* Flush cache before enable cache */ |
135 | addik r5, r0, 0 | |
136 | addik r6, r0, XILINX_DCACHE_BYTE_SIZE | |
e4a4743e | 137 | bralid r15, flush_cache |
5811830f MS |
138 | nop |
139 | ||
cfc67116 MS |
140 | /* enable instruction and data cache */ |
141 | mfs r12, rmsr | |
822d43a6 | 142 | ori r12, r12, 0x1a0 |
cfc67116 MS |
143 | mts rmsr, r12 |
144 | ||
ecc30663 | 145 | /* TODO: Redo this code to call board_init_f_*() */ |
17980495 MS |
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 */ | |
48470b7a MS |
158 | #ifdef CONFIG_DEBUG_UART |
159 | bralid r15, debug_uart_init | |
160 | nop | |
161 | #endif | |
9d242745 | 162 | #ifndef CONFIG_SPL_BUILD |
e945f6dc | 163 | or r5, r0, r0 /* flags - empty */ |
0510b14b | 164 | addi r31, r0, _gd |
9eea5016 | 165 | #if CONFIG_VAL(SYS_MALLOC_F_LEN) |
405e651d MS |
166 | addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET |
167 | swi r6, r31, GD_MALLOC_BASE | |
168 | #endif | |
2380b8f5 | 169 | brai board_init_f |
9d242745 | 170 | #else |
ca7d2266 | 171 | addi r31, r0, _gd |
9eea5016 | 172 | #if CONFIG_VAL(SYS_MALLOC_F_LEN) |
ca7d2266 MS |
173 | addi r6, r0, CONFIG_SPL_STACK_ADDR |
174 | swi r6, r31, GD_MALLOC_BASE | |
175 | #endif | |
9d242745 MS |
176 | brai board_init_r |
177 | #endif | |
507bbe3e | 178 | 1: bri 1b |
0643631a | 179 | |
0510b14b MS |
180 | .section .bss |
181 | .align 4 | |
182 | _gd: | |
183 | .space GENERATED_GBL_DATA_SIZE | |
184 | ||
9d242745 | 185 | #ifndef CONFIG_SPL_BUILD |
0643631a MS |
186 | /* |
187 | * Read 16bit little endian | |
188 | */ | |
189 | .text | |
190 | .global in16 | |
191 | .ent in16 | |
192 | .align 2 | |
193 | in16: lhu r3, r0, r5 | |
194 | bslli r4, r3, 8 | |
195 | bsrli r3, r3, 8 | |
196 | andi r4, r4, 0xffff | |
197 | or r3, r3, r4 | |
198 | rtsd r15, 8 | |
199 | sext16 r3, r3 | |
200 | .end in16 | |
201 | ||
202 | /* | |
203 | * Write 16bit little endian | |
204 | * first parameter(r5) - address, second(r6) - short value | |
205 | */ | |
206 | .text | |
207 | .global out16 | |
208 | .ent out16 | |
209 | .align 2 | |
210 | out16: bslli r3, r6, 8 | |
211 | bsrli r6, r6, 8 | |
212 | andi r3, r3, 0xffff | |
213 | or r3, r3, r6 | |
214 | sh r3, r0, r5 | |
215 | rtsd r15, 8 | |
216 | or r0, r0, r0 | |
217 | .end out16 | |
e945f6dc MS |
218 | |
219 | /* | |
220 | * Relocate u-boot | |
221 | */ | |
222 | .text | |
223 | .global relocate_code | |
224 | .ent relocate_code | |
225 | .align 2 | |
226 | relocate_code: | |
227 | /* | |
228 | * r5 - start_addr_sp | |
229 | * r6 - new_gd | |
230 | * r7 - reloc_addr | |
231 | */ | |
232 | addi r1, r5, 0 /* Start to use new SP */ | |
233 | addi r31, r6, 0 /* Start to use new GD */ | |
234 | ||
235 | add r23, r0, r7 /* Move reloc addr to r23 */ | |
236 | /* Relocate text and data - r12 temp value */ | |
237 | addi r21, r0, _start | |
238 | addi r22, r0, __end - 4 /* Include BSS too */ | |
7c4dd542 MS |
239 | |
240 | rsub r6, r21, r22 | |
241 | or r5, r0, r0 | |
242 | 1: lw r12, r21, r5 /* Load u-boot data */ | |
243 | sw r12, r23, r5 /* Write zero to loc */ | |
244 | cmp r12, r5, r6 /* Check if we have reach the end */ | |
e945f6dc | 245 | bneid r12, 1b |
7c4dd542 | 246 | addi r5, r5, 4 /* Increment to next loc - relocate code */ |
e945f6dc MS |
247 | |
248 | /* R23 points to the base address. */ | |
249 | add r23, r0, r7 /* Move reloc addr to r23 */ | |
250 | addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */ | |
251 | rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */ | |
252 | ||
253 | addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ | |
254 | lwi r7, r0, 0x28 | |
255 | swi r6, r0, 0x28 /* used first unused MB vector */ | |
256 | lbui r10, r0, 0x28 /* used first unused MB vector */ | |
257 | swi r7, r0, 0x28 | |
258 | ||
259 | #ifdef CONFIG_SYS_USR_EXCEP | |
260 | addik r6, r0, _exception_handler | |
261 | addk r6, r6, r23 /* add offset */ | |
262 | sw r6, r1, r0 | |
263 | lhu r7, r1, r10 | |
264 | rsubi r8, r10, 0xa | |
265 | sh r7, r0, r8 | |
266 | rsubi r8, r10, 0xe | |
267 | sh r6, r0, r8 | |
268 | #endif | |
269 | addik r6, r0, _hw_exception_handler | |
270 | addk r6, r6, r23 /* add offset */ | |
271 | sw r6, r1, r0 | |
272 | lhu r7, r1, r10 | |
273 | rsubi r8, r10, 0x22 | |
274 | sh r7, r0, r8 | |
275 | rsubi r8, r10, 0x26 | |
276 | sh r6, r0, r8 | |
277 | ||
278 | addik r6, r0, _interrupt_handler | |
279 | addk r6, r6, r23 /* add offset */ | |
280 | sw r6, r1, r0 | |
281 | lhu r7, r1, r10 | |
282 | rsubi r8, r10, 0x12 | |
283 | sh r7, r0, r8 | |
284 | rsubi r8, r10, 0x16 | |
285 | sh r6, r0, r8 | |
286 | ||
287 | /* Check if GOT exist */ | |
288 | addik r21, r23, _got_start | |
289 | addik r22, r23, _got_end | |
290 | cmpu r12, r21, r22 | |
291 | beqi r12, 2f /* No GOT table - jump over */ | |
292 | ||
293 | /* Skip last 3 entries plus 1 because of loop boundary below */ | |
294 | addik r22, r22, -0x10 | |
295 | ||
296 | /* Relocate the GOT. */ | |
297 | 3: lw r12, r21, r0 /* Load entry */ | |
298 | addk r12, r12, r23 /* Add reloc offset */ | |
299 | sw r12, r21, r0 /* Save entry back */ | |
300 | ||
301 | cmpu r12, r21, r22 /* Check if this cross boundary */ | |
302 | bneid r12, 3b | |
303 | addik r21. r21, 4 | |
304 | ||
305 | /* Update pointer to GOT */ | |
306 | mfs r20, rpc | |
307 | addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8 | |
308 | addk r20, r20, r23 | |
309 | ||
310 | /* Flush caches to ensure consistency */ | |
311 | addik r5, r0, 0 | |
312 | addik r6, r0, XILINX_DCACHE_BYTE_SIZE | |
313 | bralid r15, flush_cache | |
314 | nop | |
315 | ||
316 | 2: addi r5, r31, 0 /* gd is initialized in board_r.c */ | |
317 | addi r6, r0, CONFIG_SYS_TEXT_BASE | |
318 | addi r12, r23, board_init_r | |
319 | bra r12 /* Jump to relocated code */ | |
320 | ||
321 | .end relocate_code | |
9d242745 | 322 | #endif |