Signed-off-by: Luigi 'Comio' Mantellini <luigi.mantell...@idf-hit.com>
---
 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, <w...@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 <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+
+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, <w...@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 <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+
+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 <luigi.mantell...@idf-hit.com>
+ *
+ *  Copyright (c) 2003 Wolfgang Denk <w...@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 <asm-offsets.h>
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <bootstrap.h>
+
+       /*
+        * 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.mantell...@idf-hit.com
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, w...@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 <common.h>
+#include <bootstrap.h>
+#include <malloc.h>
+
+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 (;;);
+}
-- 
1.7.3

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to