diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c index 147be37990..371d4be6a7 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c @@ -120,19 +120,19 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr) const char *str; switch (bootloader_hdr->spi_speed) { case ESP_IMAGE_SPI_SPEED_DIV_2: - str = "40MHz"; + str = "32MHz"; break; case ESP_IMAGE_SPI_SPEED_DIV_3: - str = "26.7MHz"; + str = "21.3MHz"; break; case ESP_IMAGE_SPI_SPEED_DIV_4: - str = "20MHz"; + str = "16MHz"; break; case ESP_IMAGE_SPI_SPEED_DIV_1: - str = "80MHz"; + str = "64MHz"; break; default: - str = "20MHz"; + str = "16MHz"; break; } ESP_LOGI(TAG, "SPI Speed : %s", str); diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index 93c66b0f70..de821e6e43 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -18,6 +18,7 @@ #include "esp_rom_sys.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" +#include "hal/spimem_flash_ll.h" #include "soc/io_mux_reg.h" #include "soc/lp_aon_reg.h" #include "soc/lp_clkrst_reg.h" @@ -153,6 +154,7 @@ static void rtc_clk_bbpll_disable(void) static void rtc_clk_bbpll_enable(void) { clk_ll_bbpll_enable(); + spimem_flash_ll_set_clock_source(MSPI_CLK_SRC_PLL_F64M); // Switch clock to PLL at same time. } static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index eab81b1bcb..d960fce182 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -59,6 +59,7 @@ #include "esp_private/sleep_modem.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_task_wdt.h" +#include "esp_private/spi_flash_os.h" #ifdef CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/cache.h" @@ -460,6 +461,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo pd_flags &= ~RTC_SLEEP_PD_INT_8M; } + // Set mspi clock to a low-power one. +#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT + spi_flash_set_clock_src(MSPI_CLK_SRC_ROM_DEFAULT); +#endif + // Save current frequency and switch to XTAL rtc_cpu_freq_config_t cpu_freq_config; rtc_clk_cpu_freq_get_config(&cpu_freq_config); @@ -628,6 +634,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo rtc_clk_cpu_freq_set_config(&cpu_freq_config); } + // Set mspi clock to ROM default one. +#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT + spi_flash_set_clock_src(MSPI_CLK_SRC_DEFAULT); +#endif + if (!deep_sleep) { s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); misc_modules_wake_prepare(); diff --git a/components/esp_system/port/esp_system_chip.c b/components/esp_system/port/esp_system_chip.c index 464cc6101e..d965c04382 100644 --- a/components/esp_system/port/esp_system_chip.c +++ b/components/esp_system/port/esp_system_chip.c @@ -7,9 +7,11 @@ #include #include "esp_cpu.h" #include "soc/soc.h" +#include "soc/soc_caps.h" #include "esp_private/rtc_clk.h" #include "esp_private/panic_internal.h" #include "esp_private/system_internal.h" +#include "esp_private/spi_flash_os.h" #include "esp_heap_caps.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -31,6 +33,10 @@ void IRAM_ATTR esp_restart_noos_dig(void) esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); } +#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT + spi_flash_set_clock_src(MSPI_CLK_SRC_ROM_DEFAULT); +#endif + // switch to XTAL (otherwise we will keep running from the PLL) rtc_clk_cpu_set_to_default_config(); diff --git a/components/esp_system/port/soc/esp32h2/system_internal.c b/components/esp_system/port/soc/esp32h2/system_internal.c index 2bf451d23a..fae2dfe44b 100644 --- a/components/esp_system/port/soc/esp32h2/system_internal.c +++ b/components/esp_system/port/soc/esp32h2/system_internal.c @@ -21,7 +21,9 @@ #include "soc/rtc_periph.h" #include "soc/uart_reg.h" #include "hal/wdt_hal.h" +#include "hal/spimem_flash_ll.h" #include "esp_private/cache_err_int.h" +#include "esp_private/spi_flash_os.h" #include "esp32h2/rom/cache.h" #include "esp32h2/rom/rtc.h" @@ -98,6 +100,9 @@ void IRAM_ATTR esp_restart_noos(void) CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); + // If we set mspi clock frequency to PLL, but ROM does not have such clock source option. So reset the clock to XTAL when software restart. + spi_flash_set_clock_src(MSPI_CLK_SRC_ROM_DEFAULT); + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. #if !CONFIG_IDF_ENV_FPGA rtc_clk_cpu_set_to_default_config(); diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index b091de1ebe..15eab2919a 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -99,6 +99,9 @@ menu "Serial flasher config" config ESPTOOLPY_FLASHFREQ_80M bool "80 MHz" depends on SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED + config ESPTOOLPY_FLASHFREQ_64M + bool "64 MHz" + depends on SOC_MEMSPI_SRC_FREQ_64M_SUPPORTED config ESPTOOLPY_FLASHFREQ_60M bool "60 MHz" depends on SOC_MEMSPI_SRC_FREQ_60M_SUPPORTED @@ -108,6 +111,9 @@ menu "Serial flasher config" config ESPTOOLPY_FLASHFREQ_40M bool "40 MHz" depends on SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED + config ESPTOOLPY_FLASHFREQ_32M + bool "32 MHz" + depends on SOC_MEMSPI_SRC_FREQ_32M_SUPPORTED config ESPTOOLPY_FLASHFREQ_30M bool "30 MHz" depends on SOC_MEMSPI_SRC_FREQ_30M_SUPPORTED @@ -120,6 +126,9 @@ menu "Serial flasher config" config ESPTOOLPY_FLASHFREQ_20M bool "20 MHz" depends on SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED + config ESPTOOLPY_FLASHFREQ_16M + bool "16 MHz" + depends on SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED config ESPTOOLPY_FLASHFREQ_15M bool "15 MHz" depends on SOC_MEMSPI_SRC_FREQ_15M_SUPPORTED @@ -138,12 +147,15 @@ menu "Serial flasher config" default '80m' if ESPTOOLPY_FLASHFREQ_120M default '80m' if ESPTOOLPY_FLASHFREQ_80M default '60m' if ESPTOOLPY_FLASHFREQ_60M + default '48m' if ESPTOOLPY_FLASHFREQ_64M # For 0xf in esptool default '48m' if ESPTOOLPY_FLASHFREQ_48M + default '24m' if ESPTOOLPY_FLASHFREQ_32M # For 0x0 in esptool default '30m' if ESPTOOLPY_FLASHFREQ_30M default '24m' if ESPTOOLPY_FLASHFREQ_24M default '40m' if ESPTOOLPY_FLASHFREQ_40M default '26m' if ESPTOOLPY_FLASHFREQ_26M default '20m' if ESPTOOLPY_FLASHFREQ_20M + default '12m' if ESPTOOLPY_FLASHFREQ_16M # For 0x2 in esptool default '20m' # if no clock can match in bin headers, go with minimal. diff --git a/components/hal/esp32h2/include/hal/spimem_flash_ll.h b/components/hal/esp32h2/include/hal/spimem_flash_ll.h index 29f0ddffa5..e8922a1318 100644 --- a/components/hal/esp32h2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +25,8 @@ #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include "soc/pcr_struct.h" +#include "soc/clk_tree_defs.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -399,6 +401,27 @@ static inline void spimem_flash_ll_set_read_mode(spi_mem_dev_t *dev, esp_flash_i dev->ctrl = ctrl; } +__attribute__((always_inline)) +static inline void spimem_flash_ll_set_clock_source(soc_periph_mspi_clk_src_t clk_src) +{ + switch (clk_src) { + case MSPI_CLK_SRC_XTAL: + PCR.mspi_conf.mspi_clk_sel = 0; + break; + case MSPI_CLK_SRC_RC_FAST: + PCR.mspi_conf.mspi_clk_sel = 1; + break; + case MSPI_CLK_SRC_PLL_F64M: + PCR.mspi_conf.mspi_clk_sel = 2; + break; + case MSPI_CLK_SRC_PLL_F48M: + PCR.mspi_conf.mspi_clk_sel = 3; + break; + default: + HAL_ASSERT(false); + } +} + /** * Set clock frequency to work at. * @@ -550,27 +573,24 @@ static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_ */ static inline uint8_t spimem_flash_ll_get_source_freq_mhz(void) { -// ESP32H2-TODO -#if 0 - // TODO: Default is PLL480M, this is hard-coded. - // In the future, we can get the CPU clock source by calling interface. uint8_t clock_val = 0; - switch (SPIMEM0.core_clk_sel.spi01_clk_sel) { + switch (PCR.mspi_conf.mspi_clk_sel) { case 0: - clock_val = 80; + clock_val = 32; break; case 1: - clock_val = 120; + clock_val = 8; break; case 2: - clock_val = 160; + clock_val = 64; + break; + case 3: + clock_val = 32; break; default: - abort(); + HAL_ASSERT(false); } return clock_val; -#endif - return 80; } /** diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 9260ffefb6..02e10d5a27 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -819,7 +819,19 @@ config SOC_SPI_MEM_SUPPORT_WRAP bool default y -config SOC_MEMSPI_SRC_FREQ_48M_SUPPORTED +config SOC_MEMSPI_SRC_FREQ_64M_SUPPORTED + bool + default y + +config SOC_MEMSPI_SRC_FREQ_32M_SUPPORTED + bool + default y + +config SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED + bool + default y + +config SOC_MEMSPI_CLOCK_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32h2/include/soc/clk_tree_defs.h b/components/soc/esp32h2/include/soc/clk_tree_defs.h index 146308bd29..959060688c 100644 --- a/components/soc/esp32h2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h2/include/soc/clk_tree_defs.h @@ -431,6 +431,23 @@ typedef enum { PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ } soc_periph_parlio_clk_src_t; +//////////////////////////////////////////////////MSPI/////////////////////////////////////////////////////////////////// +/** + * @brief Array initializer for all supported clock sources of MSPI digital controller + */ +#define SOC_MSPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_PLL_F64M, SOC_MOD_CLK_PLL_F48M} +/** + * @brief MSPI digital controller clock source + */ +typedef enum { + MSPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + MSPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + MSPI_CLK_SRC_PLL_F64M = SOC_MOD_CLK_PLL_F64M, /*!< Select PLL_F64M as the source clock */ + MSPI_CLK_SRC_PLL_F48M = SOC_MOD_CLK_PLL_F48M, /*!< Select PLL_F48M as the source clock */ + MSPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F64M, /*!< Select PLL_F64M as the default clock choice */ + MSPI_CLK_SRC_ROM_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as ROM default clock source */ +} soc_periph_mspi_clk_src_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 0fb701b2a4..60114f5100 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -361,7 +361,10 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) -#define SOC_MEMSPI_SRC_FREQ_48M_SUPPORTED 1 +#define SOC_MEMSPI_SRC_FREQ_64M_SUPPORTED 1 +#define SOC_MEMSPI_SRC_FREQ_32M_SUPPORTED 1 +#define SOC_MEMSPI_SRC_FREQ_16M_SUPPORTED 1 +#define SOC_MEMSPI_CLOCK_IS_INDEPENDENT 1 /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM 2 // Number of counter units diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 8dd66cce37..136472fd0a 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -36,12 +36,16 @@ esp_flash_t *esp_flash_default_chip = NULL; #define DEFAULT_FLASH_SPEED 120 #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_80M #define DEFAULT_FLASH_SPEED 80 +#elif defined CONFIG_ESPTOOLPY_FLASHFREQ_64M +#define DEFAULT_FLASH_SPEED 64 #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_60M #define DEFAULT_FLASH_SPEED 60 #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_48M #define DEFAULT_FLASH_SPEED 48 #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_40M #define DEFAULT_FLASH_SPEED 40 +#elif defined CONFIG_ESPTOOLPY_FLASHFREQ_32M +#define DEFAULT_FLASH_SPEED 32 #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_30M #define DEFAULT_FLASH_SPEED 30 #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_26M diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index d7319b5243..b195038cfa 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -56,6 +56,9 @@ #if CONFIG_SPIRAM #include "esp_private/esp_psram_io.h" #endif +#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT +#include "hal/cache_hal.h" +#endif /* bytes erased by SPIEraseBlock() ROM function */ #define BLOCK_ERASE_SIZE 65536 @@ -328,3 +331,13 @@ uint8_t esp_mspi_get_io(esp_mspi_io_t io) return s_mspi_io_num_default[io]; #endif // SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE } + +#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT + +IRAM_ATTR void spi_flash_set_clock_src(soc_periph_mspi_clk_src_t clk_src) +{ + cache_hal_freeze(CACHE_TYPE_INSTRUCTION); + spimem_flash_ll_set_clock_source(clk_src); + cache_hal_unfreeze(CACHE_TYPE_INSTRUCTION); +} +#endif // SOC_MEMSPI_CLOCK_IS_INDEPENDENT diff --git a/components/spi_flash/include/esp_private/spi_flash_os.h b/components/spi_flash/include/esp_private/spi_flash_os.h index 760930ef1a..0283909262 100644 --- a/components/spi_flash/include/esp_private/spi_flash_os.h +++ b/components/spi_flash/include/esp_private/spi_flash_os.h @@ -18,6 +18,7 @@ #include "hal/spi_flash_hal.h" #include "spi_flash_override.h" #include "soc/soc_caps.h" +#include "soc/clk_tree_defs.h" #ifdef __cplusplus extern "C" { @@ -244,6 +245,16 @@ extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops; */ void spi_flash_rom_impl_init(void); +#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT +/** + * @brief This functions is used to change spi flash clock source between PLL and others, which is used after system wake up from a low power mode or + * enter low-power mode like sleep. + * @param clk_src mspi(flash) clock source. + * + * @note Only called in startup. User should not call this function. + */ +void spi_flash_set_clock_src(soc_periph_mspi_clk_src_t clk_src); +#endif #ifdef __cplusplus }