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