diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 5cb315b5f..c61808591 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -43,6 +43,16 @@ config BOOTLOADER_SPI_WP_PIN The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash. +config BOOTLOADER_VDDSDIO_BOOST + bool "Increase VDDSDIO LDO voltage to 1.9V" + default y + help + If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE + or MTDI bootstrapping pin), bootloader will change LDO settings to + output 1.9V instead. This helps prevent flash chip from browning out + during flash programming operations. + For 3.3V flash, this option has no effect. + endmenu # Bootloader diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index 012348ddf..5b68b1979 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -73,6 +73,8 @@ static void set_cache_and_start_app(uint32_t drom_addr, uint32_t irom_size, uint32_t entry_addr); static void update_flash_config(const esp_image_header_t* pfhdr); +static void vddsdio_configure(); +static void flash_gpio_configure(); static void clock_configure(void); static void uart_console_configure(void); static void wdt_reset_check(void); @@ -443,6 +445,8 @@ static bool load_boot_image(const bootloader_state_t *bs, int start_index, esp_i void bootloader_main() { + vddsdio_configure(); + flash_gpio_configure(); clock_configure(); uart_console_configure(); wdt_reset_check(); @@ -737,6 +741,105 @@ static void print_flash_info(const esp_image_header_t* phdr) } +static void vddsdio_configure() +{ +#if CONFIG_BOOTLOADER_VDDSDIO_BOOST + rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); + if (cfg.tieh == 0) { // 1.8V is used + cfg.drefh = 3; + cfg.drefm = 3; + cfg.drefl = 3; + cfg.force = 1; + cfg.enable = 1; + rtc_vddsdio_set_config(cfg); + ets_delay_us(10); // wait for regulator to become stable + } +#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST +} + + +#define FLASH_CLK_IO 6 +#define FLASH_CS_IO 11 +#define FLASH_SPIQ_IO 7 +#define FLASH_SPID_IO 8 +#define FLASH_SPIWP_IO 10 +#define FLASH_SPIHD_IO 9 +#define FLASH_IO_MATRIX_DUMMY_40M 1 +#define FLASH_IO_MATRIX_DUMMY_80M 2 +static void IRAM_ATTR flash_gpio_configure() +{ + int spi_cache_dummy = 0; + int drv = 2; +#if CONFIG_FLASHMODE_QIO + spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3 +#elif CONFIG_FLASHMODE_QOUT + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7 +#elif CONFIG_FLASHMODE_DIO + spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3 +#elif CONFIG_FLASHMODE_DOUT + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7 +#endif + /* dummy_len_plus values defined in ROM for SPI flash configuration */ + extern uint8_t g_rom_spiflash_dummy_len_plus[]; +#if CONFIG_ESPTOOLPY_FLASHFREQ_40M + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY +#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + drv = 3; +#endif + + uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); + uint32_t pkg_ver = chip_ver & 0x7; + + if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) { + // For ESP32D2WD the SPI pins are already configured + ESP_LOGI(TAG, "Detected ESP32D2WD"); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { + // For ESP32PICOD2 the SPI pins are already configured + ESP_LOGI(TAG, "Detected ESP32PICOD2"); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { + // For ESP32PICOD4 the SPI pins are already configured + ESP_LOGI(TAG, "Detected ESP32PICOD4"); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } else { + ESP_LOGI(TAG, "Detected ESP32"); + const uint32_t spiconfig = ets_efuse_get_spiconfig(); + if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) { + gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); + gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0); + gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0); + gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0); + gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0); + //select pin function gpio + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO); + // flash clock signal should come from IO MUX. + // set drive ability for clock + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } + } +} + static void clock_configure(void) { /* Set CPU to 80MHz. Keep other clocks unmodified. */ diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index 6927716c6..240363830 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -198,14 +198,22 @@ static void rtc_wdt_disable() * Placed into IRAM as flash may need some time to be powered on. */ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, - rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline)); + rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us, + rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline)); static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, - rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us) + rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us, + rtc_vddsdio_config_t vddsdio_config) { // Enter sleep esp_err_t err = esp_sleep_start(pd_flags); + // If VDDSDIO regulator was controlled by RTC registers before sleep, + // restore the configuration. + if (vddsdio_config.force) { + rtc_vddsdio_set_config(vddsdio_config); + } + // Restore CPU frequency rtc_clk_cpu_freq_set(cpu_freq); @@ -244,6 +252,7 @@ esp_err_t esp_light_sleep_start() s_config.sleep_duration -= flash_enable_time_us; } #endif //CONFIG_SPIRAM_SUPPORT + rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails rtc_wdt_enable(1000); @@ -252,7 +261,8 @@ esp_err_t esp_light_sleep_start() rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get(); // Enter sleep, then wait for flash to be ready on wakeup - esp_err_t err = esp_light_sleep_inner(pd_flags, cpu_freq, flash_enable_time_us); + esp_err_t err = esp_light_sleep_inner(pd_flags, cpu_freq, + flash_enable_time_us, vddsdio_config); // At this point, if FRC1 is used for timekeeping, time will be lagging behind. // This will update the microsecond count based on RTC timer. diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index 6be905d14..5d87a0a2b 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -22,6 +22,7 @@ #include "esp_attr.h" #include "esp_err.h" #include "esp_types.h" +#include "esp_log.h" #include "spiram_psram.h" #include "rom/ets_sys.h" #include "rom/spi_flash.h" @@ -30,6 +31,7 @@ #include "soc/io_mux_reg.h" #include "soc/dport_reg.h" #include "soc/gpio_sig_map.h" +#include "soc/efuse_reg.h" #include "driver/gpio.h" #include "driver/spi_common.h" @@ -71,6 +73,8 @@ #define PSRAM_SPIWP_IO 10 #define PSRAM_SPIHD_IO 9 +#define PSRAM_INTERNAL_IO_28 28 +#define PSRAM_INTERNAL_IO_29 29 #define PSRAM_IO_MATRIX_DUMMY_40M 1 #define PSRAM_IO_MATRIX_DUMMY_80M 2 @@ -84,7 +88,7 @@ #define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //dout 7 #endif - +static const char* TAG = "psram"; typedef enum { PSRAM_SPI_1 = 0x1, PSRAM_SPI_2, @@ -418,7 +422,6 @@ void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode) static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) { - gpio_matrix_out(FLASH_CLK_IO, SPICLK_OUT_IDX, 0, 0); gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); gpio_matrix_out(PSRAM_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); gpio_matrix_in(PSRAM_SPIQ_IO, SPIQ_IN_IDX, 0); @@ -434,16 +437,25 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M; SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + //set drive ability for clock + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S); break; case PSRAM_CACHE_F80M_S80M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M; g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_80M; SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + //set drive ability for clock + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S); break; case PSRAM_CACHE_F40M_S40M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M; SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + //set drive ability for clock + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 2, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S); break; default: break; @@ -451,17 +463,31 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy en //select pin function gpio - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 2); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 2); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, 2); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, 2); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 2); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); } //psram gpio init , different working frequency we have different solutions esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init { + uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); + uint32_t pkg_ver = chip_ver & 0x7; + if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) { + ESP_EARLY_LOGE(TAG, "ESP32D2WD do not support psram yet"); + return ESP_FAIL; + } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { + ESP_EARLY_LOGE(TAG, "ESP32PICOD2 do not support psram yet"); + return ESP_FAIL; + } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { + ESP_EARLY_LOGE(TAG, "ESP32PICOD4 do not support psram yet"); + return ESP_FAIL; + } + /* note: If the third mode(80Mhz+80Mhz) is enabled, VSPI port will be occupied by the system, Application code should never touch VSPI hardware in this case. We try to stop applications from doing this using the drivers by claiming the port for ourselves*/ @@ -515,20 +541,20 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad We do this by routing it signal to signal 224/225, which are used as a loopback; the extra run through the GPIO matrix causes the delay. We use GPIO20 (which is not in any package but has pad logic in silicon) as a temporary pad for this. So the signal path is: - GPIO6(SPI CLK) --> signal224(in then out) --> internal GPIO20 --> signal225(in then out) --> GPIO17(PSRAM CLK) + SPI CLK --> GPIO28 --> signal224(in then out) --> internal GPIO29 --> signal225(in then out) --> GPIO17(PSRAM CLK) */ - gpio_matrix_in(FLASH_CLK_IO, SIG_IN_FUNC224_IDX, 0); - gpio_matrix_out(20, SIG_IN_FUNC224_IDX, 0, 0); - gpio_matrix_in(20, SIG_IN_FUNC225_IDX, 0); + gpio_matrix_out(PSRAM_INTERNAL_IO_28, SPICLK_OUT_IDX, 0, 0); + gpio_matrix_in(PSRAM_INTERNAL_IO_28, SIG_IN_FUNC224_IDX, 0); + gpio_matrix_out(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC224_IDX, 0, 0); + gpio_matrix_in(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC225_IDX, 0); gpio_matrix_out(PSRAM_CLK_IO, SIG_IN_FUNC225_IDX, 0, 0); break; } CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M); - psram_gpio_config(mode); WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO)); - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], 2); - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], 2); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], PIN_FUNC_GPIO); uint32_t id; psram_read_id(&id); if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) { diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 37958db40..0a5d51f66 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -397,8 +397,10 @@ static void get_chip_info_esp32(esp_chip_info_t* out_info) if ((reg & EFUSE_RD_CHIP_VER_DIS_BT_M) == 0) { out_info->features |= CHIP_FEATURE_BT | CHIP_FEATURE_BLE; } - if (((reg & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S) == - EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) { + int package = (reg & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S; + if (package == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || + package == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 || + package == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { out_info->features |= CHIP_FEATURE_EMB_FLASH; } } diff --git a/components/soc/esp32/include/soc/efuse_reg.h b/components/soc/esp32/include/soc/efuse_reg.h index b9ad20ee6..affcfa878 100644 --- a/components/soc/esp32/include/soc/efuse_reg.h +++ b/components/soc/esp32/include/soc/efuse_reg.h @@ -100,6 +100,8 @@ #define EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6 0 #define EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5 1 #define EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 2 +#define EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 4 +#define EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 5 /* EFUSE_RD_SPI_PAD_CONFIG_HD : RO ;bitpos:[8:4] ;default: 5'b0 ; */ /*description: read for SPI_pad_config_hd*/ #define EFUSE_RD_SPI_PAD_CONFIG_HD 0x0000001F diff --git a/components/soc/esp32/include/soc/gpio_reg.h b/components/soc/esp32/include/soc/gpio_reg.h index 1f4b08d43..8168f4ba1 100644 --- a/components/soc/esp32/include/soc/gpio_reg.h +++ b/components/soc/esp32/include/soc/gpio_reg.h @@ -129,8 +129,7 @@ #define GPIO_STRAP_REG (DR_REG_GPIO_BASE + 0x0038) /* GPIO_STRAPPING : RO ;bitpos:[15:0] ;default: ; */ -/*description: GPIO strapping results: {2'd0 boot_sel_dig[7:1] vsdio_boot_sel - boot_sel_chip[5:0]}. Boot_sel_dig[7:1]: {U0RXD SD_CLK SD_CMD SD_DATA0 SD_DATA1 SD_DATA2 SD_DATA3}. vsdio_boot_sel: MTDI. boot_sel_chip[5:0]: {GPIO0 U0TXD GPIO2 GPIO4 MTDO GPIO5}*/ +/*description: {10'b0, MTDI, GPIO0, GPIO2, GPIO4, MTDO, GPIO5} */ #define GPIO_STRAPPING 0x0000FFFF #define GPIO_STRAPPING_M ((GPIO_STRAPPING_V)<<(GPIO_STRAPPING_S)) #define GPIO_STRAPPING_V 0xFFFF diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index f13c113b4..e600e39e3 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -554,6 +554,36 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); +/** + * Structure describing vddsdio configuration + */ +typedef struct { + uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. + uint32_t enable : 1; //!< Enable VDDSDIO regulator + uint32_t tieh : 1; //!< Select VDDSDIO voltage: 1 — 1.8V, 0 — 3.3V + uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator + uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator + uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator +} rtc_vddsdio_config_t; + +/** + * Get current VDDSDIO configuration + * If VDDSDIO configuration is overridden by RTC, get values from RTC + * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE + * Otherwise, use default values and the level of MTDI bootstrapping pin. + * @return currently used VDDSDIO configuration + */ +rtc_vddsdio_config_t rtc_vddsdio_get_config(); + +/** + * Set new VDDSDIO configuration using RTC registers. + * If config.force == 1, this overrides configuration done using bootstrapping + * pins and EFUSE. + * + * @param config new VDDSDIO configuration + */ +void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); + #ifdef __cplusplus } diff --git a/components/soc/esp32/rtc_init.c b/components/soc/esp32/rtc_init.c index ff7b6b73c..44786fbcc 100644 --- a/components/soc/esp32/rtc_init.c +++ b/components/soc/esp32/rtc_init.c @@ -18,6 +18,8 @@ #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" #include "soc/dport_reg.h" +#include "soc/efuse_reg.h" +#include "soc/gpio_reg.h" void rtc_init(rtc_config_t cfg) @@ -94,3 +96,51 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } } + +rtc_vddsdio_config_t rtc_vddsdio_get_config() +{ + rtc_vddsdio_config_t result; + uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG); + result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S; + result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S; + result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S; + if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) { + // Get configuration from RTC + result.force = 1; + result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S; + result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S; + return result; + } + uint32_t efuse_reg = REG_READ(EFUSE_BLK0_RDATA4_REG); + if (efuse_reg & EFUSE_RD_SDIO_FORCE) { + // Get configuration from EFUSE + result.force = 0; + result.enable = (efuse_reg & EFUSE_RD_XPD_SDIO_REG_M) >> EFUSE_RD_XPD_SDIO_REG_S; + result.tieh = (efuse_reg & EFUSE_RD_SDIO_TIEH_M) >> EFUSE_RD_SDIO_TIEH_S; + // in this case, DREFH/M/L are also set from EFUSE + result.drefh = (efuse_reg & EFUSE_RD_SDIO_DREFH_M) >> EFUSE_RD_SDIO_DREFH_S; + result.drefm = (efuse_reg & EFUSE_RD_SDIO_DREFM_M) >> EFUSE_RD_SDIO_DREFM_S; + result.drefl = (efuse_reg & EFUSE_RD_SDIO_DREFL_M) >> EFUSE_RD_SDIO_DREFL_S; + return result; + } + + // Otherwise, VDD_SDIO is controlled by bootstrapping pin + uint32_t strap_reg = REG_READ(GPIO_STRAP_REG); + result.force = 0; + result.tieh = (strap_reg & BIT(5)) ? 0 : 1; + result.enable = result.tieh == 0; // only power on the regulator if VDD=1.8 + return result; +} + +void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) +{ + uint32_t val = 0; + val |= (config.force << RTC_CNTL_SDIO_FORCE_S); + val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S); + val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S); + val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S); + val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S); + val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S); + val |= RTC_CNTL_SDIO_PD_EN; + REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); +} diff --git a/components/soc/esp32/rtc_sleep.c b/components/soc/esp32/rtc_sleep.c index 0b20692fa..82a04d8ca 100644 --- a/components/soc/esp32/rtc_sleep.c +++ b/components/soc/esp32/rtc_sleep.c @@ -198,11 +198,9 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0); } - if (cfg.vddsdio_pd_en) { - SET_PERI_REG_MASK(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN); - } else { - CLEAR_PERI_REG_MASK(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN); - } + /* enable VDDSDIO control by state machine */ + REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); + REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, cfg.rtc_dbias_slp); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, cfg.rtc_dbias_wak); diff --git a/tools/unit-test-app/Makefile b/tools/unit-test-app/Makefile index e4f05ec99..13873900e 100644 --- a/tools/unit-test-app/Makefile +++ b/tools/unit-test-app/Makefile @@ -7,9 +7,6 @@ PROJECT_NAME := unit-test-app include $(IDF_PATH)/make/project.mk -print_flash_cmd: - echo $(ESPTOOL_WRITE_FLASH_OPTIONS) $(ESPTOOL_ALL_FLASH_ARGS) | sed -e 's:'$(PWD)/build/'::g' - # List of unit-test-app configurations. # Each file in configs/ directory defines a configuration. The format is the # same as sdkconfig file. Configuration is applied on top of sdkconfig.defaults