137e4dafaSPeter Tyser/* 237e4dafaSPeter Tyser * (C) Copyright 2004, Psyent Corporation <www.psyent.com> 337e4dafaSPeter Tyser * Scott McNutt <smcnutt@psyent.com> 437e4dafaSPeter Tyser * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 637e4dafaSPeter Tyser */ 737e4dafaSPeter Tyser 825ddd1fbSWolfgang Denk#include <asm-offsets.h> 937e4dafaSPeter Tyser#include <config.h> 1037e4dafaSPeter Tyser#include <version.h> 1137e4dafaSPeter Tyser 1237e4dafaSPeter Tyser/************************************************************************* 1337e4dafaSPeter Tyser * RESTART 1437e4dafaSPeter Tyser ************************************************************************/ 1537e4dafaSPeter Tyser 1637e4dafaSPeter Tyser .text 1737e4dafaSPeter Tyser .global _start 1837e4dafaSPeter Tyser 1937e4dafaSPeter Tyser_start: 20fd2712d0SThomas Chou wrctl status, r0 /* Disable interrupts */ 2137e4dafaSPeter Tyser /* ICACHE INIT -- only the icache line at the reset address 2237e4dafaSPeter Tyser * is invalidated at reset. So the init must stay within 2337e4dafaSPeter Tyser * the cache line size (8 words). If GERMS is used, we'll 2437e4dafaSPeter Tyser * just be invalidating the cache a second time. If cache 2537e4dafaSPeter Tyser * is not implemented initi behaves as nop. 2637e4dafaSPeter Tyser */ 2737e4dafaSPeter Tyser ori r4, r0, %lo(CONFIG_SYS_ICACHELINE_SIZE) 2837e4dafaSPeter Tyser movhi r5, %hi(CONFIG_SYS_ICACHE_SIZE) 2937e4dafaSPeter Tyser ori r5, r5, %lo(CONFIG_SYS_ICACHE_SIZE) 30fd2712d0SThomas Chou0: initi r5 31fd2712d0SThomas Chou sub r5, r5, r4 32fd2712d0SThomas Chou bgt r5, r0, 0b 3337e4dafaSPeter Tyser br _except_end /* Skip the tramp */ 3437e4dafaSPeter Tyser 3537e4dafaSPeter Tyser /* EXCEPTION TRAMPOLINE -- the following gets copied 3637e4dafaSPeter Tyser * to the exception address (below), but is otherwise at the 3737e4dafaSPeter Tyser * default exception vector offset (0x0020). 3837e4dafaSPeter Tyser */ 3937e4dafaSPeter Tyser_except_start: 4037e4dafaSPeter Tyser movhi et, %hi(_exception) 4137e4dafaSPeter Tyser ori et, et, %lo(_exception) 4237e4dafaSPeter Tyser jmp et 4337e4dafaSPeter Tyser_except_end: 4437e4dafaSPeter Tyser 4537e4dafaSPeter Tyser /* INTERRUPTS -- for now, all interrupts masked and globally 4637e4dafaSPeter Tyser * disabled. 4737e4dafaSPeter Tyser */ 4837e4dafaSPeter Tyser wrctl ienable, r0 /* All disabled */ 4937e4dafaSPeter Tyser 5037e4dafaSPeter Tyser /* DCACHE INIT -- if dcache not implemented, initd behaves as 5137e4dafaSPeter Tyser * nop. 5237e4dafaSPeter Tyser */ 5337e4dafaSPeter Tyser movhi r4, %hi(CONFIG_SYS_DCACHELINE_SIZE) 5437e4dafaSPeter Tyser ori r4, r4, %lo(CONFIG_SYS_DCACHELINE_SIZE) 5537e4dafaSPeter Tyser movhi r5, %hi(CONFIG_SYS_DCACHE_SIZE) 5637e4dafaSPeter Tyser ori r5, r5, %lo(CONFIG_SYS_DCACHE_SIZE) 5737e4dafaSPeter Tyser mov r6, r0 5837e4dafaSPeter Tyser1: initd 0(r6) 5937e4dafaSPeter Tyser add r6, r6, r4 6037e4dafaSPeter Tyser bltu r6, r5, 1b 6137e4dafaSPeter Tyser 6237e4dafaSPeter Tyser /* RELOCATE CODE, DATA & COMMAND TABLE -- the following code 6337e4dafaSPeter Tyser * assumes code, data and the command table are all 6437e4dafaSPeter Tyser * contiguous. This lets us relocate everything as a single 6537e4dafaSPeter Tyser * block. Make sure the linker script matches this ;-) 6637e4dafaSPeter Tyser */ 6737e4dafaSPeter Tyser nextpc r4 6837e4dafaSPeter Tyser_cur: movhi r5, %hi(_cur - _start) 6937e4dafaSPeter Tyser ori r5, r5, %lo(_cur - _start) 7037e4dafaSPeter Tyser sub r4, r4, r5 /* r4 <- cur _start */ 7137e4dafaSPeter Tyser mov r8, r4 7237e4dafaSPeter Tyser movhi r5, %hi(_start) 7337e4dafaSPeter Tyser ori r5, r5, %lo(_start) /* r5 <- linked _start */ 7437e4dafaSPeter Tyser beq r4, r5, 3f 7537e4dafaSPeter Tyser 7637e4dafaSPeter Tyser movhi r6, %hi(_edata) 7737e4dafaSPeter Tyser ori r6, r6, %lo(_edata) 7837e4dafaSPeter Tyser2: ldwio r7, 0(r4) 7937e4dafaSPeter Tyser addi r4, r4, 4 8037e4dafaSPeter Tyser stwio r7, 0(r5) 8137e4dafaSPeter Tyser addi r5, r5, 4 8237e4dafaSPeter Tyser bne r5, r6, 2b 8337e4dafaSPeter Tyser3: 8437e4dafaSPeter Tyser 8537e4dafaSPeter Tyser /* JUMP TO RELOC ADDR */ 8637e4dafaSPeter Tyser movhi r4, %hi(_reloc) 8737e4dafaSPeter Tyser ori r4, r4, %lo(_reloc) 8837e4dafaSPeter Tyser jmp r4 8937e4dafaSPeter Tyser_reloc: 9037e4dafaSPeter Tyser 9137e4dafaSPeter Tyser /* COPY EXCEPTION TRAMPOLINE -- copy the tramp to the 9237e4dafaSPeter Tyser * exception address. Define CONFIG_ROM_STUBS to prevent 9337e4dafaSPeter Tyser * the copy (e.g. exception in flash or in other 9437e4dafaSPeter Tyser * softare/firmware component). 9537e4dafaSPeter Tyser */ 9637e4dafaSPeter Tyser#if !defined(CONFIG_ROM_STUBS) 9737e4dafaSPeter Tyser movhi r4, %hi(_except_start) 9837e4dafaSPeter Tyser ori r4, r4, %lo(_except_start) 9937e4dafaSPeter Tyser movhi r5, %hi(_except_end) 10037e4dafaSPeter Tyser ori r5, r5, %lo(_except_end) 10137e4dafaSPeter Tyser movhi r6, %hi(CONFIG_SYS_EXCEPTION_ADDR) 10237e4dafaSPeter Tyser ori r6, r6, %lo(CONFIG_SYS_EXCEPTION_ADDR) 10337e4dafaSPeter Tyser beq r4, r6, 7f /* Skip if at proper addr */ 10437e4dafaSPeter Tyser 10537e4dafaSPeter Tyser6: ldwio r7, 0(r4) 10637e4dafaSPeter Tyser stwio r7, 0(r6) 10737e4dafaSPeter Tyser addi r4, r4, 4 10837e4dafaSPeter Tyser addi r6, r6, 4 10937e4dafaSPeter Tyser bne r4, r5, 6b 11037e4dafaSPeter Tyser7: 11137e4dafaSPeter Tyser#endif 11237e4dafaSPeter Tyser 11337e4dafaSPeter Tyser /* STACK INIT -- zero top two words for call back chain. 11437e4dafaSPeter Tyser */ 11537e4dafaSPeter Tyser movhi sp, %hi(CONFIG_SYS_INIT_SP) 11637e4dafaSPeter Tyser ori sp, sp, %lo(CONFIG_SYS_INIT_SP) 11737e4dafaSPeter Tyser addi sp, sp, -8 11837e4dafaSPeter Tyser stw r0, 0(sp) 11937e4dafaSPeter Tyser stw r0, 4(sp) 12037e4dafaSPeter Tyser mov fp, sp 12137e4dafaSPeter Tyser 12237e4dafaSPeter Tyser /* 1235ff10aa7SThomas Chou * Call board_init_f -- never returns 12437e4dafaSPeter Tyser */ 1255ff10aa7SThomas Chou mov r4, r0 1265ff10aa7SThomas Chou movhi r2, %hi(board_init_f@h) 1275ff10aa7SThomas Chou ori r2, r2, %lo(board_init_f@h) 1285ff10aa7SThomas Chou callr r2 12937e4dafaSPeter Tyser 13037e4dafaSPeter Tyser /* NEVER RETURNS -- but branch to the _start just 13137e4dafaSPeter Tyser * in case ;-) 13237e4dafaSPeter Tyser */ 13337e4dafaSPeter Tyser br _start 13437e4dafaSPeter Tyser 13537e4dafaSPeter Tyser 1365ff10aa7SThomas Chou 1375ff10aa7SThomas Chou/* 1385ff10aa7SThomas Chou * relocate_code -- Nios2 handles the relocation above. But 1395ff10aa7SThomas Chou * the generic board code monkeys with the heap, stack, etc. 1405ff10aa7SThomas Chou * (it makes some assumptions that may not be appropriate 1415ff10aa7SThomas Chou * for Nios). Nevertheless, we capitulate here. 1425ff10aa7SThomas Chou * 1435ff10aa7SThomas Chou * We'll call the board_init_r from here since this isn't 1445ff10aa7SThomas Chou * supposed to return. 1455ff10aa7SThomas Chou * 1465ff10aa7SThomas Chou * void relocate_code (ulong sp, gd_t *global_data, 1475ff10aa7SThomas Chou * ulong reloc_addr) 1485ff10aa7SThomas Chou * __attribute__ ((noreturn)); 1495ff10aa7SThomas Chou */ 1505ff10aa7SThomas Chou .text 1515ff10aa7SThomas Chou .global relocate_code 1525ff10aa7SThomas Chou 1535ff10aa7SThomas Chourelocate_code: 1545ff10aa7SThomas Chou mov sp, r4 /* Set the new sp */ 1555ff10aa7SThomas Chou mov r4, r5 156*4192b8c3SThomas Chou 157*4192b8c3SThomas Chou /* 158*4192b8c3SThomas Chou * ZERO BSS/SBSS -- bss and sbss are assumed to be adjacent 159*4192b8c3SThomas Chou * and between __bss_start and __bss_end. 160*4192b8c3SThomas Chou */ 161*4192b8c3SThomas Chou movhi r5, %hi(__bss_start) 162*4192b8c3SThomas Chou ori r5, r5, %lo(__bss_start) 163*4192b8c3SThomas Chou movhi r6, %hi(__bss_end) 164*4192b8c3SThomas Chou ori r6, r6, %lo(__bss_end) 165*4192b8c3SThomas Chou beq r5, r6, 5f 166*4192b8c3SThomas Chou 167*4192b8c3SThomas Chou4: stwio r0, 0(r5) 168*4192b8c3SThomas Chou addi r5, r5, 4 169*4192b8c3SThomas Chou bne r5, r6, 4b 170*4192b8c3SThomas Chou5: 171*4192b8c3SThomas Chou 1725ff10aa7SThomas Chou movhi r8, %hi(board_init_r@h) 1735ff10aa7SThomas Chou ori r8, r8, %lo(board_init_r@h) 1745ff10aa7SThomas Chou callr r8 1755ff10aa7SThomas Chou ret 1765ff10aa7SThomas Chou 17737e4dafaSPeter Tyser/* 17837e4dafaSPeter Tyser * dly_clks -- Nios2 (like Nios1) doesn't have a timebase in 17937e4dafaSPeter Tyser * the core. For simple delay loops, we do our best by counting 18037e4dafaSPeter Tyser * instruction cycles. 18137e4dafaSPeter Tyser * 18237e4dafaSPeter Tyser * Instruction performance varies based on the core. For cores 18337e4dafaSPeter Tyser * with icache and static/dynamic branch prediction (II/f, II/s): 18437e4dafaSPeter Tyser * 18537e4dafaSPeter Tyser * Normal ALU (e.g. add, cmp, etc): 1 cycle 18637e4dafaSPeter Tyser * Branch (correctly predicted, taken): 2 cycles 18737e4dafaSPeter Tyser * Negative offset is predicted (II/s). 18837e4dafaSPeter Tyser * 18937e4dafaSPeter Tyser * For cores without icache and no branch prediction (II/e): 19037e4dafaSPeter Tyser * 19137e4dafaSPeter Tyser * Normal ALU (e.g. add, cmp, etc): 6 cycles 19237e4dafaSPeter Tyser * Branch (no prediction): 6 cycles 19337e4dafaSPeter Tyser * 19437e4dafaSPeter Tyser * For simplicity, if an instruction cache is implemented we 19537e4dafaSPeter Tyser * assume II/f or II/s. Otherwise, we use the II/e. 19637e4dafaSPeter Tyser * 19737e4dafaSPeter Tyser */ 19837e4dafaSPeter Tyser .globl dly_clks 19937e4dafaSPeter Tyser 20037e4dafaSPeter Tyserdly_clks: 20137e4dafaSPeter Tyser 20237e4dafaSPeter Tyser#if (CONFIG_SYS_ICACHE_SIZE > 0) 20337e4dafaSPeter Tyser subi r4, r4, 3 /* 3 clocks/loop */ 20437e4dafaSPeter Tyser#else 20537e4dafaSPeter Tyser subi r4, r4, 12 /* 12 clocks/loop */ 20637e4dafaSPeter Tyser#endif 20737e4dafaSPeter Tyser bge r4, r0, dly_clks 20837e4dafaSPeter Tyser ret 20937e4dafaSPeter Tyser 21037e4dafaSPeter Tyser .data 21137e4dafaSPeter Tyser .globl version_string 21237e4dafaSPeter Tyser 21337e4dafaSPeter Tyserversion_string: 21409c2e90cSAndreas Bießmann .ascii U_BOOT_VERSION_STRING, "\0" 215