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