diff --git a/components/hal/esp32/include/hal/spi_flash_ll.h b/components/hal/esp32/include/hal/spi_flash_ll.h index d4a2b4bcfc..0a9a956ad2 100644 --- a/components/hal/esp32/include/hal/spi_flash_ll.h +++ b/components/hal/esp32/include/hal/spi_flash_ll.h @@ -399,6 +399,16 @@ static inline void spi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup_t dev->ctrl2.setup_time = cs_setup_time - 1; } +/** + * @brief Set lock for SPI0 so that spi0 can request new cache request after a cache transfer. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on esp32 +} + /** * Get the spi flash source clock frequency. Used for calculating * the divider parameters. diff --git a/components/hal/esp32c2/include/hal/gpspi_flash_ll.h b/components/hal/esp32c2/include/hal/gpspi_flash_ll.h index 3887e7acdf..2777adf9cb 100644 --- a/components/hal/esp32c2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c2/include/hal/gpspi_flash_ll.h @@ -149,6 +149,16 @@ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on GPSPI +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/esp32c2/include/hal/spi_flash_ll.h b/components/hal/esp32c2/include/hal/spi_flash_ll.h index fea625a6fb..81bdc6f16a 100644 --- a/components/hal/esp32c2/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c2/include/hal/spi_flash_ll.h @@ -64,6 +64,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) gpspi_flash_ll_set_pe_bit((spi_dev_t*)dev) #else #define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev) #define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev) @@ -91,6 +92,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) spimem_flash_ll_set_pe_bit((spi_mem_dev_t*)dev) #endif diff --git a/components/hal/esp32c2/include/hal/spimem_flash_ll.h b/components/hal/esp32c2/include/hal/spimem_flash_ll.h index d97c41258d..25901a0eb2 100644 --- a/components/hal/esp32c2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c2/include/hal/spimem_flash_ll.h @@ -31,6 +31,7 @@ extern "C" { #define spimem_flash_ll_hw_get_id(dev) ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1) #define SPIMEM_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (60) +#define SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS (0x1f) typedef typeof(SPIMEM1.clock.val) spimem_flash_ll_clock_reg_t; @@ -207,6 +208,30 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 dev->flash_sus_ctrl.pesr_end_msk = sus_conf; } +/** + * Configure the delay after Suspend/Resume + * + * @param dev Beginning address of the peripheral registers. + * @param dly_val delay time + */ +static inline void spimem_flash_ll_set_sus_delay(spi_mem_dev_t *dev, uint32_t dly_val) +{ + dev->ctrl1.cs_hold_dly_res = dly_val; + dev->sus_status.flash_pes_dly_128 = 1; + dev->sus_status.flash_per_dly_128 = 1; +} + +/** + * Configure the cs hold delay time(used to set the minimum CS high time tSHSL) + * + * @param dev Beginning address of the peripheral registers. + * @param cs_hold_delay cs hold delay time + */ +static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t cs_hold_delay) +{ + SPIMEM0.ctrl2.cs_hold_delay = cs_hold_delay; +} + /** * Initialize auto wait idle mode * @@ -232,6 +257,35 @@ static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev) return dev->sus_status.flash_sus; } +/** + * @brief Set lock for SPI0 so that spi0 can request new cache request after a cache transfer. + * + * @param dev Beginning address of the peripheral registers. + * @param lock_time Lock delay time + */ +static inline void spimem_flash_ll_sus_set_spi0_lock_trans(spi_mem_dev_t *dev, uint32_t lock_time) +{ + dev->sus_status.spi0_lock_en = 1; + SPIMEM0.fsm.cspi_lock_delay_time = lock_time; +} + +/** + * @brief Get tsus unit values in SPI_CLK cycles + * + * @param dev Beginning address of the peripheral registers. + * @return uint32_t tsus unit values + */ +static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *dev) +{ + uint32_t tsus_unit = 0; + if (dev->sus_status.flash_pes_dly_128 == 1) { + tsus_unit = 128; + } else { + tsus_unit = 4; + } + return tsus_unit; +} + /** * Enable/disable write protection for the flash chip. * @@ -320,6 +374,17 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * This function is combined with `spimem_flash_ll_user_start`. The pe_bit will be cleared automatically once the operation done. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spimem_flash_ll_set_pe_bit(spi_mem_dev_t *dev) +{ + dev->cmd.flash_pe = 1; +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h index ae81a85e33..7a40c4a9d6 100644 --- a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h @@ -140,6 +140,16 @@ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on GPSPI +} + /** * Set HD pin high when flash work at spi mode. * diff --git a/components/hal/esp32c3/include/hal/spi_flash_ll.h b/components/hal/esp32c3/include/hal/spi_flash_ll.h index fea625a6fb..81bdc6f16a 100644 --- a/components/hal/esp32c3/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c3/include/hal/spi_flash_ll.h @@ -64,6 +64,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) gpspi_flash_ll_set_pe_bit((spi_dev_t*)dev) #else #define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev) #define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev) @@ -91,6 +92,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) spimem_flash_ll_set_pe_bit((spi_mem_dev_t*)dev) #endif diff --git a/components/hal/esp32c3/include/hal/spimem_flash_ll.h b/components/hal/esp32c3/include/hal/spimem_flash_ll.h index 76e6369b4f..cf75253aff 100644 --- a/components/hal/esp32c3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c3/include/hal/spimem_flash_ll.h @@ -32,6 +32,8 @@ extern "C" { #define spimem_flash_ll_get_hw(host_id) (((host_id)==SPI1_HOST ? &SPIMEM1 : NULL )) #define spimem_flash_ll_hw_get_id(dev) ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1) +#define SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS (0x1f) + typedef typeof(SPIMEM1.clock.val) spimem_flash_ll_clock_reg_t; /*------------------------------------------------------------------------------ @@ -207,6 +209,30 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } +/** + * Configure the delay after Suspend/Resume + * + * @param dev Beginning address of the peripheral registers. + * @param dly_val delay time + */ +static inline void spimem_flash_ll_set_sus_delay(spi_mem_dev_t *dev, uint32_t dly_val) +{ + dev->ctrl1.cs_hold_dly_res = dly_val; + dev->sus_status.pes_dly_128 = 1; + dev->sus_status.per_dly_128 = 1; +} + +/** + * Configure the cs hold delay time(used to set the minimum CS high time tSHSL) + * + * @param dev Beginning address of the peripheral registers. + * @param cs_hold_delay cs hold delay time + */ +static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t cs_hold_delay) +{ + SPIMEM0.ctrl2.cs_hold_delay = cs_hold_delay; +} + /** * Initialize auto wait idle mode * @@ -232,6 +258,35 @@ static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev) return dev->sus_status.flash_sus; } +/** + * @brief Set lock for SPI0 so that spi0 can request new cache request after a cache transfer. + * + * @param dev Beginning address of the peripheral registers. + * @param lock_time Lock delay time + */ +static inline void spimem_flash_ll_sus_set_spi0_lock_trans(spi_mem_dev_t *dev, uint32_t lock_time) +{ + dev->sus_status.spi0_lock_en = 1; + SPIMEM0.fsm.cspi_lock_delay_time = lock_time; +} + +/** + * @brief Get tsus unit values in SPI_CLK cycles + * + * @param dev Beginning address of the peripheral registers. + * @return uint32_t tsus unit values + */ +static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *dev) +{ + uint32_t tsus_unit = 0; + if (dev->sus_status.pes_dly_128 == 1) { + tsus_unit = 128; + } else { + tsus_unit = 4; + } + return tsus_unit; +} + /** * Enable/disable write protection for the flash chip. * @@ -320,6 +375,17 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * This function is combined with `spimem_flash_ll_user_start`. The pe_bit will be cleared automatically once the operation done. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spimem_flash_ll_set_pe_bit(spi_mem_dev_t *dev) +{ + dev->cmd.flash_pe = 1; +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/esp32c6/include/hal/gpspi_flash_ll.h b/components/hal/esp32c6/include/hal/gpspi_flash_ll.h index 1cd9da5ea4..d097df3ce9 100644 --- a/components/hal/esp32c6/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c6/include/hal/gpspi_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 */ @@ -140,6 +140,16 @@ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on GPSPI +} + /** * Set HD pin high when flash work at spi mode. * diff --git a/components/hal/esp32c6/include/hal/spi_flash_ll.h b/components/hal/esp32c6/include/hal/spi_flash_ll.h index 522b862cb0..64efbfdfaa 100644 --- a/components/hal/esp32c6/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c6/include/hal/spi_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 */ @@ -65,6 +65,7 @@ typedef union { #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) #define spi_flash_ll_set_extra_address(dev, extra_addr) { /* Not supported on gpspi on ESP32-C6*/ } +#define spi_flash_ll_set_pe_bit(dev) gpspi_flash_ll_set_pe_bit((spi_dev_t*)dev) #else #define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev) #define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev) @@ -92,6 +93,7 @@ typedef union { #define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time) #define spi_flash_ll_set_extra_address(dev, extra_addr) spimem_flash_ll_set_extra_address((spi_mem_dev_t*)dev, extra_addr) +#define spi_flash_ll_set_pe_bit(dev) spimem_flash_ll_set_pe_bit((spi_mem_dev_t*)dev) #endif diff --git a/components/hal/esp32c6/include/hal/spimem_flash_ll.h b/components/hal/esp32c6/include/hal/spimem_flash_ll.h index 27106133fd..71b1335202 100644 --- a/components/hal/esp32c6/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c6/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 */ @@ -33,6 +33,8 @@ extern "C" { #define spimem_flash_ll_get_hw(host_id) (((host_id)==SPI1_HOST ? &SPIMEM1 : NULL )) #define spimem_flash_ll_hw_get_id(dev) ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1) +#define SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS (0x1f) + typedef typeof(SPIMEM1.clock.val) spimem_flash_ll_clock_reg_t; /*------------------------------------------------------------------------------ @@ -208,6 +210,30 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } +/** + * Configure the delay after Suspend/Resume + * + * @param dev Beginning address of the peripheral registers. + * @param dly_val delay time + */ +static inline void spimem_flash_ll_set_sus_delay(spi_mem_dev_t *dev, uint32_t dly_val) +{ + dev->ctrl1.cs_hold_dly_res = dly_val; + dev->sus_status.flash_per_dly_128 = 1; + dev->sus_status.flash_pes_dly_128 = 1; +} + +/** + * Configure the cs hold delay time(used to set the minimum CS high time tSHSL) + * + * @param dev Beginning address of the peripheral registers. + * @param cs_hold_delay cs hold delay time + */ +static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t cs_hold_delay) +{ + SPIMEM0.ctrl2.cs_hold_delay = cs_hold_delay; +} + /** * Initialize auto wait idle mode * @@ -233,6 +259,35 @@ static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev) return dev->sus_status.flash_sus; } +/** + * @brief Set lock for SPI0 so that spi0 can request new cache request after a cache transfer. + * + * @param dev Beginning address of the peripheral registers. + * @param lock_time Lock delay time + */ +static inline void spimem_flash_ll_sus_set_spi0_lock_trans(spi_mem_dev_t *dev, uint32_t lock_time) +{ + dev->sus_status.spi0_lock_en = 1; + SPIMEM0.fsm.lock_delay_time = lock_time; +} + +/** + * @brief Get tsus unit values in SPI_CLK cycles + * + * @param dev Beginning address of the peripheral registers. + * @return uint32_t tsus unit values + */ +static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *dev) +{ + uint32_t tsus_unit = 0; + if (dev->sus_status.flash_pes_dly_128 == 1) { + tsus_unit = 128; + } else { + tsus_unit = 4; + } + return tsus_unit; +} + /** * Enable/disable write protection for the flash chip. * @@ -321,6 +376,17 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * This function is combined with `spimem_flash_ll_user_start`. The pe_bit will be cleared automatically once the operation done. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spimem_flash_ll_set_pe_bit(spi_mem_dev_t *dev) +{ + dev->cmd.flash_pe = 1; +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h index 91850dfd79..56bd7e77b8 100644 --- a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/gpspi_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 */ @@ -140,6 +140,16 @@ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on GPSPI +} + /** * Set HD pin high when flash work at spi mode. * diff --git a/components/hal/esp32h2/include/hal/spi_flash_ll.h b/components/hal/esp32h2/include/hal/spi_flash_ll.h index 425695498d..b14aff7eee 100644 --- a/components/hal/esp32h2/include/hal/spi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spi_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 */ @@ -65,6 +65,7 @@ typedef union { #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) #define spi_flash_ll_set_extra_address(dev, extra_addr) { /* Not supported on gpspi on ESP32-H2*/ } +#define spi_flash_ll_set_pe_bit(dev) gpspi_flash_ll_set_pe_bit((spi_dev_t*)dev) #else #define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev) #define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev) @@ -92,6 +93,7 @@ typedef union { #define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time) #define spi_flash_ll_set_extra_address(dev, extra_addr) spimem_flash_ll_set_extra_address((spi_mem_dev_t*)dev, extra_addr) +#define spi_flash_ll_set_pe_bit(dev) spimem_flash_ll_set_pe_bit((spi_mem_dev_t*)dev) #endif diff --git a/components/hal/esp32h2/include/hal/spimem_flash_ll.h b/components/hal/esp32h2/include/hal/spimem_flash_ll.h index e8922a1318..9135ff882a 100644 --- a/components/hal/esp32h2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spimem_flash_ll.h @@ -35,6 +35,8 @@ extern "C" { #define spimem_flash_ll_get_hw(host_id) (((host_id)==SPI1_HOST ? &SPIMEM1 : NULL )) #define spimem_flash_ll_hw_get_id(dev) ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1) +#define SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS (0x1f) + typedef typeof(SPIMEM1.clock.val) spimem_flash_ll_clock_reg_t; /*------------------------------------------------------------------------------ @@ -210,6 +212,30 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } +/** + * Configure the delay after Suspend/Resume + * + * @param dev Beginning address of the peripheral registers. + * @param dly_val delay time + */ +static inline void spimem_flash_ll_set_sus_delay(spi_mem_dev_t *dev, uint32_t dly_val) +{ + dev->ctrl1.cs_hold_dly_res = dly_val; + dev->sus_status.flash_per_dly_128 = 1; + dev->sus_status.flash_pes_dly_128 = 1; +} + +/** + * Configure the cs hold delay time(used to set the minimum CS high time tSHSL) + * + * @param dev Beginning address of the peripheral registers. + * @param cs_hold_delay cs hold delay time + */ +static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t cs_hold_delay) +{ + SPIMEM0.ctrl2.cs_hold_delay = cs_hold_delay; +} + /** * Initialize auto wait idle mode * @@ -235,6 +261,35 @@ static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev) return dev->sus_status.flash_sus; } +/** + * @brief Set lock for SPI0 so that spi0 can request new cache request after a cache transfer. + * + * @param dev Beginning address of the peripheral registers. + * @param lock_time Lock delay time + */ +static inline void spimem_flash_ll_sus_set_spi0_lock_trans(spi_mem_dev_t *dev, uint32_t lock_time) +{ + dev->sus_status.spi0_lock_en = 1; + SPIMEM0.fsm.lock_delay_time = lock_time; +} + +/** + * @brief Get tsus unit values in SPI_CLK cycles + * + * @param dev Beginning address of the peripheral registers. + * @return uint32_t tsus unit values + */ +static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *dev) +{ + uint32_t tsus_unit = 0; + if (dev->sus_status.flash_pes_dly_128 == 1) { + tsus_unit = 128; + } else { + tsus_unit = 4; + } + return tsus_unit; +} + /** * Enable/disable write protection for the flash chip. * @@ -323,6 +378,17 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * This function is combined with `spimem_flash_ll_user_start`. The pe_bit will be cleared automatically once the operation done. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spimem_flash_ll_set_pe_bit(spi_mem_dev_t *dev) +{ + dev->cmd.flash_pe = 1; +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h index 4a0d1c086b..c839a98bc5 100644 --- a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h @@ -134,6 +134,16 @@ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on GPSPI +} + /** * Set HD pin high when flash work at spi mode. * diff --git a/components/hal/esp32s2/include/hal/spi_flash_ll.h b/components/hal/esp32s2/include/hal/spi_flash_ll.h index 1aa9d800b5..b5da668b16 100644 --- a/components/hal/esp32s2/include/hal/spi_flash_ll.h +++ b/components/hal/esp32s2/include/hal/spi_flash_ll.h @@ -65,6 +65,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) gpspi_flash_ll_set_pe_bit((spi_dev_t*)dev) #else @@ -94,6 +95,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) spimem_flash_ll_set_pe_bit((spi_mem_dev_t*)dev) #endif diff --git a/components/hal/esp32s2/include/hal/spimem_flash_ll.h b/components/hal/esp32s2/include/hal/spimem_flash_ll.h index f4bf54f3f0..ed2dc569e4 100644 --- a/components/hal/esp32s2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s2/include/hal/spimem_flash_ll.h @@ -316,6 +316,17 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * This function is combined with `spimem_flash_ll_user_start`. The pe_bit will be cleared automatically once the operation done. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spimem_flash_ll_set_pe_bit(spi_mem_dev_t *dev) +{ + dev->cmd.flash_pe = 1; +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h index aab2e4d4ec..c9deccb6b6 100644 --- a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h @@ -145,6 +145,16 @@ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) +{ + // Not supported on GPSPI +} + /** * Set HD pin high when flash work at spi mode. * diff --git a/components/hal/esp32s3/include/hal/spi_flash_ll.h b/components/hal/esp32s3/include/hal/spi_flash_ll.h index f9d2ecadf6..7c046ea7df 100644 --- a/components/hal/esp32s3/include/hal/spi_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spi_flash_ll.h @@ -63,6 +63,7 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) gpspi_flash_ll_set_pe_bit((spi_dev_t*)dev) #else #define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev) @@ -91,6 +92,8 @@ typedef union { #define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev) #define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time) +#define spi_flash_ll_set_pe_bit(dev) spimem_flash_ll_set_pe_bit((spi_mem_dev_t*)dev) + #endif #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/spimem_flash_ll.h b/components/hal/esp32s3/include/hal/spimem_flash_ll.h index 4e8d5744f6..ddc49a9f4e 100644 --- a/components/hal/esp32s3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spimem_flash_ll.h @@ -32,6 +32,8 @@ extern "C" { #define spimem_flash_ll_get_hw(host_id) (((host_id)==SPI1_HOST ? &SPIMEM1 : NULL )) #define spimem_flash_ll_hw_get_id(dev) ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1) +#define SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS (0x1f) + typedef typeof(SPIMEM1.clock.val) spimem_flash_ll_clock_reg_t; /*------------------------------------------------------------------------------ @@ -120,6 +122,7 @@ static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev) static inline void spimem_flash_ll_auto_suspend_init(spi_mem_dev_t *dev, bool auto_sus) { dev->flash_sus_ctrl.flash_pes_en = auto_sus; // enable Flash Auto-Suspend. + dev->flash_sus_cmd.pes_per_en = auto_sus; } /** @@ -167,7 +170,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t */ static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd) { - abort(); //Not support on esp32s3 + //Not support on esp32s3 } /** @@ -201,7 +204,59 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool */ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_mask) { - abort();// Not supported on esp32s3 + // Not supported on esp32s3 +} + +/** + * Configure the delay after Suspend/Resume + * + * @param dev Beginning address of the peripheral registers. + * @param dly_val delay time + */ +static inline void spimem_flash_ll_set_sus_delay(spi_mem_dev_t *dev, uint32_t dly_val) +{ + dev->ctrl1.cs_hold_dly_res = dly_val; + dev->sus_status.flash_per_dly_256 = 1; + dev->sus_status.flash_pes_dly_256 = 1; +} + +/** + * Configure the cs hold delay time(used to set the minimum CS high time tSHSL) + * + * @param dev Beginning address of the peripheral registers. + * @param cs_hold_delay cs hold delay time + */ +static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t cs_hold_delay) +{ + SPIMEM0.ctrl2.cs_hold_delay = cs_hold_delay; +} + +/** + * @brief Set lock for SPI0 so that spi0 can request new cache request after a cache transfer. + * + * @param dev Beginning address of the peripheral registers. + * @param lock_time Lock delay time + */ +static inline void spimem_flash_ll_sus_set_spi0_lock_trans(spi_mem_dev_t *dev, uint32_t lock_time) +{ + // Not support on esp32s3 +} + +/** + * @brief Get tsus unit values in SPI_CLK cycles + * + * @param dev Beginning address of the peripheral registers. + * @return uint32_t tsus unit values + */ +static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *dev) +{ + uint32_t tsus_unit = 0; + if (dev->sus_status.flash_pes_dly_256 == 1) { + tsus_unit = 128; + } else { + tsus_unit = 4; + } + return tsus_unit; } /** @@ -214,6 +269,8 @@ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool { HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value. dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function. + dev->flash_sus_cmd.flash_per_wait_en = 1; + dev->flash_sus_cmd.flash_pes_wait_en = 1; } /** @@ -316,6 +373,17 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev) dev->cmd.usr = 1; } +/** + * In user mode, it is set to indicate that program/erase operation will be triggered. + * This function is combined with `spimem_flash_ll_user_start`. The pe_bit will be cleared automatically once the operation done. + * + * @param dev Beginning address of the peripheral registers. + */ +static inline void spimem_flash_ll_set_pe_bit(spi_mem_dev_t *dev) +{ + dev->cmd.flash_pe = 1; +} + /** * Check whether the host is idle to perform new commands. * diff --git a/components/hal/include/hal/spi_flash_hal.h b/components/hal/include/hal/spi_flash_hal.h index a17e1acd11..2abf7820f1 100644 --- a/components/hal/include/hal/spi_flash_hal.h +++ b/components/hal/include/hal/spi_flash_hal.h @@ -47,8 +47,9 @@ typedef struct { spi_flash_sus_cmd_conf sus_cfg; ///< To store suspend command/mask information. uint32_t slicer_flags; /// Slicer flags for configuring how to slice data correctly while reading or writing. #define SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR BIT(0) ///< Slice data according to DTR mode, the address and length must be even (A0=0). + int freq_mhz; /// Flash clock frequency. } spi_flash_hal_context_t; -ESP_STATIC_ASSERT(sizeof(spi_flash_hal_context_t) == 40, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM"); +ESP_STATIC_ASSERT(sizeof(spi_flash_hal_context_t) == 44, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM"); /// This struct provide MSPI Flash necessary timing related config, should be consistent with that in union in `spi_flash_hal_config_t`. typedef struct { diff --git a/components/hal/include/hal/spi_flash_types.h b/components/hal/include/hal/spi_flash_types.h index 53d22d9e26..d36332e2d8 100644 --- a/components/hal/include/hal/spi_flash_types.h +++ b/components/hal/include/hal/spi_flash_types.h @@ -27,6 +27,7 @@ typedef struct { #define SPI_FLASH_TRANS_FLAG_CMD16 BIT(0) ///< Send command of 16 bits #define SPI_FLASH_TRANS_FLAG_IGNORE_BASEIO BIT(1) ///< Not applying the basic io mode configuration for this transaction #define SPI_FLASH_TRANS_FLAG_BYTE_SWAP BIT(2) ///< Used for DTR mode, to swap the bytes of a pair of rising/falling edge +#define SPI_FLASH_TRANS_FLAG_PE_CMD BIT(3) ///< Indicates that this transaction is to erase/program flash chip. uint16_t command; ///< Command to send uint8_t dummy_bitlen; ///< Basic dummy bits to use uint32_t io_mode; ///< Flash working mode when `SPI_FLASH_IGNORE_BASEIO` is specified. diff --git a/components/hal/spi_flash_hal.c b/components/hal/spi_flash_hal.c index 75992468b8..30c088bec4 100644 --- a/components/hal/spi_flash_hal.c +++ b/components/hal/spi_flash_hal.c @@ -103,6 +103,7 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_ .cs_hold = cfg->cs_hold, .cs_setup = cfg->cs_setup, .base_io_mode = cfg->default_io_mode, + .freq_mhz = cfg->freq_mhz, }; #if SOC_SPI_MEM_SUPPORT_TIMING_TUNING if (cfg->using_timing_tuning) { diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index 11ba34d2f9..f563d61d47 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -170,6 +170,9 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr spi_flash_ll_set_buffer_data(dev, trans->mosi_data, trans->mosi_len); spi_flash_ll_set_miso_bitlen(dev, trans->miso_len * 8); + if ((trans->flags & SPI_FLASH_TRANS_FLAG_PE_CMD) != 0) { + spi_flash_ll_set_pe_bit(dev); + } spi_flash_ll_user_start(dev); host->driver->poll_cmd_done(host); if (trans->miso_len > 0) { diff --git a/components/hal/spi_flash_hal_iram.c b/components/hal/spi_flash_hal_iram.c index 28f02c2023..3adb6404bd 100644 --- a/components/hal/spi_flash_hal_iram.c +++ b/components/hal/spi_flash_hal_iram.c @@ -6,11 +6,14 @@ #include "sdkconfig.h" #include "hal/spi_flash_hal.h" + #if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host); void spi_flash_hal_disable_auto_resume_mode(spi_flash_host_inst_t *host); void spi_flash_hal_disable_auto_suspend_mode(spi_flash_host_inst_t *host); void spi_flash_hal_setup_auto_resume_mode(spi_flash_host_inst_t *host); +#define SPI_FLASH_TSUS_SAFE_VAL_US (30) +#define SPI_FLASH_TSHSL2_SAFE_VAL_NS (30) #endif //SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND #ifndef CONFIG_SPI_FLASH_ROM_IMPL @@ -128,10 +131,12 @@ esp_err_t spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const sp spi_mem_dev_t *dev = (spi_mem_dev_t *)spi_flash_ll_get_hw(SPI1_HOST); spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host; memcpy(&(ctx->sus_cfg), sus_conf, sizeof(spi_flash_sus_cmd_conf)); - spimem_flash_ll_set_read_sus_status(dev, sus_conf->sus_mask); spimem_flash_ll_suspend_cmd_setup(dev, sus_conf->sus_cmd); spimem_flash_ll_resume_cmd_setup(dev, sus_conf->res_cmd); +#if SOC_SPI_MEM_SUPPORT_CHECK_SUS + spimem_flash_ll_set_read_sus_status(dev, sus_conf->sus_mask); spimem_flash_ll_rd_sus_cmd_setup(dev, sus_conf->cmd_rdsr); +#endif // SOC_SPI_MEM_SUPPORT_CHECK_SUS #endif // SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND return ESP_OK; } @@ -140,8 +145,16 @@ esp_err_t spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const sp void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host) { spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI1_HOST); + spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host; spimem_flash_ll_auto_wait_idle_init(dev, true); spimem_flash_ll_auto_suspend_init(dev, true); + // tsus = ceil(SPI_FLASH_TSUS_SAFE_VAL_US * ctx->freq_mhz / spimem_flash_ll_get_tsus_unit_in_cycles); + uint32_t tsus = (SPI_FLASH_TSUS_SAFE_VAL_US * ctx->freq_mhz / spimem_flash_ll_get_tsus_unit_in_cycles(dev)) + ((SPI_FLASH_TSUS_SAFE_VAL_US * ctx->freq_mhz) % spimem_flash_ll_get_tsus_unit_in_cycles(dev) != 0); + spimem_flash_ll_set_sus_delay(dev, tsus); + // tshsl2 = ceil(SPI_FLASH_TSHSL2_SAFE_VAL_NS * spimem_flash_ll_get_source_freq_mhz() * 0.001); + uint32_t tshsl2 = (SPI_FLASH_TSHSL2_SAFE_VAL_NS * spimem_flash_ll_get_source_freq_mhz() / 1000) + ((SPI_FLASH_TSHSL2_SAFE_VAL_NS * spimem_flash_ll_get_source_freq_mhz()) % 1000 != 0); + spimem_flash_set_cs_hold_delay(dev, tshsl2); + spimem_flash_ll_sus_set_spi0_lock_trans(dev, SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS); #if SOC_SPI_MEM_SUPPORT_CHECK_SUS spimem_flash_ll_sus_check_sus_setup(dev, true); #endif diff --git a/components/soc/esp32c3/include/soc/spi_mem_struct.h b/components/soc/esp32c3/include/soc/spi_mem_struct.h index 4b78f184d0..d816a9a290 100644 --- a/components/soc/esp32c3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32c3/include/soc/spi_mem_struct.h @@ -238,7 +238,14 @@ typedef volatile struct spi_mem_dev_s { union { struct { uint32_t flash_sus: 1; /*The status of flash suspend only used in SPI1.*/ - uint32_t reserved1: 31; /*reserved*/ + uint32_t wait_pesr_cmd_2b:1; + uint32_t hpm_dly_128: 1; + uint32_t res_dly_128: 1; + uint32_t dp_dly_128: 1; + uint32_t per_dly_128: 1; + uint32_t pes_dly_128: 1; + uint32_t spi0_lock_en: 1; + uint32_t reserved1: 24; /*reserved*/ }; uint32_t val; } sus_status; diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 0304ed5edf..55d870e48e 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -951,10 +951,6 @@ config SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE bool default y -config SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND - bool - default y - config SOC_SPI_MEM_SUPPORT_SW_SUSPEND bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 5bcdb66265..287683578c 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -414,7 +414,6 @@ /*-------------------------- SPI MEM CAPS ---------------------------------------*/ #define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE (1) -#define SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND (1) #define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1) #define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) diff --git a/components/spi_flash/.build-test-rules.yml b/components/spi_flash/.build-test-rules.yml index 6f208cb0ab..aaa7c74123 100644 --- a/components/spi_flash/.build-test-rules.yml +++ b/components/spi_flash/.build-test-rules.yml @@ -11,3 +11,11 @@ components/spi_flash/test_apps/flash_encryption: - if: IDF_TARGET in ["esp32c2", "esp32s2", "esp32c6", "esp32h2"] temporary: true reason: No runners # IDF-5634 + +components/spi_flash/test_apps/flash_suspend: + disable: + - if: SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND != 1 + disable_test: + - if: IDF_TARGET != "esp32c3" + temporary: true + reason: lack of runners diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index a0c5e0e0bf..3a9f1240f3 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -147,17 +147,24 @@ menu "SPI Flash driver" help Defines how many ticks will be before returning to continue a erasing. + config SPI_FLASH_SUSPEND_QVL_SUPPORTED + # Internally usage + bool + default y if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C2 + default n + config SPI_FLASH_AUTO_SUSPEND bool "Auto suspend long erase/write operations (READ DOCS FIRST)" default n - depends on IDF_TARGET_ESP32C3 && !SPI_FLASH_ROM_IMPL + depends on SPI_FLASH_SUSPEND_QVL_SUPPORTED && !SPI_FLASH_ROM_IMPL help - This option is default n before ESP32-C3, because it needs bootloader support. + This option is default n because it can't be used in every situation. You need to + evaluate this feature through suspend part in `SPI Flash API` document. CAUTION: If you want to OTA to an app with this feature turned on, please make sure the bootloader has the support for it. (later than IDF v4.3) - Auto-suspend feature only supported by XMC chip. + Auto-suspend feature only supported by specific flash chips. If you are using an official module, please contact Espressif Business support. Also reading auto suspend part in `SPI Flash API` document before you enable this function. diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index cda8449b68..03037c472d 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -97,26 +97,7 @@ esp_flash_t *esp_flash_default_chip = NULL; .input_delay_ns = 0,\ .cs_setup = 1,\ } -#elif CONFIG_IDF_TARGET_ESP32S2 -#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \ - .host_id = SPI1_HOST,\ - .freq_mhz = DEFAULT_FLASH_SPEED, \ - .cs_num = 0, \ - .iomux = true, \ - .input_delay_ns = 0,\ - .cs_setup = 1,\ -} -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/efuse.h" -#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \ - .host_id = SPI1_HOST,\ - .freq_mhz = DEFAULT_FLASH_SPEED, \ - .cs_num = 0, \ - .iomux = true, \ - .input_delay_ns = 0,\ - .cs_setup = 1,\ -} -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#else // Other target #if !CONFIG_SPI_FLASH_AUTO_SUSPEND #define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \ .host_id = SPI1_HOST,\ @@ -137,7 +118,7 @@ esp_flash_t *esp_flash_default_chip = NULL; .cs_setup = 1,\ } #endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND -#endif +#endif // Other target static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_flash_spi_device_config_t *config, bool use_iomux, int cs_id) { diff --git a/components/spi_flash/spi_flash_chip_gd.c b/components/spi_flash/spi_flash_chip_gd.c index d8696177dd..9aabf52972 100644 --- a/components/spi_flash/spi_flash_chip_gd.c +++ b/components/spi_flash/spi_flash_chip_gd.c @@ -11,6 +11,7 @@ #include "spi_flash_chip_generic.h" #include "spi_flash_chip_gd.h" #include "spi_flash_defs.h" +#include "sdkconfig.h" #define ADDR_32BIT(addr) (addr >= (1<<24)) @@ -33,6 +34,17 @@ spi_flash_caps_t spi_flash_chip_gd_get_caps(esp_flash_t *chip) if ((chip->chip_id & 0xFF) >= 0x19) { caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT; } +#if CONFIG_SPI_FLASH_AUTO_SUSPEND + switch (chip->chip_id) { + /* The flash listed here can support suspend */ + case 0xC84017: + case 0xC84018: + caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND; + break; + default: + break; + } +#endif // flash-suspend is not supported // flash read unique id. caps_flags |= SPI_FLASH_CHIP_CAP_UNIQUE_ID; @@ -112,6 +124,18 @@ esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* } #endif //CONFIG_SPI_FLASH_ROM_IMPL +esp_err_t spi_flash_chip_gd_suspend_cmd_conf(esp_flash_t *chip) +{ + spi_flash_sus_cmd_conf sus_conf = { + .sus_mask = 0x84, + .cmd_rdsr = CMD_RDSR2, + .sus_cmd = CMD_SUSPEND, + .res_cmd = CMD_RESUME, + }; + + return chip->host->driver->sus_setup(chip->host, &sus_conf); +} + static const char chip_name[] = "gd"; // The issi chip can use the functions for generic chips except from set read mode and probe, @@ -148,7 +172,7 @@ const spi_flash_chip_t esp_flash_chip_gd = { .read_reg = spi_flash_chip_generic_read_reg, .yield = spi_flash_chip_generic_yield, - .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, + .sus_setup = spi_flash_chip_gd_suspend_cmd_conf, .read_unique_id = spi_flash_chip_generic_read_unique_id, .get_chip_caps = spi_flash_chip_gd_get_caps, .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, diff --git a/components/spi_flash/spi_flash_chip_winbond.c b/components/spi_flash/spi_flash_chip_winbond.c index 6bec557716..8da9714e32 100644 --- a/components/spi_flash/spi_flash_chip_winbond.c +++ b/components/spi_flash/spi_flash_chip_winbond.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -209,6 +201,7 @@ static esp_err_t spi_flash_command_winbond_program_4B(esp_flash_t *chip, const v .address = address, .mosi_len = length, .mosi_data = buffer, + .flags = SPI_FLASH_TRANS_FLAG_PE_CMD, }; return chip->host->driver->common_command(chip->host, &t); } @@ -220,6 +213,7 @@ esp_err_t spi_flash_command_winbond_erase_sector_4B(esp_flash_t *chip, uint32_t .command = (addr_4b? CMD_SECTOR_ERASE_4B: CMD_SECTOR_ERASE), .address_bitlen = (addr_4b? 32: 24), .address = start_address, + .flags = SPI_FLASH_TRANS_FLAG_PE_CMD, }; return chip->host->driver->common_command(chip->host, &t); } @@ -231,6 +225,7 @@ esp_err_t spi_flash_command_erase_block_4B(esp_flash_t *chip, uint32_t start_add .command = (addr_4b? CMD_LARGE_BLOCK_ERASE_4B: CMD_LARGE_BLOCK_ERASE), .address_bitlen = (addr_4b? 32: 24), .address = start_address, + .flags = SPI_FLASH_TRANS_FLAG_PE_CMD, }; return chip->host->driver->common_command(chip->host, &t); } diff --git a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c index 814c9a5d72..cf72f29859 100644 --- a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c +++ b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c @@ -459,55 +459,6 @@ static void test_flash_erase_not_trigger_wdt(const esp_partition_t *part) TEST_CASE_MULTI_FLASH_LONG("Test erasing flash chip not triggering WDT", test_flash_erase_not_trigger_wdt); - -#if CONFIG_SPI_FLASH_AUTO_SUSPEND -void esp_test_for_suspend(void) -{ - /*clear content in cache*/ -#if !CONFIG_IDF_TARGET_ESP32C3 - Cache_Invalidate_DCache_All(); -#endif - Cache_Invalidate_ICache_All(); - ESP_LOGI(TAG, "suspend test begins:"); - printf("run into test suspend function\n"); - printf("print something when flash is erasing:\n"); - printf("aaaaa bbbbb zzzzz fffff qqqqq ccccc\n"); -} - -static volatile bool task_erase_end, task_suspend_end = false; -void task_erase_large_region(void *arg) -{ - esp_partition_t *part = (esp_partition_t *)arg; - test_erase_large_region(part); - task_erase_end = true; - vTaskDelete(NULL); -} - -void task_request_suspend(void *arg) -{ - vTaskDelay(2); - ESP_LOGI(TAG, "flash go into suspend"); - esp_test_for_suspend(); - task_suspend_end = true; - vTaskDelete(NULL); -} - -static void test_flash_suspend_resume(const esp_partition_t* part) -{ - xTaskCreatePinnedToCore(task_request_suspend, "suspend", 2048, (void *)"test_for_suspend", UNITY_FREERTOS_PRIORITY + 3, NULL, 0); - xTaskCreatePinnedToCore(task_erase_large_region, "test", 2048, (void *)part, UNITY_FREERTOS_PRIORITY + 2, NULL, 0); - while (!task_erase_end || !task_suspend_end) { - } - vTaskDelay(200); -} - -TEST_CASE("SPI flash suspend and resume test", "[esp_flash][test_env=UT_T1_Flash_Suspend]") -{ - flash_test_func(test_flash_suspend_resume, 1 /* first index reserved for main flash */ ); -} - -#endif //CONFIG_SPI_FLASH_AUTO_SUSPEND - static void test_write_protection(const esp_partition_t* part) { esp_flash_t* chip = part->flash_chip; diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 9d838d8aae..7fab495004 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -999,7 +999,6 @@ components/spi_flash/include/spi_flash_chip_winbond.h components/spi_flash/spi_flash_chip_boya.c components/spi_flash/spi_flash_chip_issi.c components/spi_flash/spi_flash_chip_mxic.c -components/spi_flash/spi_flash_chip_winbond.c components/spi_flash/test/test_esp_flash.c components/spi_flash/test/test_flash_encryption.c components/spi_flash/test/test_mmap.c