diff options
Diffstat (limited to 'libgloss/mips/boot/reset.S')
-rw-r--r-- | libgloss/mips/boot/reset.S | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/libgloss/mips/boot/reset.S b/libgloss/mips/boot/reset.S new file mode 100644 index 0000000..37c674d --- /dev/null +++ b/libgloss/mips/boot/reset.S @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + + .set push + MIPS_NOMICROMIPS + +LEAF(__reset_vector) + lui k1, %hi(__cpu_init) + addiu k1, %lo(__cpu_init) + mtc0 zero, C0_COUNT /* Clear CP0 Count (Used to measure boot time.) */ + jr k1 + .space 32 /* Just to cope with a quirk of MIPS malta boards */ + /* this can be deleted for anything else */ +END(__reset_vector) + .set pop + +LEAF(__cpu_init) + + /* + * Verify the code is here due to a reset and not NMI. If this is an NMI then trigger + * a debugger breakpoint using a sdbbp instruction. + */ + + mfc0 k1, C0_STATUS + ext k1, k1, SR_NMI_SHIFT, 1 + beqz k1, $Lnot_nmi + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ + +$Lnot_nmi: + + /* Init CP0 Status, Count, Compare, Watch*, and Cause */ + jal __init_cp0 + + /* + * Initialise L2/L3 cache + * This could be done from cached code if there is a cca override or similar + */ + jal __init_l23cache + /* Save the L2 config register */ + move s0, a0 + + /* Initialize the L1 instruction cache */ + jal __init_icache + + /* + * The changing of Kernel mode cacheability must be done from KSEG1 + * Since the code is executing from KSEG0 it needs to do a jump to KSEG1, change K0 + * and jump back to KSEG0. + */ + + lui a2, %hi(__change_k0_cca) + addiu a2, a2, %lo(__change_k0_cca) + li a1, 0xf + ins a2, a1, 29, 1 /* changed to KSEG1 address by setting bit 29 */ + jalr a2 + + .weak __init_l23cache_cached + lui a2, %hi(__init_l23cache_cached) + addiu a2, a2, %lo(__init_l23cache_cached) + beqz a2, 1f + /* Pass in the L2 config register */ + move a0, s0 + jalr a2 +1: + /* Initialize the L1 data cache */ + jal __init_dcache + + /* Initialize the TLB */ + jal __init_tlb + + /* Allow everything else to be initialized via a hook */ + .weak __boot_init_hook + lui a2, %hi(__boot_init_hook) + addiu a2, a2, %lo(__boot_init_hook) + beqz a2, 1f + jalr a2 +1: + /* Skip copy to ram when executing in place */ + .weak __xip + lui a1, %hi(__xip) + addiu a1, a1, %lo(__xip) + bnez a1, $Lcopy_to_ram_done + /* Copy code and data to RAM */ + li s1, 0xffffffff + + /* Copy code and read-only/initialized data from FLASH to (uncached) RAM */ + lui a1, %hi(__flash_app_start) + addiu a1, a1, %lo(__flash_app_start) + ins a1, s1, 29, 1 /* Make it uncached (kseg1) */ + lui a2, %hi(__app_start) + addiu a2, a2, %lo(__app_start) + ins a2, s1, 29, 1 /* Make it uncached (kseg1) */ + lui a3, %hi(_edata) + addiu a3, a3, %lo(_edata) + ins a3, s1, 29, 1 /* Make it uncached (kseg1) */ + beq a2, a3, $Lcopy_to_ram_done +$Lnext_ram_word: + lw a0, 0(a1) + addiu a2, a2, 4 + addiu a1, a1, 4 + sw a0, -4(a2) + bne a3, a2, $Lnext_ram_word +$Lcopy_to_ram_done: + + # Prepare for eret to _start + lui ra, %hi($Lall_done) /* If main returns then go to all_done */ + addiu ra, ra, %lo($Lall_done) + lui t0, %hi(_start) + addiu t0, t0, %lo(_start) + mtc0 t0, C0_ERRPC /* Set ErrorEPC to _start */ + ehb + li a0, 0 /* UHI compliant null argument setup */ + + /* Return from exception will now execute the application startup code */ + eret + +$Lall_done: + /* Allow an exit hook to intercept the end of execution */ + .weak __boot_exit_hook + lui a2, %hi(__boot_exit_hook) + addiu a2, a2, %lo(__boot_exit_hook) + beqz a2, 1f + jalr a2 +1: + /* + * If _start returns it will return to this point. + * Just spin here reporting the exit. + */ + li t9, 1 /* UHI exit operation */ + move a0, va0 /* Collect exit code for UHI exit */ + sdbbp 1 /* Invoke UHI operation */ + b $Lall_done +END(__cpu_init) + +/************************************************************************************** + B O O T E X C E P T I O N H A N D L E R S (CP0 Status[BEV] = 1) +**************************************************************************************/ +/* NOTE: the linker script must insure that this code starts at start + 0x200 so the exception */ +/* vectors will be addressed properly. */ + +/* TLB refill, 32 bit task. */ +.org 0x200 +LEAF(__boot_tlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_tlb_refill) + +/* XTLB refill, 64 bit task. */ +.org 0x280 +LEAF(__boot_xtlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_xtlb_refill) + +/* Cache error exception. */ +.org 0x300 +LEAF(__boot_cache_error) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_cache_error) + +/* General exception. */ +.org 0x380 +LEAF(__boot_general_exception) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_general_exception) + +# If you want the above code to fit into 1k flash you will need to leave out the +# code below. This is the code that covers the debug exception which you normally will not get. + +/* EJTAG Debug */ +.org 0x480 +LEAF(__boot_debug_exception) + PTR_MFC0 k1, C0_DEPC + PTR_MTC0 k1, C0_DESAVE + lui k1, %hi(1f) + addiu k1, %lo(1f) + PTR_MTC0 k1, C0_DEPC + ehb + deret +1: wait + b 1b /* Stay here */ +END(__boot_debug_exception) |