zephyr/arch/arc/core/reset.S
Yuguo Zou d04ff1af7c arch: arc: Restore MPU registers to its initial states between tests
EMSK boards can't be reset between tests due to hardware configures.
MPU v3 configs in previous test could cause exceptions in the following
tests. This commit fixes this issue by restoring MPU registers initial
states at early init stage.

Signed-off-by: Yuguo Zou <yuguo.zou@synopsys.com>
2020-10-02 11:31:34 +02:00

213 lines
4.5 KiB
ArmAsm

/*
* Copyright (c) 2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Reset handler
*
* Reset handler that prepares the system for running C code.
*/
#include <toolchain.h>
#include <linker/sections.h>
#include <arch/cpu.h>
#include <swap_macros.h>
GDATA(z_interrupt_stacks)
GDATA(z_main_stack)
GDATA(_VectorTable)
/* use one of the available interrupt stacks during init */
#define INIT_STACK z_interrupt_stacks
#define INIT_STACK_SIZE CONFIG_ISR_STACK_SIZE
GTEXT(__reset)
GTEXT(__start)
/**
*
* @brief Reset vector
*
* Ran when the system comes out of reset. The processor is at supervisor level.
*
* Locking interrupts prevents anything from interrupting the CPU.
*
* When these steps are completed, jump to _PrepC(), which will finish setting
* up the system for running C code.
*
* @return N/A
*/
SECTION_FUNC(TEXT,__reset)
SECTION_FUNC(TEXT,__start)
/* lock interrupts: will get unlocked when switch to main task
* also make sure the processor in the correct status
*/
mov_s r0, 0
kflag r0
#ifdef CONFIG_ARC_SECURE_FIRMWARE
sflag r0
#endif
#if defined(CONFIG_BOOT_TIME_MEASUREMENT) && defined(CONFIG_ARCV2_TIMER)
/*
* ARCV2 timer (timer0) is a free run timer, let it start to count
* here.
*/
mov_s r0, 0xffffffff
sr r0, [_ARC_V2_TMR0_LIMIT]
mov_s r0, 0
sr r0, [_ARC_V2_TMR0_COUNT]
#endif
/* interrupt related init */
#ifndef CONFIG_ARC_NORMAL_FIRMWARE
/* IRQ_ACT and IRQ_CTRL should be initialized and set in secure mode */
sr r0, [_ARC_V2_AUX_IRQ_ACT]
sr r0, [_ARC_V2_AUX_IRQ_CTRL]
#endif
sr r0, [_ARC_V2_AUX_IRQ_HINT]
/* set the vector table base early,
* so that exception vectors can be handled.
*/
mov_s r0, _VectorTable
#ifdef CONFIG_ARC_SECURE_FIRMWARE
sr r0, [_ARC_V2_IRQ_VECT_BASE_S]
#else
sr r0, [_ARC_V2_IRQ_VECT_BASE]
#endif
#if defined(CONFIG_USERSPACE)
lr r0, [_ARC_V2_STATUS32]
bset r0, r0, _ARC_V2_STATUS32_US_BIT
kflag r0
#endif
#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
lr r0, [_ARC_V2_STATUS32]
bset r0, r0, _ARC_V2_STATUS32_AD_BIT
kflag r0
#endif
mov_s r1, 1
invalidate_and_disable_icache:
lr r0, [_ARC_V2_I_CACHE_BUILD]
and.f r0, r0, 0xff
bz.nd invalidate_dcache
mov_s r2, 0
sr r2, [_ARC_V2_IC_IVIC]
/* writing to IC_IVIC needs 3 NOPs */
nop_s
nop_s
nop_s
sr r1, [_ARC_V2_IC_CTRL]
invalidate_dcache:
lr r3, [_ARC_V2_D_CACHE_BUILD]
and.f r3, r3, 0xff
bz.nd done_cache_invalidate
sr r1, [_ARC_V2_DC_IVDC]
done_cache_invalidate:
/*
* ARC Custom Initialization
* For scenarios where board hardware is not re-initialized between tests,
* some settings need to be restored to its default initial states as a
* substitution of normal hardware reset sequence.
*/
#if defined(CONFIG_ARC_CUSTOM_INIT)
/* Set MPU (v3) registers to default */
#if CONFIG_ARC_MPU_VER == 3
/* Set default reset value to _ARC_V2_MPU_EN register */
#define ARC_MPU_EN_RESET_VALUE 0x400181C0
mov_s r1, ARC_MPU_EN_RESET_VALUE
sr r1, [_ARC_V2_MPU_EN]
/* Get MPU region numbers */
lr r3, [_ARC_V2_MPU_BUILD]
lsr_s r3, r3, 8
and r3, r3, 0xff
mov_s r1, 0
mov_s r2, 0
/* Set all MPU regions by iterating index */
mpu_regions_reset:
brge r2, r3, done_mpu_regions_reset
sr r2, [_ARC_V2_MPU_INDEX]
sr r1, [_ARC_V2_MPU_RSTART]
sr r1, [_ARC_V2_MPU_REND]
sr r1, [_ARC_V2_MPU_RPER]
add_s r2, r2, 1
b_s mpu_regions_reset
done_mpu_regions_reset:
#endif
#endif
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP_STATES) && \
!defined(CONFIG_BOOTLOADER_CONTEXT_RESTORE)
jl @_sys_resume_from_deep_sleep
#endif
#if defined(CONFIG_SMP) || CONFIG_MP_NUM_CPUS > 1
_get_cpu_id r0
breq r0, 0, _master_core_startup
/*
* Non-masters wait for master core (core 0) to boot enough
*/
_slave_core_wait:
#if CONFIG_MP_NUM_CPUS == 1
kflag 1
#endif
ld r1, [arc_cpu_wake_flag]
brne r0, r1, _slave_core_wait
ld sp, [arc_cpu_sp]
/* signal master core that slave core runs */
st 0, [arc_cpu_wake_flag]
#if defined(CONFIG_ARC_FIRQ_STACK)
push r0
jl z_arc_firq_stack_set
pop r0
#endif
j z_arc_slave_start
_master_core_startup:
#endif
#ifdef CONFIG_INIT_STACKS
/*
* use the main stack to call memset on the interrupt stack and the
* FIRQ stack when CONFIG_INIT_STACKS is enabled before switching to
* one of them for the rest of the early boot
*/
mov_s sp, z_main_stack
add sp, sp, CONFIG_MAIN_STACK_SIZE
mov_s r0, z_interrupt_stacks
mov_s r1, 0xaa
mov_s r2, CONFIG_ISR_STACK_SIZE
jl memset
#endif /* CONFIG_INIT_STACKS */
mov_s sp, INIT_STACK
add sp, sp, INIT_STACK_SIZE
#if defined(CONFIG_ARC_FIRQ_STACK)
jl z_arc_firq_stack_set
#endif
j _PrepC