162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Based on arch/nios2/kernel/head.S
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
762306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive
862306a36Sopenharmony_ci * for more details.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci *  This code can be loaded anywhere, eg FLASH ROM as reset vector,
1462306a36Sopenharmony_ci *  as long as output does not overlap it.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/linkage.h>
1862306a36Sopenharmony_ci#include <asm/cache.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	.text
2162306a36Sopenharmony_ci	.set noat
2262306a36Sopenharmony_ciENTRY(_start)
2362306a36Sopenharmony_ci	wrctl	status, r0		/* disable interrupt */
2462306a36Sopenharmony_ci	/* invalidate all instruction cache */
2562306a36Sopenharmony_ci	movia	r1, NIOS2_ICACHE_SIZE
2662306a36Sopenharmony_ci	movui	r2, NIOS2_ICACHE_LINE_SIZE
2762306a36Sopenharmony_ci1:	initi	r1
2862306a36Sopenharmony_ci	sub	r1, r1, r2
2962306a36Sopenharmony_ci	bgt	r1, r0, 1b
3062306a36Sopenharmony_ci	/* invalidate all data cache */
3162306a36Sopenharmony_ci	movia	r1, NIOS2_DCACHE_SIZE
3262306a36Sopenharmony_ci	movui	r2, NIOS2_DCACHE_LINE_SIZE
3362306a36Sopenharmony_ci1:	initd	0(r1)
3462306a36Sopenharmony_ci	sub	r1, r1, r2
3562306a36Sopenharmony_ci	bgt	r1, r0, 1b
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	nextpc	r1			/* Find out where we are */
3862306a36Sopenharmony_cichkadr:
3962306a36Sopenharmony_ci	movia	r2, chkadr
4062306a36Sopenharmony_ci	beq	r1, r2, finish_move	/* We are running in correct address,
4162306a36Sopenharmony_ci					   done */
4262306a36Sopenharmony_ci	/* move code, r1: src, r2: dest, r3: last dest */
4362306a36Sopenharmony_ci	addi	r1, r1, (_start - chkadr)	/* Source */
4462306a36Sopenharmony_ci	movia	r2, _start		/* Destination */
4562306a36Sopenharmony_ci	movia	r3, __bss_start		/* End of copy */
4662306a36Sopenharmony_ci1:	ldw	r8, 0(r1)		/* load a word from [r1] */
4762306a36Sopenharmony_ci	stw	r8, 0(r2)		/* stort a word to dest [r2] */
4862306a36Sopenharmony_ci	addi	r1, r1, 4		/* inc the src addr */
4962306a36Sopenharmony_ci	addi	r2, r2, 4		/* inc the dest addr */
5062306a36Sopenharmony_ci	blt	r2, r3, 1b
5162306a36Sopenharmony_ci	/* flush the data cache after moving */
5262306a36Sopenharmony_ci	movia	r1, NIOS2_DCACHE_SIZE
5362306a36Sopenharmony_ci	movui	r2, NIOS2_DCACHE_LINE_SIZE
5462306a36Sopenharmony_ci1:	flushd	0(r1)
5562306a36Sopenharmony_ci	sub	r1, r1, r2
5662306a36Sopenharmony_ci	bgt	r1, r0, 1b
5762306a36Sopenharmony_ci	movia	r1, finish_move
5862306a36Sopenharmony_ci	jmp	r1			/* jmp to linked address */
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cifinish_move:
6162306a36Sopenharmony_ci	/* zero out the .bss segment (uninitialized common data) */
6262306a36Sopenharmony_ci	movia	r2, __bss_start		/* presume nothing is between */
6362306a36Sopenharmony_ci	movia	r1, _end		/* the .bss and _end. */
6462306a36Sopenharmony_ci1: 	stb	r0, 0(r2)
6562306a36Sopenharmony_ci	addi	r2, r2, 1
6662306a36Sopenharmony_ci	bne	r1, r2, 1b
6762306a36Sopenharmony_ci	/*
6862306a36Sopenharmony_ci	 * set up the stack pointer, some where higher than _end.
6962306a36Sopenharmony_ci	 * The stack space must be greater than 32K for decompress.
7062306a36Sopenharmony_ci	 */
7162306a36Sopenharmony_ci	movia	sp, 0x10000
7262306a36Sopenharmony_ci	add	sp, sp, r1
7362306a36Sopenharmony_ci	/* save args passed from u-boot, maybe */
7462306a36Sopenharmony_ci	addi	sp, sp, -16
7562306a36Sopenharmony_ci	stw	r4, 0(sp)
7662306a36Sopenharmony_ci	stw	r5, 4(sp)
7762306a36Sopenharmony_ci	stw	r6, 8(sp)
7862306a36Sopenharmony_ci	stw	r7, 12(sp)
7962306a36Sopenharmony_ci	/* decompress the kernel */
8062306a36Sopenharmony_ci	call	decompress_kernel
8162306a36Sopenharmony_ci	/* pass saved args to kernel */
8262306a36Sopenharmony_ci	ldw	r4, 0(sp)
8362306a36Sopenharmony_ci	ldw	r5, 4(sp)
8462306a36Sopenharmony_ci	ldw	r6, 8(sp)
8562306a36Sopenharmony_ci	ldw	r7, 12(sp)
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/* flush all data cache after decompressing */
8862306a36Sopenharmony_ci	movia	r1, NIOS2_DCACHE_SIZE
8962306a36Sopenharmony_ci	movui	r2, NIOS2_DCACHE_LINE_SIZE
9062306a36Sopenharmony_ci1:	flushd	0(r1)
9162306a36Sopenharmony_ci	sub	r1, r1, r2
9262306a36Sopenharmony_ci	bgt	r1, r0, 1b
9362306a36Sopenharmony_ci	/* flush all instruction cache */
9462306a36Sopenharmony_ci	movia	r1, NIOS2_ICACHE_SIZE
9562306a36Sopenharmony_ci	movui	r2, NIOS2_ICACHE_LINE_SIZE
9662306a36Sopenharmony_ci1:	flushi	r1
9762306a36Sopenharmony_ci	sub	r1, r1, r2
9862306a36Sopenharmony_ci	bgt	r1, r0, 1b
9962306a36Sopenharmony_ci	flushp
10062306a36Sopenharmony_ci	/* jump to start real kernel */
10162306a36Sopenharmony_ci	movia	r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE)
10262306a36Sopenharmony_ci	jmp	r1
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	.balign 512
10562306a36Sopenharmony_cifake_headers_as_bzImage:
10662306a36Sopenharmony_ci	.short	0
10762306a36Sopenharmony_ci	.ascii	"HdrS"
10862306a36Sopenharmony_ci	.short	0x0202
10962306a36Sopenharmony_ci	.short	0
11062306a36Sopenharmony_ci	.short	0
11162306a36Sopenharmony_ci	.byte	0x00, 0x10
11262306a36Sopenharmony_ci	.short	0
11362306a36Sopenharmony_ci	.byte	0
11462306a36Sopenharmony_ci	.byte	1
11562306a36Sopenharmony_ci	.byte	0x00, 0x80
11662306a36Sopenharmony_ci	.long	0
11762306a36Sopenharmony_ci	.long	0
118