Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / arch / mips / cpu / mips32 / start.S
diff --git a/qemu/roms/u-boot/arch/mips/cpu/mips32/start.S b/qemu/roms/u-boot/arch/mips/cpu/mips32/start.S
new file mode 100644 (file)
index 0000000..68e59b5
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  Startup Code for MIPS32 CPU-core
+ *
+ *  Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+#ifndef CONFIG_SYS_MIPS_CACHE_MODE
+#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
+#endif
+
+       /*
+        * 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
+
+       .set noreorder
+
+       .globl _start
+       .text
+_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
+
+       .org 0x200
+       /* TLB refill, 32 bit task */
+1:     b       1b
+        nop
+
+       .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
+
+       .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 0 0
+
+       /* Init Timer */
+       mtc0    zero, CP0_COUNT
+       mtc0    zero, CP0_COMPARE
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+       /* CONFIG0 register */
+       li      t0, CONF_CM_UNCACHED
+       mtc0    t0, CP0_CONFIG
+#endif
+
+       /* Initialize $gp */
+       bal     1f
+        nop
+       .word   _gp
+1:
+       lw      gp, 0(ra)
+
+#ifndef CONFIG_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, CONFIG_SYS_MIPS_CACHE_MODE
+       mtc0    t0, CP0_CONFIG
+#endif
+
+       /* Set up temporary stack */
+       li      sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
+
+       la      t9, board_init_f
+       jr      t9
+        nop
+
+/*
+ * 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
+
+       move    s0, a1                  # save gd in s0
+       move    s2, a2                  # save destination address in s2
+
+       li      t0, CONFIG_SYS_MONITOR_BASE
+       sub     s1, s2, t0              # s1 <-- relocation offset
+
+       la      t3, in_ram
+       lw      t2, -12(t3)             # t2 <-- __image_copy_end
+       move    t1, a2
+
+       add     gp, s1                  # adjust gp
+
+       /*
+        * t0 = source address
+        * t1 = target address
+        * t2 = source end address
+        */
+1:
+       lw      t3, 0(t0)
+       sw      t3, 0(t1)
+       addu    t0, 4
+       blt     t0, t2, 1b
+        addu   t1, 4
+
+       /* If caches were enabled, we would have to flush them here. */
+       sub     a1, t1, s2              # a1 <-- size
+       la      t9, flush_cache
+       jalr    t9
+        move   a0, s2                  # a0 <-- destination address
+
+       /* Jump to where we've relocated ourselves */
+       addi    t0, s2, in_ram - _start
+       jr      t0
+        nop
+
+       .word   __rel_dyn_end
+       .word   __rel_dyn_start
+       .word   __image_copy_end
+       .word   _GLOBAL_OFFSET_TABLE_
+       .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      t8, -8(t0)              # t8 <-- _GLOBAL_OFFSET_TABLE_
+       add     t8, s1                  # t8 now holds relocated _G_O_T_
+       addi    t8, t8, 8               # skipping first two entries
+       li      t2, 2
+1:
+       lw      t1, 0(t8)
+       beqz    t1, 2f
+        add    t1, s1
+       sw      t1, 0(t8)
+2:
+       addi    t2, 1
+       blt     t2, t3, 1b
+        addi   t8, 4
+
+       /* Update dynamic relocations */
+       lw      t1, -16(t0)             # t1 <-- __rel_dyn_start
+       lw      t2, -20(t0)             # t2 <-- __rel_dyn_end
+
+       b       2f                      # skip first reserved entry
+        addi   t1, 8
+
+1:
+       lw      t8, -4(t1)              # t8 <-- relocation info
+
+       li      t3, 3
+       bne     t8, t3, 2f              # skip non R_MIPS_REL32 entries
+        nop
+
+       lw      t3, -8(t1)              # t3 <-- location to fix up in FLASH
+
+       lw      t8, 0(t3)               # t8 <-- original pointer
+       add     t8, s1                  # t8 <-- adjusted pointer
+
+       add     t3, s1                  # t3 <-- location to fix up in RAM
+       sw      t8, 0(t3)
+
+2:
+       blt     t1, t2, 1b
+        addi   t1, 8                   # each rel.dyn entry is 8 bytes
+
+       /*
+        * Clear BSS
+        *
+        * GOT is now relocated. Thus __bss_start and __bss_end can be
+        * accessed directly via $gp.
+        */
+       la      t1, __bss_start         # t1 <-- __bss_start
+       la      t2, __bss_end           # t2 <-- __bss_end
+
+1:
+       sw      zero, 0(t1)
+       blt     t1, t2, 1b
+        addi   t1, 4
+
+       move    a0, s0                  # a0 <-- gd
+       la      t9, board_init_r
+       jr      t9
+        move   a1, s2
+
+       .end    relocate_code