1/* 2 * Copyright (C) 2009 Wind River Systems Inc 3 * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com 4 * Copyright (C) 2004 Microtronix Datacom Ltd 5 * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd. 6 * 7 * Based on head.S for Altera's Excalibur development board with nios processor 8 * 9 * Based on the following from the Excalibur sdk distribution: 10 * NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s 11 * 12 * This file is subject to the terms and conditions of the GNU General Public 13 * License. See the file "COPYING" in the main directory of this archive 14 * for more details. 15 */ 16 17#include <linux/init.h> 18#include <linux/linkage.h> 19#include <asm/thread_info.h> 20#include <asm/processor.h> 21#include <asm/cache.h> 22#include <asm/page.h> 23#include <asm/asm-offsets.h> 24#include <asm/asm-macros.h> 25 26/* 27 * This global variable is used as an extension to the nios' 28 * STATUS register to emulate a user/supervisor mode. 29 */ 30 .data 31 .align 2 32 .set noat 33 34 .global _current_thread 35_current_thread: 36 .long 0 37/* 38 * Input(s): passed from u-boot 39 * r4 - Optional pointer to a board information structure. 40 * r5 - Optional pointer to the physical starting address of the init RAM 41 * disk. 42 * r6 - Optional pointer to the physical ending address of the init RAM 43 * disk. 44 * r7 - Optional pointer to the physical starting address of any kernel 45 * command-line parameters. 46 */ 47 48/* 49 * First executable code - detected and jumped to by the ROM bootstrap 50 * if the code resides in flash (looks for "Nios" at offset 0x0c from 51 * the potential executable image). 52 */ 53 __HEAD 54ENTRY(_start) 55 wrctl status, r0 /* Disable interrupts */ 56 57 /* Initialize all cache lines within the instruction cache */ 58 movia r1, NIOS2_ICACHE_SIZE 59 movui r2, NIOS2_ICACHE_LINE_SIZE 60 61icache_init: 62 initi r1 63 sub r1, r1, r2 64 bgt r1, r0, icache_init 65 br 1f 66 67 /* 68 * This is the default location for the exception handler. Code in jump 69 * to our handler 70 */ 71ENTRY(exception_handler_hook) 72 movia r24, inthandler 73 jmp r24 74 75ENTRY(fast_handler) 76 nextpc et 77helper: 78 stw r3, r3save - helper(et) 79 80 rdctl r3 , pteaddr 81 srli r3, r3, 12 82 slli r3, r3, 2 83 movia et, pgd_current 84 85 ldw et, 0(et) 86 add r3, et, r3 87 ldw et, 0(r3) 88 89 rdctl r3, pteaddr 90 andi r3, r3, 0xfff 91 add et, r3, et 92 ldw et, 0(et) 93 wrctl tlbacc, et 94 nextpc et 95helper2: 96 ldw r3, r3save - helper2(et) 97 subi ea, ea, 4 98 eret 99r3save: 100 .word 0x0 101ENTRY(fast_handler_end) 102 1031: 104 /* 105 * After the instruction cache is initialized, the data cache must 106 * also be initialized. 107 */ 108 movia r1, NIOS2_DCACHE_SIZE 109 movui r2, NIOS2_DCACHE_LINE_SIZE 110 111dcache_init: 112 initd 0(r1) 113 sub r1, r1, r2 114 bgt r1, r0, dcache_init 115 116 nextpc r1 /* Find out where we are */ 117chkadr: 118 movia r2, chkadr 119 beq r1, r2,finish_move /* We are running in RAM done */ 120 addi r1, r1,(_start - chkadr) /* Source */ 121 movia r2, _start /* Destination */ 122 movia r3, __bss_start /* End of copy */ 123 124loop_move: /* r1: src, r2: dest, r3: last dest */ 125 ldw r8, 0(r1) /* load a word from [r1] */ 126 stw r8, 0(r2) /* store a word to dest [r2] */ 127 flushd 0(r2) /* Flush cache for safety */ 128 addi r1, r1, 4 /* inc the src addr */ 129 addi r2, r2, 4 /* inc the dest addr */ 130 blt r2, r3, loop_move 131 132 movia r1, finish_move /* VMA(_start)->l1 */ 133 jmp r1 /* jmp to _start */ 134 135finish_move: 136 137 /* Mask off all possible interrupts */ 138 wrctl ienable, r0 139 140 /* Clear .bss */ 141 movia r2, __bss_start 142 movia r1, __bss_stop 1431: 144 stb r0, 0(r2) 145 addi r2, r2, 1 146 bne r1, r2, 1b 147 148 movia r1, init_thread_union /* set stack at top of the task union */ 149 addi sp, r1, THREAD_SIZE 150 movia r2, _current_thread /* Remember current thread */ 151 stw r1, 0(r2) 152 153 movia r1, nios2_boot_init /* save args r4-r7 passed from u-boot */ 154 callr r1 155 156 movia r1, start_kernel /* call start_kernel as a subroutine */ 157 callr r1 158 159 /* If we return from start_kernel, break to the oci debugger and 160 * buggered we are. 161 */ 162 break 163 164 /* End of startup code */ 165.set at 166