xref: /rk3399_rockchip-uboot/arch/microblaze/cpu/start.S (revision 86c1b2a86b59f3050413e78bfe40196ac3334c13)
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 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <asm-offsets.h>
28#include <config.h>
29
30	.text
31	.global _start
32_start:
33	/*
34	 * reserve registers:
35	 * r10: Stores little/big endian offset for vectors
36	 * r2: Stores imm opcode
37	 * r3: Stores brai opcode
38	 */
39
40	mts	rmsr, r0	/* disable cache */
41	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
42	addi	r1, r1, -4	/* Decrement SP to top of memory */
43
44	/* Find-out if u-boot is running on BIG/LITTLE endian platform
45	 * There are some steps which is necessary to keep in mind:
46	 * 1. Setup offset value to r6
47	 * 2. Store word offset value to address 0x0
48	 * 3. Load just byte from address 0x0
49	 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
50	 *     value that's why is on address 0x0
51	 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
52	 */
53	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
54	swi	r6, r0, 0
55	lbui	r10, r0, 0
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, r0
69	shi	r7, r0, 0x2
70	shi	r6, r0, 0x6
71/*
72 * Copy U-Boot code to CONFIG_SYS_TEXT_BASE
73 * solve problem with sbrk_base
74 */
75#if (CONFIG_SYS_RESET_ADDRESS != CONFIG_SYS_TEXT_BASE)
76	addi	r4, r0, __end
77	addi	r5, r0, __text_start
78	rsub	r4, r5, r4	/* size = __end - __text_start */
79	addi	r6, r0, CONFIG_SYS_RESET_ADDRESS	/* source address */
80	addi	r7, r0, 0	/* counter */
814:
82	lw	r8, r6, r7
83	sw	r8, r5, r7
84	addi	r7, r7, 0x4
85	cmp	r8, r4, r7
86	blti	r8, 4b
87#endif
88#endif
89
90#ifdef CONFIG_SYS_USR_EXCEP
91	/* user_vector_exception */
92	swi	r2, r0, 0x8	/* user vector exception - imm opcode */
93	swi	r3, r0, 0xC	/* user vector exception - brai opcode */
94
95	addik	r6, r0, _exception_handler
96	sw	r6, r1, r0
97	/*
98	 * BIG ENDIAN memory map for user exception
99	 * 0x8: 0xB000XXXX
100	 * 0xC: 0xB808XXXX
101	 *
102	 * then it is necessary to count address for storing the most significant
103	 * 16bits from _exception_handler address and copy it to
104	 * 0xa address. Big endian use offset in r10=0 that's why is it just
105	 * 0xa address. The same is done for the least significant 16 bits
106	 * for 0xe address.
107	 *
108	 * LITTLE ENDIAN memory map for user exception
109	 * 0x8: 0xXXXX00B0
110	 * 0xC: 0xXXXX08B8
111	 *
112	 * Offset is for little endian setup to 0x2. rsubi instruction decrease
113	 * address value to ensure that points to proper place which is
114	 * 0x8 for the most significant 16 bits and
115	 * 0xC for the least significant 16 bits
116	 */
117	lhu	r7, r1, r10
118	rsubi	r8, r10, 0xa
119	sh	r7, r0, r8
120	rsubi	r8, r10, 0xe
121	sh	r6, r0, r8
122#endif
123
124#ifdef CONFIG_SYS_INTC_0
125	/* interrupt_handler */
126	swi	r2, r0, 0x10	/* interrupt - imm opcode */
127	swi	r3, r0, 0x14	/* interrupt - brai opcode */
128
129	addik	r6, r0, _interrupt_handler
130	sw	r6, r1, r0
131	lhu	r7, r1, r10
132	rsubi	r8, r10, 0x12
133	sh	r7, r0, r8
134	rsubi	r8, r10, 0x16
135	sh	r6, r0, r8
136#endif
137
138	/* hardware exception */
139	swi	r2, r0, 0x20	/* hardware exception - imm opcode */
140	swi	r3, r0, 0x24	/* hardware exception - brai opcode */
141
142	addik	r6, r0, _hw_exception_handler
143	sw	r6, r1, r0
144	lhu	r7, r1, r10
145	rsubi	r8, r10, 0x22
146	sh	r7, r0, r8
147	rsubi	r8, r10, 0x26
148	sh	r6, r0, r8
149
150	/* enable instruction and data cache */
151	mfs	r12, rmsr
152	ori	r12, r12, 0xa0
153	mts	rmsr, r12
154
155clear_bss:
156	/* clear BSS segments */
157	addi	r5, r0, __bss_start
158	addi	r4, r0, __bss_end
159	cmp	r6, r5, r4
160	beqi	r6, 3f
1612:
162	swi     r0, r5, 0 /* write zero to loc */
163	addi    r5, r5, 4 /* increment to next loc */
164	cmp     r6, r5, r4 /* check if we have reach the end */
165	bnei    r6, 2b
1663:	/* jumping to board_init */
167	brai	board_init
1681:	bri	1b
169
170/*
171 * Read 16bit little endian
172 */
173	.text
174	.global	in16
175	.ent	in16
176	.align	2
177in16:	lhu	r3, r0, r5
178	bslli	r4, r3, 8
179	bsrli	r3, r3, 8
180	andi	r4, r4, 0xffff
181	or	r3, r3, r4
182	rtsd	r15, 8
183	sext16	r3, r3
184	.end	in16
185
186/*
187 * Write 16bit little endian
188 * first parameter(r5) - address, second(r6) - short value
189 */
190	.text
191	.global	out16
192	.ent	out16
193	.align	2
194out16:	bslli	r3, r6, 8
195	bsrli	r6, r6, 8
196	andi	r3, r3, 0xffff
197	or	r3, r3, r6
198	sh	r3, r0, r5
199	rtsd	r15, 8
200	or	r0, r0, r0
201	.end	out16
202