blob: 206be3e3ee588ed1192d3d4e5fc9e93b3645c602 [file] [log] [blame]
wdenk12490652004-04-18 21:13:41 +00001/*
Michal Simek922ce202007-03-11 13:48:24 +01002 * (C) Copyright 2007 Michal Simek
wdenk12490652004-04-18 21:13:41 +00003 * (C) Copyright 2004 Atmark Techno, Inc.
4 *
Michal Simek922ce202007-03-11 13:48:24 +01005 * Michal SIMEK <monstr@monstr.eu>
wdenk12490652004-04-18 21:13:41 +00006 * Yasushi SHOJI <yashi@atmark-techno.com>
7 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenk12490652004-04-18 21:13:41 +00009 */
10
Wolfgang Denk0191e472010-10-26 14:34:52 +020011#include <asm-offsets.h>
wdenk12490652004-04-18 21:13:41 +000012#include <config.h>
13
14 .text
15 .global _start
16_start:
Michal Simek4a30db92011-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 Simek922ce202007-03-11 13:48:24 +010024 mts rmsr, r0 /* disable cache */
Michal Simek26acb3e2014-01-21 07:30:37 +010025
Michal Simeka5e9d6e2014-11-04 13:30:14 +010026 addi r8, r0, __end
27 mts rslr, r8
Albert ARIBAUD6cb4c462015-11-25 17:56:32 +010028 /* TODO: Redo this code to call board_init_f_*() */
Michal Simek26acb3e2014-01-21 07:30:37 +010029#if defined(CONFIG_SPL_BUILD)
30 addi r1, r0, CONFIG_SPL_STACK_ADDR
Michal Simeka5e9d6e2014-11-04 13:30:14 +010031 mts rshr, r1
Michal Simek26acb3e2014-01-21 07:30:37 +010032 addi r1, r1, -4 /* Decrement SP to top of memory */
33#else
Michal Simek9ea67442015-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-VILLARD03836942008-10-16 15:01:15 +020037 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
Michal Simek9ea67442015-01-30 15:46:43 +010038#endif
Michal Simeka5e9d6e2014-11-04 13:30:14 +010039 mts rshr, r1
Michal Simek1f0c40c2007-03-26 01:39:07 +020040 addi r1, r1, -4 /* Decrement SP to top of memory */
Michal Simekead124a2010-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 Simekf9ec1722010-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 Simekead124a2010-08-12 11:47:11 +020056
Michal Simek4a30db92011-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 */
wdenk12490652004-04-18 21:13:41 +000060
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020061#ifdef CONFIG_SYS_RESET_ADDRESS
Michal Simek922ce202007-03-11 13:48:24 +010062 /* reset address */
Michal Simek4a30db92011-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-VILLARD03836942008-10-16 15:01:15 +020066 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
Michal Simek922ce202007-03-11 13:48:24 +010067 sw r6, r1, r0
Michal Simek8daf0c32011-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 Simek922ce202007-03-11 13:48:24 +010073#endif
74
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020075#ifdef CONFIG_SYS_USR_EXCEP
Michal Simek922ce202007-03-11 13:48:24 +010076 /* user_vector_exception */
Michal Simek4a30db92011-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 Simek922ce202007-03-11 13:48:24 +010080 addik r6, r0, _exception_handler
81 sw r6, r1, r0
Michal Simekead124a2010-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 Denk1136f692010-10-27 22:48:30 +020088 * 16bits from _exception_handler address and copy it to
Michal Simekead124a2010-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 Simek922ce202007-03-11 13:48:24 +0100107#endif
108
Michal Simek922ce202007-03-11 13:48:24 +0100109 /* interrupt_handler */
Michal Simek4a30db92011-07-21 10:47:21 +0200110 swi r2, r0, 0x10 /* interrupt - imm opcode */
111 swi r3, r0, 0x14 /* interrupt - brai opcode */
112
Michal Simek922ce202007-03-11 13:48:24 +0100113 addik r6, r0, _interrupt_handler
114 sw r6, r1, r0
Michal Simekead124a2010-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
wdenk12490652004-04-18 21:13:41 +0000120
Michal Simek922ce202007-03-11 13:48:24 +0100121 /* hardware exception */
Michal Simek4a30db92011-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 Simek922ce202007-03-11 13:48:24 +0100125 addik r6, r0, _hw_exception_handler
126 sw r6, r1, r0
Michal Simekead124a2010-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 Simek26acb3e2014-01-21 07:30:37 +0100132#endif /* BUILD_SPL */
Michal Simek922ce202007-03-11 13:48:24 +0100133
Michal Simeke3aa3d52012-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 Simek23162f42015-01-27 12:46:07 +0100137 bralid r15, flush_cache
Michal Simeke3aa3d52012-09-25 10:13:35 +0200138 nop
139
Michal Simek922ce202007-03-11 13:48:24 +0100140 /* enable instruction and data cache */
141 mfs r12, rmsr
Michal Simek28769382014-11-04 13:27:52 +0100142 ori r12, r12, 0x1a0
Michal Simek922ce202007-03-11 13:48:24 +0100143 mts rmsr, r12
144
Albert ARIBAUD6cb4c462015-11-25 17:56:32 +0100145 /* TODO: Redo this code to call board_init_f_*() */
Michal Simek1f0c40c2007-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 Simek26acb3e2014-01-21 07:30:37 +0100158#ifndef CONFIG_SPL_BUILD
Michal Simek65e915c2014-05-08 16:08:44 +0200159 or r5, r0, r0 /* flags - empty */
Michal Simeka79d6582015-01-30 15:45:02 +0100160 addi r31, r0, _gd
Michal Simek9ea67442015-01-30 15:46:43 +0100161#if defined(CONFIG_SYS_MALLOC_F_LEN)
162 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
163 swi r6, r31, GD_MALLOC_BASE
164#endif
Michal Simek9cabb362012-07-04 13:12:37 +0200165 brai board_init_f
Michal Simek26acb3e2014-01-21 07:30:37 +0100166#else
Michal Simekfb8e3842015-02-03 16:24:48 +0100167 addi r31, r0, _gd
168#if defined(CONFIG_SYS_MALLOC_F_LEN)
169 addi r6, r0, CONFIG_SPL_STACK_ADDR
170 swi r6, r31, GD_MALLOC_BASE
171#endif
Michal Simek26acb3e2014-01-21 07:30:37 +0100172 brai board_init_r
173#endif
wdenk12490652004-04-18 21:13:41 +00001741: bri 1b
Michal Simek04ae75f2007-04-21 21:02:40 +0200175
Michal Simeka79d6582015-01-30 15:45:02 +0100176 .section .bss
177.align 4
178_gd:
179 .space GENERATED_GBL_DATA_SIZE
180
Michal Simek26acb3e2014-01-21 07:30:37 +0100181#ifndef CONFIG_SPL_BUILD
Michal Simek04ae75f2007-04-21 21:02:40 +0200182/*
183 * Read 16bit little endian
184 */
185 .text
186 .global in16
187 .ent in16
188 .align 2
189in16: lhu r3, r0, r5
190 bslli r4, r3, 8
191 bsrli r3, r3, 8
192 andi r4, r4, 0xffff
193 or r3, r3, r4
194 rtsd r15, 8
195 sext16 r3, r3
196 .end in16
197
198/*
199 * Write 16bit little endian
200 * first parameter(r5) - address, second(r6) - short value
201 */
202 .text
203 .global out16
204 .ent out16
205 .align 2
206out16: bslli r3, r6, 8
207 bsrli r6, r6, 8
208 andi r3, r3, 0xffff
209 or r3, r3, r6
210 sh r3, r0, r5
211 rtsd r15, 8
212 or r0, r0, r0
213 .end out16
Michal Simek65e915c2014-05-08 16:08:44 +0200214
215/*
216 * Relocate u-boot
217 */
218 .text
219 .global relocate_code
220 .ent relocate_code
221 .align 2
222relocate_code:
223 /*
224 * r5 - start_addr_sp
225 * r6 - new_gd
226 * r7 - reloc_addr
227 */
228 addi r1, r5, 0 /* Start to use new SP */
229 addi r31, r6, 0 /* Start to use new GD */
230
231 add r23, r0, r7 /* Move reloc addr to r23 */
232 /* Relocate text and data - r12 temp value */
233 addi r21, r0, _start
234 addi r22, r0, __end - 4 /* Include BSS too */
Michal Simeka9228f62015-01-27 15:10:37 +0100235
236 rsub r6, r21, r22
237 or r5, r0, r0
2381: lw r12, r21, r5 /* Load u-boot data */
239 sw r12, r23, r5 /* Write zero to loc */
240 cmp r12, r5, r6 /* Check if we have reach the end */
Michal Simek65e915c2014-05-08 16:08:44 +0200241 bneid r12, 1b
Michal Simeka9228f62015-01-27 15:10:37 +0100242 addi r5, r5, 4 /* Increment to next loc - relocate code */
Michal Simek65e915c2014-05-08 16:08:44 +0200243
244 /* R23 points to the base address. */
245 add r23, r0, r7 /* Move reloc addr to r23 */
246 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
247 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
248
249 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
250 lwi r7, r0, 0x28
251 swi r6, r0, 0x28 /* used first unused MB vector */
252 lbui r10, r0, 0x28 /* used first unused MB vector */
253 swi r7, r0, 0x28
254
255#ifdef CONFIG_SYS_USR_EXCEP
256 addik r6, r0, _exception_handler
257 addk r6, r6, r23 /* add offset */
258 sw r6, r1, r0
259 lhu r7, r1, r10
260 rsubi r8, r10, 0xa
261 sh r7, r0, r8
262 rsubi r8, r10, 0xe
263 sh r6, r0, r8
264#endif
265 addik r6, r0, _hw_exception_handler
266 addk r6, r6, r23 /* add offset */
267 sw r6, r1, r0
268 lhu r7, r1, r10
269 rsubi r8, r10, 0x22
270 sh r7, r0, r8
271 rsubi r8, r10, 0x26
272 sh r6, r0, r8
273
274 addik r6, r0, _interrupt_handler
275 addk r6, r6, r23 /* add offset */
276 sw r6, r1, r0
277 lhu r7, r1, r10
278 rsubi r8, r10, 0x12
279 sh r7, r0, r8
280 rsubi r8, r10, 0x16
281 sh r6, r0, r8
282
283 /* Check if GOT exist */
284 addik r21, r23, _got_start
285 addik r22, r23, _got_end
286 cmpu r12, r21, r22
287 beqi r12, 2f /* No GOT table - jump over */
288
289 /* Skip last 3 entries plus 1 because of loop boundary below */
290 addik r22, r22, -0x10
291
292 /* Relocate the GOT. */
2933: lw r12, r21, r0 /* Load entry */
294 addk r12, r12, r23 /* Add reloc offset */
295 sw r12, r21, r0 /* Save entry back */
296
297 cmpu r12, r21, r22 /* Check if this cross boundary */
298 bneid r12, 3b
299 addik r21. r21, 4
300
301 /* Update pointer to GOT */
302 mfs r20, rpc
303 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
304 addk r20, r20, r23
305
306 /* Flush caches to ensure consistency */
307 addik r5, r0, 0
308 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
309 bralid r15, flush_cache
310 nop
311
3122: addi r5, r31, 0 /* gd is initialized in board_r.c */
313 addi r6, r0, CONFIG_SYS_TEXT_BASE
314 addi r12, r23, board_init_r
315 bra r12 /* Jump to relocated code */
316
317 .end relocate_code
Michal Simek26acb3e2014-01-21 07:30:37 +0100318#endif