blob: 953d3a15eef21c391f611bf01b346d187d79246f [file] [log] [blame]
wdenk507bbe32004-04-18 21:13:41 +00001/*
Michal Simekcfc67112007-03-11 13:48:24 +01002 * (C) Copyright 2007 Michal Simek
wdenk507bbe32004-04-18 21:13:41 +00003 * (C) Copyright 2004 Atmark Techno, Inc.
4 *
Michal Simekcfc67112007-03-11 13:48:24 +01005 * Michal SIMEK <monstr@monstr.eu>
wdenk507bbe32004-04-18 21:13:41 +00006 * Yasushi SHOJI <yashi@atmark-techno.com>
7 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenk507bbe32004-04-18 21:13:41 +00009 */
10
Wolfgang Denk25ddd1f2010-10-26 14:34:52 +020011#include <asm-offsets.h>
wdenk507bbe32004-04-18 21:13:41 +000012#include <config.h>
13
14 .text
15 .global _start
16_start:
Michal Simek86c1b2a2011-07-21 10:47:21 +020017 /*
18 * reserve registers:
19 * r10: Stores little/big endian offset for vectors
20 * r2: Stores imm opcode
21 * r3: Stores brai opcode
22 */
23
Michal Simekcfc67112007-03-11 13:48:24 +010024 mts rmsr, r0 /* disable cache */
Michal Simek9d242742014-01-21 07:30:37 +010025
Michal Simekda931af2014-11-04 13:30:14 +010026 addi r8, r0, __end
27 mts rslr, r8
Michal Simek9d242742014-01-21 07:30:37 +010028#if defined(CONFIG_SPL_BUILD)
29 addi r1, r0, CONFIG_SPL_STACK_ADDR
Michal Simekda931af2014-11-04 13:30:14 +010030 mts rshr, r1
Michal Simek9d242742014-01-21 07:30:37 +010031 addi r1, r1, -4 /* Decrement SP to top of memory */
32#else
Michal Simek405e6512015-01-30 15:46:43 +010033#if defined(CONFIG_SYS_MALLOC_F_LEN)
34 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
35#else
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020036 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
Michal Simek405e6512015-01-30 15:46:43 +010037#endif
Michal Simekda931af2014-11-04 13:30:14 +010038 mts rshr, r1
Michal Simek17980492007-03-26 01:39:07 +020039 addi r1, r1, -4 /* Decrement SP to top of memory */
Michal Simekb98cba02010-08-12 11:47:11 +020040
41 /* Find-out if u-boot is running on BIG/LITTLE endian platform
42 * There are some steps which is necessary to keep in mind:
43 * 1. Setup offset value to r6
44 * 2. Store word offset value to address 0x0
45 * 3. Load just byte from address 0x0
46 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
47 * value that's why is on address 0x0
48 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
49 */
50 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
Michal Simekf3090fc2010-11-15 09:54:43 +000051 lwi r7, r0, 0x28
52 swi r6, r0, 0x28 /* used first unused MB vector */
53 lbui r10, r0, 0x28 /* used first unused MB vector */
54 swi r7, r0, 0x28
Michal Simekb98cba02010-08-12 11:47:11 +020055
Michal Simek86c1b2a2011-07-21 10:47:21 +020056 /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
57 addi r2, r0, 0xb0000000 /* hex b000 opcode imm */
58 addi r3, r0, 0xb8080000 /* hew b808 opcode brai */
wdenk507bbe32004-04-18 21:13:41 +000059
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020060#ifdef CONFIG_SYS_RESET_ADDRESS
Michal Simekcfc67112007-03-11 13:48:24 +010061 /* reset address */
Michal Simek86c1b2a2011-07-21 10:47:21 +020062 swi r2, r0, 0x0 /* reset address - imm opcode */
63 swi r3, r0, 0x4 /* reset address - brai opcode */
64
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020065 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
Michal Simekcfc67112007-03-11 13:48:24 +010066 sw r6, r1, r0
Michal Simek5562bcc2011-08-30 15:22:24 +020067 lhu r7, r1, r10
68 rsubi r8, r10, 0x2
69 sh r7, r0, r8
70 rsubi r8, r10, 0x6
71 sh r6, r0, r8
Michal Simekcfc67112007-03-11 13:48:24 +010072#endif
73
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020074#ifdef CONFIG_SYS_USR_EXCEP
Michal Simekcfc67112007-03-11 13:48:24 +010075 /* user_vector_exception */
Michal Simek86c1b2a2011-07-21 10:47:21 +020076 swi r2, r0, 0x8 /* user vector exception - imm opcode */
77 swi r3, r0, 0xC /* user vector exception - brai opcode */
78
Michal Simekcfc67112007-03-11 13:48:24 +010079 addik r6, r0, _exception_handler
80 sw r6, r1, r0
Michal Simekb98cba02010-08-12 11:47:11 +020081 /*
82 * BIG ENDIAN memory map for user exception
83 * 0x8: 0xB000XXXX
84 * 0xC: 0xB808XXXX
85 *
86 * then it is necessary to count address for storing the most significant
Wolfgang Denk071bc922010-10-27 22:48:30 +020087 * 16bits from _exception_handler address and copy it to
Michal Simekb98cba02010-08-12 11:47:11 +020088 * 0xa address. Big endian use offset in r10=0 that's why is it just
89 * 0xa address. The same is done for the least significant 16 bits
90 * for 0xe address.
91 *
92 * LITTLE ENDIAN memory map for user exception
93 * 0x8: 0xXXXX00B0
94 * 0xC: 0xXXXX08B8
95 *
96 * Offset is for little endian setup to 0x2. rsubi instruction decrease
97 * address value to ensure that points to proper place which is
98 * 0x8 for the most significant 16 bits and
99 * 0xC for the least significant 16 bits
100 */
101 lhu r7, r1, r10
102 rsubi r8, r10, 0xa
103 sh r7, r0, r8
104 rsubi r8, r10, 0xe
105 sh r6, r0, r8
Michal Simekcfc67112007-03-11 13:48:24 +0100106#endif
107
Michal Simekcfc67112007-03-11 13:48:24 +0100108 /* interrupt_handler */
Michal Simek86c1b2a2011-07-21 10:47:21 +0200109 swi r2, r0, 0x10 /* interrupt - imm opcode */
110 swi r3, r0, 0x14 /* interrupt - brai opcode */
111
Michal Simekcfc67112007-03-11 13:48:24 +0100112 addik r6, r0, _interrupt_handler
113 sw r6, r1, r0
Michal Simekb98cba02010-08-12 11:47:11 +0200114 lhu r7, r1, r10
115 rsubi r8, r10, 0x12
116 sh r7, r0, r8
117 rsubi r8, r10, 0x16
118 sh r6, r0, r8
Michal Simekcfc67112007-03-11 13:48:24 +0100119
120 /* hardware exception */
Michal Simek86c1b2a2011-07-21 10:47:21 +0200121 swi r2, r0, 0x20 /* hardware exception - imm opcode */
122 swi r3, r0, 0x24 /* hardware exception - brai opcode */
123
Michal Simekcfc67112007-03-11 13:48:24 +0100124 addik r6, r0, _hw_exception_handler
125 sw r6, r1, r0
Michal Simekb98cba02010-08-12 11:47:11 +0200126 lhu r7, r1, r10
127 rsubi r8, r10, 0x22
128 sh r7, r0, r8
129 rsubi r8, r10, 0x26
130 sh r6, r0, r8
Michal Simek9d242742014-01-21 07:30:37 +0100131#endif /* BUILD_SPL */
Michal Simekcfc67112007-03-11 13:48:24 +0100132
Michal Simek58118302012-09-25 10:13:35 +0200133 /* Flush cache before enable cache */
134 addik r5, r0, 0
135 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
Michal Simeke4a47432015-01-27 12:46:07 +0100136 bralid r15, flush_cache
Michal Simek58118302012-09-25 10:13:35 +0200137 nop
138
Michal Simekcfc67112007-03-11 13:48:24 +0100139 /* enable instruction and data cache */
140 mfs r12, rmsr
Michal Simek822d43a2014-11-04 13:27:52 +0100141 ori r12, r12, 0x1a0
Michal Simekcfc67112007-03-11 13:48:24 +0100142 mts rmsr, r12
143
Michal Simek17980492007-03-26 01:39:07 +0200144clear_bss:
145 /* clear BSS segments */
146 addi r5, r0, __bss_start
147 addi r4, r0, __bss_end
148 cmp r6, r5, r4
149 beqi r6, 3f
1502:
151 swi r0, r5, 0 /* write zero to loc */
152 addi r5, r5, 4 /* increment to next loc */
153 cmp r6, r5, r4 /* check if we have reach the end */
154 bnei r6, 2b
1553: /* jumping to board_init */
Michal Simek9d242742014-01-21 07:30:37 +0100156#ifndef CONFIG_SPL_BUILD
Michal Simeke945f6d2014-05-08 16:08:44 +0200157 or r5, r0, r0 /* flags - empty */
Michal Simek0510b142015-01-30 15:45:02 +0100158 addi r31, r0, _gd
Michal Simek405e6512015-01-30 15:46:43 +0100159#if defined(CONFIG_SYS_MALLOC_F_LEN)
160 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
161 swi r6, r31, GD_MALLOC_BASE
162#endif
Michal Simek2380b8f2012-07-04 13:12:37 +0200163 brai board_init_f
Michal Simek9d242742014-01-21 07:30:37 +0100164#else
Michal Simekca7d2262015-02-03 16:24:48 +0100165 addi r31, r0, _gd
166#if defined(CONFIG_SYS_MALLOC_F_LEN)
167 addi r6, r0, CONFIG_SPL_STACK_ADDR
168 swi r6, r31, GD_MALLOC_BASE
169#endif
Michal Simek9d242742014-01-21 07:30:37 +0100170 brai board_init_r
171#endif
wdenk507bbe32004-04-18 21:13:41 +00001721: bri 1b
Michal Simek06436312007-04-21 21:02:40 +0200173
Michal Simek0510b142015-01-30 15:45:02 +0100174 .section .bss
175.align 4
176_gd:
177 .space GENERATED_GBL_DATA_SIZE
178
Michal Simek9d242742014-01-21 07:30:37 +0100179#ifndef CONFIG_SPL_BUILD
Michal Simek06436312007-04-21 21:02:40 +0200180/*
181 * Read 16bit little endian
182 */
183 .text
184 .global in16
185 .ent in16
186 .align 2
187in16: lhu r3, r0, r5
188 bslli r4, r3, 8
189 bsrli r3, r3, 8
190 andi r4, r4, 0xffff
191 or r3, r3, r4
192 rtsd r15, 8
193 sext16 r3, r3
194 .end in16
195
196/*
197 * Write 16bit little endian
198 * first parameter(r5) - address, second(r6) - short value
199 */
200 .text
201 .global out16
202 .ent out16
203 .align 2
204out16: bslli r3, r6, 8
205 bsrli r6, r6, 8
206 andi r3, r3, 0xffff
207 or r3, r3, r6
208 sh r3, r0, r5
209 rtsd r15, 8
210 or r0, r0, r0
211 .end out16
Michal Simeke945f6d2014-05-08 16:08:44 +0200212
213/*
214 * Relocate u-boot
215 */
216 .text
217 .global relocate_code
218 .ent relocate_code
219 .align 2
220relocate_code:
221 /*
222 * r5 - start_addr_sp
223 * r6 - new_gd
224 * r7 - reloc_addr
225 */
226 addi r1, r5, 0 /* Start to use new SP */
227 addi r31, r6, 0 /* Start to use new GD */
228
229 add r23, r0, r7 /* Move reloc addr to r23 */
230 /* Relocate text and data - r12 temp value */
231 addi r21, r0, _start
232 addi r22, r0, __end - 4 /* Include BSS too */
Michal Simek7c4dd542015-01-27 15:10:37 +0100233
234 rsub r6, r21, r22
235 or r5, r0, r0
2361: lw r12, r21, r5 /* Load u-boot data */
237 sw r12, r23, r5 /* Write zero to loc */
238 cmp r12, r5, r6 /* Check if we have reach the end */
Michal Simeke945f6d2014-05-08 16:08:44 +0200239 bneid r12, 1b
Michal Simek7c4dd542015-01-27 15:10:37 +0100240 addi r5, r5, 4 /* Increment to next loc - relocate code */
Michal Simeke945f6d2014-05-08 16:08:44 +0200241
242 /* R23 points to the base address. */
243 add r23, r0, r7 /* Move reloc addr to r23 */
244 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
245 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
246
247 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
248 lwi r7, r0, 0x28
249 swi r6, r0, 0x28 /* used first unused MB vector */
250 lbui r10, r0, 0x28 /* used first unused MB vector */
251 swi r7, r0, 0x28
252
253#ifdef CONFIG_SYS_USR_EXCEP
254 addik r6, r0, _exception_handler
255 addk r6, r6, r23 /* add offset */
256 sw r6, r1, r0
257 lhu r7, r1, r10
258 rsubi r8, r10, 0xa
259 sh r7, r0, r8
260 rsubi r8, r10, 0xe
261 sh r6, r0, r8
262#endif
263 addik r6, r0, _hw_exception_handler
264 addk r6, r6, r23 /* add offset */
265 sw r6, r1, r0
266 lhu r7, r1, r10
267 rsubi r8, r10, 0x22
268 sh r7, r0, r8
269 rsubi r8, r10, 0x26
270 sh r6, r0, r8
271
272 addik r6, r0, _interrupt_handler
273 addk r6, r6, r23 /* add offset */
274 sw r6, r1, r0
275 lhu r7, r1, r10
276 rsubi r8, r10, 0x12
277 sh r7, r0, r8
278 rsubi r8, r10, 0x16
279 sh r6, r0, r8
280
281 /* Check if GOT exist */
282 addik r21, r23, _got_start
283 addik r22, r23, _got_end
284 cmpu r12, r21, r22
285 beqi r12, 2f /* No GOT table - jump over */
286
287 /* Skip last 3 entries plus 1 because of loop boundary below */
288 addik r22, r22, -0x10
289
290 /* Relocate the GOT. */
2913: lw r12, r21, r0 /* Load entry */
292 addk r12, r12, r23 /* Add reloc offset */
293 sw r12, r21, r0 /* Save entry back */
294
295 cmpu r12, r21, r22 /* Check if this cross boundary */
296 bneid r12, 3b
297 addik r21. r21, 4
298
299 /* Update pointer to GOT */
300 mfs r20, rpc
301 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
302 addk r20, r20, r23
303
304 /* Flush caches to ensure consistency */
305 addik r5, r0, 0
306 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
307 bralid r15, flush_cache
308 nop
309
3102: addi r5, r31, 0 /* gd is initialized in board_r.c */
311 addi r6, r0, CONFIG_SYS_TEXT_BASE
312 addi r12, r23, board_init_r
313 bra r12 /* Jump to relocated code */
314
315 .end relocate_code
Michal Simek9d242742014-01-21 07:30:37 +0100316#endif