]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - arch/microblaze/cpu/start.S
microblaze: Do not use CONFIG_SYS_GENERIC_GLOBAL_DATA
[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         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
34         mts     rshr, r1
35         addi    r1, r1, -4      /* Decrement SP to top of memory */
36
37         /* Find-out if u-boot is running on BIG/LITTLE endian platform
38          * There are some steps which is necessary to keep in mind:
39          * 1. Setup offset value to r6
40          * 2. Store word offset value to address 0x0
41          * 3. Load just byte from address 0x0
42          * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
43          *     value that's why is on address 0x0
44          * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
45          */
46         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
47         lwi     r7, r0, 0x28
48         swi     r6, r0, 0x28 /* used first unused MB vector */
49         lbui    r10, r0, 0x28 /* used first unused MB vector */
50         swi     r7, r0, 0x28
51
52         /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
53         addi    r2, r0, 0xb0000000      /* hex b000 opcode imm */
54         addi    r3, r0, 0xb8080000      /* hew b808 opcode brai */
55
56 #ifdef CONFIG_SYS_RESET_ADDRESS
57         /* reset address */
58         swi     r2, r0, 0x0     /* reset address - imm opcode */
59         swi     r3, r0, 0x4     /* reset address - brai opcode */
60
61         addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
62         sw      r6, r1, r0
63         lhu     r7, r1, r10
64         rsubi   r8, r10, 0x2
65         sh      r7, r0, r8
66         rsubi   r8, r10, 0x6
67         sh      r6, r0, r8
68 #endif
69
70 #ifdef CONFIG_SYS_USR_EXCEP
71         /* user_vector_exception */
72         swi     r2, r0, 0x8     /* user vector exception - imm opcode */
73         swi     r3, r0, 0xC     /* user vector exception - brai opcode */
74
75         addik   r6, r0, _exception_handler
76         sw      r6, r1, r0
77         /*
78          * BIG ENDIAN memory map for user exception
79          * 0x8: 0xB000XXXX
80          * 0xC: 0xB808XXXX
81          *
82          * then it is necessary to count address for storing the most significant
83          * 16bits from _exception_handler address and copy it to
84          * 0xa address. Big endian use offset in r10=0 that's why is it just
85          * 0xa address. The same is done for the least significant 16 bits
86          * for 0xe address.
87          *
88          * LITTLE ENDIAN memory map for user exception
89          * 0x8: 0xXXXX00B0
90          * 0xC: 0xXXXX08B8
91          *
92          * Offset is for little endian setup to 0x2. rsubi instruction decrease
93          * address value to ensure that points to proper place which is
94          * 0x8 for the most significant 16 bits and
95          * 0xC for the least significant 16 bits
96          */
97         lhu     r7, r1, r10
98         rsubi   r8, r10, 0xa
99         sh      r7, r0, r8
100         rsubi   r8, r10, 0xe
101         sh      r6, r0, r8
102 #endif
103
104         /* interrupt_handler */
105         swi     r2, r0, 0x10    /* interrupt - imm opcode */
106         swi     r3, r0, 0x14    /* interrupt - brai opcode */
107
108         addik   r6, r0, _interrupt_handler
109         sw      r6, r1, r0
110         lhu     r7, r1, r10
111         rsubi   r8, r10, 0x12
112         sh      r7, r0, r8
113         rsubi   r8, r10, 0x16
114         sh      r6, r0, r8
115
116         /* hardware exception */
117         swi     r2, r0, 0x20    /* hardware exception - imm opcode */
118         swi     r3, r0, 0x24    /* hardware exception - brai opcode */
119
120         addik   r6, r0, _hw_exception_handler
121         sw      r6, r1, r0
122         lhu     r7, r1, r10
123         rsubi   r8, r10, 0x22
124         sh      r7, r0, r8
125         rsubi   r8, r10, 0x26
126         sh      r6, r0, r8
127 #endif /* BUILD_SPL */
128
129         /* Flush cache before enable cache */
130         addik   r5, r0, 0
131         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
132         bralid r15, flush_cache
133         nop
134
135         /* enable instruction and data cache */
136         mfs     r12, rmsr
137         ori     r12, r12, 0x1a0
138         mts     rmsr, r12
139
140 clear_bss:
141         /* clear BSS segments */
142         addi    r5, r0, __bss_start
143         addi    r4, r0, __bss_end
144         cmp     r6, r5, r4
145         beqi    r6, 3f
146 2:
147         swi     r0, r5, 0 /* write zero to loc */
148         addi    r5, r5, 4 /* increment to next loc */
149         cmp     r6, r5, r4 /* check if we have reach the end */
150         bnei    r6, 2b
151 3:      /* jumping to board_init */
152 #ifndef CONFIG_SPL_BUILD
153         or      r5, r0, r0      /* flags - empty */
154         addi    r31, r0, _gd
155         brai    board_init_f
156 #else
157         addi    r31, r0, CONFIG_SYS_SPL_MALLOC_END
158         brai    board_init_r
159 #endif
160 1:      bri     1b
161
162  .section .bss
163 .align 4
164 _gd:
165          .space  GENERATED_GBL_DATA_SIZE
166
167 #ifndef CONFIG_SPL_BUILD
168 /*
169  * Read 16bit little endian
170  */
171         .text
172         .global in16
173         .ent    in16
174         .align  2
175 in16:   lhu     r3, r0, r5
176         bslli   r4, r3, 8
177         bsrli   r3, r3, 8
178         andi    r4, r4, 0xffff
179         or      r3, r3, r4
180         rtsd    r15, 8
181         sext16  r3, r3
182         .end    in16
183
184 /*
185  * Write 16bit little endian
186  * first parameter(r5) - address, second(r6) - short value
187  */
188         .text
189         .global out16
190         .ent    out16
191         .align  2
192 out16:  bslli   r3, r6, 8
193         bsrli   r6, r6, 8
194         andi    r3, r3, 0xffff
195         or      r3, r3, r6
196         sh      r3, r0, r5
197         rtsd    r15, 8
198         or      r0, r0, r0
199         .end    out16
200
201 /*
202  * Relocate u-boot
203  */
204         .text
205         .global relocate_code
206         .ent    relocate_code
207         .align  2
208 relocate_code:
209         /*
210          * r5 - start_addr_sp
211          * r6 - new_gd
212          * r7 - reloc_addr
213          */
214         addi    r1, r5, 0 /* Start to use new SP */
215         addi    r31, r6, 0 /* Start to use new GD */
216
217         add     r23, r0, r7 /* Move reloc addr to r23 */
218         /* Relocate text and data - r12 temp value */
219         addi    r21, r0, _start
220         addi    r22, r0, __end - 4 /* Include BSS too */
221
222         rsub    r6, r21, r22
223         or      r5, r0, r0
224 1:      lw      r12, r21, r5 /* Load u-boot data */
225         sw      r12, r23, r5 /* Write zero to loc */
226         cmp     r12, r5, r6 /* Check if we have reach the end */
227         bneid   r12, 1b
228         addi    r5, r5, 4 /* Increment to next loc - relocate code */
229
230        /* R23 points to the base address. */
231         add     r23, r0, r7 /* Move reloc addr to r23 */
232         addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
233         rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
234
235         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
236         lwi     r7, r0, 0x28
237         swi     r6, r0, 0x28 /* used first unused MB vector */
238         lbui    r10, r0, 0x28 /* used first unused MB vector */
239         swi     r7, r0, 0x28
240
241 #ifdef CONFIG_SYS_USR_EXCEP
242         addik   r6, r0, _exception_handler
243         addk    r6, r6, r23 /* add offset */
244         sw      r6, r1, r0
245         lhu     r7, r1, r10
246         rsubi   r8, r10, 0xa
247         sh      r7, r0, r8
248         rsubi   r8, r10, 0xe
249         sh      r6, r0, r8
250 #endif
251         addik   r6, r0, _hw_exception_handler
252         addk    r6, r6, r23 /* add offset */
253         sw      r6, r1, r0
254         lhu     r7, r1, r10
255         rsubi   r8, r10, 0x22
256         sh      r7, r0, r8
257         rsubi   r8, r10, 0x26
258         sh      r6, r0, r8
259
260         addik   r6, r0, _interrupt_handler
261         addk    r6, r6, r23 /* add offset */
262         sw      r6, r1, r0
263         lhu     r7, r1, r10
264         rsubi   r8, r10, 0x12
265         sh      r7, r0, r8
266         rsubi   r8, r10, 0x16
267         sh      r6, r0, r8
268
269         /* Check if GOT exist */
270         addik   r21, r23, _got_start
271         addik   r22, r23, _got_end
272         cmpu    r12, r21, r22
273         beqi    r12, 2f /* No GOT table - jump over */
274
275         /* Skip last 3 entries plus 1 because of loop boundary below */
276         addik   r22, r22, -0x10
277
278         /* Relocate the GOT. */
279 3:      lw      r12, r21, r0 /* Load entry */
280         addk    r12, r12, r23 /* Add reloc offset */
281         sw      r12, r21, r0 /* Save entry back */
282
283         cmpu    r12, r21, r22 /* Check if this cross boundary */
284         bneid   r12, 3b
285         addik   r21. r21, 4
286
287         /* Update pointer to GOT */
288         mfs     r20, rpc
289         addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
290         addk    r20, r20, r23
291
292         /* Flush caches to ensure consistency */
293         addik   r5, r0, 0
294         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
295         bralid  r15, flush_cache
296         nop
297
298 2:      addi    r5, r31, 0 /* gd is initialized in board_r.c */
299         addi    r6, r0, CONFIG_SYS_TEXT_BASE
300         addi    r12, r23, board_init_r
301         bra     r12 /* Jump to relocated code */
302
303         .end    relocate_code
304 #endif