arm: socfpga: Enable all FPGA config support for Arria 10
[platform/kernel/u-boot.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         /* TODO: Redo this code to call board_init_f_*() */
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 /* CONFIG_SPL_BUILD */
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_*() */
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 #ifdef CONFIG_DEBUG_UART
159         bralid  r15, debug_uart_init
160         nop
161 #endif
162 #ifndef CONFIG_SPL_BUILD
163         or      r5, r0, r0      /* flags - empty */
164         addi    r31, r0, _gd
165 #if defined(CONFIG_SYS_MALLOC_F_LEN)
166         addi    r6, r0, CONFIG_SYS_INIT_SP_OFFSET
167         swi     r6, r31, GD_MALLOC_BASE
168 #endif
169         brai    board_init_f
170 #else
171         addi    r31, r0, _gd
172 #if defined(CONFIG_SYS_MALLOC_F_LEN)
173         addi    r6, r0, CONFIG_SPL_STACK_ADDR
174         swi     r6, r31, GD_MALLOC_BASE
175 #endif
176         brai    board_init_r
177 #endif
178 1:      bri     1b
179
180  .section .bss
181 .align 4
182 _gd:
183          .space  GENERATED_GBL_DATA_SIZE
184
185 #ifndef CONFIG_SPL_BUILD
186 /*
187  * Read 16bit little endian
188  */
189         .text
190         .global in16
191         .ent    in16
192         .align  2
193 in16:   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
210 out16:  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
218
219 /*
220  * Relocate u-boot
221  */
222         .text
223         .global relocate_code
224         .ent    relocate_code
225         .align  2
226 relocate_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 */
239
240         rsub    r6, r21, r22
241         or      r5, r0, r0
242 1:      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 */
245         bneid   r12, 1b
246         addi    r5, r5, 4 /* Increment to next loc - relocate code */
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. */
297 3:      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
316 2:      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
322 #endif