blob: e9923b65ef3237bd1e2a60d3db34e0c5ee537146 [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
Albert ARIBAUDecc30662015-11-25 17:56:32 +010028 /* TODO: Redo this code to call board_init_f_*() */
Michal Simek9d242742014-01-21 07:30:37 +010029#if defined(CONFIG_SPL_BUILD)
30 addi r1, r0, CONFIG_SPL_STACK_ADDR
Michal Simekda931af2014-11-04 13:30:14 +010031 mts rshr, r1
Michal Simek9d242742014-01-21 07:30:37 +010032 addi r1, r1, -4 /* Decrement SP to top of memory */
33#else
Michal Simek405e6512015-01-30 15:46:43 +010034#if defined(CONFIG_SYS_MALLOC_F_LEN)
35 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
36#else
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020037 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
Michal Simek405e6512015-01-30 15:46:43 +010038#endif
Michal Simekda931af2014-11-04 13:30:14 +010039 mts rshr, r1
Michal Simek17980492007-03-26 01:39:07 +020040 addi r1, r1, -4 /* Decrement SP to top of memory */
Michal Simekb98cba02010-08-12 11:47:11 +020041
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 */
Michal Simekf3090fc2010-11-15 09:54:43 +000052 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
Michal Simekb98cba02010-08-12 11:47:11 +020056
Michal Simek86c1b2a2011-07-21 10:47:21 +020057 /* 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 */
wdenk507bbe32004-04-18 21:13:41 +000060
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020061#ifdef CONFIG_SYS_RESET_ADDRESS
Michal Simekcfc67112007-03-11 13:48:24 +010062 /* reset address */
Michal Simek86c1b2a2011-07-21 10:47:21 +020063 swi r2, r0, 0x0 /* reset address - imm opcode */
64 swi r3, r0, 0x4 /* reset address - brai opcode */
65
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020066 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
Michal Simekcfc67112007-03-11 13:48:24 +010067 sw r6, r1, r0
Michal Simek5562bcc2011-08-30 15:22:24 +020068 lhu r7, r1, r10
69 rsubi r8, r10, 0x2
70 sh r7, r0, r8
71 rsubi r8, r10, 0x6
72 sh r6, r0, r8
Michal Simekcfc67112007-03-11 13:48:24 +010073#endif
74
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020075#ifdef CONFIG_SYS_USR_EXCEP
Michal Simekcfc67112007-03-11 13:48:24 +010076 /* user_vector_exception */
Michal Simek86c1b2a2011-07-21 10:47:21 +020077 swi r2, r0, 0x8 /* user vector exception - imm opcode */
78 swi r3, r0, 0xC /* user vector exception - brai opcode */
79
Michal Simekcfc67112007-03-11 13:48:24 +010080 addik r6, r0, _exception_handler
81 sw r6, r1, r0
Michal Simekb98cba02010-08-12 11:47:11 +020082 /*
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
Wolfgang Denk071bc922010-10-27 22:48:30 +020088 * 16bits from _exception_handler address and copy it to
Michal Simekb98cba02010-08-12 11:47:11 +020089 * 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
Michal Simekcfc67112007-03-11 13:48:24 +0100107#endif
108
Michal Simekcfc67112007-03-11 13:48:24 +0100109 /* interrupt_handler */
Michal Simek86c1b2a2011-07-21 10:47:21 +0200110 swi r2, r0, 0x10 /* interrupt - imm opcode */
111 swi r3, r0, 0x14 /* interrupt - brai opcode */
112
Michal Simekcfc67112007-03-11 13:48:24 +0100113 addik r6, r0, _interrupt_handler
114 sw r6, r1, r0
Michal Simekb98cba02010-08-12 11:47:11 +0200115 lhu r7, r1, r10
116 rsubi r8, r10, 0x12
117 sh r7, r0, r8
118 rsubi r8, r10, 0x16
119 sh r6, r0, r8
Michal Simekcfc67112007-03-11 13:48:24 +0100120
121 /* hardware exception */
Michal Simek86c1b2a2011-07-21 10:47:21 +0200122 swi r2, r0, 0x20 /* hardware exception - imm opcode */
123 swi r3, r0, 0x24 /* hardware exception - brai opcode */
124
Michal Simekcfc67112007-03-11 13:48:24 +0100125 addik r6, r0, _hw_exception_handler
126 sw r6, r1, r0
Michal Simekb98cba02010-08-12 11:47:11 +0200127 lhu r7, r1, r10
128 rsubi r8, r10, 0x22
129 sh r7, r0, r8
130 rsubi r8, r10, 0x26
131 sh r6, r0, r8
Michal Simek9d242742014-01-21 07:30:37 +0100132#endif /* BUILD_SPL */
Michal Simekcfc67112007-03-11 13:48:24 +0100133
Michal Simek58118302012-09-25 10:13:35 +0200134 /* Flush cache before enable cache */
135 addik r5, r0, 0
136 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
Michal Simeke4a47432015-01-27 12:46:07 +0100137 bralid r15, flush_cache
Michal Simek58118302012-09-25 10:13:35 +0200138 nop
139
Michal Simekcfc67112007-03-11 13:48:24 +0100140 /* enable instruction and data cache */
141 mfs r12, rmsr
Michal Simek822d43a2014-11-04 13:27:52 +0100142 ori r12, r12, 0x1a0
Michal Simekcfc67112007-03-11 13:48:24 +0100143 mts rmsr, r12
144
Albert ARIBAUDecc30662015-11-25 17:56:32 +0100145 /* TODO: Redo this code to call board_init_f_*() */
Michal Simek17980492007-03-26 01:39:07 +0200146clear_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
1522:
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
1573: /* jumping to board_init */
Michal Simek48470b72015-12-10 12:55:39 +0100158#ifdef CONFIG_DEBUG_UART
159 bralid r15, debug_uart_init
160 nop
161#endif
Michal Simek9d242742014-01-21 07:30:37 +0100162#ifndef CONFIG_SPL_BUILD
Michal Simeke945f6d2014-05-08 16:08:44 +0200163 or r5, r0, r0 /* flags - empty */
Michal Simek0510b142015-01-30 15:45:02 +0100164 addi r31, r0, _gd
Michal Simek405e6512015-01-30 15:46:43 +0100165#if defined(CONFIG_SYS_MALLOC_F_LEN)
166 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
167 swi r6, r31, GD_MALLOC_BASE
168#endif
Michal Simek2380b8f2012-07-04 13:12:37 +0200169 brai board_init_f
Michal Simek9d242742014-01-21 07:30:37 +0100170#else
Michal Simekca7d2262015-02-03 16:24:48 +0100171 addi r31, r0, _gd
172#if defined(CONFIG_SYS_MALLOC_F_LEN)
173 addi r6, r0, CONFIG_SPL_STACK_ADDR
174 swi r6, r31, GD_MALLOC_BASE
175#endif
Michal Simek9d242742014-01-21 07:30:37 +0100176 brai board_init_r
177#endif
wdenk507bbe32004-04-18 21:13:41 +00001781: bri 1b
Michal Simek06436312007-04-21 21:02:40 +0200179
Michal Simek0510b142015-01-30 15:45:02 +0100180 .section .bss
181.align 4
182_gd:
183 .space GENERATED_GBL_DATA_SIZE
184
Michal Simek9d242742014-01-21 07:30:37 +0100185#ifndef CONFIG_SPL_BUILD
Michal Simek06436312007-04-21 21:02:40 +0200186/*
187 * Read 16bit little endian
188 */
189 .text
190 .global in16
191 .ent in16
192 .align 2
193in16: 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
210out16: 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
Michal Simeke945f6d2014-05-08 16:08:44 +0200218
219/*
220 * Relocate u-boot
221 */
222 .text
223 .global relocate_code
224 .ent relocate_code
225 .align 2
226relocate_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 */
Michal Simek7c4dd542015-01-27 15:10:37 +0100239
240 rsub r6, r21, r22
241 or r5, r0, r0
2421: 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 */
Michal Simeke945f6d2014-05-08 16:08:44 +0200245 bneid r12, 1b
Michal Simek7c4dd542015-01-27 15:10:37 +0100246 addi r5, r5, 4 /* Increment to next loc - relocate code */
Michal Simeke945f6d2014-05-08 16:08:44 +0200247
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. */
2973: 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
3162: 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
Michal Simek9d242742014-01-21 07:30:37 +0100322#endif