forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.0 KiB
175 lines
4.0 KiB
/* |
|
* Copyright (C) 2009 Wind River Systems Inc |
|
* Implemented by fredrik.markstrom@gmail.com and [email protected] |
|
* Copyright (C) 2004 Microtronix Datacom Ltd |
|
* Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd. |
|
* |
|
* Based on head.S for Altera's Excalibur development board with nios processor |
|
* |
|
* Based on the following from the Excalibur sdk distribution: |
|
* NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.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. |
|
*/ |
|
|
|
#include <linux/init.h> |
|
#include <linux/linkage.h> |
|
#include <asm/thread_info.h> |
|
#include <asm/processor.h> |
|
#include <asm/cache.h> |
|
#include <asm/page.h> |
|
#include <asm/asm-offsets.h> |
|
#include <asm/asm-macros.h> |
|
|
|
/* |
|
* ZERO_PAGE is a special page that is used for zero-initialized |
|
* data and COW. |
|
*/ |
|
.data |
|
.global empty_zero_page |
|
.align 12 |
|
empty_zero_page: |
|
.space PAGE_SIZE |
|
|
|
/* |
|
* This global variable is used as an extension to the nios' |
|
* STATUS register to emulate a user/supervisor mode. |
|
*/ |
|
.data |
|
.align 2 |
|
.set noat |
|
|
|
.global _current_thread |
|
_current_thread: |
|
.long 0 |
|
/* |
|
* Input(s): passed from u-boot |
|
* r4 - Optional pointer to a board information structure. |
|
* r5 - Optional pointer to the physical starting address of the init RAM |
|
* disk. |
|
* r6 - Optional pointer to the physical ending address of the init RAM |
|
* disk. |
|
* r7 - Optional pointer to the physical starting address of any kernel |
|
* command-line parameters. |
|
*/ |
|
|
|
/* |
|
* First executable code - detected and jumped to by the ROM bootstrap |
|
* if the code resides in flash (looks for "Nios" at offset 0x0c from |
|
* the potential executable image). |
|
*/ |
|
__HEAD |
|
ENTRY(_start) |
|
wrctl status, r0 /* Disable interrupts */ |
|
|
|
/* Initialize all cache lines within the instruction cache */ |
|
movia r1, NIOS2_ICACHE_SIZE |
|
movui r2, NIOS2_ICACHE_LINE_SIZE |
|
|
|
icache_init: |
|
initi r1 |
|
sub r1, r1, r2 |
|
bgt r1, r0, icache_init |
|
br 1f |
|
|
|
/* |
|
* This is the default location for the exception handler. Code in jump |
|
* to our handler |
|
*/ |
|
ENTRY(exception_handler_hook) |
|
movia r24, inthandler |
|
jmp r24 |
|
|
|
ENTRY(fast_handler) |
|
nextpc et |
|
helper: |
|
stw r3, r3save - helper(et) |
|
|
|
rdctl r3 , pteaddr |
|
srli r3, r3, 12 |
|
slli r3, r3, 2 |
|
movia et, pgd_current |
|
|
|
ldw et, 0(et) |
|
add r3, et, r3 |
|
ldw et, 0(r3) |
|
|
|
rdctl r3, pteaddr |
|
andi r3, r3, 0xfff |
|
add et, r3, et |
|
ldw et, 0(et) |
|
wrctl tlbacc, et |
|
nextpc et |
|
helper2: |
|
ldw r3, r3save - helper2(et) |
|
subi ea, ea, 4 |
|
eret |
|
r3save: |
|
.word 0x0 |
|
ENTRY(fast_handler_end) |
|
|
|
1: |
|
/* |
|
* After the instruction cache is initialized, the data cache must |
|
* also be initialized. |
|
*/ |
|
movia r1, NIOS2_DCACHE_SIZE |
|
movui r2, NIOS2_DCACHE_LINE_SIZE |
|
|
|
dcache_init: |
|
initd 0(r1) |
|
sub r1, r1, r2 |
|
bgt r1, r0, dcache_init |
|
|
|
nextpc r1 /* Find out where we are */ |
|
chkadr: |
|
movia r2, chkadr |
|
beq r1, r2,finish_move /* We are running in RAM done */ |
|
addi r1, r1,(_start - chkadr) /* Source */ |
|
movia r2, _start /* Destination */ |
|
movia r3, __bss_start /* End of copy */ |
|
|
|
loop_move: /* r1: src, r2: dest, r3: last dest */ |
|
ldw r8, 0(r1) /* load a word from [r1] */ |
|
stw r8, 0(r2) /* store a word to dest [r2] */ |
|
flushd 0(r2) /* Flush cache for safety */ |
|
addi r1, r1, 4 /* inc the src addr */ |
|
addi r2, r2, 4 /* inc the dest addr */ |
|
blt r2, r3, loop_move |
|
|
|
movia r1, finish_move /* VMA(_start)->l1 */ |
|
jmp r1 /* jmp to _start */ |
|
|
|
finish_move: |
|
|
|
/* Mask off all possible interrupts */ |
|
wrctl ienable, r0 |
|
|
|
/* Clear .bss */ |
|
movia r2, __bss_start |
|
movia r1, __bss_stop |
|
1: |
|
stb r0, 0(r2) |
|
addi r2, r2, 1 |
|
bne r1, r2, 1b |
|
|
|
movia r1, init_thread_union /* set stack at top of the task union */ |
|
addi sp, r1, THREAD_SIZE |
|
movia r2, _current_thread /* Remember current thread */ |
|
stw r1, 0(r2) |
|
|
|
movia r1, nios2_boot_init /* save args r4-r7 passed from u-boot */ |
|
callr r1 |
|
|
|
movia r1, start_kernel /* call start_kernel as a subroutine */ |
|
callr r1 |
|
|
|
/* If we return from start_kernel, break to the oci debugger and |
|
* buggered we are. |
|
*/ |
|
break |
|
|
|
/* End of startup code */ |
|
.set at
|
|
|