2018-05-06 21:58:06 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
2003-03-27 12:09:35 +00:00
|
|
|
/*
|
|
|
|
* Startup Code for MIPS32 CPU-core
|
|
|
|
*
|
|
|
|
* Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
|
|
|
|
*/
|
|
|
|
|
2010-10-26 12:34:52 +00:00
|
|
|
#include <asm-offsets.h>
|
2003-03-27 12:09:35 +00:00
|
|
|
#include <config.h>
|
2015-01-29 10:04:08 +00:00
|
|
|
#include <asm/asm.h>
|
2003-03-27 12:09:35 +00:00
|
|
|
#include <asm/regdef.h>
|
|
|
|
#include <asm/mipsregs.h>
|
2022-05-25 16:16:03 +00:00
|
|
|
#include <system-constants.h>
|
2015-01-18 21:18:38 +00:00
|
|
|
|
2015-01-29 10:04:09 +00:00
|
|
|
#ifdef CONFIG_32BIT
|
2015-01-29 10:04:10 +00:00
|
|
|
# define STATUS_SET 0
|
2015-01-29 10:04:09 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_64BIT
|
2015-01-29 10:04:10 +00:00
|
|
|
# define STATUS_SET ST0_KX
|
2015-01-29 10:04:09 +00:00
|
|
|
#endif
|
|
|
|
|
2003-03-27 12:09:35 +00:00
|
|
|
.set noreorder
|
|
|
|
|
2016-02-07 23:37:59 +00:00
|
|
|
.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
|
|
|
|
|
2016-02-07 18:39:58 +00:00
|
|
|
.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
|
|
|
|
|
2016-09-25 16:36:38 +00:00
|
|
|
.macro setup_stack_gd
|
|
|
|
li t0, -16
|
2022-05-25 16:16:03 +00:00
|
|
|
PTR_LI t1, SYS_INIT_SP_ADDR
|
2016-09-25 16:36:38 +00:00
|
|
|
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
|
2023-09-26 14:14:27 +00:00
|
|
|
#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \
|
2020-04-21 07:28:33 +00:00
|
|
|
!CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
|
2017-07-24 09:45:27 +00:00
|
|
|
li t2, CONFIG_VAL(SYS_MALLOC_F_LEN)
|
2016-09-25 16:36:38 +00:00
|
|
|
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)
|
mips: start.S: avoid overwriting outside gd when clearing global data in stack
When setting up initial stack, global data will also be put in the stack,
and being cleared.
The assembler instructions for clearing gd is as follows:
move t0, k0
1:
PTR_S zero, 0(t0)
blt t0, t1, 1b
PTR_ADDIU t0, PTRSIZE
t0 is the start address of gd, t1 is the end address of gd (t0 + GD_SIZE).
[PTR_ADDIU t0, PTRSIZE] is in the delay slot of [blt t0, t1, 1b], so it
will be executed before the branch operation.
However the comparison for the BLT instruction is done before executing the
delay slot. This means when the last word just before k1 is cleared, the
loop will continue to run once. This will clear an extra word at k1, which
is outside the global data.
Global data is placed at the top of the stack. If the initial stack is a
SRAM or locked cache, the area outside them may be inaccessible. A write
operation performed in this area may cause an exception.
To solve this, [PTR_ADDIU t0, PTRSIZE] should be placed before the BLT
instruction.
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Stefan Roese <sr@denx.de>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
2020-04-21 07:28:28 +00:00
|
|
|
PTR_ADDIU t0, PTRSIZE
|
2016-09-25 16:36:38 +00:00
|
|
|
blt t0, t1, 1b
|
mips: start.S: avoid overwriting outside gd when clearing global data in stack
When setting up initial stack, global data will also be put in the stack,
and being cleared.
The assembler instructions for clearing gd is as follows:
move t0, k0
1:
PTR_S zero, 0(t0)
blt t0, t1, 1b
PTR_ADDIU t0, PTRSIZE
t0 is the start address of gd, t1 is the end address of gd (t0 + GD_SIZE).
[PTR_ADDIU t0, PTRSIZE] is in the delay slot of [blt t0, t1, 1b], so it
will be executed before the branch operation.
However the comparison for the BLT instruction is done before executing the
delay slot. This means when the last word just before k1 is cleared, the
loop will continue to run once. This will clear an extra word at k1, which
is outside the global data.
Global data is placed at the top of the stack. If the initial stack is a
SRAM or locked cache, the area outside them may be inaccessible. A write
operation performed in this area may cause an exception.
To solve this, [PTR_ADDIU t0, PTRSIZE] should be placed before the BLT
instruction.
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Stefan Roese <sr@denx.de>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
2020-04-21 07:28:28 +00:00
|
|
|
nop
|
2016-09-25 16:36:38 +00:00
|
|
|
|
2023-09-26 14:14:27 +00:00
|
|
|
#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \
|
2020-04-21 07:28:33 +00:00
|
|
|
!CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
|
2016-09-25 16:36:38 +00:00
|
|
|
PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset
|
|
|
|
#endif
|
|
|
|
.endm
|
|
|
|
|
2015-12-19 19:20:45 +00:00
|
|
|
ENTRY(_start)
|
2020-10-28 14:09:59 +00:00
|
|
|
/*
|
|
|
|
* U-Boot entry point.
|
|
|
|
* Do not add instructions to the branch delay slot! Some SoC's
|
|
|
|
* like Octeon might patch the final U-Boot binary at this location
|
|
|
|
* with additional boot headers.
|
|
|
|
*/
|
2013-02-12 21:22:12 +00:00
|
|
|
b reset
|
2020-10-28 14:09:59 +00:00
|
|
|
nop
|
2013-02-12 21:22:12 +00:00
|
|
|
|
2018-09-07 17:18:44 +00:00
|
|
|
#if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
|
2011-07-27 11:22:37 +00:00
|
|
|
/*
|
2018-09-07 17:18:44 +00:00
|
|
|
* Store some board-specific boot configuration. This is used by some
|
|
|
|
* MIPS systems like Malta.
|
2011-07-27 11:22:37 +00:00
|
|
|
*/
|
2016-02-14 17:52:57 +00:00
|
|
|
.org 0x10
|
2018-09-07 17:18:44 +00:00
|
|
|
.word CONFIG_MIPS_BOOT_CONFIG_WORD0
|
|
|
|
.word CONFIG_MIPS_BOOT_CONFIG_WORD1
|
2003-03-27 12:09:35 +00:00
|
|
|
#endif
|
2003-06-27 21:31:46 +00:00
|
|
|
|
2016-02-14 17:52:57 +00:00
|
|
|
#if defined(CONFIG_ROM_EXCEPTION_VECTORS)
|
2016-02-07 18:39:58 +00:00
|
|
|
/*
|
|
|
|
* Exception vector entry points. When running from ROM, an exception
|
|
|
|
* cannot be handled. Halt execution and transfer control to debugger,
|
|
|
|
* if one is attached.
|
|
|
|
*/
|
2013-02-12 21:22:12 +00:00
|
|
|
.org 0x200
|
|
|
|
/* TLB refill, 32 bit task */
|
2016-02-07 18:39:58 +00:00
|
|
|
uhi_mips_exception
|
2013-02-12 21:22:12 +00:00
|
|
|
|
|
|
|
.org 0x280
|
|
|
|
/* XTLB refill, 64 bit task */
|
2016-02-07 18:39:58 +00:00
|
|
|
uhi_mips_exception
|
2013-02-12 21:22:12 +00:00
|
|
|
|
|
|
|
.org 0x300
|
|
|
|
/* Cache error exception */
|
2016-02-07 18:39:58 +00:00
|
|
|
uhi_mips_exception
|
2013-02-12 21:22:12 +00:00
|
|
|
|
|
|
|
.org 0x380
|
|
|
|
/* General exception */
|
2016-02-07 18:39:58 +00:00
|
|
|
uhi_mips_exception
|
2013-02-12 21:22:12 +00:00
|
|
|
|
|
|
|
.org 0x400
|
|
|
|
/* Catch interrupt exceptions */
|
2016-02-07 18:39:58 +00:00
|
|
|
uhi_mips_exception
|
2013-02-12 21:22:12 +00:00
|
|
|
|
|
|
|
.org 0x480
|
|
|
|
/* EJTAG debug exception */
|
|
|
|
1: b 1b
|
|
|
|
nop
|
|
|
|
|
2016-02-14 17:52:57 +00:00
|
|
|
.org 0x500
|
|
|
|
#endif
|
|
|
|
|
2003-03-27 12:09:35 +00:00
|
|
|
reset:
|
2020-10-28 14:09:59 +00:00
|
|
|
mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
|
2016-09-21 13:59:54 +00:00
|
|
|
#if __mips_isa_rev >= 6
|
|
|
|
mfc0 t0, CP0_CONFIG, 5
|
|
|
|
and t0, t0, MIPS_CONF5_VP
|
|
|
|
beqz t0, 1f
|
|
|
|
nop
|
|
|
|
|
|
|
|
b 2f
|
|
|
|
mfc0 t0, CP0_GLOBALNUMBER
|
|
|
|
#endif
|
|
|
|
|
2017-04-24 22:39:20 +00:00
|
|
|
#ifdef CONFIG_ARCH_BMIPS
|
|
|
|
1: mfc0 t0, CP0_DIAGNOSTIC, 3
|
|
|
|
and t0, t0, (1 << 31)
|
|
|
|
#else
|
2016-09-21 13:59:54 +00:00
|
|
|
1: mfc0 t0, CP0_EBASE
|
2020-07-11 23:46:18 +00:00
|
|
|
and t0, t0, MIPS_EBASE_CPUNUM
|
2017-04-24 22:39:20 +00:00
|
|
|
#endif
|
2016-09-21 13:59:54 +00:00
|
|
|
|
|
|
|
/* Hang if this isn't the first CPU in the system */
|
|
|
|
2: beqz t0, 4f
|
|
|
|
nop
|
|
|
|
3: wait
|
|
|
|
b 3b
|
|
|
|
nop
|
2003-03-27 12:09:35 +00:00
|
|
|
|
2016-02-07 23:37:59 +00:00
|
|
|
/* Init CP0 Status */
|
|
|
|
4: mfc0 t0, CP0_STATUS
|
|
|
|
and t0, ST0_IMPL
|
|
|
|
or t0, ST0_BEV | ST0_ERL | STATUS_SET
|
|
|
|
mtc0 t0, CP0_STATUS
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check whether CP0 Config1 is implemented. If not continue
|
|
|
|
* with legacy Watch register initialization.
|
|
|
|
*/
|
|
|
|
mfc0 t0, CP0_CONFIG
|
|
|
|
bgez t0, wr_legacy
|
|
|
|
nop
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
|
wr_legacy:
|
|
|
|
MTC0 zero, CP0_WATCHLO
|
2016-01-09 21:24:47 +00:00
|
|
|
mtc0 zero, CP0_WATCHHI
|
2003-03-27 12:09:35 +00:00
|
|
|
|
2016-02-07 23:37:59 +00:00
|
|
|
wr_done:
|
|
|
|
/* Clear WP, IV and SW interrupts */
|
2008-03-25 12:30:07 +00:00
|
|
|
mtc0 zero, CP0_CAUSE
|
|
|
|
|
2016-02-07 23:37:59 +00:00
|
|
|
/* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
|
2003-03-27 12:09:35 +00:00
|
|
|
mtc0 zero, CP0_COMPARE
|
|
|
|
|
2020-07-11 22:45:57 +00:00
|
|
|
#ifdef CONFIG_MIPS_CACHE_DISABLE
|
2020-07-11 22:45:56 +00:00
|
|
|
/* Disable caches */
|
|
|
|
PTR_LA t9, mips_cache_disable
|
|
|
|
jalr t9
|
|
|
|
nop
|
2011-05-06 15:18:13 +00:00
|
|
|
#endif
|
2003-03-27 12:09:35 +00:00
|
|
|
|
2016-09-21 10:18:53 +00:00
|
|
|
#ifdef CONFIG_MIPS_CM
|
|
|
|
PTR_LA t9, mips_cm_map
|
|
|
|
jalr t9
|
|
|
|
nop
|
|
|
|
#endif
|
|
|
|
|
2016-06-04 14:13:21 +00:00
|
|
|
#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM
|
2020-04-21 07:28:27 +00:00
|
|
|
#ifdef CONFIG_MIPS_SRAM_INIT
|
|
|
|
/* Initialize the SRAM first */
|
|
|
|
PTR_LA t9, mips_sram_init
|
|
|
|
jalr t9
|
|
|
|
nop
|
|
|
|
#endif
|
|
|
|
|
2016-06-04 14:13:21 +00:00
|
|
|
/* Set up initial stack and global data */
|
|
|
|
setup_stack_gd
|
2017-04-24 17:03:34 +00:00
|
|
|
|
|
|
|
# ifdef CONFIG_DEBUG_UART
|
|
|
|
/* Earliest point to set up debug uart */
|
|
|
|
PTR_LA t9, debug_uart_init
|
|
|
|
jalr t9
|
|
|
|
nop
|
|
|
|
# endif
|
2016-06-04 14:13:21 +00:00
|
|
|
#endif
|
|
|
|
|
2021-08-28 01:18:30 +00:00
|
|
|
#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
|
2016-09-21 10:18:51 +00:00
|
|
|
# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
2011-05-06 15:18:13 +00:00
|
|
|
/* Initialize any external memory */
|
2015-01-29 10:04:08 +00:00
|
|
|
PTR_LA t9, lowlevel_init
|
2007-10-27 06:27:06 +00:00
|
|
|
jalr t9
|
2011-05-06 15:18:13 +00:00
|
|
|
nop
|
2016-09-21 10:18:51 +00:00
|
|
|
# endif
|
2020-07-11 22:45:57 +00:00
|
|
|
#endif
|
2003-03-27 12:09:35 +00:00
|
|
|
|
2020-06-30 10:33:16 +00:00
|
|
|
#ifdef CONFIG_MIPS_MACH_EARLY_INIT
|
|
|
|
bal mips_mach_early_init
|
|
|
|
nop
|
|
|
|
#endif
|
|
|
|
|
2020-07-11 22:45:57 +00:00
|
|
|
#ifdef CONFIG_MIPS_CACHE_SETUP
|
2011-05-06 15:18:13 +00:00
|
|
|
/* Initialize caches... */
|
2015-01-29 10:04:08 +00:00
|
|
|
PTR_LA t9, mips_cache_reset
|
2007-10-27 06:27:06 +00:00
|
|
|
jalr t9
|
2011-05-06 15:18:13 +00:00
|
|
|
nop
|
2020-07-11 22:45:57 +00:00
|
|
|
#endif
|
2016-09-21 10:18:51 +00:00
|
|
|
|
2021-08-28 01:18:30 +00:00
|
|
|
#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
|
2016-09-21 10:18:51 +00:00
|
|
|
# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
|
|
|
/* Initialize any external memory */
|
|
|
|
PTR_LA t9, lowlevel_init
|
|
|
|
jalr t9
|
|
|
|
nop
|
|
|
|
# endif
|
2011-05-06 15:18:13 +00:00
|
|
|
#endif
|
2003-03-27 12:09:35 +00:00
|
|
|
|
2016-06-04 14:13:21 +00:00
|
|
|
#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM
|
2016-09-25 16:36:38 +00:00
|
|
|
/* Set up initial stack and global data */
|
|
|
|
setup_stack_gd
|
2017-04-24 17:03:34 +00:00
|
|
|
|
|
|
|
# ifdef CONFIG_DEBUG_UART
|
|
|
|
/* Earliest point to set up debug uart */
|
|
|
|
PTR_LA t9, debug_uart_init
|
|
|
|
jalr t9
|
|
|
|
nop
|
|
|
|
# endif
|
2016-06-04 14:13:21 +00:00
|
|
|
#endif
|
2016-01-09 21:24:47 +00:00
|
|
|
|
2016-01-21 14:32:51 +00:00
|
|
|
move a0, zero # a0 <-- boot_flags = 0
|
2015-01-29 10:04:08 +00:00
|
|
|
PTR_LA t9, board_init_f
|
2016-02-07 18:39:58 +00:00
|
|
|
|
2008-04-17 14:35:13 +00:00
|
|
|
jr t9
|
2014-11-20 22:55:32 +00:00
|
|
|
move ra, zero
|
2003-03-27 12:09:35 +00:00
|
|
|
|
2015-12-19 19:20:45 +00:00
|
|
|
END(_start)
|