| /* |
| * 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: |
| |
| /* |
| * Init ARC internal architecture state |
| * Force to initialize internal architecture state to reset values |
| * 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. |
| */ |
| #ifdef CONFIG_INIT_ARCH_HW_AT_BOOT |
| /* 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_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 |