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