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