1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Based on arch/nios2/kernel/head.S 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public 7*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive 8*4882a593Smuzhiyun * for more details. 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun/* 13*4882a593Smuzhiyun * This code can be loaded anywhere, eg FLASH ROM as reset vector, 14*4882a593Smuzhiyun * as long as output does not overlap it. 15*4882a593Smuzhiyun */ 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun#include <linux/linkage.h> 18*4882a593Smuzhiyun#include <asm/cache.h> 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun .text 21*4882a593Smuzhiyun .set noat 22*4882a593SmuzhiyunENTRY(_start) 23*4882a593Smuzhiyun wrctl status, r0 /* disable interrupt */ 24*4882a593Smuzhiyun /* invalidate all instruction cache */ 25*4882a593Smuzhiyun movia r1, NIOS2_ICACHE_SIZE 26*4882a593Smuzhiyun movui r2, NIOS2_ICACHE_LINE_SIZE 27*4882a593Smuzhiyun1: initi r1 28*4882a593Smuzhiyun sub r1, r1, r2 29*4882a593Smuzhiyun bgt r1, r0, 1b 30*4882a593Smuzhiyun /* invalidate all data cache */ 31*4882a593Smuzhiyun movia r1, NIOS2_DCACHE_SIZE 32*4882a593Smuzhiyun movui r2, NIOS2_DCACHE_LINE_SIZE 33*4882a593Smuzhiyun1: initd 0(r1) 34*4882a593Smuzhiyun sub r1, r1, r2 35*4882a593Smuzhiyun bgt r1, r0, 1b 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun nextpc r1 /* Find out where we are */ 38*4882a593Smuzhiyunchkadr: 39*4882a593Smuzhiyun movia r2, chkadr 40*4882a593Smuzhiyun beq r1, r2, finish_move /* We are running in correct address, 41*4882a593Smuzhiyun done */ 42*4882a593Smuzhiyun /* move code, r1: src, r2: dest, r3: last dest */ 43*4882a593Smuzhiyun addi r1, r1, (_start - chkadr) /* Source */ 44*4882a593Smuzhiyun movia r2, _start /* Destination */ 45*4882a593Smuzhiyun movia r3, __bss_start /* End of copy */ 46*4882a593Smuzhiyun1: ldw r8, 0(r1) /* load a word from [r1] */ 47*4882a593Smuzhiyun stw r8, 0(r2) /* stort a word to dest [r2] */ 48*4882a593Smuzhiyun addi r1, r1, 4 /* inc the src addr */ 49*4882a593Smuzhiyun addi r2, r2, 4 /* inc the dest addr */ 50*4882a593Smuzhiyun blt r2, r3, 1b 51*4882a593Smuzhiyun /* flush the data cache after moving */ 52*4882a593Smuzhiyun movia r1, NIOS2_DCACHE_SIZE 53*4882a593Smuzhiyun movui r2, NIOS2_DCACHE_LINE_SIZE 54*4882a593Smuzhiyun1: flushd 0(r1) 55*4882a593Smuzhiyun sub r1, r1, r2 56*4882a593Smuzhiyun bgt r1, r0, 1b 57*4882a593Smuzhiyun movia r1, finish_move 58*4882a593Smuzhiyun jmp r1 /* jmp to linked address */ 59*4882a593Smuzhiyun 60*4882a593Smuzhiyunfinish_move: 61*4882a593Smuzhiyun /* zero out the .bss segment (uninitialized common data) */ 62*4882a593Smuzhiyun movia r2, __bss_start /* presume nothing is between */ 63*4882a593Smuzhiyun movia r1, _end /* the .bss and _end. */ 64*4882a593Smuzhiyun1: stb r0, 0(r2) 65*4882a593Smuzhiyun addi r2, r2, 1 66*4882a593Smuzhiyun bne r1, r2, 1b 67*4882a593Smuzhiyun /* 68*4882a593Smuzhiyun * set up the stack pointer, some where higher than _end. 69*4882a593Smuzhiyun * The stack space must be greater than 32K for decompress. 70*4882a593Smuzhiyun */ 71*4882a593Smuzhiyun movia sp, 0x10000 72*4882a593Smuzhiyun add sp, sp, r1 73*4882a593Smuzhiyun /* save args passed from u-boot, maybe */ 74*4882a593Smuzhiyun addi sp, sp, -16 75*4882a593Smuzhiyun stw r4, 0(sp) 76*4882a593Smuzhiyun stw r5, 4(sp) 77*4882a593Smuzhiyun stw r6, 8(sp) 78*4882a593Smuzhiyun stw r7, 12(sp) 79*4882a593Smuzhiyun /* decompress the kernel */ 80*4882a593Smuzhiyun call decompress_kernel 81*4882a593Smuzhiyun /* pass saved args to kernel */ 82*4882a593Smuzhiyun ldw r4, 0(sp) 83*4882a593Smuzhiyun ldw r5, 4(sp) 84*4882a593Smuzhiyun ldw r6, 8(sp) 85*4882a593Smuzhiyun ldw r7, 12(sp) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* flush all data cache after decompressing */ 88*4882a593Smuzhiyun movia r1, NIOS2_DCACHE_SIZE 89*4882a593Smuzhiyun movui r2, NIOS2_DCACHE_LINE_SIZE 90*4882a593Smuzhiyun1: flushd 0(r1) 91*4882a593Smuzhiyun sub r1, r1, r2 92*4882a593Smuzhiyun bgt r1, r0, 1b 93*4882a593Smuzhiyun /* flush all instruction cache */ 94*4882a593Smuzhiyun movia r1, NIOS2_ICACHE_SIZE 95*4882a593Smuzhiyun movui r2, NIOS2_ICACHE_LINE_SIZE 96*4882a593Smuzhiyun1: flushi r1 97*4882a593Smuzhiyun sub r1, r1, r2 98*4882a593Smuzhiyun bgt r1, r0, 1b 99*4882a593Smuzhiyun flushp 100*4882a593Smuzhiyun /* jump to start real kernel */ 101*4882a593Smuzhiyun movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE) 102*4882a593Smuzhiyun jmp r1 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun .balign 512 105*4882a593Smuzhiyunfake_headers_as_bzImage: 106*4882a593Smuzhiyun .short 0 107*4882a593Smuzhiyun .ascii "HdrS" 108*4882a593Smuzhiyun .short 0x0202 109*4882a593Smuzhiyun .short 0 110*4882a593Smuzhiyun .short 0 111*4882a593Smuzhiyun .byte 0x00, 0x10 112*4882a593Smuzhiyun .short 0 113*4882a593Smuzhiyun .byte 0 114*4882a593Smuzhiyun .byte 1 115*4882a593Smuzhiyun .byte 0x00, 0x80 116*4882a593Smuzhiyun .long 0 117*4882a593Smuzhiyun .long 0 118