18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Based on arch/nios2/kernel/head.S
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
78c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive
88c2ecf20Sopenharmony_ci * for more details.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/*
138c2ecf20Sopenharmony_ci *  This code can be loaded anywhere, eg FLASH ROM as reset vector,
148c2ecf20Sopenharmony_ci *  as long as output does not overlap it.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/linkage.h>
188c2ecf20Sopenharmony_ci#include <asm/cache.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	.text
218c2ecf20Sopenharmony_ci	.set noat
228c2ecf20Sopenharmony_ciENTRY(_start)
238c2ecf20Sopenharmony_ci	wrctl	status, r0		/* disable interrupt */
248c2ecf20Sopenharmony_ci	/* invalidate all instruction cache */
258c2ecf20Sopenharmony_ci	movia	r1, NIOS2_ICACHE_SIZE
268c2ecf20Sopenharmony_ci	movui	r2, NIOS2_ICACHE_LINE_SIZE
278c2ecf20Sopenharmony_ci1:	initi	r1
288c2ecf20Sopenharmony_ci	sub	r1, r1, r2
298c2ecf20Sopenharmony_ci	bgt	r1, r0, 1b
308c2ecf20Sopenharmony_ci	/* invalidate all data cache */
318c2ecf20Sopenharmony_ci	movia	r1, NIOS2_DCACHE_SIZE
328c2ecf20Sopenharmony_ci	movui	r2, NIOS2_DCACHE_LINE_SIZE
338c2ecf20Sopenharmony_ci1:	initd	0(r1)
348c2ecf20Sopenharmony_ci	sub	r1, r1, r2
358c2ecf20Sopenharmony_ci	bgt	r1, r0, 1b
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	nextpc	r1			/* Find out where we are */
388c2ecf20Sopenharmony_cichkadr:
398c2ecf20Sopenharmony_ci	movia	r2, chkadr
408c2ecf20Sopenharmony_ci	beq	r1, r2, finish_move	/* We are running in correct address,
418c2ecf20Sopenharmony_ci					   done */
428c2ecf20Sopenharmony_ci	/* move code, r1: src, r2: dest, r3: last dest */
438c2ecf20Sopenharmony_ci	addi	r1, r1, (_start - chkadr)	/* Source */
448c2ecf20Sopenharmony_ci	movia	r2, _start		/* Destination */
458c2ecf20Sopenharmony_ci	movia	r3, __bss_start		/* End of copy */
468c2ecf20Sopenharmony_ci1:	ldw	r8, 0(r1)		/* load a word from [r1] */
478c2ecf20Sopenharmony_ci	stw	r8, 0(r2)		/* stort a word to dest [r2] */
488c2ecf20Sopenharmony_ci	addi	r1, r1, 4		/* inc the src addr */
498c2ecf20Sopenharmony_ci	addi	r2, r2, 4		/* inc the dest addr */
508c2ecf20Sopenharmony_ci	blt	r2, r3, 1b
518c2ecf20Sopenharmony_ci	/* flush the data cache after moving */
528c2ecf20Sopenharmony_ci	movia	r1, NIOS2_DCACHE_SIZE
538c2ecf20Sopenharmony_ci	movui	r2, NIOS2_DCACHE_LINE_SIZE
548c2ecf20Sopenharmony_ci1:	flushd	0(r1)
558c2ecf20Sopenharmony_ci	sub	r1, r1, r2
568c2ecf20Sopenharmony_ci	bgt	r1, r0, 1b
578c2ecf20Sopenharmony_ci	movia	r1, finish_move
588c2ecf20Sopenharmony_ci	jmp	r1			/* jmp to linked address */
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cifinish_move:
618c2ecf20Sopenharmony_ci	/* zero out the .bss segment (uninitialized common data) */
628c2ecf20Sopenharmony_ci	movia	r2, __bss_start		/* presume nothing is between */
638c2ecf20Sopenharmony_ci	movia	r1, _end		/* the .bss and _end. */
648c2ecf20Sopenharmony_ci1: 	stb	r0, 0(r2)
658c2ecf20Sopenharmony_ci	addi	r2, r2, 1
668c2ecf20Sopenharmony_ci	bne	r1, r2, 1b
678c2ecf20Sopenharmony_ci	/*
688c2ecf20Sopenharmony_ci	 * set up the stack pointer, some where higher than _end.
698c2ecf20Sopenharmony_ci	 * The stack space must be greater than 32K for decompress.
708c2ecf20Sopenharmony_ci	 */
718c2ecf20Sopenharmony_ci	movia	sp, 0x10000
728c2ecf20Sopenharmony_ci	add	sp, sp, r1
738c2ecf20Sopenharmony_ci	/* save args passed from u-boot, maybe */
748c2ecf20Sopenharmony_ci	addi	sp, sp, -16
758c2ecf20Sopenharmony_ci	stw	r4, 0(sp)
768c2ecf20Sopenharmony_ci	stw	r5, 4(sp)
778c2ecf20Sopenharmony_ci	stw	r6, 8(sp)
788c2ecf20Sopenharmony_ci	stw	r7, 12(sp)
798c2ecf20Sopenharmony_ci	/* decompress the kernel */
808c2ecf20Sopenharmony_ci	call	decompress_kernel
818c2ecf20Sopenharmony_ci	/* pass saved args to kernel */
828c2ecf20Sopenharmony_ci	ldw	r4, 0(sp)
838c2ecf20Sopenharmony_ci	ldw	r5, 4(sp)
848c2ecf20Sopenharmony_ci	ldw	r6, 8(sp)
858c2ecf20Sopenharmony_ci	ldw	r7, 12(sp)
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* flush all data cache after decompressing */
888c2ecf20Sopenharmony_ci	movia	r1, NIOS2_DCACHE_SIZE
898c2ecf20Sopenharmony_ci	movui	r2, NIOS2_DCACHE_LINE_SIZE
908c2ecf20Sopenharmony_ci1:	flushd	0(r1)
918c2ecf20Sopenharmony_ci	sub	r1, r1, r2
928c2ecf20Sopenharmony_ci	bgt	r1, r0, 1b
938c2ecf20Sopenharmony_ci	/* flush all instruction cache */
948c2ecf20Sopenharmony_ci	movia	r1, NIOS2_ICACHE_SIZE
958c2ecf20Sopenharmony_ci	movui	r2, NIOS2_ICACHE_LINE_SIZE
968c2ecf20Sopenharmony_ci1:	flushi	r1
978c2ecf20Sopenharmony_ci	sub	r1, r1, r2
988c2ecf20Sopenharmony_ci	bgt	r1, r0, 1b
998c2ecf20Sopenharmony_ci	flushp
1008c2ecf20Sopenharmony_ci	/* jump to start real kernel */
1018c2ecf20Sopenharmony_ci	movia	r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE)
1028c2ecf20Sopenharmony_ci	jmp	r1
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	.balign 512
1058c2ecf20Sopenharmony_cifake_headers_as_bzImage:
1068c2ecf20Sopenharmony_ci	.short	0
1078c2ecf20Sopenharmony_ci	.ascii	"HdrS"
1088c2ecf20Sopenharmony_ci	.short	0x0202
1098c2ecf20Sopenharmony_ci	.short	0
1108c2ecf20Sopenharmony_ci	.short	0
1118c2ecf20Sopenharmony_ci	.byte	0x00, 0x10
1128c2ecf20Sopenharmony_ci	.short	0
1138c2ecf20Sopenharmony_ci	.byte	0
1148c2ecf20Sopenharmony_ci	.byte	1
1158c2ecf20Sopenharmony_ci	.byte	0x00, 0x80
1168c2ecf20Sopenharmony_ci	.long	0
1178c2ecf20Sopenharmony_ci	.long	0
118