From patchwork Sat Dec 4 13:23:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: luigi.mantellini@idf-hit.com X-Patchwork-Id: 74269 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 32724B7080 for ; Sun, 5 Dec 2010 00:31:26 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4983228259; Sat, 4 Dec 2010 14:31:06 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id krGlLXgXKnNH; Sat, 4 Dec 2010 14:31:05 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BE1C32826F; Sat, 4 Dec 2010 14:31:02 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id AE2D02826F for ; Sat, 4 Dec 2010 14:30:59 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HdO95FM1M6a8 for ; Sat, 4 Dec 2010 14:30:58 +0100 (CET) Received: from mx103.fabbricadigitale.it (mx2.fabbricadigitale.it [217.169.111.37]) by theia.denx.de (Postfix) with ESMTPS id 76E8328261 for ; Sat, 4 Dec 2010 14:30:58 +0100 (CET) Received: from localhost (mx103 [127.0.0.1]) by mx103.fabbricadigitale.it (MM4Csmtpd) with ESMTP id BBE5FE0001BA for ; Sat, 4 Dec 2010 14:24:23 +0100 (CET) X-Virus-Scanned: amavisd-new at fabbricadigitale.it Received: from mx103.fabbricadigitale.it ([127.0.0.1]) by localhost (mx103.fabbricadigitale.it [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 36qaOtJXEnya for ; Sat, 4 Dec 2010 14:24:23 +0100 (CET) Received: from EX02MailShare.fdmsha.local (unknown [172.16.26.10]) by mx103.fabbricadigitale.it (MM4Csmtpd) with ESMTPS id 9965BE000090 for ; Sat, 4 Dec 2010 14:24:23 +0100 (CET) Received: from abel.dialface.net (85.40.213.226) by EX02MailShare.fdmsha.local (172.16.26.10) with Microsoft SMTP Server id 8.1.340.0; Sat, 4 Dec 2010 14:24:21 +0100 From: Luigi 'Comio' Mantellini To: Date: Sat, 4 Dec 2010 14:23:49 +0100 Message-ID: <1291469030-24984-6-git-send-email-luigi.mantellini@idf-hit.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1291469030-24984-1-git-send-email-luigi.mantellini@idf-hit.com> References: <1291469030-24984-1-git-send-email-luigi.mantellini@idf-hit.com> MIME-Version: 1.0 Cc: Luigi 'Comio' Mantellini Subject: [U-Boot] [PATCH 5/6 v2] Enable bootstrap support for MIPS architecture. X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Luigi 'Comio' Mantellini Signed-off-by: Luigi 'Comio' Mantellini --- arch/mips/config.mk | 2 +- arch/mips/cpu/Makefile | 28 ++- arch/mips/cpu/cpu.c | 12 - arch/mips/cpu/reset.c | 39 ++++ arch/mips/cpu/reset_bootstrap.c | 39 ++++ arch/mips/cpu/start_bootstrap.S | 455 +++++++++++++++++++++++++++++++++++++++ arch/mips/lib/Makefile | 15 ++- arch/mips/lib/board_bootstrap.c | 331 ++++++++++++++++++++++++++++ 8 files changed, 903 insertions(+), 18 deletions(-) create mode 100644 arch/mips/cpu/reset.c create mode 100644 arch/mips/cpu/reset_bootstrap.c create mode 100644 arch/mips/cpu/start_bootstrap.S create mode 100644 arch/mips/lib/board_bootstrap.c diff --git a/arch/mips/config.mk b/arch/mips/config.mk index aa06761..4655169 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -47,6 +47,6 @@ PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__ # On the other hand, we want PIC in the U-Boot code to relocate it from ROM # to RAM. $28 is always used as gp. # -PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic +PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic -g PLATFORM_CPPFLAGS += -msoft-float PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib diff --git a/arch/mips/cpu/Makefile b/arch/mips/cpu/Makefile index 06df8d1..6a9a2af 100644 --- a/arch/mips/cpu/Makefile +++ b/arch/mips/cpu/Makefile @@ -24,25 +24,45 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).o +BOOTSTRAP_LIB = $(obj)lib$(CPU)_bootstrap.o + +BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB) START = start.o SOBJS-y = cache.o -COBJS-y = cpu.o interrupts.o +COBJS-y = cpu.o reset.o interrupts.o SOBJS-$(CONFIG_INCA_IP) += incaip_wdt.o COBJS-$(CONFIG_INCA_IP) += asc_serial.o incaip_clock.o +COBJS-$(CONFIG_IFX_ASC) += ifx_asc.o COBJS-$(CONFIG_PURPLE) += asc_serial.o COBJS-$(CONFIG_SOC_AU1X00) += au1x00_eth.o au1x00_serial.o au1x00_usb_ohci.o -SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +BOOTSTRAP_START = start_bootstrap.o +BOOTSTRAP_START-$(CONFIG_BOOTSTRAP) += $(BOOTSTRAP_START) +BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += cpu.o interrupts.o reset_bootstrap.o +BOOTSTRAP_SOBJS-$(CONFIG_BOOTSTRAP) += cache.o +BOOTSTRAP_COBJS-$(CONFIG_IFX_ASC) += ifx_asc.o + +BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y) $(BOOTSTRAP_COBJS-y)) +BOOTSTRAP_START := $(addprefix $(obj),$(BOOTSTRAP_START-y)) + +SRCS := $(sort $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) $(BOOTSTRAP_START-y:.o=.S) $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) START := $(addprefix $(obj),$(START)) -all: $(obj).depend $(START) $(LIB) +all: $(START) $(LIB) $(BOOTSTRAP_START-y) $(BOOTSTRAP_LIB-y) -$(LIB): $(OBJS) +$(START): $(obj).depend + +$(LIB): $(obj).depend $(OBJS) $(call cmd_link_o_target, $(OBJS)) +$(BOOTSTRAP_START): $(obj).depend + +$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS) + $(call cmd_link_o_target, $(BOOTSTRAP_OBJS)) + ######################################################################### # defines $(obj).depend target diff --git a/arch/mips/cpu/cpu.c b/arch/mips/cpu/cpu.c index 3ae397c..45bf07c 100644 --- a/arch/mips/cpu/cpu.c +++ b/arch/mips/cpu/cpu.c @@ -38,18 +38,6 @@ : \ : "i" (op), "R" (*(unsigned char *)(addr))) -void __attribute__((weak)) _machine_restart(void) -{ -} - -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - _machine_restart(); - - fprintf(stderr, "*** reset failed ***\n"); - return 0; -} - void flush_cache(ulong start_addr, ulong size) { unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE; diff --git a/arch/mips/cpu/reset.c b/arch/mips/cpu/reset.c new file mode 100644 index 0000000..397fb62 --- /dev/null +++ b/arch/mips/cpu/reset.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, + * + * 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 + */ + +#include +#include +#include +#include + +void __attribute__((weak)) _machine_restart(void) +{ +} + +int __attribute__((weak)) do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + _machine_restart(); + + fprintf(stderr, "*** reset failed ***\n"); + return 0; +} diff --git a/arch/mips/cpu/reset_bootstrap.c b/arch/mips/cpu/reset_bootstrap.c new file mode 100644 index 0000000..0bef625 --- /dev/null +++ b/arch/mips/cpu/reset_bootstrap.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, + * + * 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 + */ + +#include +#include +#include +#include + +void __attribute__((weak)) _machine_restart(void) +{ +} + +int __attribute__((weak)) do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + _machine_restart(); + + printf("*** reset failed ***\n"); + return 0; +} diff --git a/arch/mips/cpu/start_bootstrap.S b/arch/mips/cpu/start_bootstrap.S new file mode 100644 index 0000000..782e473 --- /dev/null +++ b/arch/mips/cpu/start_bootstrap.S @@ -0,0 +1,455 @@ +/* + * Startup Code for MIPS32 CPU-core base on start.S source + * + * Copyright (c) 2010 Industrie Dial Face S.p.A. + * Luigi 'Comio' Mantellini + * + * 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 + */ + +#include +#include +#include +#include +#include + + /* + * For the moment disable interrupts, mark the kernel mode and + * set ST0_KX so that the CPU does not spit fire when using + * 64-bit addresses. + */ + .macro setup_c0_status set clr + .set push + mfc0 t0, CP0_STATUS + or t0, ST0_CU0 | \set | 0x1f | \clr + xor t0, 0x1f | \clr + mtc0 t0, CP0_STATUS + .set noreorder + sll zero, 3 # ehb + .set pop + .endm + + .macro setup_c0_status_reset +#ifdef CONFIG_64BIT + setup_c0_status ST0_KX 0 +#else + setup_c0_status 0 0 +#endif + .endm + +#define RVECENT(f,n) \ + b f; nop +#define XVECENT(f,bev) \ + b f ; \ + li k0,bev + + .set noreorder + + .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 + mtc0 zero, CP0_WATCHHI + + /* WP(Watch Pending), SW0/1 should be cleared. */ + mtc0 zero, CP0_CAUSE + + setup_c0_status_reset + + /* Init Timer */ + mtc0 zero, CP0_COUNT + mtc0 zero, CP0_COMPARE + +#if !defined(CONFIG_BOOTSTRAP_SKIP_LOWLEVEL_INIT) + /* CONFIG0 register */ + li t0, CONF_CM_UNCACHED + mtc0 t0, CP0_CONFIG +#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ + + /* Initialize $gp. + */ + bal 1f + nop + .word _gp +1: + lw gp, 0(ra) + +#if !defined(CONFIG_BOOTSTRAP_SKIP_LOWLEVEL_INIT) + /* Initialize any external memory. + */ + la t9, lowlevel_init + jalr t9 + nop + + /* Initialize caches... + */ + la t9, mips_cache_reset + jalr t9 + nop + + /* ... and enable them. + */ + li t0, CONF_CM_CACHABLE_NONCOHERENT + mtc0 t0, CP0_CONFIG +#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ + + /* 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 +#endif + + li t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET + la sp, 0(t0) + + la t9, bootstrap_board_init_f + jr t9 + nop + +#if defined(_CONFIG_BOOTSTRAP_RELOCATE) +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * a0 = addr_sp + * a1 = gd + * a2 = destination address + */ + .globl relocate_code + .ent relocate_code +relocate_code: + move sp, a0 /* Set new stack pointer */ + + li t0, CONFIG_BOOTSTRAP_TEXT_BASE + la t3, in_ram + lw t2, -12(t3) /* t2 <-- uboot_end_data */ + 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_BOOTSTRAP_TEXT_BASE + add gp, a2 /* gp now adjusted */ + sub s1, gp, t6 /* s1 <-- relocation offset */ + + /* + * 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 + jalr t9 + nop + + /* Jump to where we've relocated ourselves. + */ + addi t0, s2, in_ram - _start + jr t0 + nop + + .word _gp + .word _GLOBAL_OFFSET_TABLE_ + .word uboot_end_data + .word uboot_end + .word num_got_entries + +in_ram: + /* + * Now we want to update GOT. + * + * 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 +1: + lw t1, 0(t4) + beqz t1, 2f + add t1, s1 + sw t1, 0(t4) +2: + addi t2, 1 + blt t2, t3, 1b + addi t4, 4 /* delay slot */ + + /* 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 + + sub t1, 4 +1: + addi t1, 4 + bltl t1, t2, 1b + sw zero, 0(t1) /* delay slot */ + + move a0, s0 /* a0 <-- gd */ + la t9, bootstrap_board_init_r + jr t9 + move a1, s2 /* delay slot */ + + .end relocate_code +#endif + +/* + * void copy_and_jump (void) + * + * This function copies/unzips the u-boot image and runs it. + * This "function" does not return + * +*/ + .globl copy_and_jump + .ent copy_and_jump +copy_and_jump: + + /* copy_uboot(CONFIG_SYS_MONITOR_BASE, payload_uncsize, payload_start, payload_size) */ + li a0, CONFIG_SYS_MONITOR_BASE + la a1, payload_uncsize + lw a1, 0(a1) + la a2, payload_start + la a3, payload_size + la t9, copy_uboot + jalr t9 + lw a3, 0(a3) /* delay slot */ + + li t9, CONFIG_SYS_MONITOR_BASE + jr t9 + nop + + .end copy_and_jump + + /* Exception handlers. + */ +romReserved: + b romReserved + +romExcHandle: + b romExcHandle diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 4e90704..3570581 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -24,6 +24,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).o +BOOTSTRAP_LIB = $(obj)lib$(ARCH)_bootstrap.o + +BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB) SOBJS-y += @@ -35,12 +38,22 @@ COBJS-y += bootm.o endif COBJS-y += time.o -SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += board_bootstrap.o +BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += time.o + +BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y) $(BOOTSTRAP_COBJS-y)) + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) +all: $(LIB) $(BOOTSTRAP_LIB-y) + $(LIB): $(obj).depend $(OBJS) $(call cmd_link_o_target, $(OBJS)) +$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS) + $(call cmd_link_o_target, $(BOOTSTRAP_OBJS)) + ######################################################################### # defines $(obj).depend target diff --git a/arch/mips/lib/board_bootstrap.c b/arch/mips/lib/board_bootstrap.c new file mode 100644 index 0000000..8c1b205 --- /dev/null +++ b/arch/mips/lib/board_bootstrap.c @@ -0,0 +1,331 @@ +/* + * (C) Copyright 2010 Industrie Dial Face S.p.A. + * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +extern int timer_init(void); + +extern int incaip_set_cpuclk(void); + +extern ulong uboot_end_data; +extern ulong uboot_end; + +extern void copy_and_jump(void); + +static char *failed = "*** failed ***\n"; + +/* + * mips_io_port_base is the begin of the address space to which x86 style + * I/O ports are mapped. + */ +unsigned long mips_io_port_base = -1; + +int __board_early_init_f(void) +{ + /* + * Nothing to do in this dummy implementation + */ + return 0; +} + +#if defined(_CONFIG_BOOTSTRAP_FAKEMALLOC) +static void fake_malloc_init(void) +{ + ulong addr; + void *ptr; + uint *status; + uint *count; + + addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; + addr &= ~(4096 - 1); + addr -= TOTAL_MALLOC_LEN; + + status = (void *)addr; + count = (void *)(addr + sizeof(uint)); + + *status = addr + 16; + *count = 0; + + debug ("Init fake memory manager @%08lx total %d\n", addr, TOTAL_MALLOC_LEN - 16); +} + +static void *__fake_malloc(size_t n) +{ + ulong addr; + void *ptr; + uint *status; + uint *count; + + addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; + addr &= ~(4096 - 1); + addr -= TOTAL_MALLOC_LEN; + + status = (uint *)addr; + count = (uint *)(addr + sizeof(uint)); + ptr = (void *)(*status); + + if (!ptr || *count + n> (TOTAL_MALLOC_LEN - 16)) { + /* Memory already used */ + debug ("No enough memory\n"); + + return NULL; + } + + *count += n; + *status += n; + + debug ("Allocate memory @%08lx / %d (available %d)\n", (ulong)ptr, n, TOTAL_MALLOC_LEN - 16 - *count); + + return ptr; +} + +static void __fake_free(void *ptr) +{ + debug ("Free memory @%08lx\n", (ulong)ptr); + + return; +} + +void *malloc(size_t) __attribute__((weak, alias("__fake_malloc"))); +void free(void *) __attribute__((weak, alias("__fake_free"))); +#endif + +int board_early_init_f(void) __attribute__((weak, alias("__board_early_init_f"))); +int bootstrap_board_early_init_f(void) __attribute__((weak, alias("board_early_init_f"))); + +static int bootstrap_init_func_ram (void) +{ + if ((gd->ram_size = bootstrap_initdram (0)) > 0) { + return (0); + } + puts (failed); + return (1); +} + +static int bootstrap_display_banner(void) +{ + puts ("bootstrap..."); + return (0); +} + +static int bootstrap_init_baudrate (void) +{ +#if defined(CONFIG_BOOTSTRAP_BAUDRATE) + gd->baudrate = CONFIG_BOOTSTRAP_BAUDRATE; +#else + gd->baudrate = CONFIG_BAUDRATE; +#endif + return 0; +} + +/* + * Breath some life into the board... + * + * The first part of initialization is running from Flash memory; + * its main purpose is to initialize the RAM so that we + * can relocate the monitor code to RAM. + */ + +/* + * All attempts to come up with a "common" initialization sequence + * that works for all boards and architectures failed: some of the + * requirements are just _too_ different. To get rid of the resulting + * mess of board dependend #ifdef'ed code we now make the whole + * initialization sequence configurable to the user. + * + * The requirements for any new initalization function is simple: it + * receives a pointer to the "global data" structure as it's only + * argument, and returns an integer return code, where 0 means + * "continue" and != 0 means "fatal error, hang the system". + */ +typedef int (init_fnc_t) (void); + +static init_fnc_t *init_sequence[] = { + bootstrap_board_early_init_f, + timer_init, + bootstrap_init_baudrate,/* initialze baudrate settings */ + serial_init, /* serial communications setup */ + bootstrap_display_banner, /* say that we are here */ + bootstrap_checkboard, + bootstrap_init_func_ram, + NULL, +}; + + +void bootstrap_board_init_f(ulong bootflag) +{ + gd_t gd_data, *id; + bd_t *bd; + init_fnc_t **init_fnc_ptr; + ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_BOOTSTRAP_TEXT_BASE; + ulong *s; + + /* Pointer is writable since we allocated a register for it. + */ + gd = &gd_data; + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("": : :"memory"); + + memset ((void *)gd, 0, sizeof (gd_t)); + + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { + if ((*init_fnc_ptr)() != 0) { + bootstrap_hang (); + } + } + + /* + * Now that we have DRAM mapped and working, we can + * relocate the code and continue running from DRAM. + */ + addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; + + /* We can reserve some RAM "on top" here. + */ + + /* round down to next 4 kB limit. + */ + addr &= ~(4096 - 1); + debug ("Top of RAM usable for U-Boot at: %08lx\n", addr); + +#if defined(_CONFIG_BOOTSTRAP_RELOCATE) + /* Reserve memory for U-Boot code, data & bss + * round down to next 16 kB limit + */ + addr -= len; + addr &= ~(16 * 1024 - 1); + + debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr); +#endif + +#if defined(_CONFIG_BOOTSTRAP_MALLOC) + /* Reserve memory for malloc() arena. + */ + addr_sp = addr - TOTAL_MALLOC_LEN; + debug ("Reserving %dk for malloc() at: %08lx\n", + TOTAL_MALLOC_LEN >> 10, addr_sp); +#else + addr_sp = addr; +#endif + +#if defined(_CONFIG_BOOTSTRAP_FAKEMALLOC) + fake_malloc_init(); +#endif + + /* + * (permanently) allocate a Board Info struct + * and a permanent copy of the "global" data + */ + addr_sp -= sizeof(bd_t); + bd = (bd_t *)addr_sp; + gd->bd = bd; + debug ("Reserving %zu Bytes for Board Info at: %08lx\n", + sizeof(bd_t), addr_sp); + + addr_sp -= sizeof(gd_t); + id = (gd_t *)addr_sp; + debug ("Reserving %zu Bytes for Global Data at: %08lx\n", + sizeof (gd_t), addr_sp); + + /* + * Finally, we set up a new (bigger) stack. + * + * Leave some safety gap for SP, force alignment on 16 byte boundary + * Clear initial stack frame + */ + addr_sp -= 16; + addr_sp &= ~0xF; + s = (ulong *)addr_sp; + *s-- = 0; + *s-- = 0; + addr_sp = (ulong)s; + debug ("Stack Pointer at: %08lx\n", addr_sp); + + /* + * Save local variables to board info struct + */ + bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of DRAM memory */ + bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */ + bd->bi_baudrate = gd->baudrate; /* Console Baudrate */ + + memcpy (id, (void *)gd, sizeof (gd_t)); + +#if defined(_CONFIG_BOOTSTRAP_RELOCATE) + relocate_code (addr_sp, id, addr); +#else + copy_and_jump(); +#endif + + /* NOTREACHED - relocate_code() does not return */ +} +/************************************************************************ + * + * This is the next part if the initialization sequence: we are now + * running from RAM and have a "normal" C environment, i. e. global + * data can be written, BSS has been cleared, the stack size in not + * that critical any more, etc. + * + ************************************************************************ + */ + +#if defined(_CONFIG_BOOTSTRAP_RELOCATE) +void bootstrap_board_init_r (gd_t *id, ulong dest_addr) +{ + extern void malloc_bin_reloc (void); + + bd_t *bd; + + gd = id; + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + + debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr); + + gd->reloc_off = dest_addr - CONFIG_BOOTSTRAP_TEXT_BASE; + + bd = gd->bd; + +#if defined(_CONFIG_BOOTSTRAP_MALLOC) && !defined(_CONFIG_BOOTSTRAP_FAKEMALLOC) + /* The Malloc area is immediately below the monitor copy in DRAM */ + mem_malloc_init(CONFIG_BOOTSTRAP_TEXT_BASE + gd->reloc_off - + TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN); + malloc_bin_reloc(); +#endif + + copy_and_jump(); + + /* NOTREACHED - no way out of command loop except booting */ +} +#endif + +void bootstrap_hang (void) +{ + puts ("### ERROR ### Please RESET the board ###\n"); + for (;;); +}