]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/microblaze/cpu/start.S
microblaze: Add support for CONFIG_SYS_MALLOC_F_LEN
[karo-tx-uboot.git] / arch / microblaze / cpu / start.S
1 /*
2  * (C) Copyright 2007 Michal Simek
3  * (C) Copyright 2004 Atmark Techno, Inc.
4  *
5  * Michal  SIMEK <monstr@monstr.eu>
6  * Yasushi SHOJI <yashi@atmark-techno.com>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <asm-offsets.h>
12 #include <config.h>
13
14         .text
15         .global _start
16 _start:
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
24         mts     rmsr, r0        /* disable cache */
25
26         addi    r8, r0, __end
27         mts     rslr, r8
28 #if defined(CONFIG_SPL_BUILD)
29         addi    r1, r0, CONFIG_SPL_STACK_ADDR
30         mts     rshr, r1
31         addi    r1, r1, -4      /* Decrement SP to top of memory */
32 #else
33 #if defined(CONFIG_SYS_MALLOC_F_LEN)
34         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
35 #else
36         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
37 #endif
38         mts     rshr, r1
39         addi    r1, r1, -4      /* Decrement SP to top of memory */
40
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 */
51         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
55
56         /* 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 */
59
60 #ifdef CONFIG_SYS_RESET_ADDRESS
61         /* reset address */
62         swi     r2, r0, 0x0     /* reset address - imm opcode */
63         swi     r3, r0, 0x4     /* reset address - brai opcode */
64
65         addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
66         sw      r6, r1, r0
67         lhu     r7, r1, r10
68         rsubi   r8, r10, 0x2
69         sh      r7, r0, r8
70         rsubi   r8, r10, 0x6
71         sh      r6, r0, r8
72 #endif
73
74 #ifdef CONFIG_SYS_USR_EXCEP
75         /* user_vector_exception */
76         swi     r2, r0, 0x8     /* user vector exception - imm opcode */
77         swi     r3, r0, 0xC     /* user vector exception - brai opcode */
78
79         addik   r6, r0, _exception_handler
80         sw      r6, r1, r0
81         /*
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
87          * 16bits from _exception_handler address and copy it to
88          * 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
106 #endif
107
108         /* interrupt_handler */
109         swi     r2, r0, 0x10    /* interrupt - imm opcode */
110         swi     r3, r0, 0x14    /* interrupt - brai opcode */
111
112         addik   r6, r0, _interrupt_handler
113         sw      r6, r1, r0
114         lhu     r7, r1, r10
115         rsubi   r8, r10, 0x12
116         sh      r7, r0, r8
117         rsubi   r8, r10, 0x16
118         sh      r6, r0, r8
119
120         /* hardware exception */
121         swi     r2, r0, 0x20    /* hardware exception - imm opcode */
122         swi     r3, r0, 0x24    /* hardware exception - brai opcode */
123
124         addik   r6, r0, _hw_exception_handler
125         sw      r6, r1, r0
126         lhu     r7, r1, r10
127         rsubi   r8, r10, 0x22
128         sh      r7, r0, r8
129         rsubi   r8, r10, 0x26
130         sh      r6, r0, r8
131 #endif /* BUILD_SPL */
132
133         /* Flush cache before enable cache */
134         addik   r5, r0, 0
135         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
136         bralid r15, flush_cache
137         nop
138
139         /* enable instruction and data cache */
140         mfs     r12, rmsr
141         ori     r12, r12, 0x1a0
142         mts     rmsr, r12
143
144 clear_bss:
145         /* clear BSS segments */
146         addi    r5, r0, __bss_start
147         addi    r4, r0, __bss_end
148         cmp     r6, r5, r4
149         beqi    r6, 3f
150 2:
151         swi     r0, r5, 0 /* write zero to loc */
152         addi    r5, r5, 4 /* increment to next loc */
153         cmp     r6, r5, r4 /* check if we have reach the end */
154         bnei    r6, 2b
155 3:      /* jumping to board_init */
156 #ifndef CONFIG_SPL_BUILD
157         or      r5, r0, r0      /* flags - empty */
158         addi    r31, r0, _gd
159 #if defined(CONFIG_SYS_MALLOC_F_LEN)
160         addi    r6, r0, CONFIG_SYS_INIT_SP_OFFSET
161         swi     r6, r31, GD_MALLOC_BASE
162 #endif
163         brai    board_init_f
164 #else
165         addi    r31, r0, CONFIG_SYS_SPL_MALLOC_END
166         brai    board_init_r
167 #endif
168 1:      bri     1b
169
170  .section .bss
171 .align 4
172 _gd:
173          .space  GENERATED_GBL_DATA_SIZE
174
175 #ifndef CONFIG_SPL_BUILD
176 /*
177  * Read 16bit little endian
178  */
179         .text
180         .global in16
181         .ent    in16
182         .align  2
183 in16:   lhu     r3, r0, r5
184         bslli   r4, r3, 8
185         bsrli   r3, r3, 8
186         andi    r4, r4, 0xffff
187         or      r3, r3, r4
188         rtsd    r15, 8
189         sext16  r3, r3
190         .end    in16
191
192 /*
193  * Write 16bit little endian
194  * first parameter(r5) - address, second(r6) - short value
195  */
196         .text
197         .global out16
198         .ent    out16
199         .align  2
200 out16:  bslli   r3, r6, 8
201         bsrli   r6, r6, 8
202         andi    r3, r3, 0xffff
203         or      r3, r3, r6
204         sh      r3, r0, r5
205         rtsd    r15, 8
206         or      r0, r0, r0
207         .end    out16
208
209 /*
210  * Relocate u-boot
211  */
212         .text
213         .global relocate_code
214         .ent    relocate_code
215         .align  2
216 relocate_code:
217         /*
218          * r5 - start_addr_sp
219          * r6 - new_gd
220          * r7 - reloc_addr
221          */
222         addi    r1, r5, 0 /* Start to use new SP */
223         addi    r31, r6, 0 /* Start to use new GD */
224
225         add     r23, r0, r7 /* Move reloc addr to r23 */
226         /* Relocate text and data - r12 temp value */
227         addi    r21, r0, _start
228         addi    r22, r0, __end - 4 /* Include BSS too */
229
230         rsub    r6, r21, r22
231         or      r5, r0, r0
232 1:      lw      r12, r21, r5 /* Load u-boot data */
233         sw      r12, r23, r5 /* Write zero to loc */
234         cmp     r12, r5, r6 /* Check if we have reach the end */
235         bneid   r12, 1b
236         addi    r5, r5, 4 /* Increment to next loc - relocate code */
237
238        /* R23 points to the base address. */
239         add     r23, r0, r7 /* Move reloc addr to r23 */
240         addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
241         rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
242
243         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
244         lwi     r7, r0, 0x28
245         swi     r6, r0, 0x28 /* used first unused MB vector */
246         lbui    r10, r0, 0x28 /* used first unused MB vector */
247         swi     r7, r0, 0x28
248
249 #ifdef CONFIG_SYS_USR_EXCEP
250         addik   r6, r0, _exception_handler
251         addk    r6, r6, r23 /* add offset */
252         sw      r6, r1, r0
253         lhu     r7, r1, r10
254         rsubi   r8, r10, 0xa
255         sh      r7, r0, r8
256         rsubi   r8, r10, 0xe
257         sh      r6, r0, r8
258 #endif
259         addik   r6, r0, _hw_exception_handler
260         addk    r6, r6, r23 /* add offset */
261         sw      r6, r1, r0
262         lhu     r7, r1, r10
263         rsubi   r8, r10, 0x22
264         sh      r7, r0, r8
265         rsubi   r8, r10, 0x26
266         sh      r6, r0, r8
267
268         addik   r6, r0, _interrupt_handler
269         addk    r6, r6, r23 /* add offset */
270         sw      r6, r1, r0
271         lhu     r7, r1, r10
272         rsubi   r8, r10, 0x12
273         sh      r7, r0, r8
274         rsubi   r8, r10, 0x16
275         sh      r6, r0, r8
276
277         /* Check if GOT exist */
278         addik   r21, r23, _got_start
279         addik   r22, r23, _got_end
280         cmpu    r12, r21, r22
281         beqi    r12, 2f /* No GOT table - jump over */
282
283         /* Skip last 3 entries plus 1 because of loop boundary below */
284         addik   r22, r22, -0x10
285
286         /* Relocate the GOT. */
287 3:      lw      r12, r21, r0 /* Load entry */
288         addk    r12, r12, r23 /* Add reloc offset */
289         sw      r12, r21, r0 /* Save entry back */
290
291         cmpu    r12, r21, r22 /* Check if this cross boundary */
292         bneid   r12, 3b
293         addik   r21. r21, 4
294
295         /* Update pointer to GOT */
296         mfs     r20, rpc
297         addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
298         addk    r20, r20, r23
299
300         /* Flush caches to ensure consistency */
301         addik   r5, r0, 0
302         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
303         bralid  r15, flush_cache
304         nop
305
306 2:      addi    r5, r31, 0 /* gd is initialized in board_r.c */
307         addi    r6, r0, CONFIG_SYS_TEXT_BASE
308         addi    r12, r23, board_init_r
309         bra     r12 /* Jump to relocated code */
310
311         .end    relocate_code
312 #endif