X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fmips%2Fcpu%2Fstart.S;h=fc6dd66aa655b9e1c7a8b25c5311e96e0ff6f4cb;hb=6d54868eeb2697c9a905c4d3521efbacc44c5258;hp=57db589b94f266e7057ca966a72b6487918cd186;hpb=83653121d7382fccfe329cb732f77f116341ef1d;p=u-boot diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 57db589b94..fc6dd66aa6 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -3,29 +3,41 @@ * * Copyright (c) 2003 Wolfgang Denk * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ +#include #include +#include #include #include +#ifndef CONFIG_SYS_MIPS_CACHE_MODE +#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT +#endif + +#ifndef CONFIG_SYS_INIT_SP_ADDR +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \ + CONFIG_SYS_INIT_SP_OFFSET) +#endif + +#ifdef CONFIG_32BIT +# define MIPS_RELOC 3 +# define STATUS_SET 0 +#endif + +#ifdef CONFIG_64BIT +# ifdef CONFIG_SYS_LITTLE_ENDIAN +# define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \ + (((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym)) +# else +# define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \ + ((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24) +# endif +# define MIPS_RELOC MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03) +# define STATUS_SET ST0_KX +#endif + /* * For the moment disable interrupts, mark the kernel mode and * set ST0_KX so that the CPU does not spit fire when using @@ -42,255 +54,145 @@ .set pop .endm - .macro setup_c0_status_reset -#ifdef CONFIG_64BIT - setup_c0_status ST0_KX 0 -#else - setup_c0_status 0 0 + .set noreorder + +ENTRY(_start) + /* U-Boot entry point */ + b reset + nop + + .org 0x10 +#if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG) + /* + * Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to + * access external NOR flashes. If the board boots from NOR flash the + * internal BootROM does a blind read at address 0xB0000010 to read the + * initial configuration for that EBU in order to access the flash + * device with correct parameters. This config option is board-specific. + */ + .word CONFIG_SYS_XWAY_EBU_BOOTCFG + .word 0x0 +#elif defined(CONFIG_MALTA) + /* + * Linux expects the Board ID here. + */ + .word 0x00000420 # 0x420 (Malta Board with CoreLV) + .word 0x00000000 #endif - .endm -#define RVECENT(f,n) \ - b f; nop -#define XVECENT(f,bev) \ - b f ; \ - li k0,bev + .org 0x200 + /* TLB refill, 32 bit task */ +1: b 1b + nop - .set noreorder + .org 0x280 + /* XTLB refill, 64 bit task */ +1: b 1b + nop + + .org 0x300 + /* Cache error exception */ +1: b 1b + nop + + .org 0x380 + /* General exception */ +1: b 1b + nop + + .org 0x400 + /* Catch interrupt exceptions */ +1: b 1b + nop + + .org 0x480 + /* EJTAG debug exception */ +1: b 1b + nop - .globl _start - .text -_start: - RVECENT(reset,0) /* U-boot entry point */ - RVECENT(reset,1) /* software reboot */ -#if defined(CONFIG_INCA_IP) - .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ - .word 0x00000000 /* phase of the flash */ -#elif defined(CONFIG_PURPLE) - .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ - .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ -#else - RVECENT(romReserved,2) -#endif - RVECENT(romReserved,3) - RVECENT(romReserved,4) - RVECENT(romReserved,5) - RVECENT(romReserved,6) - RVECENT(romReserved,7) - RVECENT(romReserved,8) - RVECENT(romReserved,9) - RVECENT(romReserved,10) - RVECENT(romReserved,11) - RVECENT(romReserved,12) - RVECENT(romReserved,13) - RVECENT(romReserved,14) - RVECENT(romReserved,15) - RVECENT(romReserved,16) - RVECENT(romReserved,17) - RVECENT(romReserved,18) - RVECENT(romReserved,19) - RVECENT(romReserved,20) - RVECENT(romReserved,21) - RVECENT(romReserved,22) - RVECENT(romReserved,23) - RVECENT(romReserved,24) - RVECENT(romReserved,25) - RVECENT(romReserved,26) - RVECENT(romReserved,27) - RVECENT(romReserved,28) - RVECENT(romReserved,29) - RVECENT(romReserved,30) - RVECENT(romReserved,31) - RVECENT(romReserved,32) - RVECENT(romReserved,33) - RVECENT(romReserved,34) - RVECENT(romReserved,35) - RVECENT(romReserved,36) - RVECENT(romReserved,37) - RVECENT(romReserved,38) - RVECENT(romReserved,39) - RVECENT(romReserved,40) - RVECENT(romReserved,41) - RVECENT(romReserved,42) - RVECENT(romReserved,43) - RVECENT(romReserved,44) - RVECENT(romReserved,45) - RVECENT(romReserved,46) - RVECENT(romReserved,47) - RVECENT(romReserved,48) - RVECENT(romReserved,49) - RVECENT(romReserved,50) - RVECENT(romReserved,51) - RVECENT(romReserved,52) - RVECENT(romReserved,53) - RVECENT(romReserved,54) - RVECENT(romReserved,55) - RVECENT(romReserved,56) - RVECENT(romReserved,57) - RVECENT(romReserved,58) - RVECENT(romReserved,59) - RVECENT(romReserved,60) - RVECENT(romReserved,61) - RVECENT(romReserved,62) - RVECENT(romReserved,63) - XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */ - RVECENT(romReserved,65) - RVECENT(romReserved,66) - RVECENT(romReserved,67) - RVECENT(romReserved,68) - RVECENT(romReserved,69) - RVECENT(romReserved,70) - RVECENT(romReserved,71) - RVECENT(romReserved,72) - RVECENT(romReserved,73) - RVECENT(romReserved,74) - RVECENT(romReserved,75) - RVECENT(romReserved,76) - RVECENT(romReserved,77) - RVECENT(romReserved,78) - RVECENT(romReserved,79) - XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */ - RVECENT(romReserved,81) - RVECENT(romReserved,82) - RVECENT(romReserved,83) - RVECENT(romReserved,84) - RVECENT(romReserved,85) - RVECENT(romReserved,86) - RVECENT(romReserved,87) - RVECENT(romReserved,88) - RVECENT(romReserved,89) - RVECENT(romReserved,90) - RVECENT(romReserved,91) - RVECENT(romReserved,92) - RVECENT(romReserved,93) - RVECENT(romReserved,94) - RVECENT(romReserved,95) - XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */ - RVECENT(romReserved,97) - RVECENT(romReserved,98) - RVECENT(romReserved,99) - RVECENT(romReserved,100) - RVECENT(romReserved,101) - RVECENT(romReserved,102) - RVECENT(romReserved,103) - RVECENT(romReserved,104) - RVECENT(romReserved,105) - RVECENT(romReserved,106) - RVECENT(romReserved,107) - RVECENT(romReserved,108) - RVECENT(romReserved,109) - RVECENT(romReserved,110) - RVECENT(romReserved,111) - XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */ - RVECENT(romReserved,113) - RVECENT(romReserved,114) - RVECENT(romReserved,115) - RVECENT(romReserved,116) - RVECENT(romReserved,116) - RVECENT(romReserved,118) - RVECENT(romReserved,119) - RVECENT(romReserved,120) - RVECENT(romReserved,121) - RVECENT(romReserved,122) - RVECENT(romReserved,123) - RVECENT(romReserved,124) - RVECENT(romReserved,125) - RVECENT(romReserved,126) - RVECENT(romReserved,127) - - /* We hope there are no more reserved vectors! - * 128 * 8 == 1024 == 0x400 - * so this is address R_VEC+0x400 == 0xbfc00400 - */ -#ifdef CONFIG_PURPLE -/* 0xbfc00400 */ - .word 0xdc870000 - .word 0xfca70000 - .word 0x20840008 - .word 0x20a50008 - .word 0x20c6ffff - .word 0x14c0fffa - .word 0x00000000 - .word 0x03e00008 - .word 0x00000000 - .word 0x00000000 -/* 0xbfc00428 */ - .word 0xdc870000 - .word 0xfca70000 - .word 0x20840008 - .word 0x20a50008 - .word 0x20c6ffff - .word 0x14c0fffa - .word 0x00000000 - .word 0x03e00008 - .word 0x00000000 - .word 0x00000000 -#endif /* CONFIG_PURPLE */ .align 4 reset: - /* Clear watch registers. - */ - mtc0 zero, CP0_WATCHLO + /* Clear watch registers */ + MTC0 zero, CP0_WATCHLO mtc0 zero, CP0_WATCHHI - /* WP(Watch Pending), SW0/1 should be cleared. */ + /* WP(Watch Pending), SW0/1 should be cleared */ mtc0 zero, CP0_CAUSE - setup_c0_status_reset + setup_c0_status STATUS_SET 0 /* Init Timer */ mtc0 zero, CP0_COUNT mtc0 zero, CP0_COMPARE -#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) +#ifndef CONFIG_SKIP_LOWLEVEL_INIT /* CONFIG0 register */ li t0, CONF_CM_UNCACHED mtc0 t0, CP0_CONFIG -#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ +#endif - /* Initialize $gp. + /* + * Initialize $gp, force pointer sized alignment of bal instruction to + * forbid the compiler to put nop's between bal and _gp. This is + * required to keep _gp and ra aligned to 8 byte. */ + .align PTRLOG bal 1f - nop - .word _gp + nop + PTR _gp 1: - lw gp, 0(ra) + PTR_L gp, 0(ra) -#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) - /* Initialize any external memory. - */ - la t9, lowlevel_init +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + /* Initialize any external memory */ + PTR_LA t9, lowlevel_init jalr t9 - nop + nop - /* Initialize caches... - */ - la t9, mips_cache_reset + /* Initialize caches... */ + PTR_LA t9, mips_cache_reset jalr t9 - nop + nop - /* ... and enable them. - */ - li t0, CONF_CM_CACHABLE_NONCOHERENT + /* ... and enable them */ + li t0, CONFIG_SYS_MIPS_CACHE_MODE mtc0 t0, CP0_CONFIG -#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ +#endif - /* Set up temporary stack. - */ -#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS - li a0, CONFIG_SYS_INIT_SP_OFFSET - la t9, mips_cache_lock - jalr t9 - nop + /* Set up temporary stack */ + li t0, -16 + PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR + and sp, t1, t0 # force 16 byte alignment + PTR_SUBU \ + sp, sp, GD_SIZE # reserve space for gd + and sp, sp, t0 # force 16 byte alignment + move k0, sp # save gd pointer +#ifdef CONFIG_SYS_MALLOC_F_LEN + li t2, CONFIG_SYS_MALLOC_F_LEN + PTR_SUBU \ + sp, sp, t2 # reserve space for early malloc + and sp, sp, t0 # force 16 byte alignment #endif + move fp, sp - li t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET - la sp, 0(t0) + /* Clear gd */ + move t0, k0 +1: + PTR_S zero, 0(t0) + blt t0, t1, 1b + PTR_ADDIU t0, PTRSIZE + +#ifdef CONFIG_SYS_MALLOC_F_LEN + PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset +#endif - la t9, board_init_f + move a0, zero # a0 <-- boot_flags = 0 + PTR_LA t9, board_init_f jr t9 - nop + move ra, zero + + END(_start) /* * void relocate_code (addr_sp, gd, addr_moni) @@ -302,71 +204,50 @@ reset: * a1 = gd * a2 = destination address */ - .globl relocate_code - .ent relocate_code -relocate_code: - move sp, a0 /* Set new stack pointer */ - - li t0, CONFIG_SYS_MONITOR_BASE - la t3, in_ram - lw t2, -12(t3) /* t2 <-- uboot_end_data */ +ENTRY(relocate_code) + move sp, a0 # set new stack pointer + move fp, sp + + move s0, a1 # save gd in s0 + move s2, a2 # save destination address in s2 + + PTR_LI t0, CONFIG_SYS_MONITOR_BASE + PTR_SUB s1, s2, t0 # s1 <-- relocation offset + + PTR_LA t3, in_ram + PTR_L t2, -(3 * PTRSIZE)(t3) # t2 <-- __image_copy_end move t1, a2 - move s2, a2 /* s2 <-- destination address */ - /* - * Fix $gp: - * - * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address - */ - move t6, gp - sub gp, CONFIG_SYS_MONITOR_BASE - add gp, a2 /* gp now adjusted */ - sub s1, gp, t6 /* s1 <-- relocation offset */ + PTR_ADD gp, s1 # adjust gp /* * t0 = source address * t1 = target address * t2 = source end address */ - - /* - * Save destination address and size for later usage in flush_cache() - */ - move s0, a1 /* save gd in s0 */ - move a0, t1 /* a0 <-- destination addr */ - sub a1, t2, t0 /* a1 <-- size */ - - /* On the purple board we copy the code earlier in a special way - * in order to solve flash problems - */ -#ifndef CONFIG_PURPLE 1: - lw t3, 0(t0) - sw t3, 0(t1) - addu t0, 4 - ble t0, t2, 1b - addu t1, 4 /* delay slot */ -#endif - - /* If caches were enabled, we would have to flush them here. - */ - - /* a0 & a1 are already set up for flush_cache(start, size) */ - la t9, flush_cache + PTR_L t3, 0(t0) + PTR_S t3, 0(t1) + PTR_ADDU t0, PTRSIZE + blt t0, t2, 1b + PTR_ADDU t1, PTRSIZE + + /* If caches were enabled, we would have to flush them here. */ + PTR_SUB a1, t1, s2 # a1 <-- size + PTR_LA t9, flush_cache jalr t9 - nop + move a0, s2 # a0 <-- destination address - /* Jump to where we've relocated ourselves. - */ - addi t0, s2, in_ram - _start + /* Jump to where we've relocated ourselves */ + PTR_ADDIU t0, s2, in_ram - _start jr t0 - nop + nop - .word _gp - .word _GLOBAL_OFFSET_TABLE_ - .word uboot_end_data - .word uboot_end - .word num_got_entries + PTR __rel_dyn_end + PTR __rel_dyn_start + PTR __image_copy_end + PTR _GLOBAL_OFFSET_TABLE_ + PTR num_got_entries in_ram: /* @@ -375,47 +256,65 @@ in_ram: * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object * generated by GNU ld. Skip these reserved entries from relocation. */ - lw t3, -4(t0) /* t3 <-- num_got_entries */ - lw t4, -16(t0) /* t4 <-- _GLOBAL_OFFSET_TABLE_ */ - lw t5, -20(t0) /* t5 <-- _gp */ - sub t4, t5 /* compute offset*/ - add t4, t4, gp /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */ - addi t4, t4, 8 /* Skipping first two entries. */ - li t2, 2 + PTR_L t3, -(1 * PTRSIZE)(t0) # t3 <-- num_got_entries + PTR_L t8, -(2 * PTRSIZE)(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_ + PTR_ADD t8, s1 # t8 now holds relocated _G_O_T_ + PTR_ADDIU t8, t8, 2 * PTRSIZE # skipping first two entries + PTR_LI t2, 2 1: - lw t1, 0(t4) + PTR_L t1, 0(t8) beqz t1, 2f - add t1, s1 - sw t1, 0(t4) + PTR_ADD t1, s1 + PTR_S t1, 0(t8) 2: - addi t2, 1 + PTR_ADDIU t2, 1 blt t2, t3, 1b - addi t4, 4 /* delay slot */ + PTR_ADDIU t8, PTRSIZE - /* Clear BSS. - */ - lw t1, -12(t0) /* t1 <-- uboot_end_data */ - lw t2, -8(t0) /* t2 <-- uboot_end */ - add t1, s1 /* adjust pointers */ - add t2, s1 + /* Update dynamic relocations */ + PTR_L t1, -(4 * PTRSIZE)(t0) # t1 <-- __rel_dyn_start + PTR_L t2, -(5 * PTRSIZE)(t0) # t2 <-- __rel_dyn_end + + b 2f # skip first reserved entry + PTR_ADDIU t1, 2 * PTRSIZE - sub t1, 4 1: - addi t1, 4 - bltl t1, t2, 1b - sw zero, 0(t1) /* delay slot */ + lw t8, -4(t1) # t8 <-- relocation info - move a0, s0 /* a0 <-- gd */ - la t9, board_init_r - jr t9 - move a1, s2 /* delay slot */ + PTR_LI t3, MIPS_RELOC + bne t8, t3, 2f # skip non-MIPS_RELOC entries + nop + + PTR_L t3, -(2 * PTRSIZE)(t1) # t3 <-- location to fix up in FLASH + + PTR_L t8, 0(t3) # t8 <-- original pointer + PTR_ADD t8, s1 # t8 <-- adjusted pointer - .end relocate_code + PTR_ADD t3, s1 # t3 <-- location to fix up in RAM + PTR_S t8, 0(t3) - /* Exception handlers. +2: + blt t1, t2, 1b + PTR_ADDIU t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes + + /* + * Clear BSS + * + * GOT is now relocated. Thus __bss_start and __bss_end can be + * accessed directly via $gp. */ -romReserved: - b romReserved + PTR_LA t1, __bss_start # t1 <-- __bss_start + PTR_LA t2, __bss_end # t2 <-- __bss_end + +1: + PTR_S zero, 0(t1) + blt t1, t2, 1b + PTR_ADDIU t1, PTRSIZE + + move a0, s0 # a0 <-- gd + move a1, s2 + PTR_LA t9, board_init_r + jr t9 + move ra, zero -romExcHandle: - b romExcHandle + END(relocate_code)