diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index 2ff0e595a2..2f4e906220 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -119,6 +119,15 @@ bool bootloader_common_label_search(const char *list, char *label); */ void bootloader_configure_spi_pins(int drv); +/** + * @brief Get flash CS IO + * + * Can be determined by eFuse values, or the default value + * + * @return Flash CS IO + */ +uint8_t bootloader_flash_get_cs_io(void); + /** * @brief Calculates a sha-256 for a given partition or returns a appended digest. * diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 2369436d7e..2acbd74fa9 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -23,6 +23,7 @@ #include "esp_rom_crc.h" #include "esp_rom_gpio.h" #include "esp_rom_sys.h" +#include "esp_rom_efuse.h" #include "esp_flash_partitions.h" #include "bootloader_flash_priv.h" #include "bootloader_common.h" @@ -191,8 +192,19 @@ void bootloader_common_vddsdio_configure(void) #endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST } - RESET_REASON bootloader_common_get_reset_reason(int cpu_no) { return (RESET_REASON)esp_rom_get_reset_reason(cpu_no); } + +uint8_t bootloader_flash_get_cs_io(void) +{ + uint8_t cs_io; + const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); + if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { + cs_io = SPI_CS0_GPIO_NUM; + } else { + cs_io = (spiconfig >> 18) & 0x3f; + } + return cs_io; +} diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index bf8443b296..2d09fa5f12 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -33,5 +33,22 @@ menu "Hardware Settings" config ESP_SLEEP_RTC_BUS_ISO_WORKAROUND bool default y if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + + config ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND + bool "PSRAM leakage current workaround in light sleep" + depends on SPIRAM + help + When the CS pin of SPIRAM is not pulled up, the sleep current will + increase during light sleep. If the CS pin of SPIRAM has an external + pull-up, you do not need to select this option, otherwise, you + should enable this option. + + config ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND + bool "Flash leakage current workaround in light sleep" + help + When the CS pin of Flash is not pulled up, the sleep current will + increase during light sleep. If the CS pin of Flash has an external + pull-up, you do not need to select this option, otherwise, you + should enable this option. endmenu endmenu diff --git a/components/esp_hw_support/include/soc/esp32/spiram.h b/components/esp_hw_support/include/soc/esp32/spiram.h index e58712d1fa..a6086f3d31 100644 --- a/components/esp_hw_support/include/soc/esp32/spiram.h +++ b/components/esp_hw_support/include/soc/esp32/spiram.h @@ -85,6 +85,15 @@ size_t esp_spiram_get_size(void); */ void esp_spiram_writeback_cache(void); +/** + * @brief get psram CS IO + * + * This interface should be called after PSRAM is enabled, otherwise it will + * return an invalid value -1/0xff. + * + * @return psram CS IO or -1/0xff if psram not enabled + */ +uint8_t esp_spiram_get_cs_io(void); /** diff --git a/components/esp_hw_support/include/soc/esp32s2/spiram.h b/components/esp_hw_support/include/soc/esp32s2/spiram.h index 7750d45abe..70d07e61a8 100644 --- a/components/esp_hw_support/include/soc/esp32s2/spiram.h +++ b/components/esp_hw_support/include/soc/esp32s2/spiram.h @@ -70,6 +70,15 @@ size_t esp_spiram_get_size(void); */ void esp_spiram_writeback_cache(void); +/** + * @brief get psram CS IO + * + * This interface should be called after PSRAM is enabled, otherwise it will + * return an invalid value -1/0xff. + * + * @return psram CS IO or -1/0xff if psram not enabled + */ +uint8_t esp_spiram_get_cs_io(void); /** diff --git a/components/esp_hw_support/include/soc/esp32s3/spiram.h b/components/esp_hw_support/include/soc/esp32s3/spiram.h index 7efb616946..067c3d27bf 100644 --- a/components/esp_hw_support/include/soc/esp32s3/spiram.h +++ b/components/esp_hw_support/include/soc/esp32s3/spiram.h @@ -79,6 +79,16 @@ void esp_spiram_writeback_cache(void); */ bool esp_spiram_is_initialized(void); +/** + * @brief get psram CS IO + * + * This interface should be called after PSRAM is enabled, otherwise it will + * return an invalid value -1/0xff. + * + * @return psram CS IO or -1/0xff if psram not enabled + */ +uint8_t esp_spiram_get_cs_io(void); + /** * @brief Reserve a pool of internal memory for specific DMA/internal allocations * diff --git a/components/esp_hw_support/port/esp32/spiram.c b/components/esp_hw_support/port/esp32/spiram.c index d0806f16ef..651aff4e12 100644 --- a/components/esp_hw_support/port/esp32/spiram.c +++ b/components/esp_hw_support/port/esp32/spiram.c @@ -316,4 +316,8 @@ bool esp_spiram_is_initialized(void) return spiram_inited; } +uint8_t esp_spiram_get_cs_io(void) +{ + return psram_get_cs_io(); +} #endif diff --git a/components/esp_hw_support/port/esp32/spiram_psram.c b/components/esp_hw_support/port/esp32/spiram_psram.c index f0d579a13d..e3de144b53 100644 --- a/components/esp_hw_support/port/esp32/spiram_psram.c +++ b/components/esp_hw_support/port/esp32/spiram_psram.c @@ -195,6 +195,13 @@ typedef struct { static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +static uint8_t s_psram_cs_io = (uint8_t)-1; + +uint8_t psram_get_cs_io(void) +{ + return s_psram_cs_io; +} + static void psram_clear_spi_fifo(psram_spi_num_t spi_num) { int i; @@ -839,6 +846,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad ESP_EARLY_LOGE(TAG, "Not a valid or known package id: %d", pkg_ver); abort(); } + s_psram_cs_io = psram_io.psram_cs_io; const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { diff --git a/components/esp_hw_support/port/esp32/spiram_psram.h b/components/esp_hw_support/port/esp32/spiram_psram.h index 263fb924dc..abcc98f0ff 100644 --- a/components/esp_hw_support/port/esp32/spiram_psram.h +++ b/components/esp_hw_support/port/esp32/spiram_psram.h @@ -63,6 +63,13 @@ psram_size_t psram_get_size(void); */ esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode); +/** + * @brief get psram CS IO + * + * @return psram CS IO + */ +uint8_t psram_get_cs_io(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32s2/spiram.c b/components/esp_hw_support/port/esp32s2/spiram.c index 38eb9ea8c6..ebb2be078b 100644 --- a/components/esp_hw_support/port/esp32s2/spiram.c +++ b/components/esp_hw_support/port/esp32s2/spiram.c @@ -377,6 +377,11 @@ bool esp_spiram_is_initialized(void) return spiram_inited; } +uint8_t esp_spiram_get_cs_io(void) +{ + return psram_get_cs_io(); +} + /* Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been @@ -415,4 +420,5 @@ bool esp_spiram_test(void) return true; } } + #endif diff --git a/components/esp_hw_support/port/esp32s2/spiram_psram.c b/components/esp_hw_support/port/esp32s2/spiram_psram.c index beb83ef2f6..d4dec8eac9 100644 --- a/components/esp_hw_support/port/esp32s2/spiram_psram.c +++ b/components/esp_hw_support/port/esp32s2/spiram_psram.c @@ -160,6 +160,13 @@ static uint32_t s_psram_id = 0; static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); +static uint8_t s_psram_cs_io = (uint8_t)-1; + +uint8_t psram_get_cs_io(void) +{ + return s_psram_cs_io; +} + static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode) { if (mode == PSRAM_CMD_QPI) { @@ -367,6 +374,7 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) psram_io.psram_spiwp_sd3_io = esp_rom_efuse_get_flash_wp_gpio(); } esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig); + s_psram_cs_io = psram_io.psram_cs_io; } psram_size_t psram_get_size(void) diff --git a/components/esp_hw_support/port/esp32s2/spiram_psram.h b/components/esp_hw_support/port/esp32s2/spiram_psram.h index 8b30922e99..819bdc6203 100644 --- a/components/esp_hw_support/port/esp32s2/spiram_psram.h +++ b/components/esp_hw_support/port/esp32s2/spiram_psram.h @@ -68,5 +68,11 @@ typedef enum { esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode); +/** + * @brief get psram CS IO + * + * @return psram CS IO + */ +uint8_t psram_get_cs_io(void); #endif diff --git a/components/esp_hw_support/port/esp32s3/opiram_psram.c b/components/esp_hw_support/port/esp32s3/opiram_psram.c index 584f45ce3a..3b28e601a7 100644 --- a/components/esp_hw_support/port/esp32s3/opiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/opiram_psram.c @@ -38,7 +38,7 @@ #define OCT_PSRAM_ADDR_BITLEN 32 #define OCT_PSRAM_RD_DUMMY_BITLEN (2*(10-1)) #define OCT_PSRAM_WR_DUMMY_BITLEN (2*(5-1)) -#define OCT_PSRAM_CS1_IO 26 +#define OCT_PSRAM_CS1_IO CONFIG_DEFAULT_PSRAM_CS_IO #define OCT_PSRAM_CS_SETUP_TIME 3 #define OCT_PSRAM_CS_HOLD_TIME 3 @@ -102,6 +102,11 @@ static const char* TAG = "opi psram"; static DRAM_ATTR psram_size_t s_psram_size; static void IRAM_ATTR s_config_psram_spi_phases(void); +uint8_t IRAM_ATTR psram_get_cs_io(void) +{ + return OCT_PSRAM_CS1_IO; +} + /** * Initialise mode registers of the PSRAM */ @@ -224,7 +229,7 @@ static void IRAM_ATTR s_init_psram_pins(void) //Set cs1 pin function PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1); //Set mspi cs1 drive strength - PIN_SET_DRV(IO_MUX_GPIO26_REG, 3); + PIN_SET_DRV(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], 3); //Set psram clock pin drive strength REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3); } diff --git a/components/esp_hw_support/port/esp32s3/spiram.c b/components/esp_hw_support/port/esp32s3/spiram.c index e713fab3e3..d0fa5f09af 100644 --- a/components/esp_hw_support/port/esp32s3/spiram.c +++ b/components/esp_hw_support/port/esp32s3/spiram.c @@ -329,4 +329,9 @@ bool esp_spiram_is_initialized(void) return s_spiram_inited; } +uint8_t esp_spiram_get_cs_io(void) +{ + return psram_get_cs_io(); +} + #endif diff --git a/components/esp_hw_support/port/esp32s3/spiram_psram.c b/components/esp_hw_support/port/esp32s3/spiram_psram.c index b0e07abd19..535d52349a 100644 --- a/components/esp_hw_support/port/esp32s3/spiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/spiram_psram.c @@ -121,6 +121,13 @@ static uint32_t s_psram_id = 0; static void IRAM_ATTR config_psram_spi_phases(void); extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); +static uint8_t s_psram_cs_io = (uint8_t)-1; + +uint8_t psram_get_cs_io(void) +{ + return s_psram_cs_io; +} + static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode) { if (mode == PSRAM_CMD_QPI) { @@ -301,6 +308,7 @@ static void IRAM_ATTR psram_gpio_config(void) esp_rom_gpio_connect_out_signal(cs1_io, SPICS1_OUT_IDX, 0, 0); gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs1_io], PIN_FUNC_GPIO); } + s_psram_cs_io = cs1_io; //WP HD uint8_t wp_io = PSRAM_SPIWP_SD3_IO; diff --git a/components/esp_hw_support/port/esp32s3/spiram_psram.h b/components/esp_hw_support/port/esp32s3/spiram_psram.h index 7d9a083756..06128ccfcc 100644 --- a/components/esp_hw_support/port/esp32s3/spiram_psram.h +++ b/components/esp_hw_support/port/esp32s3/spiram_psram.h @@ -68,5 +68,11 @@ typedef enum { esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode); +/** + * @brief get psram CS IO + * + * @return psram CS IO + */ +uint8_t psram_get_cs_io(void); #endif diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 776ef053d8..b9f874c3c6 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -19,6 +19,15 @@ #include "driver/gpio.h" #include "esp_private/gpio.h" #include "esp_private/sleep_gpio.h" +#include "bootloader_common.h" + +#ifdef CONFIG_IDF_TARGET_ESP32 +#include "esp32/spiram.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/spiram.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/spiram.h" +#endif static const char *TAG = "sleep"; @@ -53,6 +62,12 @@ void esp_sleep_config_gpio_isolate(void) gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); } } +#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM + gpio_sleep_set_pull_mode(esp_spiram_get_cs_io(), GPIO_PULLUP_ONLY); +#endif +#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND + gpio_sleep_set_pull_mode(bootloader_flash_get_cs_io(), GPIO_PULLUP_ONLY); +#endif } void esp_sleep_enable_gpio_switch(bool enable)