blob: 8ffe15cc38a81b12ef8303e9bcbb766af65c37ab [file] [log] [blame]
Shubham Kulkarnic75b3c72021-07-20 11:43:28 +05301/*
2 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <stdint.h>
8#include <string.h>
9#include "sdkconfig.h"
10#include "esp_attr.h"
11#include "esp_image_format.h"
12
13#include "bootloader_init.h"
14#include "bootloader_mem.h"
15#include "bootloader_clock.h"
16#include "bootloader_flash_config.h"
17#include "bootloader_flash.h"
18#include "bootloader_flash_priv.h"
19
20#include "soc/dport_reg.h"
21#include "soc/efuse_reg.h"
22#include "soc/rtc.h"
23
24#include "hal/wdt_hal.h"
25
26#include "esp32/rom/cache.h"
27#include "esp32/rom/ets_sys.h"
28#include "esp32/rom/spi_flash.h"
29#include "esp32/rom/uart.h"
30
31esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
32
33void bootloader_clear_bss_section(void)
34{
35 memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
36}
37
38static void bootloader_common_vddsdio_configure(void)
39{
40 rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
41 if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { /* VDDSDIO regulator is enabled @ 1.8V */
42 cfg.drefh = 3;
43 cfg.drefm = 3;
44 cfg.drefl = 3;
45 cfg.force = 1;
46 rtc_vddsdio_set_config(cfg);
47 ets_delay_us(10); /* wait for regulator to become stable */
48 }
49}
50
51static void bootloader_reset_mmu(void)
52{
53 /* completely reset MMU in case serial bootloader was running */
54 Cache_Read_Disable(0);
55#if !CONFIG_FREERTOS_UNICORE
56 Cache_Read_Disable(1);
57#endif
58 Cache_Flush(0);
59#if !CONFIG_FREERTOS_UNICORE
60 Cache_Flush(1);
61#endif
62 mmu_init(0);
63#if !CONFIG_FREERTOS_UNICORE
64 /* The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
65 necessary to work around a hardware bug. */
66 DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
67 mmu_init(1);
68 DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
69#endif
70
71 /* normal ROM boot exits with DROM0 cache unmasked,
72 but serial bootloader exits with it masked. */
73 DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
74#if !CONFIG_FREERTOS_UNICORE
75 DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
76#endif
77}
78
79static esp_err_t bootloader_check_rated_cpu_clock(void)
80{
81 int rated_freq = bootloader_clock_get_rated_freq_mhz();
82 if (rated_freq < 80) {
83 return ESP_FAIL;
84 }
85 return ESP_OK;
86}
87
88esp_err_t bootloader_read_bootloader_header(void)
89{
90 if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
91 return ESP_FAIL;
92 }
93 return ESP_OK;
94}
95
96static void update_flash_config(const esp_image_header_t *bootloader_hdr)
97{
98 uint32_t size;
99 switch (bootloader_hdr->spi_size) {
100 case ESP_IMAGE_FLASH_SIZE_1MB:
101 size = 1;
102 break;
103 case ESP_IMAGE_FLASH_SIZE_2MB:
104 size = 2;
105 break;
106 case ESP_IMAGE_FLASH_SIZE_4MB:
107 size = 4;
108 break;
109 case ESP_IMAGE_FLASH_SIZE_8MB:
110 size = 8;
111 break;
112 case ESP_IMAGE_FLASH_SIZE_16MB:
113 size = 16;
114 break;
115 default:
116 size = 2;
117 }
118 Cache_Read_Disable(0);
119 /* Set flash chip size */
120 esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
121 /* TODO: set mode */
122 /* TODO: set frequency */
123 Cache_Flush(0);
124 Cache_Read_Enable(0);
125}
126
127static void IRAM_ATTR bootloader_init_flash_configure(void)
128{
129 bootloader_flash_gpio_config(&bootloader_image_hdr);
130 bootloader_flash_dummy_config(&bootloader_image_hdr);
131 bootloader_flash_cs_timing_config();
132}
133
134static esp_err_t bootloader_init_spi_flash(void)
135{
136 bootloader_init_flash_configure();
137 esp_rom_spiflash_unlock();
138
139 update_flash_config(&bootloader_image_hdr);
140 return ESP_OK;
141}
142
143void bootloader_config_wdt(void)
144{
145 wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
146 wdt_hal_write_protect_disable(&rtc_wdt_ctx);
147 wdt_hal_set_flashboot_en(&rtc_wdt_ctx, false);
148 wdt_hal_write_protect_enable(&rtc_wdt_ctx);
149
150#ifdef CONFIG_ESP_MCUBOOT_WDT_ENABLE
151 wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
152 uint32_t stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000);
153 wdt_hal_write_protect_disable(&rtc_wdt_ctx);
154 wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
155 wdt_hal_enable(&rtc_wdt_ctx);
156 wdt_hal_write_protect_enable(&rtc_wdt_ctx);
157#endif
158
159 wdt_hal_context_t wdt_ctx = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
160 wdt_hal_write_protect_disable(&wdt_ctx);
161 wdt_hal_set_flashboot_en(&wdt_ctx, false);
162 wdt_hal_write_protect_enable(&wdt_ctx);
163}
164
165static void bootloader_init_uart_console(void)
166{
167 const int uart_num = 0;
168
169 uartAttach();
170 ets_install_uart_printf();
171 uart_tx_wait_idle(0);
172
173 const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
174 uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
175}
176
177
178esp_err_t bootloader_init(void)
179{
180 esp_err_t ret = ESP_OK;
181
182 bootloader_init_mem();
183
184 /* check that static RAM is after the stack */
185#ifndef NDEBUG
186 {
187 assert(&_bss_start <= &_bss_end);
188 assert(&_data_start <= &_data_end);
189 assert(sp < &_bss_start);
190 assert(sp < &_data_start);
191 }
192#endif
193 /* clear bss section */
194 bootloader_clear_bss_section();
195 /* bootst up vddsdio */
196 bootloader_common_vddsdio_configure();
197 /* reset MMU */
198 bootloader_reset_mmu();
199 /* check rated CPU clock */
200 if ((ret = bootloader_check_rated_cpu_clock()) != ESP_OK) {
201 goto err;
202 }
203 /* config clock */
204 bootloader_clock_configure();
205 /* initialize uart console, from now on, we can use ets_printf */
206 bootloader_init_uart_console();
207 /* read bootloader header */
208 if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
209 goto err;
210 }
211 /* initialize spi flash */
212 if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
213 goto err;
214 }
215 /* config WDT */
216 bootloader_config_wdt();
217err:
218 return ret;
219}