]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/microblaze/cpu/start.S
Merge git://git.denx.de/u-boot-fsl-qoriq
[people/ms/u-boot.git] / arch / microblaze / cpu / start.S
CommitLineData
507bbe3e 1/*
cfc67116 2 * (C) Copyright 2007 Michal Simek
507bbe3e
WD
3 * (C) Copyright 2004 Atmark Techno, Inc.
4 *
cfc67116 5 * Michal SIMEK <monstr@monstr.eu>
507bbe3e
WD
6 * Yasushi SHOJI <yashi@atmark-techno.com>
7 *
1a459660 8 * SPDX-License-Identifier: GPL-2.0+
507bbe3e
WD
9 */
10
25ddd1fb 11#include <asm-offsets.h>
507bbe3e
WD
12#include <config.h>
13
14 .text
15 .global _start
16_start:
86c1b2a8
MS
17 /*
18 * reserve registers:
19 * r10: Stores little/big endian offset for vectors
20 * r2: Stores imm opcode
21 * r3: Stores brai opcode
22 */
23
cfc67116 24 mts rmsr, r0 /* disable cache */
9d242745 25
da931af1
MS
26 addi r8, r0, __end
27 mts rslr, r8
ecc30663 28 /* TODO: Redo this code to call board_init_f_*() */
9d242745
MS
29#if defined(CONFIG_SPL_BUILD)
30 addi r1, r0, CONFIG_SPL_STACK_ADDR
da931af1 31 mts rshr, r1
9d242745 32 addi r1, r1, -4 /* Decrement SP to top of memory */
405e651d 33#else
9eea5016
AY
34#if CONFIG_VAL(SYS_MALLOC_F_LEN)
35 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN)
9d242745 36#else
6d0f6bcf 37 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
405e651d 38#endif
da931af1 39 mts rshr, r1
17980495 40 addi r1, r1, -4 /* Decrement SP to top of memory */
b98cba09
MS
41
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 */
f3090fce
MS
52 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
b98cba09 56
86c1b2a8
MS
57 /* 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 */
507bbe3e 60
6d0f6bcf 61#ifdef CONFIG_SYS_RESET_ADDRESS
cfc67116 62 /* reset address */
86c1b2a8
MS
63 swi r2, r0, 0x0 /* reset address - imm opcode */
64 swi r3, r0, 0x4 /* reset address - brai opcode */
65
6d0f6bcf 66 addik r6, r0, CONFIG_SYS_RESET_ADDRESS
cfc67116 67 sw r6, r1, r0
5562bcc2
MS
68 lhu r7, r1, r10
69 rsubi r8, r10, 0x2
70 sh r7, r0, r8
71 rsubi r8, r10, 0x6
72 sh r6, r0, r8
cfc67116
MS
73#endif
74
6d0f6bcf 75#ifdef CONFIG_SYS_USR_EXCEP
cfc67116 76 /* user_vector_exception */
86c1b2a8
MS
77 swi r2, r0, 0x8 /* user vector exception - imm opcode */
78 swi r3, r0, 0xC /* user vector exception - brai opcode */
79
cfc67116
MS
80 addik r6, r0, _exception_handler
81 sw r6, r1, r0
b98cba09
MS
82 /*
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
071bc923 88 * 16bits from _exception_handler address and copy it to
b98cba09
MS
89 * 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
cfc67116
MS
107#endif
108
cfc67116 109 /* interrupt_handler */
86c1b2a8
MS
110 swi r2, r0, 0x10 /* interrupt - imm opcode */
111 swi r3, r0, 0x14 /* interrupt - brai opcode */
112
cfc67116
MS
113 addik r6, r0, _interrupt_handler
114 sw r6, r1, r0
b98cba09
MS
115 lhu r7, r1, r10
116 rsubi r8, r10, 0x12
117 sh r7, r0, r8
118 rsubi r8, r10, 0x16
119 sh r6, r0, r8
507bbe3e 120
cfc67116 121 /* hardware exception */
86c1b2a8
MS
122 swi r2, r0, 0x20 /* hardware exception - imm opcode */
123 swi r3, r0, 0x24 /* hardware exception - brai opcode */
124
cfc67116
MS
125 addik r6, r0, _hw_exception_handler
126 sw r6, r1, r0
b98cba09
MS
127 lhu r7, r1, r10
128 rsubi r8, r10, 0x22
129 sh r7, r0, r8
130 rsubi r8, r10, 0x26
131 sh r6, r0, r8
1d82e2c1 132#endif /* CONFIG_SPL_BUILD */
cfc67116 133
5811830f
MS
134 /* Flush cache before enable cache */
135 addik r5, r0, 0
136 addik r6, r0, XILINX_DCACHE_BYTE_SIZE
e4a4743e 137 bralid r15, flush_cache
5811830f
MS
138 nop
139
cfc67116
MS
140 /* enable instruction and data cache */
141 mfs r12, rmsr
822d43a6 142 ori r12, r12, 0x1a0
cfc67116
MS
143 mts rmsr, r12
144
ecc30663 145 /* TODO: Redo this code to call board_init_f_*() */
17980495
MS
146clear_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 */
48470b7a
MS
158#ifdef CONFIG_DEBUG_UART
159 bralid r15, debug_uart_init
160 nop
161#endif
9d242745 162#ifndef CONFIG_SPL_BUILD
e945f6dc 163 or r5, r0, r0 /* flags - empty */
0510b14b 164 addi r31, r0, _gd
9eea5016 165#if CONFIG_VAL(SYS_MALLOC_F_LEN)
405e651d
MS
166 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
167 swi r6, r31, GD_MALLOC_BASE
168#endif
2380b8f5 169 brai board_init_f
9d242745 170#else
ca7d2266 171 addi r31, r0, _gd
9eea5016 172#if CONFIG_VAL(SYS_MALLOC_F_LEN)
ca7d2266
MS
173 addi r6, r0, CONFIG_SPL_STACK_ADDR
174 swi r6, r31, GD_MALLOC_BASE
175#endif
9d242745
MS
176 brai board_init_r
177#endif
507bbe3e 1781: bri 1b
0643631a 179
0510b14b
MS
180 .section .bss
181.align 4
182_gd:
183 .space GENERATED_GBL_DATA_SIZE
184
9d242745 185#ifndef CONFIG_SPL_BUILD
0643631a
MS
186/*
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
e945f6dc
MS
218
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 */
7c4dd542
MS
239
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 */
e945f6dc 245 bneid r12, 1b
7c4dd542 246 addi r5, r5, 4 /* Increment to next loc - relocate code */
e945f6dc
MS
247
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
9d242745 322#endif