#include <config.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>

/* Unlike most u-boot targets, on pnx8330 we don't get control just after
   reset, but instead are loaded from flash and executed in partially-
   initialized environment. So there is no need to init everything, or to
   use in-cache stack.
   
   So after the start, we just set GOT pointer, set SP to a valid in-ram
   address, and jump to C-level startup code. */

	.text
	.set noreorder
	.globl _start
	.ent _start

	/*
	   Note: All data fields in aimage header structure are little endian...
	         Therefore assigning values from within this assembler source
		 file is unsafe if the code will ever be assembled in
		 big-endian mode...
	*/
_start:

        b       1f              /* 0x000 : header : vector                  */
        nop                     /* 0x004 : header : vector2                 */
        .word   0               /* 0x008 : header : magic                   */
        .word   0               /* 0x00c : header : magic2                  */
        .word   0               /* 0x010 : header : release_id              */
        .word   0               /* 0x014 : header : platform_id             */
        .word   0               /* 0x018 : header : type                    */
        .word   0               /* 0x01c : header : length                  */
        .word   0               /* 0x020 : header : data_length             */
        .word   0               /* 0x024 : header : data_start_offset       */
        .word   0               /* 0x028 : header : data_link_address       */
        .word   0               /* 0x02c : header : data_entry_point_offset */
        .word   0               /* 0x030 : header : flags                   */
        .word   0               /* 0x034 : header : build_time              */
        .word   0               /* 0x038 : header : build_host_offset       */
        .word   0               /* 0x03c : header : signature[ 0]           */
        .word   0               /* 0x040 : header : signature[ 1]           */
        .word   0               /* 0x044 : header : signature[ 2]           */
        .word   0               /* 0x048 : header : signature[ 3]           */
        .word   0               /* 0x04c : header : signature[ 4]           */
        .word   0               /* 0x050 : header : signature[ 5]           */
        .word   0               /* 0x054 : header : signature[ 6]           */
        .word   0               /* 0x058 : header : signature[ 7]           */
        .word   0               /* 0x05c : header : signature[ 8]           */
        .word   0               /* 0x060 : header : signature[ 9]           */
        .word   0               /* 0x064 : header : signature[10]           */
        .word   0               /* 0x068 : header : signature[11]           */
        .word   0               /* 0x06c : header : signature[12]           */
        .word   0               /* 0x070 : header : signature[13]           */
        .word   0               /* 0x074 : header : signature[14]           */
        .word   0               /* 0x078 : header : signature[15]           */
        .word   0               /* 0x07c : header : signature[16]           */
        .word   0               /* 0x080 : header : signature[17]           */
        .word   0               /* 0x084 : header : signature[18]           */
        .word   0               /* 0x088 : header : signature[19]           */
        .word   0               /* 0x08c : header : signature[20]           */
        .word   0               /* 0x090 : header : signature[21]           */
        .word   0               /* 0x094 : header : signature[22]           */
        .word   0               /* 0x098 : header : signature[23]           */
        .word   0               /* 0x09c : header : signature[24]           */
        .word   0               /* 0x0a0 : header : signature[25]           */
        .word   0               /* 0x0a4 : header : signature[26]           */
        .word   0               /* 0x0a8 : header : signature[27]           */
        .word   0               /* 0x0ac : header : signature[28]           */
        .word   0               /* 0x0b0 : header : signature[29]           */
        .word   0               /* 0x0b4 : header : signature[30]           */
        .word   0               /* 0x0b8 : header : signature[31]           */
        .word   0               /* 0x0bc : header : hash[0]                 */
        .word   0               /* 0x0c0 : header : hash[1]                 */
        .word   0               /* 0x0c4 : header : hash[2]                 */
        .word   0               /* 0x0c8 : header : hash[3]                 */
        .word   0               /* 0x0cc : header : hash[4]                 */
        .word   0               /* 0x0d0 : header : reserved[0]             */
        .word   0               /* 0x0d4 : header : reserved[1]             */
        .word   0               /* 0x0d8 : header : reserved[2]             */
        .word   0               /* 0x0dc : header : reserved[3]             */
        .word   0               /* 0x0e0 : header : reserved[4]             */
        .word   0               /* 0x0e4 : header : reserved[5]             */
        .word   0               /* 0x0e8 : header : reserved[6]             */
        .word   0               /* 0x0ec : header : reserved[7]             */
        .word   0               /* 0x0f0 : header : iv[0]                   */
        .word   0               /* 0x0f4 : header : iv[1]                   */
        .word   0               /* 0x0f8 : header : iv[2]                   */
        .word   0               /* 0x0fc : header : iv[3]                   */

        .word   0               /* 0x100 : header extension : magic         */
        .word   0               /* 0x104 : header extension : magic2        */
        .word   0               /* 0x108 : header extension : signature[ 0] */
        .word   0               /* 0x10c : header extension : signature[ 1] */
        .word   0               /* 0x110 : header extension : signature[ 2] */
        .word   0               /* 0x114 : header extension : signature[ 3] */
        .word   0               /* 0x118 : header extension : signature[ 4] */
        .word   0               /* 0x11c : header extension : signature[ 5] */
        .word   0               /* 0x120 : header extension : signature[ 6] */
        .word   0               /* 0x124 : header extension : signature[ 7] */
        .word   0               /* 0x128 : header extension : signature[ 8] */
        .word   0               /* 0x12c : header extension : signature[ 9] */
        .word   0               /* 0x130 : header extension : signature[10] */
        .word   0               /* 0x134 : header extension : signature[11] */
        .word   0               /* 0x138 : header extension : signature[12] */
        .word   0               /* 0x13c : header extension : signature[13] */
        .word   0               /* 0x140 : header extension : signature[14] */
        .word   0               /* 0x144 : header extension : signature[15] */
        .word   0               /* 0x148 : header extension : signature[16] */
        .word   0               /* 0x14c : header extension : signature[17] */
        .word   0               /* 0x150 : header extension : signature[18] */
        .word   0               /* 0x154 : header extension : signature[19] */
        .word   0               /* 0x158 : header extension : signature[20] */
        .word   0               /* 0x15c : header extension : signature[21] */
        .word   0               /* 0x160 : header extension : signature[22] */
        .word   0               /* 0x164 : header extension : signature[23] */
        .word   0               /* 0x168 : header extension : signature[24] */
        .word   0               /* 0x16c : header extension : signature[25] */
        .word   0               /* 0x170 : header extension : signature[26] */
        .word   0               /* 0x174 : header extension : signature[27] */
        .word   0               /* 0x178 : header extension : signature[28] */
        .word   0               /* 0x17c : header extension : signature[29] */
        .word   0               /* 0x180 : header extension : signature[30] */
        .word   0               /* 0x184 : header extension : signature[31] */
        .word   0               /* 0x188 : header extension : reserved[ 0]  */
        .word   0               /* 0x18c : header extension : reserved[ 1]  */
        .word   0               /* 0x190 : header extension : reserved[ 2]  */
        .word   0               /* 0x194 : header extension : reserved[ 3]  */
        .word   0               /* 0x198 : header extension : reserved[ 4]  */
        .word   0               /* 0x19c : header extension : reserved[ 5]  */
        .word   0               /* 0x1a0 : header extension : reserved[ 6]  */
        .word   0               /* 0x1a4 : header extension : reserved[ 7]  */
        .word   0               /* 0x1a8 : header extension : reserved[ 8]  */
        .word   0               /* 0x1ac : header extension : reserved[ 9]  */
        .word   0               /* 0x1b0 : header extension : reserved[10]  */
        .word   0               /* 0x1b4 : header extension : reserved[11]  */
        .word   0               /* 0x1b8 : header extension : reserved[12]  */
        .word   0               /* 0x1bc : header extension : reserved[13]  */
        .word   0               /* 0x1c0 : header extension : reserved[14]  */
        .word   0               /* 0x1c4 : header extension : reserved[15]  */
        .word   0               /* 0x1c8 : header extension : reserved[16]  */
        .word   0               /* 0x1cc : header extension : reserved[17]  */
        .word   0               /* 0x1d0 : header extension : reserved[18]  */
        .word   0               /* 0x1d4 : header extension : reserved[19]  */
        .word   0               /* 0x1d8 : header extension : reserved[20]  */
        .word   0               /* 0x1dc : header extension : reserved[21]  */
        .word   0               /* 0x1e0 : header extension : reserved[22]  */
        .word   0               /* 0x1e4 : header extension : reserved[23]  */
        .word   0               /* 0x1e8 : header extension : reserved[24]  */
        .word   0               /* 0x1ec : header extension : reserved[25]  */
        .word   0               /* 0x1f0 : header extension : reserved[26]  */
        .word   0               /* 0x1f4 : header extension : reserved[27]  */
        .word   0               /* 0x1f8 : header extension : reserved[28]  */
        .word   0               /* 0x1fc : header extension : reserved[29]  */

