diff options
Diffstat (limited to 'arch/mips/mach-mtmips/mt7621/spl/start.S')
-rw-r--r-- | arch/mips/mach-mtmips/mt7621/spl/start.S | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/arch/mips/mach-mtmips/mt7621/spl/start.S b/arch/mips/mach-mtmips/mt7621/spl/start.S new file mode 100644 index 0000000000..3cad3567e7 --- /dev/null +++ b/arch/mips/mach-mtmips/mt7621/spl/start.S @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 MediaTek Inc. All rights reserved. + * + * Author: Weijie Gao <weijie.gao@mediatek.com> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/cacheops.h> +#include <asm/addrspace.h> +#include <asm/mipsmtregs.h> +#include <asm/cm.h> +#include "../mt7621.h" +#include "dram.h" + +#ifndef CONFIG_SYS_INIT_SP_ADDR +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \ + CONFIG_SYS_INIT_SP_OFFSET) +#endif + +#define SP_ADDR_TEMP 0xbe10dff0 + + .macro init_wr sel + MTC0 zero, CP0_WATCHLO,\sel + mtc0 t1, CP0_WATCHHI,\sel + .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) && \ + !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) + 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) && \ + !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) + PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset +#endif + .endm + + .set noreorder + +ENTRY(_start) + b 1f + mtc0 zero, CP0_COUNT + + /* Stage header required by BootROM */ + .org 0x8 + .word 0 # ep, filled by mkimage + .word 0 # stage_size, filled by mkimage + .word 0 # has_stage2 + .word 0 # next_ep + .word 0 # next_size + .word 0 # next_offset + +1: + /* Init CP0 Status */ + mfc0 t0, CP0_STATUS + and t0, ST0_IMPL + or t0, ST0_BEV | ST0_ERL + mtc0 t0, CP0_STATUS + ehb + + /* 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 + + /* Clear WP, IV and SW interrupts */ + mtc0 zero, CP0_CAUSE + + /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ + mtc0 zero, CP0_COMPARE + + /* VPE1 goes to wait code directly */ + mfc0 t0, CP0_TCBIND + andi t0, TCBIND_CURVPE + bnez t0, launch_vpe_entry + nop + + /* Core1 goes to specific launch entry */ + PTR_LI t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) + lw t1, GCR_Cx_ID(t0) + bnez t1, launch_core_entry + nop + + /* MT7530 reset */ + li t0, KSEG1ADDR(SYSCTL_BASE) + lw t1, SYSCTL_RSTCTL_REG(t0) + ori t1, MCM_RST + sw t1, SYSCTL_RSTCTL_REG(t0) + + /* Disable DMA route for PSE SRAM set by BootROM */ + PTR_LI t0, KSEG1ADDR(DMA_CFG_ARB_BASE) + sw zero, DMA_ROUTE_REG(t0) + + /* Set CPU clock to 500MHz (Required if boot from NAND) */ + li t0, KSEG1ADDR(SYSCTL_BASE) + lw t1, SYSCTL_CLKCFG0_REG(t0) + ins t1, zero, 30, 2 # CPU_CLK_SEL + sw t1, SYSCTL_CLKCFG0_REG(t0) + + /* Set CPU clock divider to 1/1 */ + li t0, KSEG1ADDR(RBUS_BASE) + li t1, 0x101 + sw t1, RBUS_DYN_CFG0_REG(t0) + + /* (Re-)initialize the SRAM */ + bal mips_sram_init + nop + + /* Set up temporary stack */ + li sp, SP_ADDR_TEMP + + /* Setup full CPS */ + bal mips_cm_map + nop + + bal mt7621_cps_init + nop + + /* Prepare for CPU/DDR initialization binary blob */ + bal prepare_stage_bin + nop + + /* Call CPU/DDR initialization binary blob */ + li t9, STAGE_LOAD_ADDR + jalr t9 + nop + + /* Switch CPU PLL source */ + li t0, KSEG1ADDR(SYSCTL_BASE) + lw t1, SYSCTL_CLKCFG0_REG(t0) + li t2, 1 + ins t1, t2, CPU_CLK_SEL_S, 2 + sw t1, SYSCTL_CLKCFG0_REG(t0) + + /* + * Currently SPL is running on locked L2 cache (on KSEG0). + * To reset the entire cache, we have to writeback SPL to DRAM first. + * Cache flush won't work here. Use memcpy instead. + */ + + la a0, __text_start + move a1, a0 + la a2, __image_copy_end + sub a2, a2, a1 + li a3, 5 + ins a0, a3, 29, 3 # convert to KSEG1 + + bal memcpy + nop + + /* Disable caches */ + bal mips_cache_disable + nop + + /* Reset caches */ + bal mips_cache_reset + nop + + /* Disable SRAM */ + li t0, KSEG1ADDR(FE_BASE) + li t1, FE_PSE_RESET + sw t1, FE_RST_GLO_REG(t0) + + /* Clear the .bss section */ + la a0, __bss_start + la a1, __bss_end +1: sw zero, 0(a0) + addiu a0, 4 + ble a0, a1, 1b + nop + + /* Set up initial stack and global data */ + setup_stack_gd + +#if CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) + /* Set malloc base */ + li t0, (CONFIG_SYS_INIT_SP_ADDR + 15) & (~15) + PTR_S t0, GD_MALLOC_BASE(k0) # gd->malloc_base offset +#endif + +#if defined(CONFIG_DEBUG_UART) && defined(CONFIG_SPL_SERIAL) + /* Earliest point to set up debug uart */ + bal debug_uart_init + nop +#endif + + /* Setup timer */ + bal set_timer_freq_simple + nop + + /* Bootup secondary CPUs */ + bal secondary_cpu_init + nop + + move a0, zero # a0 <-- boot_flags = 0 + bal board_init_f + move ra, zero + + END(_start) |