| /* |
| * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> |
| * |
| * Based on arch/nios2/kernel/head.S |
| * |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file "COPYING" in the main directory of this archive |
| * for more details. |
| * |
| */ |
| |
| /* |
| * This code can be loaded anywhere, eg FLASH ROM as reset vector, |
| * as long as output does not overlap it. |
| */ |
| |
| #include <linux/linkage.h> |
| #include <asm/cache.h> |
| |
| .text |
| .set noat |
| ENTRY(_start) |
| wrctl status, r0 /* disable interrupt */ |
| /* invalidate all instruction cache */ |
| movia r1, NIOS2_ICACHE_SIZE |
| movui r2, NIOS2_ICACHE_LINE_SIZE |
| 1: initi r1 |
| sub r1, r1, r2 |
| bgt r1, r0, 1b |
| /* invalidate all data cache */ |
| movia r1, NIOS2_DCACHE_SIZE |
| movui r2, NIOS2_DCACHE_LINE_SIZE |
| 1: initd 0(r1) |
| sub r1, r1, r2 |
| bgt r1, r0, 1b |
| |
| nextpc r1 /* Find out where we are */ |
| chkadr: |
| movia r2, chkadr |
| beq r1, r2, finish_move /* We are running in correct address, |
| done */ |
| /* move code, r1: src, r2: dest, r3: last dest */ |
| addi r1, r1, (_start - chkadr) /* Source */ |
| movia r2, _start /* Destination */ |
| movia r3, __bss_start /* End of copy */ |
| 1: ldw r8, 0(r1) /* load a word from [r1] */ |
| stw r8, 0(r2) /* stort a word to dest [r2] */ |
| addi r1, r1, 4 /* inc the src addr */ |
| addi r2, r2, 4 /* inc the dest addr */ |
| blt r2, r3, 1b |
| /* flush the data cache after moving */ |
| movia r1, NIOS2_DCACHE_SIZE |
| movui r2, NIOS2_DCACHE_LINE_SIZE |
| 1: flushd 0(r1) |
| sub r1, r1, r2 |
| bgt r1, r0, 1b |
| movia r1, finish_move |
| jmp r1 /* jmp to linked address */ |
| |
| finish_move: |
| /* zero out the .bss segment (uninitialized common data) */ |
| movia r2, __bss_start /* presume nothing is between */ |
| movia r1, _end /* the .bss and _end. */ |
| 1: stb r0, 0(r2) |
| addi r2, r2, 1 |
| bne r1, r2, 1b |
| /* |
| * set up the stack pointer, some where higher than _end. |
| * The stack space must be greater than 32K for decompress. |
| */ |
| movia sp, 0x10000 |
| add sp, sp, r1 |
| /* save args passed from u-boot, maybe */ |
| addi sp, sp, -16 |
| stw r4, 0(sp) |
| stw r5, 4(sp) |
| stw r6, 8(sp) |
| stw r7, 12(sp) |
| /* decompress the kernel */ |
| call decompress_kernel |
| /* pass saved args to kernel */ |
| ldw r4, 0(sp) |
| ldw r5, 4(sp) |
| ldw r6, 8(sp) |
| ldw r7, 12(sp) |
| |
| /* flush all data cache after decompressing */ |
| movia r1, NIOS2_DCACHE_SIZE |
| movui r2, NIOS2_DCACHE_LINE_SIZE |
| 1: flushd 0(r1) |
| sub r1, r1, r2 |
| bgt r1, r0, 1b |
| /* flush all instruction cache */ |
| movia r1, NIOS2_ICACHE_SIZE |
| movui r2, NIOS2_ICACHE_LINE_SIZE |
| 1: flushi r1 |
| sub r1, r1, r2 |
| bgt r1, r0, 1b |
| flushp |
| /* jump to start real kernel */ |
| movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE) |
| jmp r1 |
| |
| .balign 512 |
| fake_headers_as_bzImage: |
| .short 0 |
| .ascii "HdrS" |
| .short 0x0202 |
| .short 0 |
| .short 0 |
| .byte 0x00, 0x10 |
| .short 0 |
| .byte 0 |
| .byte 1 |
| .byte 0x00, 0x80 |
| .long 0 |
| .long 0 |