1:
	/* Clear watch registers  */
	mtc0	zero, CP0_WATCHLO
	mtc0	zero, CP0_WATCHHI

	/* STATUS register */
	mfc0	k0, CP0_STATUS
	li	t0, ~ST0_IE
	and	k0, t0
	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	/* disable caches for now */
	mtc0	t0, CP0_CONFIG

#if defined (CONFIG_SOC_PNX833X) && (CONFIG_SOC_PNX833X == 1)

	/* Setup minimal exception handler in internal SRAM */
	bal	1f
	nop

	lui	k0, %hi(0xB7E08000)
	addiu	k0, k0, %lo(0xB7E08000) 	/* 0xB7E08000 : reset block base address */
	sw	zero, 0x14(k0)			/* 0xB7E08014 : RESET_CONTROL_2 register */
	sw	zero, 0x04(k0)			/* 0xB7E08004 : RESET_CONTROL register */

1:	lw	s0, 0x00(ra)
	lw	s1, 0x04(ra)
	lw	s2, 0x08(ra)
	lw	s3, 0x0C(ra)

	li	a0, 0xB7F80000			/* 0xB7F80000 : internal SRAM base address */
	sw	s0, 0x180(a0)
	sw	s1, 0x184(a0)
	sw	s2, 0x188(a0)
	sw	s3, 0x18C(a0)

	mfc0	t0, CP0_STATUS
	li	t1, ST0_BEV
	or	t2, t0, t1			# set BEV bit
	mtc0	t2, CP0_STATUS
	mtc0	a0, CP0_EBASE
	li	t1, ~(ST0_BEV)
	and	t2, t0, t1			# clear BEV bit
	mtc0	t2, CP0_STATUS
	nop

