1/*
2 * Copyright (c) 2014 Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/**
8 * @file
9 * @brief Reset handler
10 *
11 * Reset handler that prepares the system for running C code.
12 */
13
14#include <zephyr/toolchain.h>
15#include <zephyr/linker/sections.h>
16#include <zephyr/arch/cpu.h>
17#include <swap_macros.h>
18#include <zephyr/arch/arc/asm-compat/assembler.h>
19#ifdef CONFIG_ARC_EARLY_SOC_INIT
20  #include <soc_ctrl.h>
21#endif
22
23GDATA(z_interrupt_stacks)
24GDATA(z_main_stack)
25GDATA(_VectorTable)
26
27/* use one of the available interrupt stacks during init */
28
29
30#define INIT_STACK z_interrupt_stacks
31#define INIT_STACK_SIZE CONFIG_ISR_STACK_SIZE
32
33GTEXT(__reset)
34GTEXT(__start)
35
36/**
37 * @brief Reset vector
38 *
39 * Ran when the system comes out of reset. The processor is at supervisor level.
40 *
41 * Locking interrupts prevents anything from interrupting the CPU.
42 *
43 * When these steps are completed, jump to _PrepC(), which will finish setting
44 * up the system for running C code.
45 */
46
47SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__reset)
48SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__start)
49	/* lock interrupts: will get unlocked when switch to main task
50	 * also make sure the processor in the correct status
51	 */
52	mov_s r0, 0
53	kflag r0
54
55#ifdef CONFIG_ARC_SECURE_FIRMWARE
56	sflag r0
57#endif
58	/* interrupt related init */
59#ifndef CONFIG_ARC_NORMAL_FIRMWARE
60	/* IRQ_ACT and IRQ_CTRL should be initialized and set in secure mode */
61	sr r0, [_ARC_V2_AUX_IRQ_ACT]
62	sr r0, [_ARC_V2_AUX_IRQ_CTRL]
63#endif
64	sr r0, [_ARC_V2_AUX_IRQ_HINT]
65
66	/* set the vector table base early,
67	 * so that exception vectors can be handled.
68	 */
69	MOVR r0, _VectorTable
70#ifdef CONFIG_ARC_SECURE_FIRMWARE
71	sr r0, [_ARC_V2_IRQ_VECT_BASE_S]
72#else
73	SRR r0, [_ARC_V2_IRQ_VECT_BASE]
74#endif
75
76	lr r0, [_ARC_V2_STATUS32]
77	bset r0, r0, _ARC_V2_STATUS32_DZ_BIT
78	kflag r0
79
80#if defined(CONFIG_USERSPACE)
81	lr r0, [_ARC_V2_STATUS32]
82	bset r0, r0, _ARC_V2_STATUS32_US_BIT
83	kflag r0
84#endif
85
86#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
87	lr r0, [_ARC_V2_STATUS32]
88	bset r0, r0, _ARC_V2_STATUS32_AD_BIT
89	kflag r0
90#endif
91
92/* Invalidate icache */
93	lr r0, [_ARC_V2_I_CACHE_BUILD]
94	and.f r0, r0, 0xff
95	bz.nd done_icache_invalidate
96
97	mov_s r2, 0
98	sr r2, [_ARC_V2_IC_IVIC]
99	/* writing to IC_IVIC needs 3 NOPs */
100	nop_s
101	nop_s
102	nop_s
103done_icache_invalidate:
104
105/* Invalidate dcache */
106	lr r3, [_ARC_V2_D_CACHE_BUILD]
107	and.f r3, r3, 0xff
108	bz.nd done_dcache_invalidate
109
110	mov_s r1, 1
111	sr r1, [_ARC_V2_DC_IVDC]
112
113done_dcache_invalidate:
114
115#ifdef CONFIG_ARC_EARLY_SOC_INIT
116	soc_early_asm_init_percpu
117#endif
118
119	_dsp_extension_probe
120
121/*
122 * Init ARC internal architecture state
123 * Force to initialize internal architecture state to reset values
124 * For scenarios where board hardware is not re-initialized between tests,
125 * some settings need to be restored to its default initial states as a
126 * substitution of normal hardware reset sequence.
127 */
128#ifdef CONFIG_INIT_ARCH_HW_AT_BOOT
129	/* Set MPU (v4 or v8) registers to default */
130#if CONFIG_ARC_MPU_VER == 4 || CONFIG_ARC_MPU_VER == 8
131	/* Set default reset value to _ARC_V2_MPU_EN register */
132#define ARC_MPU_EN_RESET_VALUE 0x400181C0
133	mov_s r1, ARC_MPU_EN_RESET_VALUE
134	sr r1, [_ARC_V2_MPU_EN]
135	/* Get MPU region numbers */
136	lr r3, [_ARC_V2_MPU_BUILD]
137	lsr_s r3, r3, 8
138	and r3, r3, 0xff
139	mov_s r1, 0
140	mov_s r2, 0
141	/* Set all MPU regions by iterating index */
142mpu_regions_reset:
143	brge r2, r3, done_mpu_regions_reset
144	sr r2, [_ARC_V2_MPU_INDEX]
145	sr r1, [_ARC_V2_MPU_RSTART]
146	sr r1, [_ARC_V2_MPU_REND]
147	sr r1, [_ARC_V2_MPU_RPER]
148	add_s r2, r2, 1
149	b_s mpu_regions_reset
150done_mpu_regions_reset:
151#endif
152#endif
153
154#if defined(CONFIG_SMP) || CONFIG_MP_MAX_NUM_CPUS  > 1
155	_get_cpu_id r0
156	breq r0, 0, _master_core_startup
157
158/*
159 * Non-masters wait for master core (core 0) to boot enough
160 */
161_slave_core_wait:
162#if CONFIG_MP_MAX_NUM_CPUS == 1
163	kflag	1
164#endif
165	ld r1, [arc_cpu_wake_flag]
166	brne r0, r1, _slave_core_wait
167
168	LDR sp, arc_cpu_sp
169	/* signal master core that slave core runs */
170	st 0, [arc_cpu_wake_flag]
171
172#if defined(CONFIG_ARC_FIRQ_STACK)
173	push r0
174	jl z_arc_firq_stack_set
175	pop r0
176#endif
177	j z_arc_slave_start
178
179_master_core_startup:
180#endif
181
182#ifdef CONFIG_INIT_STACKS
183	/*
184	 * use the main stack to call memset on the interrupt stack and the
185	 * FIRQ stack when CONFIG_INIT_STACKS is enabled before switching to
186	 * one of them for the rest of the early boot
187	 */
188	mov_s sp, z_main_stack
189	add sp, sp, CONFIG_MAIN_STACK_SIZE
190
191	mov_s r0, z_interrupt_stacks
192	mov_s r1, 0xaa
193	mov_s r2, CONFIG_ISR_STACK_SIZE
194	jl memset
195
196#endif /* CONFIG_INIT_STACKS */
197
198	mov_s sp, INIT_STACK
199	add sp, sp, INIT_STACK_SIZE
200
201#if defined(CONFIG_ARC_FIRQ_STACK)
202	jl z_arc_firq_stack_set
203#endif
204
205	j _PrepC
206