1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /* Include esp-idf headers first to avoid redefining BIT() macro */
8 #include <soc.h>
9 #include <soc/rtc_cntl_reg.h>
10 #include <soc/timer_group_reg.h>
11 #include <soc/ext_mem_defs.h>
12 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
13 #include <xtensa/config/core-isa.h>
14 #include <xtensa/corebits.h>
15 #include <esp_private/spi_flash_os.h>
16 #include <esp_private/esp_mmu_map_private.h>
17 #include <esp_private/mspi_timing_tuning.h>
18 #include <esp_flash_internal.h>
19 #include <esp_private/cache_utils.h>
20 #include <sdkconfig.h>
21 
22 #if CONFIG_ESP_SPIRAM
23 #include "psram.h"
24 #endif
25 
26 #include <zephyr/kernel_structs.h>
27 #include <zephyr/toolchain.h>
28 #include <zephyr/types.h>
29 #include <zephyr/linker/linker-defs.h>
30 #include <kernel_internal.h>
31 #include <zephyr/sys/util.h>
32 
33 #include <esp_private/system_internal.h>
34 #include <esp32s3/rom/cache.h>
35 #include <esp32s3/rom/rtc.h>
36 #include <soc/syscon_reg.h>
37 #include <hal/soc_hal.h>
38 #include <hal/wdt_hal.h>
39 #include <hal/cpu_hal.h>
40 #include <esp_cpu.h>
41 #include <soc/gpio_periph.h>
42 #include <esp_err.h>
43 #include <esp_timer.h>
44 #include <esp_clk_internal.h>
45 #include <esp_app_format.h>
46 
47 #include <zephyr/sys/printk.h>
48 #include "esp_log.h"
49 
50 #include <zephyr/drivers/flash.h>
51 #include <zephyr/storage/flash_map.h>
52 
53 #define TAG "boot.esp32s3"
54 
55 extern void z_prep_c(void);
56 extern void esp_reset_reason_init(void);
57 extern int esp_appcpu_init(void);
58 
59 #ifndef CONFIG_MCUBOOT
60 /*
61  * This function is a container for SoC patches
62  * that needs to be applied during the startup.
63  */
esp_errata(void)64 static void IRAM_ATTR esp_errata(void)
65 {
66 	/* Handle the clock gating fix */
67 	REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN);
68 	/* The clock gating signal of the App core is invalid. We use RUNSTALL and RESETTING
69 	 * signals to ensure that the App core stops running in single-core mode.
70 	 */
71 	REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL);
72 	REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETTING);
73 
74 	/* Handle the Dcache case following the IDF startup code */
75 #if CONFIG_ESP32S3_DATA_CACHE_16KB
76 	Cache_Invalidate_DCache_All();
77 	Cache_Occupy_Addr(SOC_DROM_LOW, 0x4000);
78 #endif
79 }
80 #endif /* CONFIG_MCUBOOT */
81 
82 /*
83  * This is written in C rather than assembly since, during the port bring up,
84  * Zephyr is being booted by the Espressif bootloader.  With it, the C stack
85  * is already set up.
86  */
__esp_platform_start(void)87 void IRAM_ATTR __esp_platform_start(void)
88 {
89 	extern uint32_t _init_start;
90 
91 	/* Move the exception vector table to IRAM. */
92 	__asm__ __volatile__("wsr %0, vecbase" : : "r"(&_init_start));
93 
94 	z_bss_zero();
95 
96 	/* Disable normal interrupts. */
97 	__asm__ __volatile__("wsr %0, PS" : : "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
98 
99 	/* Initialize the architecture CPU pointer.  Some of the
100 	 * initialization code wants a valid arch_current_thread() before
101 	 * arch_kernel_init() is invoked.
102 	 */
103 	__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
104 
105 #ifndef CONFIG_MCUBOOT
106 	/* Configure the mode of instruction cache : cache size, cache line size. */
107 	esp_config_instruction_cache_mode();
108 
109 	/* If we need use SPIRAM, we should use data cache.
110 	 * Configure the mode of data : cache size, cache line size.
111 	 */
112 	esp_config_data_cache_mode();
113 
114 	/* Apply SoC patches */
115 	esp_errata();
116 
117 	/* ESP-IDF/MCUboot 2nd stage bootloader enables RTC WDT to check on startup sequence
118 	 * related issues in application. Hence disable that as we are about to start
119 	 * Zephyr environment.
120 	 */
121 	wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
122 
123 	wdt_hal_write_protect_disable(&rtc_wdt_ctx);
124 	wdt_hal_disable(&rtc_wdt_ctx);
125 	wdt_hal_write_protect_enable(&rtc_wdt_ctx);
126 
127 	esp_reset_reason_init();
128 
129 	esp_timer_early_init();
130 
131 	esp_mspi_pin_init();
132 
133 	esp_flash_app_init();
134 
135 	mspi_timing_flash_tuning();
136 
137 	esp_mmu_map_init();
138 
139 #if CONFIG_ESP_SPIRAM
140 	esp_init_psram();
141 #endif /* CONFIG_ESP_SPIRAM */
142 
143 #endif /* !CONFIG_MCUBOOT */
144 
145 	esp_intr_initialize();
146 
147 #if CONFIG_ESP_SPIRAM
148 	/* Init Shared Multi Heap for PSRAM */
149 	int err = esp_psram_smh_init();
150 
151 	if (err) {
152 		printk("Failed to initialize PSRAM shared multi heap (%d)\n", err);
153 	}
154 #endif
155 
156 	/* Start Zephyr */
157 	z_prep_c();
158 
159 	CODE_UNREACHABLE;
160 }
161 
162 /* Boot-time static default printk handler, possibly to be overridden later. */
arch_printk_char_out(int c)163 int IRAM_ATTR arch_printk_char_out(int c)
164 {
165 	if (c == '\n') {
166 		esp_rom_uart_tx_one_char('\r');
167 	}
168 	esp_rom_uart_tx_one_char(c);
169 	return 0;
170 }
171 
sys_arch_reboot(int type)172 void sys_arch_reboot(int type)
173 {
174 	esp_restart_noos();
175 }
176 
177 #if defined(CONFIG_SOC_ENABLE_APPCPU) && !defined(CONFIG_MCUBOOT)
178 extern int esp_appcpu_init(void);
179 SYS_INIT(esp_appcpu_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
180 #endif
181