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