]> git.sur5r.net Git - u-boot/blob - arch/microblaze/cpu/start.S
Merge remote-tracking branch 'u-boot/master' into 'u-boot-arm/master'
[u-boot] / 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, _gd
166 #if defined(CONFIG_SYS_MALLOC_F_LEN)
167         addi    r6, r0, CONFIG_SPL_STACK_ADDR
168         swi     r6, r31, GD_MALLOC_BASE
169 #endif
170         brai    board_init_r
171 #endif
172 1:      bri     1b
173
174  .section .bss
175 .align 4
176 _gd:
177          .space  GENERATED_GBL_DATA_SIZE
178
179 #ifndef CONFIG_SPL_BUILD
180 /*
181  * Read 16bit little endian
182  */
183         .text
184         .global in16
185         .ent    in16
186         .align  2
187 in16:   lhu     r3, r0, r5
188         bslli   r4, r3, 8
189         bsrli   r3, r3, 8
190         andi    r4, r4, 0xffff
191         or      r3, r3, r4
192         rtsd    r15, 8
193         sext16  r3, r3
194         .end    in16
195
196 /*
197  * Write 16bit little endian
198  * first parameter(r5) - address, second(r6) - short value
199  */
200         .text
201         .global out16
202         .ent    out16
203         .align  2
204 out16:  bslli   r3, r6, 8
205         bsrli   r6, r6, 8
206         andi    r3, r3, 0xffff
207         or      r3, r3, r6
208         sh      r3, r0, r5
209         rtsd    r15, 8
210         or      r0, r0, r0
211         .end    out16
212
213 /*
214  * Relocate u-boot
215  */
216         .text
217         .global relocate_code
218         .ent    relocate_code
219         .align  2
220 relocate_code:
221         /*
222          * r5 - start_addr_sp
223          * r6 - new_gd
224          * r7 - reloc_addr
225          */
226         addi    r1, r5, 0 /* Start to use new SP */
227         addi    r31, r6, 0 /* Start to use new GD */
228
229         add     r23, r0, r7 /* Move reloc addr to r23 */
230         /* Relocate text and data - r12 temp value */
231         addi    r21, r0, _start
232         addi    r22, r0, __end - 4 /* Include BSS too */
233
234         rsub    r6, r21, r22
235         or      r5, r0, r0
236 1:      lw      r12, r21, r5 /* Load u-boot data */
237         sw      r12, r23, r5 /* Write zero to loc */
238         cmp     r12, r5, r6 /* Check if we have reach the end */
239         bneid   r12, 1b
240         addi    r5, r5, 4 /* Increment to next loc - relocate code */
241
242        /* R23 points to the base address. */
243         add     r23, r0, r7 /* Move reloc addr to r23 */
244         addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
245         rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
246
247         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
248         lwi     r7, r0, 0x28
249         swi     r6, r0, 0x28 /* used first unused MB vector */
250         lbui    r10, r0, 0x28 /* used first unused MB vector */
251         swi     r7, r0, 0x28
252
253 #ifdef CONFIG_SYS_USR_EXCEP
254         addik   r6, r0, _exception_handler
255         addk    r6, r6, r23 /* add offset */
256         sw      r6, r1, r0
257         lhu     r7, r1, r10
258         rsubi   r8, r10, 0xa
259         sh      r7, r0, r8
260         rsubi   r8, r10, 0xe
261         sh      r6, r0, r8
262 #endif
263         addik   r6, r0, _hw_exception_handler
264         addk    r6, r6, r23 /* add offset */
265         sw      r6, r1, r0
266         lhu     r7, r1, r10
267         rsubi   r8, r10, 0x22
268         sh      r7, r0, r8
269         rsubi   r8, r10, 0x26
270         sh      r6, r0, r8
271
272         addik   r6, r0, _interrupt_handler
273         addk    r6, r6, r23 /* add offset */
274         sw      r6, r1, r0
275         lhu     r7, r1, r10
276         rsubi   r8, r10, 0x12
277         sh      r7, r0, r8
278         rsubi   r8, r10, 0x16
279         sh      r6, r0, r8
280
281         /* Check if GOT exist */
282         addik   r21, r23, _got_start
283         addik   r22, r23, _got_end
284         cmpu    r12, r21, r22
285         beqi    r12, 2f /* No GOT table - jump over */
286
287         /* Skip last 3 entries plus 1 because of loop boundary below */
288         addik   r22, r22, -0x10
289
290         /* Relocate the GOT. */
291 3:      lw      r12, r21, r0 /* Load entry */
292         addk    r12, r12, r23 /* Add reloc offset */
293         sw      r12, r21, r0 /* Save entry back */
294
295         cmpu    r12, r21, r22 /* Check if this cross boundary */
296         bneid   r12, 3b
297         addik   r21. r21, 4
298
299         /* Update pointer to GOT */
300         mfs     r20, rpc
301         addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
302         addk    r20, r20, r23
303
304         /* Flush caches to ensure consistency */
305         addik   r5, r0, 0
306         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
307         bralid  r15, flush_cache
308         nop
309
310 2:      addi    r5, r31, 0 /* gd is initialized in board_r.c */
311         addi    r6, r0, CONFIG_SYS_TEXT_BASE
312         addi    r12, r23, board_init_r
313         bra     r12 /* Jump to relocated code */
314
315         .end    relocate_code
316 #endif