]> git.sur5r.net Git - u-boot/blob - arch/microblaze/cpu/start.S
Merge git://git.denx.de/u-boot-dm
[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         /* TODO: Redo this code to call board_init_f_mem() */
29 #if defined(CONFIG_SPL_BUILD)
30         addi    r1, r0, CONFIG_SPL_STACK_ADDR
31         mts     rshr, r1
32         addi    r1, r1, -4      /* Decrement SP to top of memory */
33 #else
34 #if defined(CONFIG_SYS_MALLOC_F_LEN)
35         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
36 #else
37         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
38 #endif
39         mts     rshr, r1
40         addi    r1, r1, -4      /* Decrement SP to top of memory */
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 */
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
56
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 */
60
61 #ifdef CONFIG_SYS_RESET_ADDRESS
62         /* reset address */
63         swi     r2, r0, 0x0     /* reset address - imm opcode */
64         swi     r3, r0, 0x4     /* reset address - brai opcode */
65
66         addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
67         sw      r6, r1, r0
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
73 #endif
74
75 #ifdef CONFIG_SYS_USR_EXCEP
76         /* user_vector_exception */
77         swi     r2, r0, 0x8     /* user vector exception - imm opcode */
78         swi     r3, r0, 0xC     /* user vector exception - brai opcode */
79
80         addik   r6, r0, _exception_handler
81         sw      r6, r1, r0
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
88          * 16bits from _exception_handler address and copy it to
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
107 #endif
108
109         /* interrupt_handler */
110         swi     r2, r0, 0x10    /* interrupt - imm opcode */
111         swi     r3, r0, 0x14    /* interrupt - brai opcode */
112
113         addik   r6, r0, _interrupt_handler
114         sw      r6, r1, r0
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
120
121         /* hardware exception */
122         swi     r2, r0, 0x20    /* hardware exception - imm opcode */
123         swi     r3, r0, 0x24    /* hardware exception - brai opcode */
124
125         addik   r6, r0, _hw_exception_handler
126         sw      r6, r1, r0
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
132 #endif /* BUILD_SPL */
133
134         /* Flush cache before enable cache */
135         addik   r5, r0, 0
136         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
137         bralid r15, flush_cache
138         nop
139
140         /* enable instruction and data cache */
141         mfs     r12, rmsr
142         ori     r12, r12, 0x1a0
143         mts     rmsr, r12
144
145         /* TODO: Redo this code to call board_init_f_mem() */
146 clear_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
152 2:
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
157 3:      /* jumping to board_init */
158 #ifndef CONFIG_SPL_BUILD
159         or      r5, r0, r0      /* flags - empty */
160         addi    r31, r0, _gd
161 #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
165         brai    board_init_f
166 #else
167         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
172         brai    board_init_r
173 #endif
174 1:      bri     1b
175
176  .section .bss
177 .align 4
178 _gd:
179          .space  GENERATED_GBL_DATA_SIZE
180
181 #ifndef CONFIG_SPL_BUILD
182 /*
183  * Read 16bit little endian
184  */
185         .text
186         .global in16
187         .ent    in16
188         .align  2
189 in16:   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
206 out16:  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
214
215 /*
216  * Relocate u-boot
217  */
218         .text
219         .global relocate_code
220         .ent    relocate_code
221         .align  2
222 relocate_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 */
235
236         rsub    r6, r21, r22
237         or      r5, r0, r0
238 1:      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 */
241         bneid   r12, 1b
242         addi    r5, r5, 4 /* Increment to next loc - relocate code */
243
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. */
293 3:      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
312 2:      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
318 #endif