1 /*
2  * Copyright (c) 2013-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief ARM Cortex-M System Control Block interface
10  *
11  *
12  * Most of the SCB interface consists of simple bit-flipping methods, and is
13  * implemented as inline functions in scb.h. This module thus contains only data
14  * definitions and more complex routines, if needed.
15  */
16 
17 #include <zephyr/kernel.h>
18 #include <zephyr/arch/cpu.h>
19 #include <zephyr/sys/util.h>
20 #include <zephyr/sys/barrier.h>
21 #include <cmsis_core.h>
22 #include <zephyr/linker/linker-defs.h>
23 #include <zephyr/cache.h>
24 #include <zephyr/arch/cache.h>
25 
26 #if defined(CONFIG_CPU_HAS_NXP_SYSMPU)
27 #include <fsl_sysmpu.h>
28 #endif
29 
30 /**
31  *
32  * @brief Reset the system
33  *
34  * This routine resets the processor.
35  *
36  */
37 
sys_arch_reboot(int type)38 void __weak sys_arch_reboot(int type)
39 {
40 	ARG_UNUSED(type);
41 
42 	NVIC_SystemReset();
43 }
44 
45 #if defined(CONFIG_ARM_MPU)
46 #if defined(CONFIG_CPU_HAS_ARM_MPU)
47 /**
48  *
49  * @brief Clear all MPU region configuration
50  *
51  * This routine clears all ARM MPU region configuration.
52  *
53  */
z_arm_clear_arm_mpu_config(void)54 void z_arm_clear_arm_mpu_config(void)
55 {
56 	int i;
57 
58 	int num_regions =
59 		((MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos);
60 
61 	for (i = 0; i < num_regions; i++) {
62 		ARM_MPU_ClrRegion(i);
63 	}
64 }
65 #elif CONFIG_CPU_HAS_NXP_SYSMPU
z_arm_clear_arm_mpu_config(void)66 void z_arm_clear_arm_mpu_config(void)
67 {
68 	int i;
69 
70 	int num_regions = FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT;
71 
72 	SYSMPU_Enable(SYSMPU, false);
73 
74 	/* NXP MPU region 0 is reserved for the debugger */
75 	for (i = 1; i < num_regions; i++) {
76 		SYSMPU_RegionEnable(SYSMPU, i, false);
77 	}
78 }
79 #endif /* CONFIG_CPU_HAS_NXP_SYSMPU */
80 #endif /* CONFIG_ARM_MPU */
81 
82 #if defined(CONFIG_INIT_ARCH_HW_AT_BOOT)
83 /**
84  *
85  * @brief Reset system control blocks and core registers
86  *
87  * This routine resets Cortex-M system control block
88  * components and core registers.
89  *
90  */
z_arm_init_arch_hw_at_boot(void)91 void z_arm_init_arch_hw_at_boot(void)
92 {
93     /* Disable interrupts */
94 	__disable_irq();
95 
96 #if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
97 	__set_FAULTMASK(0);
98 #endif
99 
100 	/* Initialize System Control Block components */
101 
102 #if defined(CONFIG_ARM_MPU)
103 	/* Clear MPU region configuration */
104 	z_arm_clear_arm_mpu_config();
105 #endif /* CONFIG_ARM_MPU */
106 
107 	/* Disable NVIC interrupts */
108 	for (uint8_t i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) {
109 		NVIC->ICER[i] = 0xFFFFFFFF;
110 	}
111 	/* Clear pending NVIC interrupts */
112 	for (uint8_t i = 0; i < ARRAY_SIZE(NVIC->ICPR); i++) {
113 		NVIC->ICPR[i] = 0xFFFFFFFF;
114 	}
115 
116 #if defined(CONFIG_ARCH_CACHE)
117 #if defined(CONFIG_DCACHE)
118 	/* Reset D-Cache settings. If the D-Cache was enabled,
119 	 * SCB_DisableDCache() takes care of cleaning and invalidating it.
120 	 * If it was already disabled, just call SCB_InvalidateDCache() to
121 	 * reset it to a known clean state.
122 	 */
123 	if (SCB->CCR & SCB_CCR_DC_Msk) {
124 		/*
125 		 * Do not use sys_cache_data_disable at this point, but instead
126 		 * the architecture specific function. This ensures that the
127 		 * cache is disabled although CONFIG_CACHE_MANAGEMENT might be
128 		 * disabled.
129 		 */
130 		SCB_DisableDCache();
131 	} else {
132 		SCB_InvalidateDCache();
133 	}
134 #endif /* CONFIG_DCACHE */
135 
136 #if defined(CONFIG_ICACHE)
137 	/*
138 	 * Reset I-Cache settings.
139 	 * Do not use sys_cache_data_disable at this point, but instead
140 	 * the architecture specific function. This ensures that the
141 	 * cache is disabled although CONFIG_CACHE_MANAGEMENT might be
142 	 * disabled.
143 	 */
144 	SCB_DisableICache();
145 #endif /* CONFIG_ICACHE */
146 #endif /* CONFIG_ARCH_CACHE */
147 
148 	/* Restore Interrupts */
149 	__enable_irq();
150 
151 	barrier_dsync_fence_full();
152 	barrier_isync_fence_full();
153 }
154 #endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */
155