127d22413SLey Foon Tan/* 227d22413SLey Foon Tan * Copyright (C) 2009 Wind River Systems Inc 327d22413SLey Foon Tan * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com 427d22413SLey Foon Tan * Copyright (C) 2004 Microtronix Datacom Ltd 527d22413SLey Foon Tan * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd. 627d22413SLey Foon Tan * 727d22413SLey Foon Tan * Based on head.S for Altera's Excalibur development board with nios processor 827d22413SLey Foon Tan * 927d22413SLey Foon Tan * Based on the following from the Excalibur sdk distribution: 1027d22413SLey Foon Tan * NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s 1127d22413SLey Foon Tan * 1227d22413SLey Foon Tan * This file is subject to the terms and conditions of the GNU General Public 1327d22413SLey Foon Tan * License. See the file "COPYING" in the main directory of this archive 1427d22413SLey Foon Tan * for more details. 1527d22413SLey Foon Tan */ 1627d22413SLey Foon Tan 1727d22413SLey Foon Tan#include <linux/init.h> 1827d22413SLey Foon Tan#include <linux/linkage.h> 1927d22413SLey Foon Tan#include <asm/thread_info.h> 2027d22413SLey Foon Tan#include <asm/processor.h> 2127d22413SLey Foon Tan#include <asm/cache.h> 2227d22413SLey Foon Tan#include <asm/page.h> 2327d22413SLey Foon Tan#include <asm/asm-offsets.h> 2427d22413SLey Foon Tan#include <asm/asm-macros.h> 2527d22413SLey Foon Tan 2627d22413SLey Foon Tan/* 2727d22413SLey Foon Tan * ZERO_PAGE is a special page that is used for zero-initialized 2827d22413SLey Foon Tan * data and COW. 2927d22413SLey Foon Tan */ 3027d22413SLey Foon Tan.data 3127d22413SLey Foon Tan.global empty_zero_page 3227d22413SLey Foon Tan.align 12 3327d22413SLey Foon Tanempty_zero_page: 3427d22413SLey Foon Tan .space PAGE_SIZE 3527d22413SLey Foon Tan 3627d22413SLey Foon Tan/* 3727d22413SLey Foon Tan * This global variable is used as an extension to the nios' 3827d22413SLey Foon Tan * STATUS register to emulate a user/supervisor mode. 3927d22413SLey Foon Tan */ 4027d22413SLey Foon Tan .data 4127d22413SLey Foon Tan .align 2 4227d22413SLey Foon Tan .set noat 4327d22413SLey Foon Tan 4427d22413SLey Foon Tan .global _current_thread 4527d22413SLey Foon Tan_current_thread: 4627d22413SLey Foon Tan .long 0 4727d22413SLey Foon Tan/* 4827d22413SLey Foon Tan * Input(s): passed from u-boot 4927d22413SLey Foon Tan * r4 - Optional pointer to a board information structure. 5027d22413SLey Foon Tan * r5 - Optional pointer to the physical starting address of the init RAM 5127d22413SLey Foon Tan * disk. 5227d22413SLey Foon Tan * r6 - Optional pointer to the physical ending address of the init RAM 5327d22413SLey Foon Tan * disk. 5427d22413SLey Foon Tan * r7 - Optional pointer to the physical starting address of any kernel 5527d22413SLey Foon Tan * command-line parameters. 5627d22413SLey Foon Tan */ 5727d22413SLey Foon Tan 5827d22413SLey Foon Tan/* 5927d22413SLey Foon Tan * First executable code - detected and jumped to by the ROM bootstrap 6027d22413SLey Foon Tan * if the code resides in flash (looks for "Nios" at offset 0x0c from 6127d22413SLey Foon Tan * the potential executable image). 6227d22413SLey Foon Tan */ 6327d22413SLey Foon Tan __HEAD 6427d22413SLey Foon TanENTRY(_start) 6527d22413SLey Foon Tan wrctl status, r0 /* Disable interrupts */ 6627d22413SLey Foon Tan 6727d22413SLey Foon Tan /* Initialize all cache lines within the instruction cache */ 6827d22413SLey Foon Tan movia r1, NIOS2_ICACHE_SIZE 6927d22413SLey Foon Tan movui r2, NIOS2_ICACHE_LINE_SIZE 7027d22413SLey Foon Tan 7127d22413SLey Foon Tanicache_init: 7227d22413SLey Foon Tan initi r1 7327d22413SLey Foon Tan sub r1, r1, r2 7427d22413SLey Foon Tan bgt r1, r0, icache_init 7527d22413SLey Foon Tan br 1f 7627d22413SLey Foon Tan 7727d22413SLey Foon Tan /* 7827d22413SLey Foon Tan * This is the default location for the exception handler. Code in jump 7927d22413SLey Foon Tan * to our handler 8027d22413SLey Foon Tan */ 8127d22413SLey Foon TanENTRY(exception_handler_hook) 8227d22413SLey Foon Tan movia r24, inthandler 8327d22413SLey Foon Tan jmp r24 8427d22413SLey Foon Tan 8527d22413SLey Foon TanENTRY(fast_handler) 8627d22413SLey Foon Tan nextpc et 8727d22413SLey Foon Tanhelper: 8827d22413SLey Foon Tan stw r3, r3save - helper(et) 8927d22413SLey Foon Tan 9027d22413SLey Foon Tan rdctl r3 , pteaddr 9127d22413SLey Foon Tan srli r3, r3, 12 9227d22413SLey Foon Tan slli r3, r3, 2 9327d22413SLey Foon Tan movia et, pgd_current 9427d22413SLey Foon Tan 9527d22413SLey Foon Tan ldw et, 0(et) 9627d22413SLey Foon Tan add r3, et, r3 9727d22413SLey Foon Tan ldw et, 0(r3) 9827d22413SLey Foon Tan 9927d22413SLey Foon Tan rdctl r3, pteaddr 10027d22413SLey Foon Tan andi r3, r3, 0xfff 10127d22413SLey Foon Tan add et, r3, et 10227d22413SLey Foon Tan ldw et, 0(et) 10327d22413SLey Foon Tan wrctl tlbacc, et 10427d22413SLey Foon Tan nextpc et 10527d22413SLey Foon Tanhelper2: 10627d22413SLey Foon Tan ldw r3, r3save - helper2(et) 10727d22413SLey Foon Tan subi ea, ea, 4 10827d22413SLey Foon Tan eret 10927d22413SLey Foon Tanr3save: 11027d22413SLey Foon Tan .word 0x0 11127d22413SLey Foon TanENTRY(fast_handler_end) 11227d22413SLey Foon Tan 11327d22413SLey Foon Tan1: 11427d22413SLey Foon Tan /* 11527d22413SLey Foon Tan * After the instruction cache is initialized, the data cache must 11627d22413SLey Foon Tan * also be initialized. 11727d22413SLey Foon Tan */ 11827d22413SLey Foon Tan movia r1, NIOS2_DCACHE_SIZE 11927d22413SLey Foon Tan movui r2, NIOS2_DCACHE_LINE_SIZE 12027d22413SLey Foon Tan 12127d22413SLey Foon Tandcache_init: 12227d22413SLey Foon Tan initd 0(r1) 12327d22413SLey Foon Tan sub r1, r1, r2 12427d22413SLey Foon Tan bgt r1, r0, dcache_init 12527d22413SLey Foon Tan 12627d22413SLey Foon Tan nextpc r1 /* Find out where we are */ 12727d22413SLey Foon Tanchkadr: 12827d22413SLey Foon Tan movia r2, chkadr 12927d22413SLey Foon Tan beq r1, r2,finish_move /* We are running in RAM done */ 13027d22413SLey Foon Tan addi r1, r1,(_start - chkadr) /* Source */ 13127d22413SLey Foon Tan movia r2, _start /* Destination */ 13227d22413SLey Foon Tan movia r3, __bss_start /* End of copy */ 13327d22413SLey Foon Tan 13427d22413SLey Foon Tanloop_move: /* r1: src, r2: dest, r3: last dest */ 13527d22413SLey Foon Tan ldw r8, 0(r1) /* load a word from [r1] */ 13627d22413SLey Foon Tan stw r8, 0(r2) /* store a word to dest [r2] */ 13727d22413SLey Foon Tan flushd 0(r2) /* Flush cache for safety */ 13827d22413SLey Foon Tan addi r1, r1, 4 /* inc the src addr */ 13927d22413SLey Foon Tan addi r2, r2, 4 /* inc the dest addr */ 14027d22413SLey Foon Tan blt r2, r3, loop_move 14127d22413SLey Foon Tan 14227d22413SLey Foon Tan movia r1, finish_move /* VMA(_start)->l1 */ 14327d22413SLey Foon Tan jmp r1 /* jmp to _start */ 14427d22413SLey Foon Tan 14527d22413SLey Foon Tanfinish_move: 14627d22413SLey Foon Tan 14727d22413SLey Foon Tan /* Mask off all possible interrupts */ 14827d22413SLey Foon Tan wrctl ienable, r0 14927d22413SLey Foon Tan 15027d22413SLey Foon Tan /* Clear .bss */ 15127d22413SLey Foon Tan movia r2, __bss_start 15227d22413SLey Foon Tan movia r1, __bss_stop 15327d22413SLey Foon Tan1: 15427d22413SLey Foon Tan stb r0, 0(r2) 15527d22413SLey Foon Tan addi r2, r2, 1 15627d22413SLey Foon Tan bne r1, r2, 1b 15727d22413SLey Foon Tan 15827d22413SLey Foon Tan movia r1, init_thread_union /* set stack at top of the task union */ 15927d22413SLey Foon Tan addi sp, r1, THREAD_SIZE 16027d22413SLey Foon Tan movia r2, _current_thread /* Remember current thread */ 16127d22413SLey Foon Tan stw r1, 0(r2) 16227d22413SLey Foon Tan 16327d22413SLey Foon Tan movia r1, nios2_boot_init /* save args r4-r7 passed from u-boot */ 16427d22413SLey Foon Tan callr r1 16527d22413SLey Foon Tan 16627d22413SLey Foon Tan movia r1, start_kernel /* call start_kernel as a subroutine */ 16727d22413SLey Foon Tan callr r1 16827d22413SLey Foon Tan 16927d22413SLey Foon Tan /* If we return from start_kernel, break to the oci debugger and 17027d22413SLey Foon Tan * buggered we are. 17127d22413SLey Foon Tan */ 17227d22413SLey Foon Tan break 17327d22413SLey Foon Tan 17427d22413SLey Foon Tan /* End of startup code */ 17527d22413SLey Foon Tan.set at 176