diff options
Diffstat (limited to 'cpu/mips/start.S')
| -rw-r--r-- | cpu/mips/start.S | 350 | 
1 files changed, 350 insertions, 0 deletions
| diff --git a/cpu/mips/start.S b/cpu/mips/start.S new file mode 100644 index 000000000..bf1165561 --- /dev/null +++ b/cpu/mips/start.S @@ -0,0 +1,350 @@ +/* + *  Startup Code for MIPS32 CPU-core + * + *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <config.h> +#include <version.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> + + +#define RVECENT(f,n) \ +   b f; nop +#define XVECENT(f,bev) \ +   b f     ;           \ +   li k0,bev + +	.set noreorder + +	.globl _start +	.text +_start: +	RVECENT(reset,0)	/* U-boot entry point */ +	RVECENT(reset,1)	/* software reboot */ +#ifdef CONFIG_INCA_IP +	.word 0x000020C4	/* EBU init code, fetched during booting */ +	.word 0x00000000        /* phase of the flash                    */ +#else +	RVECENT(romReserved,2) +#endif +	RVECENT(romReserved,3) +	RVECENT(romReserved,4) +	RVECENT(romReserved,5) +	RVECENT(romReserved,6) +	RVECENT(romReserved,7) +	RVECENT(romReserved,8) +	RVECENT(romReserved,9) +	RVECENT(romReserved,10) +	RVECENT(romReserved,11) +	RVECENT(romReserved,12) +	RVECENT(romReserved,13) +	RVECENT(romReserved,14) +	RVECENT(romReserved,15) +	RVECENT(romReserved,16) +	RVECENT(romReserved,17)  +	RVECENT(romReserved,18) +	RVECENT(romReserved,19) +	RVECENT(romReserved,20) +	RVECENT(romReserved,21) +	RVECENT(romReserved,22) +	RVECENT(romReserved,23) +	RVECENT(romReserved,24) +	RVECENT(romReserved,25) +	RVECENT(romReserved,26) +	RVECENT(romReserved,27) +	RVECENT(romReserved,28) +	RVECENT(romReserved,29) +	RVECENT(romReserved,30) +	RVECENT(romReserved,31) +	RVECENT(romReserved,32) +	RVECENT(romReserved,33) +	RVECENT(romReserved,34) +	RVECENT(romReserved,35) +	RVECENT(romReserved,36) +	RVECENT(romReserved,37) +	RVECENT(romReserved,38) +	RVECENT(romReserved,39) +	RVECENT(romReserved,40) +	RVECENT(romReserved,41) +	RVECENT(romReserved,42) +	RVECENT(romReserved,43) +	RVECENT(romReserved,44) +	RVECENT(romReserved,45) +	RVECENT(romReserved,46) +	RVECENT(romReserved,47) +	RVECENT(romReserved,48) +	RVECENT(romReserved,49) +	RVECENT(romReserved,50) +	RVECENT(romReserved,51) +	RVECENT(romReserved,52) +	RVECENT(romReserved,53) +	RVECENT(romReserved,54) +	RVECENT(romReserved,55) +	RVECENT(romReserved,56) +	RVECENT(romReserved,57) +	RVECENT(romReserved,58) +	RVECENT(romReserved,59) +	RVECENT(romReserved,60) +	RVECENT(romReserved,61) +	RVECENT(romReserved,62) +	RVECENT(romReserved,63)  +	XVECENT(romExcHandle,0x200)	/* bfc00200: R4000 tlbmiss vector */ +	RVECENT(romReserved,65) +	RVECENT(romReserved,66) +	RVECENT(romReserved,67) +	RVECENT(romReserved,68) +	RVECENT(romReserved,69) +	RVECENT(romReserved,70) +	RVECENT(romReserved,71) +	RVECENT(romReserved,72) +	RVECENT(romReserved,73) +	RVECENT(romReserved,74) +	RVECENT(romReserved,75) +	RVECENT(romReserved,76) +	RVECENT(romReserved,77) +	RVECENT(romReserved,78) +	RVECENT(romReserved,79)  +	XVECENT(romExcHandle,0x280)	/* bfc00280: R4000 xtlbmiss vector */ +	RVECENT(romReserved,81) +	RVECENT(romReserved,82) +	RVECENT(romReserved,83) +	RVECENT(romReserved,84) +	RVECENT(romReserved,85) +	RVECENT(romReserved,86) +	RVECENT(romReserved,87) +	RVECENT(romReserved,88) +	RVECENT(romReserved,89) +	RVECENT(romReserved,90) +	RVECENT(romReserved,91) +	RVECENT(romReserved,92) +	RVECENT(romReserved,93) +	RVECENT(romReserved,94) +	RVECENT(romReserved,95)  +	XVECENT(romExcHandle,0x300)	/* bfc00300: R4000 cache vector */ +	RVECENT(romReserved,97) +	RVECENT(romReserved,98) +	RVECENT(romReserved,99) +	RVECENT(romReserved,100) +	RVECENT(romReserved,101) +	RVECENT(romReserved,102) +	RVECENT(romReserved,103) +	RVECENT(romReserved,104) +	RVECENT(romReserved,105) +	RVECENT(romReserved,106) +	RVECENT(romReserved,107) +	RVECENT(romReserved,108) +	RVECENT(romReserved,109) +	RVECENT(romReserved,110) +	RVECENT(romReserved,111) +	XVECENT(romExcHandle,0x380)	/* bfc00380: R4000 general vector */ +	RVECENT(romReserved,113) +	RVECENT(romReserved,114) +	RVECENT(romReserved,115) +	RVECENT(romReserved,116) +	RVECENT(romReserved,116) +	RVECENT(romReserved,118) +	RVECENT(romReserved,119) +	RVECENT(romReserved,120) +	RVECENT(romReserved,121) +	RVECENT(romReserved,122) +	RVECENT(romReserved,123) +	RVECENT(romReserved,124) +	RVECENT(romReserved,125) +	RVECENT(romReserved,126) +	RVECENT(romReserved,127) +    +	/* We hope there are no more reserved vectors! +	 * 128 * 8 == 1024 == 0x400 +	 * so this is address R_VEC+0x400 == 0xbfc00400 +	 */ +	.align 4 +reset: + +	/* Clear watch registers. +	 */ +	mtc0	zero, CP0_WATCHLO +	mtc0	zero, CP0_WATCHHI + +	/* STATUS register */ +	mfc0	k0, CP0_STATUS +	li	k1, ~ST0_IE +	and	k0, k1 +	mtc0	k0, CP0_STATUS + +	/* CAUSE register */ +	mtc0	zero, CP0_CAUSE + +	/* Init Timer */ +	mtc0	zero, CP0_COUNT +	mtc0	zero, CP0_COMPARE + +	/* CONFIG0 register */ +	li	t0, CONF_CM_UNCACHED +	mtc0	t0, CP0_CONFIG + +#ifdef CONFIG_INCA_IP +	/* Disable INCA-IP Watchdog. +	 */ +	bal	disable_incaip_wdt +	nop +#endif + +	/* Initialize any external memory.  +	 */ +	bal	memsetup +	nop + +	/* Initialize caches... +	 */ +	bal	mips_cache_reset +	nop + +	/* ... and enable them. +	 */ +	li	t0, CONF_CM_CACHABLE_NONCOHERENT +	mtc0	t0, CP0_CONFIG + + +	/* Set up temporary stack. +	 */ +	li	a0, CFG_INIT_SP_OFFSET +	bal	mips_cache_lock +	nop + +	li	t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET +	la	sp, 0(t0) + +	/* Initialize GOT pointer. +	 */ +	bal	1f +	nop +	.word	_GLOBAL_OFFSET_TABLE_ - 1f + 4 +1: +	move	gp, ra +	lw	t1, 0(ra) +	add	gp, t1 +	la	t9, board_init_f +	j	t9 +	nop + + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * a0 = addr_sp + * a1 = gd + * a2 = destination address + */ +	.globl	relocate_code +	.ent	relocate_code +relocate_code: +	move	sp, a0		/* Set new stack pointer		*/ + +	/* +	 * Fix GOT pointer: +	 * +	 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address +	 */ +	move	t6, gp +	sub	gp, CFG_MONITOR_BASE +	add	gp, a2			/* gp now adjusted		*/ +	sub	t6, gp, t6		/* t6 <-- relocation offset	*/ +	 +	li	t0, CFG_MONITOR_BASE +	add	t2, t0, CFG_MONITOR_LEN +	move	t1, a2 + +	/* +	 * t0 = source address +	 * t1 = target address +	 * t2 = source end address +	 */ +1: +	lw	t3, 0(t0) +	sw	t3, 0(t1) +	addu	t0, 4 +	ble	t0, t2, 1b +	addu	t1, 4			/* delay slot			*/ + +	/* If caches were enabled, we would have to flush them here. +	 */ + +	/* Jump to where we've relocated ourselves. +	 */ +	addi	t0, a2, in_ram - _start +	j	t0 +	nop + +	.word	uboot_end_data +	.word	uboot_end +	.word	num_got_entries + +in_ram: +	/* Now we want to update GOT. +	 */ +	lw	t3, -4(t0)	/* t3 <-- num_got_entries	*/ +	addi	t4, gp, 8	/* Skipping first two entries.	*/ +	li	t2, 2 +1: +	lw	t1, 0(t4) +	beqz	t1, 2f +	add	t1, t6 +	sw	t1, 0(t4) +2: +	addi	t2, 1 +	blt	t2, t3, 1b +	addi	t4, 4		/* delay slot			*/ + +	/* Clear BSS. +	 */ +	lw	t1, -12(t0)	/* t1 <-- uboot_end_data	*/ +	lw	t2, -8(t0)	/* t2 <-- uboot_end		*/ +	add	t1, t6		/* adjust pointers		*/ +	add	t2, t6 + +	sub	t1, 4 +1:	addi	t1, 4 +	bltl	t1, t2, 1b +	sw	zero, 0(t1)	/* delay slot			*/ +	 +	move	a0, a1 +	la	t9, board_init_r +	j	t9 +	move	a1, a2		/* delay slot			*/ + +	.end	relocate_code +	 + + +	/* Exception handlers. +	 */ +romReserved: +	b romReserved + +romExcHandle: +	b romExcHandle + |