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 <zephyr/drivers/interrupt_controller/intc_esp32.h>
12 #include <xtensa/config/core-isa.h>
13 #include <xtensa/corebits.h>
14 #include <esp_private/spi_flash_os.h>
15 #include <esp_private/esp_mmu_map_private.h>
16 #include <esp_flash_internal.h>
17 #if CONFIG_ESP_SPIRAM
18 #include "psram.h"
19 #endif
20 
21 #include <zephyr/kernel_structs.h>
22 #include <string.h>
23 #include <zephyr/toolchain.h>
24 #include <zephyr/types.h>
25 #include <zephyr/linker/linker-defs.h>
26 #include <kernel_internal.h>
27 
28 #include <esp_private/system_internal.h>
29 #include <esp32/rom/cache.h>
30 #include <esp_cpu.h>
31 #include <hal/soc_hal.h>
32 #include <hal/cpu_hal.h>
33 #include <soc/gpio_periph.h>
34 #include <esp_err.h>
35 #include <esp_timer.h>
36 #include <hal/wdt_hal.h>
37 #include <esp_app_format.h>
38 
39 #ifndef CONFIG_SOC_ENABLE_APPCPU
40 #include "esp_clk_internal.h"
41 #endif /* CONFIG_SOC_ENABLE_APPCPU */
42 
43 #include <zephyr/sys/printk.h>
44 #include "esp_log.h"
45 
46 #define TAG "boot.esp32"
47 
48 extern void z_prep_c(void);
49 extern void esp_reset_reason_init(void);
50 extern int esp_appcpu_init(void);
51 
52 /*
53  * This is written in C rather than assembly since, during the port bring up,
54  * Zephyr is being booted by the Espressif bootloader.  With it, the C stack
55  * is already set up.
56  */
__esp_platform_start(void)57 void IRAM_ATTR __esp_platform_start(void)
58 {
59 	extern uint32_t _init_start;
60 
61 	/* Move the exception vector table to IRAM. */
62 	__asm__ __volatile__ ("wsr %0, vecbase" : : "r"(&_init_start));
63 
64 	z_bss_zero();
65 
66 	__asm__ __volatile__ ("" : : "g"(&__bss_start) : "memory");
67 
68 	/* Disable normal interrupts. */
69 	__asm__ __volatile__ ("wsr %0, PS" : : "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
70 
71 	/* Initialize the architecture CPU pointer.  Some of the
72 	 * initialization code wants a valid arch_current_thread() before
73 	 * z_prep_c() is invoked.
74 	 */
75 	__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
76 
77 	esp_reset_reason_init();
78 
79 #ifndef CONFIG_MCUBOOT
80 	/* ESP-IDF/MCUboot 2nd stage bootloader enables RTC WDT to check
81 	 * on startup sequence related issues in application. Hence disable that
82 	 * as we are about to start Zephyr environment.
83 	 */
84 	wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
85 
86 	wdt_hal_write_protect_disable(&rtc_wdt_ctx);
87 	wdt_hal_disable(&rtc_wdt_ctx);
88 	wdt_hal_write_protect_enable(&rtc_wdt_ctx);
89 
90 	esp_timer_early_init();
91 
92 	esp_mspi_pin_init();
93 
94 	esp_flash_app_init();
95 
96 	esp_mmu_map_init();
97 
98 #if CONFIG_ESP_SPIRAM
99 	esp_init_psram();
100 #endif /* CONFIG_ESP_SPIRAM */
101 
102 #endif /* !CONFIG_MCUBOOT */
103 
104 	esp_intr_initialize();
105 
106 #if CONFIG_ESP_SPIRAM
107 	/* Init Shared Multi Heap for PSRAM */
108 	int err = esp_psram_smh_init();
109 
110 	if (err) {
111 		printk("Failed to initialize PSRAM shared multi heap (%d)\n", err);
112 	}
113 #endif
114 
115 	/* Start Zephyr */
116 	z_prep_c();
117 
118 	CODE_UNREACHABLE;
119 }
120 
121 /* Boot-time static default printk handler, possibly to be overridden later. */
arch_printk_char_out(int c)122 int IRAM_ATTR arch_printk_char_out(int c)
123 {
124 	if (c == '\n') {
125 		esp_rom_uart_tx_one_char('\r');
126 	}
127 	esp_rom_uart_tx_one_char(c);
128 	return 0;
129 }
130 
sys_arch_reboot(int type)131 void sys_arch_reboot(int type)
132 {
133 	esp_restart_noos();
134 }
135 
136 #if defined(CONFIG_SOC_ENABLE_APPCPU) && !defined(CONFIG_MCUBOOT)
137 extern int esp_appcpu_init(void);
138 SYS_INIT(esp_appcpu_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
139 #endif
140