blob: 9479737aa296e2b746916e7719b0d8204c154e00 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
wdenk507bbe32004-04-18 21:13:41 +00002/*
Michal Simekcfc67112007-03-11 13:48:24 +01003 * (C) Copyright 2007 Michal Simek
wdenk507bbe32004-04-18 21:13:41 +00004 * (C) Copyright 2004 Atmark Techno, Inc.
5 *
Michal Simekcfc67112007-03-11 13:48:24 +01006 * Michal SIMEK <monstr@monstr.eu>
wdenk507bbe32004-04-18 21:13:41 +00007 * Yasushi SHOJI <yashi@atmark-techno.com>
wdenk507bbe32004-04-18 21:13:41 +00008 */
9
Wolfgang Denk25ddd1f2010-10-26 14:34:52 +020010#include <asm-offsets.h>
wdenk507bbe32004-04-18 21:13:41 +000011#include <config.h>
12
13 .text
14 .global _start
15_start:
Michal Simekcfc67112007-03-11 13:48:24 +010016 mts rmsr, r0 /* disable cache */
Michal Simek9d242742014-01-21 07:30:37 +010017
Michal Simekda931af2014-11-04 13:30:14 +010018 addi r8, r0, __end
19 mts rslr, r8
Ovidiu Panaitf5d8b1a2020-09-24 11:54:37 +030020
Michal Simek9d242742014-01-21 07:30:37 +010021#if defined(CONFIG_SPL_BUILD)
22 addi r1, r0, CONFIG_SPL_STACK_ADDR
Michal Simek405e6512015-01-30 15:46:43 +010023#else
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020024 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
Michal Simek405e6512015-01-30 15:46:43 +010025#endif
Ovidiu Panaitf5d8b1a2020-09-24 11:54:37 +030026
Michal Simek17980492007-03-26 01:39:07 +020027 addi r1, r1, -4 /* Decrement SP to top of memory */
Michal Simekb98cba02010-08-12 11:47:11 +020028
Ovidiu Panaitf5d8b1a2020-09-24 11:54:37 +030029 /* Call board_init_f_alloc_reserve with the current stack pointer as
30 * parameter. */
31 add r5, r0, r1
32 bralid r15, board_init_f_alloc_reserve
33 nop
34
35 /* board_init_f_alloc_reserve returns a pointer to the allocated area
36 * in r3. Set the new stack pointer below this area. */
37 add r1, r0, r3
38 mts rshr, r1
39 addi r1, r1, -4
40
41 /* Call board_init_f_init_reserve with the address returned by
42 * board_init_f_alloc_reserve as parameter. */
43 add r5, r0, r3
44 bralid r15, board_init_f_init_reserve
45 nop
46
47#if !defined(CONFIG_SPL_BUILD)
Ovidiu Panait627085e2020-09-24 11:54:36 +030048 /* Setup vectors with pre-relocation symbols */
49 or r5, r0, r0
50 bralid r15, __setup_exceptions
51 nop
Ovidiu Panaitf5d8b1a2020-09-24 11:54:37 +030052#endif
Michal Simekcfc67112007-03-11 13:48:24 +010053
Michal Simek58118302012-09-25 10:13:35 +020054 /* Flush cache before enable cache */
55 addik r5, r0, 0
56 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
Ovidiu Panait627085e2020-09-24 11:54:36 +030057 bralid r15, flush_cache
Michal Simek58118302012-09-25 10:13:35 +020058 nop
59
Michal Simekcfc67112007-03-11 13:48:24 +010060 /* enable instruction and data cache */
61 mfs r12, rmsr
Michal Simek822d43a2014-11-04 13:27:52 +010062 ori r12, r12, 0x1a0
Michal Simekcfc67112007-03-11 13:48:24 +010063 mts rmsr, r12
64
Michal Simek17980492007-03-26 01:39:07 +020065clear_bss:
66 /* clear BSS segments */
67 addi r5, r0, __bss_start
68 addi r4, r0, __bss_end
69 cmp r6, r5, r4
70 beqi r6, 3f
712:
72 swi r0, r5, 0 /* write zero to loc */
73 addi r5, r5, 4 /* increment to next loc */
74 cmp r6, r5, r4 /* check if we have reach the end */
75 bnei r6, 2b
763: /* jumping to board_init */
Michal Simek48470b72015-12-10 12:55:39 +010077#ifdef CONFIG_DEBUG_UART
78 bralid r15, debug_uart_init
79 nop
80#endif
Michal Simek9d242742014-01-21 07:30:37 +010081#ifndef CONFIG_SPL_BUILD
Michal Simeke945f6d2014-05-08 16:08:44 +020082 or r5, r0, r0 /* flags - empty */
Michal Simek2380b8f2012-07-04 13:12:37 +020083 brai board_init_f
Michal Simek9d242742014-01-21 07:30:37 +010084#else
85 brai board_init_r
86#endif
wdenk507bbe32004-04-18 21:13:41 +0000871: bri 1b
Michal Simek06436312007-04-21 21:02:40 +020088
Michal Simek9d242742014-01-21 07:30:37 +010089#ifndef CONFIG_SPL_BUILD
Ovidiu Panait627085e2020-09-24 11:54:36 +030090 .text
91 .ent __setup_exceptions
92 .align 2
93/*
94 * Set up reset, interrupt, user exception and hardware exception vectors.
95 *
96 * Parameters:
97 * r5 - relocation offset (zero when setting up vectors before
98 * relocation, and gd->reloc_off when setting up vectors after
99 * relocation)
100 * - the relocation offset is added to the _exception_handler,
101 * _interrupt_handler and _hw_exception_handler symbols to reflect the
102 * post-relocation memory addresses
103 *
104 * Reserve registers:
105 * r10: Stores little/big endian offset for vectors
106 * r2: Stores imm opcode
107 * r3: Stores brai opcode
108 */
109__setup_exceptions:
110 addik r1, r1, -28
111 swi r2, r1, 4
112 swi r3, r1, 8
113 swi r6, r1, 12
114 swi r7, r1, 16
115 swi r8, r1, 20
116 swi r10, r1, 24
117
118 /* Find-out if u-boot is running on BIG/LITTLE endian platform
119 * There are some steps which is necessary to keep in mind:
120 * 1. Setup offset value to r6
121 * 2. Store word offset value to address 0x0
122 * 3. Load just byte from address 0x0
123 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
124 * value that's why is on address 0x0
125 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
126 */
127 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
128 lwi r7, r0, 0x28
129 swi r6, r0, 0x28 /* used first unused MB vector */
130 lbui r10, r0, 0x28 /* used first unused MB vector */
131 swi r7, r0, 0x28
132
133 /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
134 addi r2, r0, 0xb0000000 /* hex b000 opcode imm */
135 addi r3, r0, 0xb8080000 /* hew b808 opcode brai */
136
137#ifdef CONFIG_SYS_RESET_ADDRESS
138 /* reset address */
139 swi r2, r0, 0x0 /* reset address - imm opcode */
140 swi r3, r0, 0x4 /* reset address - brai opcode */
141
142 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
143 sw r6, r1, r0
144 lhu r7, r1, r10
145 rsubi r8, r10, 0x2
146 sh r7, r0, r8
147 rsubi r8, r10, 0x6
148 sh r6, r0, r8
149#endif
150
151#ifdef CONFIG_SYS_USR_EXCEP
152 /* user_vector_exception */
153 swi r2, r0, 0x8 /* user vector exception - imm opcode */
154 swi r3, r0, 0xC /* user vector exception - brai opcode */
155
156 addik r6, r5, _exception_handler
157 sw r6, r1, r0
158 /*
159 * BIG ENDIAN memory map for user exception
160 * 0x8: 0xB000XXXX
161 * 0xC: 0xB808XXXX
162 *
163 * then it is necessary to count address for storing the most significant
164 * 16bits from _exception_handler address and copy it to
165 * 0xa address. Big endian use offset in r10=0 that's why is it just
166 * 0xa address. The same is done for the least significant 16 bits
167 * for 0xe address.
168 *
169 * LITTLE ENDIAN memory map for user exception
170 * 0x8: 0xXXXX00B0
171 * 0xC: 0xXXXX08B8
172 *
173 * Offset is for little endian setup to 0x2. rsubi instruction decrease
174 * address value to ensure that points to proper place which is
175 * 0x8 for the most significant 16 bits and
176 * 0xC for the least significant 16 bits
177 */
178 lhu r7, r1, r10
179 rsubi r8, r10, 0xa
180 sh r7, r0, r8
181 rsubi r8, r10, 0xe
182 sh r6, r0, r8
183#endif
184
185 /* interrupt_handler */
186 swi r2, r0, 0x10 /* interrupt - imm opcode */
187 swi r3, r0, 0x14 /* interrupt - brai opcode */
188
189 addik r6, r5, _interrupt_handler
190 sw r6, r1, r0
191 lhu r7, r1, r10
192 rsubi r8, r10, 0x12
193 sh r7, r0, r8
194 rsubi r8, r10, 0x16
195 sh r6, r0, r8
196
197 /* hardware exception */
198 swi r2, r0, 0x20 /* hardware exception - imm opcode */
199 swi r3, r0, 0x24 /* hardware exception - brai opcode */
200
201 addik r6, r5, _hw_exception_handler
202 sw r6, r1, r0
203 lhu r7, r1, r10
204 rsubi r8, r10, 0x22
205 sh r7, r0, r8
206 rsubi r8, r10, 0x26
207 sh r6, r0, r8
208
209 lwi r10, r1, 24
210 lwi r8, r1, 20
211 lwi r7, r1, 16
212 lwi r6, r1, 12
213 lwi r3, r1, 8
214 lwi r2, r1, 4
215 addik r1, r1, 28
216
217 rtsd r15, 8
218 or r0, r0, r0
219 .end __setup_exceptions
220
Michal Simek06436312007-04-21 21:02:40 +0200221/*
222 * Read 16bit little endian
223 */
224 .text
225 .global in16
226 .ent in16
227 .align 2
228in16: lhu r3, r0, r5
229 bslli r4, r3, 8
230 bsrli r3, r3, 8
231 andi r4, r4, 0xffff
232 or r3, r3, r4
233 rtsd r15, 8
234 sext16 r3, r3
235 .end in16
236
237/*
238 * Write 16bit little endian
239 * first parameter(r5) - address, second(r6) - short value
240 */
241 .text
242 .global out16
243 .ent out16
244 .align 2
245out16: bslli r3, r6, 8
246 bsrli r6, r6, 8
247 andi r3, r3, 0xffff
248 or r3, r3, r6
249 sh r3, r0, r5
250 rtsd r15, 8
251 or r0, r0, r0
252 .end out16
Michal Simeke945f6d2014-05-08 16:08:44 +0200253
254/*
255 * Relocate u-boot
256 */
257 .text
258 .global relocate_code
259 .ent relocate_code
260 .align 2
261relocate_code:
262 /*
263 * r5 - start_addr_sp
264 * r6 - new_gd
265 * r7 - reloc_addr
266 */
267 addi r1, r5, 0 /* Start to use new SP */
268 addi r31, r6, 0 /* Start to use new GD */
269
270 add r23, r0, r7 /* Move reloc addr to r23 */
271 /* Relocate text and data - r12 temp value */
272 addi r21, r0, _start
273 addi r22, r0, __end - 4 /* Include BSS too */
Michal Simek7c4dd542015-01-27 15:10:37 +0100274
275 rsub r6, r21, r22
276 or r5, r0, r0
2771: lw r12, r21, r5 /* Load u-boot data */
278 sw r12, r23, r5 /* Write zero to loc */
279 cmp r12, r5, r6 /* Check if we have reach the end */
Michal Simeke945f6d2014-05-08 16:08:44 +0200280 bneid r12, 1b
Michal Simek7c4dd542015-01-27 15:10:37 +0100281 addi r5, r5, 4 /* Increment to next loc - relocate code */
Michal Simeke945f6d2014-05-08 16:08:44 +0200282
Michal Simek3ad95ed2019-10-21 12:20:16 +0200283 /* R23 points to the base address. */
Michal Simeke945f6d2014-05-08 16:08:44 +0200284 add r23, r0, r7 /* Move reloc addr to r23 */
285 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
286 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
287
Ovidiu Panait627085e2020-09-24 11:54:36 +0300288 /* Setup vectors with post-relocation symbols */
289 add r5, r0, r23 /* load gd->reloc_off to r5 */
290 bralid r15, __setup_exceptions
291 nop
Michal Simeke945f6d2014-05-08 16:08:44 +0200292
293 /* Check if GOT exist */
294 addik r21, r23, _got_start
295 addik r22, r23, _got_end
296 cmpu r12, r21, r22
297 beqi r12, 2f /* No GOT table - jump over */
298
299 /* Skip last 3 entries plus 1 because of loop boundary below */
300 addik r22, r22, -0x10
301
302 /* Relocate the GOT. */
3033: lw r12, r21, r0 /* Load entry */
304 addk r12, r12, r23 /* Add reloc offset */
305 sw r12, r21, r0 /* Save entry back */
306
307 cmpu r12, r21, r22 /* Check if this cross boundary */
308 bneid r12, 3b
309 addik r21. r21, 4
310
311 /* Update pointer to GOT */
312 mfs r20, rpc
313 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
314 addk r20, r20, r23
315
316 /* Flush caches to ensure consistency */
317 addik r5, r0, 0
318 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
319 bralid r15, flush_cache
320 nop
321
3222: addi r5, r31, 0 /* gd is initialized in board_r.c */
323 addi r6, r0, CONFIG_SYS_TEXT_BASE
324 addi r12, r23, board_init_r
325 bra r12 /* Jump to relocated code */
326
327 .end relocate_code
Michal Simek9d242742014-01-21 07:30:37 +0100328#endif