#endif

	/* Set up temporary stack and initialize GOT pointer */
	bal	1f
	nop
	.word	CFG_INIT_SP
	.word	_GLOBAL_OFFSET_TABLE_
1:	move	t0, ra
	lw	t1, 0(t0)
	move	sp, t1
	lw	t1, 4(t0)
	move	gp, t1

	/* Call lowlevel init */
	la	t9, lowlevel_init
	jalr	t9
	nop

	/* Initialize caches...  */
	la      t9, mips_cache_reset
	jalr    t9
	nop

	/* ... and enable them.  */
	li	t0, CONF_CM_CACHABLE_NO_WA
	mtc0	t0, CP0_CONFIG

	/* Jump to C-level early init function */
	la	t9, board_init_f
	j	t9
	nop

	.end _start

/* Based on code from cpu/mips/start.S */

/*
 * 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		*/

	li	t0, CFG_MONITOR_BASE
	la	t3, in_ram
	lw	t2, -12(t3)	/* t2 <-- uboot_end_data	*/
	
	/* Make t1 to point to destination address in KSEG1 mapping,
	   to avoid any need to flush caches */
	move	t1, a2
	li	t4, 0x1FFFFFFF
	and	t1, t1, t4
	li	t4, 0xA0000000
	add	t1, t1, t4

	/*
	 * 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	*/

	/*
	 * t0 = source address
	 * t1 = target address (in KSEG1-mapping)
	 * 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			*/

	/* 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

