X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Fmips%2Fcpu%2Fstart.S;h=dd93df9e4a1ffe6d089ac2f8199cda9b1d1d0388;hb=2434f58c784e3216b7925fe00ce49c113c6a511e;hp=e95cdca61eba2db1b88700c7d297558a09e405d1;hpb=45fe3809b9923b92f221d70eb45ae071059fd5e0;p=oweals%2Fu-boot.git diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index e95cdca61e..dd93df9e4a 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -1,9 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Startup Code for MIPS32 CPU-core * * Copyright (c) 2003 Wolfgang Denk - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -12,10 +11,6 @@ #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) @@ -38,281 +33,245 @@ # 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 - * 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 + .set noreorder + + .macro init_wr sel + MTC0 zero, CP0_WATCHLO,\sel + mtc0 t1, CP0_WATCHHI,\sel + mfc0 t0, CP0_WATCHHI,\sel + bgez t0, wr_done + nop .endm - .set noreorder + .macro uhi_mips_exception + move k0, t9 # preserve t9 in k0 + move k1, a0 # preserve a0 in k1 + li t9, 15 # UHI exception operation + li a0, 0 # Use hard register context + sdbbp 1 # Invoke UHI operation + .endm + + .macro setup_stack_gd + 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 +#if CONFIG_VAL(SYS_MALLOC_F_LEN) + li t2, CONFIG_VAL(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 + + /* Clear gd */ + move t0, k0 +1: + PTR_S zero, 0(t0) + PTR_ADDIU t0, PTRSIZE + blt t0, t1, 1b + nop + +#if CONFIG_VAL(SYS_MALLOC_F_LEN) + PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset +#endif + .endm ENTRY(_start) - /* U-boot entry point */ + /* U-Boot entry point */ b reset - nop + mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing - .org 0x10 -#if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG) +#if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG) /* - * 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. + * Store some board-specific boot configuration. This is used by some + * MIPS systems like Malta. */ - .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 + .org 0x10 + .word CONFIG_MIPS_BOOT_CONFIG_WORD0 + .word CONFIG_MIPS_BOOT_CONFIG_WORD1 #endif +#if defined(CONFIG_ROM_EXCEPTION_VECTORS) + /* + * Exception vector entry points. When running from ROM, an exception + * cannot be handled. Halt execution and transfer control to debugger, + * if one is attached. + */ .org 0x200 /* TLB refill, 32 bit task */ -1: b 1b - nop + uhi_mips_exception .org 0x280 /* XTLB refill, 64 bit task */ -1: b 1b - nop + uhi_mips_exception .org 0x300 /* Cache error exception */ -1: b 1b - nop + uhi_mips_exception .org 0x380 /* General exception */ -1: b 1b - nop + uhi_mips_exception .org 0x400 /* Catch interrupt exceptions */ -1: b 1b - nop + uhi_mips_exception .org 0x480 /* EJTAG debug exception */ 1: b 1b nop - .align 4 -reset: + .org 0x500 +#endif - /* Clear watch registers */ - MTC0 zero, CP0_WATCHLO - MTC0 zero, CP0_WATCHHI +reset: +#if __mips_isa_rev >= 6 + mfc0 t0, CP0_CONFIG, 5 + and t0, t0, MIPS_CONF5_VP + beqz t0, 1f + nop - /* WP(Watch Pending), SW0/1 should be cleared */ - mtc0 zero, CP0_CAUSE + b 2f + mfc0 t0, CP0_GLOBALNUMBER +#endif - setup_c0_status STATUS_SET 0 +#ifdef CONFIG_ARCH_BMIPS +1: mfc0 t0, CP0_DIAGNOSTIC, 3 + and t0, t0, (1 << 31) +#else +1: mfc0 t0, CP0_EBASE + and t0, t0, EBASE_CPUNUM +#endif - /* Init Timer */ - mtc0 zero, CP0_COUNT - mtc0 zero, CP0_COMPARE + /* Hang if this isn't the first CPU in the system */ +2: beqz t0, 4f + nop +3: wait + b 3b + nop -#ifndef CONFIG_SKIP_LOWLEVEL_INIT - /* CONFIG0 register */ - li t0, CONF_CM_UNCACHED - mtc0 t0, CP0_CONFIG -#endif + /* Init CP0 Status */ +4: mfc0 t0, CP0_STATUS + and t0, ST0_IMPL + or t0, ST0_BEV | ST0_ERL | STATUS_SET + mtc0 t0, CP0_STATUS /* - * 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. + * Check whether CP0 Config1 is implemented. If not continue + * with legacy Watch register initialization. */ - .align PTRLOG - bal 1f + mfc0 t0, CP0_CONFIG + bgez t0, wr_legacy nop - PTR _gp -1: - PTR_L gp, 0(ra) -#ifndef CONFIG_SKIP_LOWLEVEL_INIT - /* Initialize any external memory */ - PTR_LA t9, lowlevel_init - jalr t9 + /* + * Check WR bit in CP0 Config1 to determine if Watch registers + * are implemented. + */ + mfc0 t0, CP0_CONFIG, 1 + andi t0, (1 << 3) + beqz t0, wr_done nop - /* Initialize caches... */ - PTR_LA t9, mips_cache_reset - jalr t9 + /* Clear Watch Status bits and disable watch exceptions */ + li t1, 0x7 # Clear I, R and W conditions + init_wr 0 + init_wr 1 + init_wr 2 + init_wr 3 + init_wr 4 + init_wr 5 + init_wr 6 + init_wr 7 + b wr_done nop - /* ... and enable them */ - li t0, CONFIG_SYS_MIPS_CACHE_MODE - mtc0 t0, CP0_CONFIG -#endif +wr_legacy: + MTC0 zero, CP0_WATCHLO + mtc0 zero, CP0_WATCHHI - /* Set up temporary stack */ - PTR_LI t0, -16 - PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR - and sp, t1, t0 # force 16 byte alignment - PTR_SUB 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 - PTR_LI t2, CONFIG_SYS_MALLOC_F_LEN - PTR_SUB sp, sp, t2 # reserve space for early malloc - and sp, sp, t0 # force 16 byte alignment -#endif - move fp, sp +wr_done: + /* Clear WP, IV and SW interrupts */ + mtc0 zero, CP0_CAUSE - /* Clear gd */ - move t0, k0 -1: - sw zero, 0(t0) - blt t0, t1, 1b - PTR_ADDI t0, 4 + /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ + mtc0 zero, CP0_COMPARE -#ifdef CONFIG_SYS_MALLOC_F_LEN - PTR_ADDU t0, k0, GD_MALLOC_BASE # gd->malloc_base offset - sw sp, 0(t0) +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + mfc0 t0, CP0_CONFIG + and t0, t0, MIPS_CONF_IMPL + or t0, t0, CONF_CM_UNCACHED + mtc0 t0, CP0_CONFIG + ehb #endif - PTR_LA t9, board_init_f - jr t9 - move ra, zero - - END(_start) - -/* - * 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 - */ -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 - - PTR_ADD gp, s1 # adjust gp - - /* - * t0 = source address - * t1 = target address - * t2 = source end address - */ -1: - lw t3, 0(t0) - sw t3, 0(t1) - PTR_ADDU t0, 4 - blt t0, t2, 1b - PTR_ADDU t1, 4 - - /* If caches were enabled, we would have to flush them here. */ - PTR_SUB a1, t1, s2 # a1 <-- size - PTR_LA t9, flush_cache +#ifdef CONFIG_MIPS_CM + PTR_LA t9, mips_cm_map jalr t9 - move a0, s2 # a0 <-- destination address - - /* Jump to where we've relocated ourselves */ - PTR_ADDI t0, s2, in_ram - _start - jr t0 nop +#endif - PTR __rel_dyn_end - PTR __rel_dyn_start - PTR __image_copy_end - PTR _GLOBAL_OFFSET_TABLE_ - PTR 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. - */ - 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_ADDI t8, t8, 2 * PTRSIZE # skipping first two entries - PTR_LI t2, 2 -1: - PTR_L t1, 0(t8) - beqz t1, 2f - PTR_ADD t1, s1 - PTR_S t1, 0(t8) -2: - PTR_ADDI t2, 1 - blt t2, t3, 1b - PTR_ADDI t8, PTRSIZE - - /* 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_ADDI t1, 2 * PTRSIZE +#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM +#ifdef CONFIG_MIPS_SRAM_INIT + /* Initialize the SRAM first */ + PTR_LA t9, mips_sram_init + jalr t9 + nop +#endif -1: - lw t8, -4(t1) # t8 <-- relocation info + /* Set up initial stack and global data */ + setup_stack_gd - PTR_LI t3, MIPS_RELOC - bne t8, t3, 2f # skip non-MIPS_RELOC entries +# ifdef CONFIG_DEBUG_UART + /* Earliest point to set up debug uart */ + PTR_LA t9, debug_uart_init + jalr t9 nop +# endif +#endif - PTR_L t3, -(2 * PTRSIZE)(t1) # t3 <-- location to fix up in FLASH +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD + /* Initialize any external memory */ + PTR_LA t9, lowlevel_init + jalr t9 + nop +# endif - PTR_L t8, 0(t3) # t8 <-- original pointer - PTR_ADD t8, s1 # t8 <-- adjusted pointer + /* Initialize caches... */ + PTR_LA t9, mips_cache_reset + jalr t9 + nop - PTR_ADD t3, s1 # t3 <-- location to fix up in RAM - PTR_S t8, 0(t3) +# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD + /* Initialize any external memory */ + PTR_LA t9, lowlevel_init + jalr t9 + nop +# endif +#endif -2: - blt t1, t2, 1b - PTR_ADDI t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes +#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM + /* Set up initial stack and global data */ + setup_stack_gd - /* - * Clear BSS - * - * GOT is now relocated. Thus __bss_start and __bss_end can be - * accessed directly via $gp. - */ - PTR_LA t1, __bss_start # t1 <-- __bss_start - PTR_LA t2, __bss_end # t2 <-- __bss_end +# ifdef CONFIG_DEBUG_UART + /* Earliest point to set up debug uart */ + PTR_LA t9, debug_uart_init + jalr t9 + nop +# endif +#endif -1: - PTR_S zero, 0(t1) - blt t1, t2, 1b - PTR_ADDI t1, PTRSIZE + move a0, zero # a0 <-- boot_flags = 0 + PTR_LA t9, board_init_f - move a0, s0 # a0 <-- gd - move a1, s2 - PTR_LA t9, board_init_r jr t9 move ra, zero - END(relocate_code) + END(_start)