]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/microblaze/cpu/start.S
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[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 #if defined(CONFIG_SPL_BUILD)
27         addi    r1, r0, CONFIG_SPL_STACK_ADDR
28         addi    r1, r1, -4      /* Decrement SP to top of memory */
29 #else
30         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
31         addi    r1, r1, -4      /* Decrement SP to top of memory */
32
33         /* Find-out if u-boot is running on BIG/LITTLE endian platform
34          * There are some steps which is necessary to keep in mind:
35          * 1. Setup offset value to r6
36          * 2. Store word offset value to address 0x0
37          * 3. Load just byte from address 0x0
38          * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
39          *     value that's why is on address 0x0
40          * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
41          */
42         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
43         lwi     r7, r0, 0x28
44         swi     r6, r0, 0x28 /* used first unused MB vector */
45         lbui    r10, r0, 0x28 /* used first unused MB vector */
46         swi     r7, r0, 0x28
47
48         /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
49         addi    r2, r0, 0xb0000000      /* hex b000 opcode imm */
50         addi    r3, r0, 0xb8080000      /* hew b808 opcode brai */
51
52 #ifdef CONFIG_SYS_RESET_ADDRESS
53         /* reset address */
54         swi     r2, r0, 0x0     /* reset address - imm opcode */
55         swi     r3, r0, 0x4     /* reset address - brai opcode */
56
57         addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
58         sw      r6, r1, r0
59         lhu     r7, r1, r10
60         rsubi   r8, r10, 0x2
61         sh      r7, r0, r8
62         rsubi   r8, r10, 0x6
63         sh      r6, r0, r8
64 #endif
65
66 #ifdef CONFIG_SYS_USR_EXCEP
67         /* user_vector_exception */
68         swi     r2, r0, 0x8     /* user vector exception - imm opcode */
69         swi     r3, r0, 0xC     /* user vector exception - brai opcode */
70
71         addik   r6, r0, _exception_handler
72         sw      r6, r1, r0
73         /*
74          * BIG ENDIAN memory map for user exception
75          * 0x8: 0xB000XXXX
76          * 0xC: 0xB808XXXX
77          *
78          * then it is necessary to count address for storing the most significant
79          * 16bits from _exception_handler address and copy it to
80          * 0xa address. Big endian use offset in r10=0 that's why is it just
81          * 0xa address. The same is done for the least significant 16 bits
82          * for 0xe address.
83          *
84          * LITTLE ENDIAN memory map for user exception
85          * 0x8: 0xXXXX00B0
86          * 0xC: 0xXXXX08B8
87          *
88          * Offset is for little endian setup to 0x2. rsubi instruction decrease
89          * address value to ensure that points to proper place which is
90          * 0x8 for the most significant 16 bits and
91          * 0xC for the least significant 16 bits
92          */
93         lhu     r7, r1, r10
94         rsubi   r8, r10, 0xa
95         sh      r7, r0, r8
96         rsubi   r8, r10, 0xe
97         sh      r6, r0, r8
98 #endif
99
100         /* interrupt_handler */
101         swi     r2, r0, 0x10    /* interrupt - imm opcode */
102         swi     r3, r0, 0x14    /* interrupt - brai opcode */
103
104         addik   r6, r0, _interrupt_handler
105         sw      r6, r1, r0
106         lhu     r7, r1, r10
107         rsubi   r8, r10, 0x12
108         sh      r7, r0, r8
109         rsubi   r8, r10, 0x16
110         sh      r6, r0, r8
111
112         /* hardware exception */
113         swi     r2, r0, 0x20    /* hardware exception - imm opcode */
114         swi     r3, r0, 0x24    /* hardware exception - brai opcode */
115
116         addik   r6, r0, _hw_exception_handler
117         sw      r6, r1, r0
118         lhu     r7, r1, r10
119         rsubi   r8, r10, 0x22
120         sh      r7, r0, r8
121         rsubi   r8, r10, 0x26
122         sh      r6, r0, r8
123 #endif /* BUILD_SPL */
124
125         /* Flush cache before enable cache */
126         addik   r5, r0, 0
127         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
128 flush:  bralid r15, flush_cache
129         nop
130
131         /* enable instruction and data cache */
132         mfs     r12, rmsr
133         ori     r12, r12, 0xa0
134         mts     rmsr, r12
135
136 clear_bss:
137         /* clear BSS segments */
138         addi    r5, r0, __bss_start
139         addi    r4, r0, __bss_end
140         cmp     r6, r5, r4
141         beqi    r6, 3f
142 2:
143         swi     r0, r5, 0 /* write zero to loc */
144         addi    r5, r5, 4 /* increment to next loc */
145         cmp     r6, r5, r4 /* check if we have reach the end */
146         bnei    r6, 2b
147 3:      /* jumping to board_init */
148 #ifndef CONFIG_SPL_BUILD
149         brai    board_init_f
150 #else
151         brai    board_init_r
152 #endif
153 1:      bri     1b
154
155 #ifndef CONFIG_SPL_BUILD
156 /*
157  * Read 16bit little endian
158  */
159         .text
160         .global in16
161         .ent    in16
162         .align  2
163 in16:   lhu     r3, r0, r5
164         bslli   r4, r3, 8
165         bsrli   r3, r3, 8
166         andi    r4, r4, 0xffff
167         or      r3, r3, r4
168         rtsd    r15, 8
169         sext16  r3, r3
170         .end    in16
171
172 /*
173  * Write 16bit little endian
174  * first parameter(r5) - address, second(r6) - short value
175  */
176         .text
177         .global out16
178         .ent    out16
179         .align  2
180 out16:  bslli   r3, r6, 8
181         bsrli   r6, r6, 8
182         andi    r3, r3, 0xffff
183         or      r3, r3, r6
184         sh      r3, r0, r5
185         rtsd    r15, 8
186         or      r0, r0, r0
187         .end    out16
188 #endif