blob: 22903e3bc4e5e403975e09788e4b6f343dee700e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
wdenk12490652004-04-18 21:13:41 +00002/*
Michal Simek922ce202007-03-11 13:48:24 +01003 * (C) Copyright 2007 Michal Simek
wdenk12490652004-04-18 21:13:41 +00004 * (C) Copyright 2004 Atmark Techno, Inc.
5 *
Michal Simek922ce202007-03-11 13:48:24 +01006 * Michal SIMEK <monstr@monstr.eu>
wdenk12490652004-04-18 21:13:41 +00007 * Yasushi SHOJI <yashi@atmark-techno.com>
wdenk12490652004-04-18 21:13:41 +00008 */
9
Wolfgang Denk0191e472010-10-26 14:34:52 +020010#include <asm-offsets.h>
wdenk12490652004-04-18 21:13:41 +000011#include <config.h>
12
13 .text
14 .global _start
15_start:
Michal Simek4a30db92011-07-21 10:47:21 +020016 /*
17 * reserve registers:
18 * r10: Stores little/big endian offset for vectors
19 * r2: Stores imm opcode
20 * r3: Stores brai opcode
21 */
22
Michal Simek922ce202007-03-11 13:48:24 +010023 mts rmsr, r0 /* disable cache */
Michal Simek26acb3e2014-01-21 07:30:37 +010024
Michal Simeka5e9d6e2014-11-04 13:30:14 +010025 addi r8, r0, __end
26 mts rslr, r8
Albert ARIBAUD6cb4c462015-11-25 17:56:32 +010027 /* TODO: Redo this code to call board_init_f_*() */
Michal Simek26acb3e2014-01-21 07:30:37 +010028#if defined(CONFIG_SPL_BUILD)
29 addi r1, r0, CONFIG_SPL_STACK_ADDR
Michal Simeka5e9d6e2014-11-04 13:30:14 +010030 mts rshr, r1
Michal Simek26acb3e2014-01-21 07:30:37 +010031 addi r1, r1, -4 /* Decrement SP to top of memory */
32#else
Andy Yanc2d85e72017-07-24 17:49:01 +080033#if CONFIG_VAL(SYS_MALLOC_F_LEN)
34 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN)
Michal Simek9ea67442015-01-30 15:46:43 +010035#else
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020036 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
Michal Simek9ea67442015-01-30 15:46:43 +010037#endif
Michal Simeka5e9d6e2014-11-04 13:30:14 +010038 mts rshr, r1
Michal Simek1f0c40c2007-03-26 01:39:07 +020039 addi r1, r1, -4 /* Decrement SP to top of memory */
Michal Simekead124a2010-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 Simekf9ec1722010-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 Simekead124a2010-08-12 11:47:11 +020055
Michal Simek4a30db92011-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 */
wdenk12490652004-04-18 21:13:41 +000059
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020060#ifdef CONFIG_SYS_RESET_ADDRESS
Michal Simek922ce202007-03-11 13:48:24 +010061 /* reset address */
Michal Simek4a30db92011-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-VILLARD03836942008-10-16 15:01:15 +020065 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
Michal Simek922ce202007-03-11 13:48:24 +010066 sw r6, r1, r0
Michal Simek8daf0c32011-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 Simek922ce202007-03-11 13:48:24 +010072#endif
73
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020074#ifdef CONFIG_SYS_USR_EXCEP
Michal Simek922ce202007-03-11 13:48:24 +010075 /* user_vector_exception */
Michal Simek4a30db92011-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 Simek922ce202007-03-11 13:48:24 +010079 addik r6, r0, _exception_handler
80 sw r6, r1, r0
Michal Simekead124a2010-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 Denk1136f692010-10-27 22:48:30 +020087 * 16bits from _exception_handler address and copy it to
Michal Simekead124a2010-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 Simek922ce202007-03-11 13:48:24 +0100106#endif
107
Michal Simek922ce202007-03-11 13:48:24 +0100108 /* interrupt_handler */
Michal Simek4a30db92011-07-21 10:47:21 +0200109 swi r2, r0, 0x10 /* interrupt - imm opcode */
110 swi r3, r0, 0x14 /* interrupt - brai opcode */
111
Michal Simek922ce202007-03-11 13:48:24 +0100112 addik r6, r0, _interrupt_handler
113 sw r6, r1, r0
Michal Simekead124a2010-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
wdenk12490652004-04-18 21:13:41 +0000119
Michal Simek922ce202007-03-11 13:48:24 +0100120 /* hardware exception */
Michal Simek4a30db92011-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 Simek922ce202007-03-11 13:48:24 +0100124 addik r6, r0, _hw_exception_handler
125 sw r6, r1, r0
Michal Simekead124a2010-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 Simekad400c62017-01-30 12:20:37 +0100131#endif /* CONFIG_SPL_BUILD */
Michal Simek922ce202007-03-11 13:48:24 +0100132
Michal Simeke3aa3d52012-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 Simek23162f42015-01-27 12:46:07 +0100136 bralid r15, flush_cache
Michal Simeke3aa3d52012-09-25 10:13:35 +0200137 nop
138
Michal Simek922ce202007-03-11 13:48:24 +0100139 /* enable instruction and data cache */
140 mfs r12, rmsr
Michal Simek28769382014-11-04 13:27:52 +0100141 ori r12, r12, 0x1a0
Michal Simek922ce202007-03-11 13:48:24 +0100142 mts rmsr, r12
143
Albert ARIBAUD6cb4c462015-11-25 17:56:32 +0100144 /* TODO: Redo this code to call board_init_f_*() */
Michal Simek1f0c40c2007-03-26 01:39:07 +0200145clear_bss:
146 /* clear BSS segments */
147 addi r5, r0, __bss_start
148 addi r4, r0, __bss_end
149 cmp r6, r5, r4
150 beqi r6, 3f
1512:
152 swi r0, r5, 0 /* write zero to loc */
153 addi r5, r5, 4 /* increment to next loc */
154 cmp r6, r5, r4 /* check if we have reach the end */
155 bnei r6, 2b
1563: /* jumping to board_init */
Michal Simekb5904112015-12-10 12:55:39 +0100157#ifdef CONFIG_DEBUG_UART
158 bralid r15, debug_uart_init
159 nop
160#endif
Michal Simek26acb3e2014-01-21 07:30:37 +0100161#ifndef CONFIG_SPL_BUILD
Michal Simek65e915c2014-05-08 16:08:44 +0200162 or r5, r0, r0 /* flags - empty */
Michal Simeka79d6582015-01-30 15:45:02 +0100163 addi r31, r0, _gd
Andy Yanc2d85e72017-07-24 17:49:01 +0800164#if CONFIG_VAL(SYS_MALLOC_F_LEN)
Michal Simek9ea67442015-01-30 15:46:43 +0100165 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
166 swi r6, r31, GD_MALLOC_BASE
167#endif
Michal Simek9cabb362012-07-04 13:12:37 +0200168 brai board_init_f
Michal Simek26acb3e2014-01-21 07:30:37 +0100169#else
Michal Simekfb8e3842015-02-03 16:24:48 +0100170 addi r31, r0, _gd
Andy Yanc2d85e72017-07-24 17:49:01 +0800171#if CONFIG_VAL(SYS_MALLOC_F_LEN)
Michal Simekfb8e3842015-02-03 16:24:48 +0100172 addi r6, r0, CONFIG_SPL_STACK_ADDR
173 swi r6, r31, GD_MALLOC_BASE
174#endif
Michal Simek26acb3e2014-01-21 07:30:37 +0100175 brai board_init_r
176#endif
wdenk12490652004-04-18 21:13:41 +00001771: bri 1b
Michal Simek04ae75f2007-04-21 21:02:40 +0200178
Michal Simeka79d6582015-01-30 15:45:02 +0100179 .section .bss
180.align 4
181_gd:
182 .space GENERATED_GBL_DATA_SIZE
183
Michal Simek26acb3e2014-01-21 07:30:37 +0100184#ifndef CONFIG_SPL_BUILD
Michal Simek04ae75f2007-04-21 21:02:40 +0200185/*
186 * Read 16bit little endian
187 */
188 .text
189 .global in16
190 .ent in16
191 .align 2
192in16: lhu r3, r0, r5
193 bslli r4, r3, 8
194 bsrli r3, r3, 8
195 andi r4, r4, 0xffff
196 or r3, r3, r4
197 rtsd r15, 8
198 sext16 r3, r3
199 .end in16
200
201/*
202 * Write 16bit little endian
203 * first parameter(r5) - address, second(r6) - short value
204 */
205 .text
206 .global out16
207 .ent out16
208 .align 2
209out16: bslli r3, r6, 8
210 bsrli r6, r6, 8
211 andi r3, r3, 0xffff
212 or r3, r3, r6
213 sh r3, r0, r5
214 rtsd r15, 8
215 or r0, r0, r0
216 .end out16
Michal Simek65e915c2014-05-08 16:08:44 +0200217
218/*
219 * Relocate u-boot
220 */
221 .text
222 .global relocate_code
223 .ent relocate_code
224 .align 2
225relocate_code:
226 /*
227 * r5 - start_addr_sp
228 * r6 - new_gd
229 * r7 - reloc_addr
230 */
231 addi r1, r5, 0 /* Start to use new SP */
232 addi r31, r6, 0 /* Start to use new GD */
233
234 add r23, r0, r7 /* Move reloc addr to r23 */
235 /* Relocate text and data - r12 temp value */
236 addi r21, r0, _start
237 addi r22, r0, __end - 4 /* Include BSS too */
Michal Simeka9228f62015-01-27 15:10:37 +0100238
239 rsub r6, r21, r22
240 or r5, r0, r0
2411: lw r12, r21, r5 /* Load u-boot data */
242 sw r12, r23, r5 /* Write zero to loc */
243 cmp r12, r5, r6 /* Check if we have reach the end */
Michal Simek65e915c2014-05-08 16:08:44 +0200244 bneid r12, 1b
Michal Simeka9228f62015-01-27 15:10:37 +0100245 addi r5, r5, 4 /* Increment to next loc - relocate code */
Michal Simek65e915c2014-05-08 16:08:44 +0200246
247 /* R23 points to the base address. */
248 add r23, r0, r7 /* Move reloc addr to r23 */
249 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
250 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
251
252 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
253 lwi r7, r0, 0x28
254 swi r6, r0, 0x28 /* used first unused MB vector */
255 lbui r10, r0, 0x28 /* used first unused MB vector */
256 swi r7, r0, 0x28
257
258#ifdef CONFIG_SYS_USR_EXCEP
259 addik r6, r0, _exception_handler
260 addk r6, r6, r23 /* add offset */
261 sw r6, r1, r0
262 lhu r7, r1, r10
263 rsubi r8, r10, 0xa
264 sh r7, r0, r8
265 rsubi r8, r10, 0xe
266 sh r6, r0, r8
267#endif
268 addik r6, r0, _hw_exception_handler
269 addk r6, r6, r23 /* add offset */
270 sw r6, r1, r0
271 lhu r7, r1, r10
272 rsubi r8, r10, 0x22
273 sh r7, r0, r8
274 rsubi r8, r10, 0x26
275 sh r6, r0, r8
276
277 addik r6, r0, _interrupt_handler
278 addk r6, r6, r23 /* add offset */
279 sw r6, r1, r0
280 lhu r7, r1, r10
281 rsubi r8, r10, 0x12
282 sh r7, r0, r8
283 rsubi r8, r10, 0x16
284 sh r6, r0, r8
285
286 /* Check if GOT exist */
287 addik r21, r23, _got_start
288 addik r22, r23, _got_end
289 cmpu r12, r21, r22
290 beqi r12, 2f /* No GOT table - jump over */
291
292 /* Skip last 3 entries plus 1 because of loop boundary below */
293 addik r22, r22, -0x10
294
295 /* Relocate the GOT. */
2963: lw r12, r21, r0 /* Load entry */
297 addk r12, r12, r23 /* Add reloc offset */
298 sw r12, r21, r0 /* Save entry back */
299
300 cmpu r12, r21, r22 /* Check if this cross boundary */
301 bneid r12, 3b
302 addik r21. r21, 4
303
304 /* Update pointer to GOT */
305 mfs r20, rpc
306 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
307 addk r20, r20, r23
308
309 /* Flush caches to ensure consistency */
310 addik r5, r0, 0
311 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
312 bralid r15, flush_cache
313 nop
314
3152: addi r5, r31, 0 /* gd is initialized in board_r.c */
316 addi r6, r0, CONFIG_SYS_TEXT_BASE
317 addi r12, r23, board_init_r
318 bra r12 /* Jump to relocated code */
319
320 .end relocate_code
Michal Simek26acb3e2014-01-21 07:30:37 +0100321#endif