1 /*
2  * Copyright (c) 2013-2014 Wind River Systems, Inc.
3  * Copyright 2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file
10  * @brief Full C support initialization
11  *
12  *
13  * Initialization of full C support: zero the .bss, copy the .data if XIP,
14  * call z_cstart().
15  *
16  * Stack is available in this module, but not the global data/bss until their
17  * initialization is performed.
18  */
19 
20 #include <zephyr/kernel.h>
21 #include <kernel_internal.h>
22 #include <zephyr/linker/linker-defs.h>
23 #include <zephyr/sys/barrier.h>
24 #include <zephyr/arch/arm/cortex_a_r/lib_helpers.h>
25 #include <zephyr/platform/hooks.h>
26 #include <zephyr/arch/cache.h>
27 
28 #if defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A)
29 #include <cortex_a_r/stack.h>
30 #endif
31 
32 #ifdef CONFIG_ARM_MPU
33 extern void z_arm_mpu_init(void);
34 extern void z_arm_configure_static_mpu_regions(void);
35 #elif defined(CONFIG_ARM_AARCH32_MMU)
36 extern int z_arm_mmu_init(void);
37 #endif
38 
39 #if defined(CONFIG_CPU_HAS_FPU)
40 
z_arm_floating_point_init(void)41 static inline void z_arm_floating_point_init(void)
42 {
43 #if defined(CONFIG_FPU)
44 	uint32_t reg_val = 0;
45 
46 	/*
47 	 * CPACR : Coprocessor Access Control Register -> CP15 1/0/2
48 	 * comp. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition,
49 	 * chap. B4.1.40
50 	 *
51 	 * Must be accessed in >= PL1!
52 	 * [23..22] = CP11 access control bits,
53 	 * [21..20] = CP10 access control bits.
54 	 * 11b = Full access as defined for the respective CP,
55 	 * 10b = UNDEFINED,
56 	 * 01b = Access at PL1 only,
57 	 * 00b = No access.
58 	 */
59 	reg_val = __get_CPACR();
60 	/* Enable PL1 access to CP10, CP11 */
61 	reg_val |= (CPACR_CP10(CPACR_FA) | CPACR_CP11(CPACR_FA));
62 	__set_CPACR(reg_val);
63 	barrier_isync_fence_full();
64 
65 	/*
66 	 * FPEXC: Floating-Point Exception Control register
67 	 * comp. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition,
68 	 * chap. B6.1.38
69 	 *
70 	 * Must be accessed in >= PL1!
71 	 * [31] EX bit = determines which registers comprise the current state
72 	 *               of the FPU. The effects of setting this bit to 1 are
73 	 *               subarchitecture defined. If EX=0, the following
74 	 *               registers contain the complete current state
75 	 *               information of the FPU and must therefore be saved
76 	 *               during a context switch:
77 	 *               * D0-D15
78 	 *               * D16-D31 if implemented
79 	 *               * FPSCR
80 	 *               * FPEXC.
81 	 * [30] EN bit = Advanced SIMD/Floating Point Extensions enable bit.
82 	 * [29..00]    = Subarchitecture defined -> not relevant here.
83 	 */
84 	__set_FPEXC(FPEXC_EN);
85 #endif
86 }
87 
88 #endif /* CONFIG_CPU_HAS_FPU */
89 
90 extern FUNC_NORETURN void z_cstart(void);
91 
92 /**
93  *
94  * @brief Prepare to and run C code
95  *
96  * This routine prepares for the execution of and runs C code.
97  *
98  */
z_prep_c(void)99 void z_prep_c(void)
100 {
101 #if defined(CONFIG_SOC_PREP_HOOK)
102 	soc_prep_hook();
103 #endif
104 	/* Initialize tpidruro with our struct _cpu instance address */
105 	write_tpidruro((uintptr_t)&_kernel.cpus[0]);
106 
107 #if defined(CONFIG_CPU_HAS_FPU)
108 	z_arm_floating_point_init();
109 #endif
110 	z_bss_zero();
111 	z_data_copy();
112 #if ((defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A)) && defined(CONFIG_INIT_STACKS))
113 	z_arm_init_stacks();
114 #endif
115 	z_arm_interrupt_init();
116 #if CONFIG_ARCH_CACHE
117 	arch_cache_init();
118 #endif
119 #ifdef CONFIG_ARM_MPU
120 	z_arm_mpu_init();
121 	z_arm_configure_static_mpu_regions();
122 #elif defined(CONFIG_ARM_AARCH32_MMU)
123 	z_arm_mmu_init();
124 #endif
125 	z_cstart();
126 	CODE_UNREACHABLE;
127 }
128