xref: /openbmc/u-boot/arch/mips/cpu/start.S (revision 14d0a02a)
1/*
2 *  Startup Code for MIPS32 CPU-core
3 *
4 *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <config.h>
26#include <asm/regdef.h>
27#include <asm/mipsregs.h>
28
29	/*
30	 * For the moment disable interrupts, mark the kernel mode and
31	 * set ST0_KX so that the CPU does not spit fire when using
32	 * 64-bit addresses.
33	 */
34	.macro	setup_c0_status set clr
35	.set	push
36	mfc0	t0, CP0_STATUS
37	or	t0, ST0_CU0 | \set | 0x1f | \clr
38	xor	t0, 0x1f | \clr
39	mtc0	t0, CP0_STATUS
40	.set	noreorder
41	sll	zero, 3				# ehb
42	.set	pop
43	.endm
44
45	.macro	setup_c0_status_reset
46#ifdef CONFIG_64BIT
47	setup_c0_status ST0_KX 0
48#else
49	setup_c0_status 0 0
50#endif
51	.endm
52
53#define RVECENT(f,n) \
54   b f; nop
55#define XVECENT(f,bev) \
56   b f     ;           \
57   li k0,bev
58
59	.set noreorder
60
61	.globl _start
62	.text
63_start:
64	RVECENT(reset,0)	/* U-boot entry point */
65	RVECENT(reset,1)	/* software reboot */
66#if defined(CONFIG_INCA_IP)
67	.word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
68	.word 0x00000000           /* phase of the flash                    */
69#elif defined(CONFIG_PURPLE)
70	.word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
71	.word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
72#else
73	RVECENT(romReserved,2)
74#endif
75	RVECENT(romReserved,3)
76	RVECENT(romReserved,4)
77	RVECENT(romReserved,5)
78	RVECENT(romReserved,6)
79	RVECENT(romReserved,7)
80	RVECENT(romReserved,8)
81	RVECENT(romReserved,9)
82	RVECENT(romReserved,10)
83	RVECENT(romReserved,11)
84	RVECENT(romReserved,12)
85	RVECENT(romReserved,13)
86	RVECENT(romReserved,14)
87	RVECENT(romReserved,15)
88	RVECENT(romReserved,16)
89	RVECENT(romReserved,17)
90	RVECENT(romReserved,18)
91	RVECENT(romReserved,19)
92	RVECENT(romReserved,20)
93	RVECENT(romReserved,21)
94	RVECENT(romReserved,22)
95	RVECENT(romReserved,23)
96	RVECENT(romReserved,24)
97	RVECENT(romReserved,25)
98	RVECENT(romReserved,26)
99	RVECENT(romReserved,27)
100	RVECENT(romReserved,28)
101	RVECENT(romReserved,29)
102	RVECENT(romReserved,30)
103	RVECENT(romReserved,31)
104	RVECENT(romReserved,32)
105	RVECENT(romReserved,33)
106	RVECENT(romReserved,34)
107	RVECENT(romReserved,35)
108	RVECENT(romReserved,36)
109	RVECENT(romReserved,37)
110	RVECENT(romReserved,38)
111	RVECENT(romReserved,39)
112	RVECENT(romReserved,40)
113	RVECENT(romReserved,41)
114	RVECENT(romReserved,42)
115	RVECENT(romReserved,43)
116	RVECENT(romReserved,44)
117	RVECENT(romReserved,45)
118	RVECENT(romReserved,46)
119	RVECENT(romReserved,47)
120	RVECENT(romReserved,48)
121	RVECENT(romReserved,49)
122	RVECENT(romReserved,50)
123	RVECENT(romReserved,51)
124	RVECENT(romReserved,52)
125	RVECENT(romReserved,53)
126	RVECENT(romReserved,54)
127	RVECENT(romReserved,55)
128	RVECENT(romReserved,56)
129	RVECENT(romReserved,57)
130	RVECENT(romReserved,58)
131	RVECENT(romReserved,59)
132	RVECENT(romReserved,60)
133	RVECENT(romReserved,61)
134	RVECENT(romReserved,62)
135	RVECENT(romReserved,63)
136	XVECENT(romExcHandle,0x200)	/* bfc00200: R4000 tlbmiss vector */
137	RVECENT(romReserved,65)
138	RVECENT(romReserved,66)
139	RVECENT(romReserved,67)
140	RVECENT(romReserved,68)
141	RVECENT(romReserved,69)
142	RVECENT(romReserved,70)
143	RVECENT(romReserved,71)
144	RVECENT(romReserved,72)
145	RVECENT(romReserved,73)
146	RVECENT(romReserved,74)
147	RVECENT(romReserved,75)
148	RVECENT(romReserved,76)
149	RVECENT(romReserved,77)
150	RVECENT(romReserved,78)
151	RVECENT(romReserved,79)
152	XVECENT(romExcHandle,0x280)	/* bfc00280: R4000 xtlbmiss vector */
153	RVECENT(romReserved,81)
154	RVECENT(romReserved,82)
155	RVECENT(romReserved,83)
156	RVECENT(romReserved,84)
157	RVECENT(romReserved,85)
158	RVECENT(romReserved,86)
159	RVECENT(romReserved,87)
160	RVECENT(romReserved,88)
161	RVECENT(romReserved,89)
162	RVECENT(romReserved,90)
163	RVECENT(romReserved,91)
164	RVECENT(romReserved,92)
165	RVECENT(romReserved,93)
166	RVECENT(romReserved,94)
167	RVECENT(romReserved,95)
168	XVECENT(romExcHandle,0x300)	/* bfc00300: R4000 cache vector */
169	RVECENT(romReserved,97)
170	RVECENT(romReserved,98)
171	RVECENT(romReserved,99)
172	RVECENT(romReserved,100)
173	RVECENT(romReserved,101)
174	RVECENT(romReserved,102)
175	RVECENT(romReserved,103)
176	RVECENT(romReserved,104)
177	RVECENT(romReserved,105)
178	RVECENT(romReserved,106)
179	RVECENT(romReserved,107)
180	RVECENT(romReserved,108)
181	RVECENT(romReserved,109)
182	RVECENT(romReserved,110)
183	RVECENT(romReserved,111)
184	XVECENT(romExcHandle,0x380)	/* bfc00380: R4000 general vector */
185	RVECENT(romReserved,113)
186	RVECENT(romReserved,114)
187	RVECENT(romReserved,115)
188	RVECENT(romReserved,116)
189	RVECENT(romReserved,116)
190	RVECENT(romReserved,118)
191	RVECENT(romReserved,119)
192	RVECENT(romReserved,120)
193	RVECENT(romReserved,121)
194	RVECENT(romReserved,122)
195	RVECENT(romReserved,123)
196	RVECENT(romReserved,124)
197	RVECENT(romReserved,125)
198	RVECENT(romReserved,126)
199	RVECENT(romReserved,127)
200
201	/* We hope there are no more reserved vectors!
202	 * 128 * 8 == 1024 == 0x400
203	 * so this is address R_VEC+0x400 == 0xbfc00400
204	 */
205#ifdef CONFIG_PURPLE
206/* 0xbfc00400 */
207	.word	0xdc870000
208	.word	0xfca70000
209	.word	0x20840008
210	.word	0x20a50008
211	.word	0x20c6ffff
212	.word	0x14c0fffa
213	.word	0x00000000
214	.word	0x03e00008
215	.word	0x00000000
216	.word	0x00000000
217/* 0xbfc00428 */
218	.word	0xdc870000
219	.word	0xfca70000
220	.word	0x20840008
221	.word	0x20a50008
222	.word	0x20c6ffff
223	.word	0x14c0fffa
224	.word	0x00000000
225	.word	0x03e00008
226	.word	0x00000000
227	.word	0x00000000
228#endif /* CONFIG_PURPLE */
229	.align 4
230reset:
231
232	/* Clear watch registers.
233	 */
234	mtc0	zero, CP0_WATCHLO
235	mtc0	zero, CP0_WATCHHI
236
237	/* WP(Watch Pending), SW0/1 should be cleared. */
238	mtc0	zero, CP0_CAUSE
239
240	setup_c0_status_reset
241
242	/* Init Timer */
243	mtc0	zero, CP0_COUNT
244	mtc0	zero, CP0_COMPARE
245
246#if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
247	/* CONFIG0 register */
248	li	t0, CONF_CM_UNCACHED
249	mtc0	t0, CP0_CONFIG
250#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
251
252	/* Initialize $gp.
253	 */
254	bal	1f
255	nop
256	.word	_gp
2571:
258	lw	gp, 0(ra)
259
260#if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
261	/* Initialize any external memory.
262	 */
263	la	t9, lowlevel_init
264	jalr	t9
265	nop
266
267	/* Initialize caches...
268	 */
269	la	t9, mips_cache_reset
270	jalr	t9
271	nop
272
273	/* ... and enable them.
274	 */
275	li	t0, CONF_CM_CACHABLE_NONCOHERENT
276	mtc0	t0, CP0_CONFIG
277#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
278
279	/* Set up temporary stack.
280	 */
281#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
282	li	a0, CONFIG_SYS_INIT_SP_OFFSET
283	la	t9, mips_cache_lock
284	jalr	t9
285	nop
286#endif
287
288	li	t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
289	la	sp, 0(t0)
290
291	la	t9, board_init_f
292	jr	t9
293	nop
294
295/*
296 * void relocate_code (addr_sp, gd, addr_moni)
297 *
298 * This "function" does not return, instead it continues in RAM
299 * after relocating the monitor code.
300 *
301 * a0 = addr_sp
302 * a1 = gd
303 * a2 = destination address
304 */
305	.globl	relocate_code
306	.ent	relocate_code
307relocate_code:
308	move	sp, a0		/* Set new stack pointer	*/
309
310	li	t0, CONFIG_SYS_MONITOR_BASE
311	la	t3, in_ram
312	lw	t2, -12(t3)	/* t2 <-- uboot_end_data	*/
313	move	t1, a2
314	move	s2, a2		/* s2 <-- destination address	*/
315
316	/*
317	 * Fix $gp:
318	 *
319	 * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
320	 */
321	move	t6, gp
322	sub	gp, CONFIG_SYS_MONITOR_BASE
323	add	gp, a2		/* gp now adjusted		*/
324	sub	s1, gp, t6	/* s1 <-- relocation offset	*/
325
326	/*
327	 * t0 = source address
328	 * t1 = target address
329	 * t2 = source end address
330	 */
331
332	/*
333	 * Save destination address and size for later usage in flush_cache()
334	 */
335	move	s0, a1		/* save gd in s0		*/
336	move	a0, t1		/* a0 <-- destination addr	*/
337	sub	a1, t2, t0	/* a1 <-- size			*/
338
339	/* On the purple board we copy the code earlier in a special way
340	 * in order to solve flash problems
341	 */
342#ifndef CONFIG_PURPLE
3431:
344	lw	t3, 0(t0)
345	sw	t3, 0(t1)
346	addu	t0, 4
347	ble	t0, t2, 1b
348	addu	t1, 4		/* delay slot			*/
349#endif
350
351	/* If caches were enabled, we would have to flush them here.
352	 */
353
354	/* a0 & a1 are already set up for flush_cache(start, size) */
355	la	t9, flush_cache
356	jalr	t9
357	nop
358
359	/* Jump to where we've relocated ourselves.
360	 */
361	addi	t0, s2, in_ram - _start
362	jr	t0
363	nop
364
365	.word	_gp
366	.word	_GLOBAL_OFFSET_TABLE_
367	.word	uboot_end_data
368	.word	uboot_end
369	.word	num_got_entries
370
371in_ram:
372	/*
373	 * Now we want to update GOT.
374	 *
375	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
376	 * generated by GNU ld. Skip these reserved entries from relocation.
377	 */
378	lw	t3, -4(t0)	/* t3 <-- num_got_entries	*/
379	lw	t4, -16(t0)	/* t4 <-- _GLOBAL_OFFSET_TABLE_	*/
380	lw	t5, -20(t0)	/* t5 <-- _gp	*/
381	sub	t4, t5		/* compute offset*/
382	add	t4, t4, gp	/* t4 now holds relocated _GLOBAL_OFFSET_TABLE_	*/
383	addi	t4, t4, 8	/* Skipping first two entries.	*/
384	li	t2, 2
3851:
386	lw	t1, 0(t4)
387	beqz	t1, 2f
388	add	t1, s1
389	sw	t1, 0(t4)
3902:
391	addi	t2, 1
392	blt	t2, t3, 1b
393	addi	t4, 4		/* delay slot			*/
394
395	/* Clear BSS.
396	 */
397	lw	t1, -12(t0)	/* t1 <-- uboot_end_data	*/
398	lw	t2, -8(t0)	/* t2 <-- uboot_end		*/
399	add	t1, s1		/* adjust pointers		*/
400	add	t2, s1
401
402	sub	t1, 4
4031:
404	addi	t1, 4
405	bltl	t1, t2, 1b
406	sw	zero, 0(t1)	/* delay slot			*/
407
408	move	a0, s0		/* a0 <-- gd			*/
409	la	t9, board_init_r
410	jr	t9
411	move	a1, s2		/* delay slot			*/
412
413	.end	relocate_code
414
415	/* Exception handlers.
416	 */
417romReserved:
418	b	romReserved
419
420romExcHandle:
421	b	romExcHandle
422