Преглед на файлове

spi_flash: 2nd stage for supporting flash suspend. (1). Support more esp chips (2). Improve real-time performance (3). Making timing more stable (4) Add documents

Cao Sen Miao преди 2 години
родител
ревизия
ed96dadd06
променени са 34 файла, в които са добавени 514 реда и са изтрити 103 реда
  1. 10 0
      components/hal/esp32/include/hal/spi_flash_ll.h
  2. 10 0
      components/hal/esp32c2/include/hal/gpspi_flash_ll.h
  3. 2 0
      components/hal/esp32c2/include/hal/spi_flash_ll.h
  4. 65 0
      components/hal/esp32c2/include/hal/spimem_flash_ll.h
  5. 10 0
      components/hal/esp32c3/include/hal/gpspi_flash_ll.h
  6. 2 0
      components/hal/esp32c3/include/hal/spi_flash_ll.h
  7. 66 0
      components/hal/esp32c3/include/hal/spimem_flash_ll.h
  8. 11 1
      components/hal/esp32c6/include/hal/gpspi_flash_ll.h
  9. 3 1
      components/hal/esp32c6/include/hal/spi_flash_ll.h
  10. 67 1
      components/hal/esp32c6/include/hal/spimem_flash_ll.h
  11. 11 1
      components/hal/esp32h2/include/hal/gpspi_flash_ll.h
  12. 3 1
      components/hal/esp32h2/include/hal/spi_flash_ll.h
  13. 66 0
      components/hal/esp32h2/include/hal/spimem_flash_ll.h
  14. 10 0
      components/hal/esp32s2/include/hal/gpspi_flash_ll.h
  15. 2 0
      components/hal/esp32s2/include/hal/spi_flash_ll.h
  16. 11 0
      components/hal/esp32s2/include/hal/spimem_flash_ll.h
  17. 10 0
      components/hal/esp32s3/include/hal/gpspi_flash_ll.h
  18. 3 0
      components/hal/esp32s3/include/hal/spi_flash_ll.h
  19. 70 2
      components/hal/esp32s3/include/hal/spimem_flash_ll.h
  20. 2 1
      components/hal/include/hal/spi_flash_hal.h
  21. 1 0
      components/hal/include/hal/spi_flash_types.h
  22. 1 0
      components/hal/spi_flash_hal.c
  23. 3 0
      components/hal/spi_flash_hal_common.inc
  24. 14 1
      components/hal/spi_flash_hal_iram.c
  25. 8 1
      components/soc/esp32c3/include/soc/spi_mem_struct.h
  26. 0 4
      components/soc/esp32s2/include/soc/Kconfig.soc_caps.in
  27. 0 1
      components/soc/esp32s2/include/soc/soc_caps.h
  28. 8 0
      components/spi_flash/.build-test-rules.yml
  29. 10 3
      components/spi_flash/Kconfig
  30. 2 21
      components/spi_flash/esp_flash_spi_init.c
  31. 25 1
      components/spi_flash/spi_flash_chip_gd.c
  32. 8 13
      components/spi_flash/spi_flash_chip_winbond.c
  33. 0 49
      components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c
  34. 0 1
      tools/ci/check_copyright_ignore.txt

+ 10 - 0
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;
     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
  * Get the spi flash source clock frequency. Used for calculating
  * the divider parameters.
  * the divider parameters.

+ 10 - 0
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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 2 - 0
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_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_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_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
 #else
 #define spi_flash_ll_reset(dev)                              spimem_flash_ll_reset((spi_mem_dev_t*)dev)
 #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)
 #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_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_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_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
 #endif
 
 

+ 65 - 0
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_hw_get_id(dev)   ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1)
 
 
 #define SPIMEM_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ  (60)
 #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;
 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;
     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
  * 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;
     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.
  * 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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 10 - 0
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;
     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.
  * Set HD pin high when flash work at spi mode.
  *
  *

+ 2 - 0
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_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_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_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
 #else
 #define spi_flash_ll_reset(dev)                              spimem_flash_ll_reset((spi_mem_dev_t*)dev)
 #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)
 #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_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_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_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
 #endif
 
 

+ 66 - 0
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_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_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;
 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);
     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
  * 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;
     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.
  * 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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 11 - 1
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
  * 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;
     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.
  * Set HD pin high when flash work at spi mode.
  *
  *

+ 3 - 1
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
  * 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_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_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_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
 #else
 #define spi_flash_ll_reset(dev)                              spimem_flash_ll_reset((spi_mem_dev_t*)dev)
 #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)
 #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_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_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_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
 #endif
 
 

+ 67 - 1
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
  * 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_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_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;
 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);
     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
  * 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;
     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.
  * 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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 11 - 1
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
  * 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;
     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.
  * Set HD pin high when flash work at spi mode.
  *
  *

+ 3 - 1
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
  * 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_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_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_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
 #else
 #define spi_flash_ll_reset(dev)                              spimem_flash_ll_reset((spi_mem_dev_t*)dev)
 #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)
 #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_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_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_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
 #endif
 
 

+ 66 - 0
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_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_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;
 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);
     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
  * 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;
     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.
  * 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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 10 - 0
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;
     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.
  * Set HD pin high when flash work at spi mode.
  *
  *

+ 2 - 0
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_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_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_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
 #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_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_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_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
 #endif
 
 

+ 11 - 0
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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 10 - 0
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;
     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.
  * Set HD pin high when flash work at spi mode.
  *
  *

+ 3 - 0
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_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_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_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
 #else
 #define spi_flash_ll_reset(dev)                              spimem_flash_ll_reset((spi_mem_dev_t*)dev)
 #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_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_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_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
 #endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 70 - 2
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_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_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;
 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)
 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_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)
 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)
 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.
     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_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;
     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.
  * Check whether the host is idle to perform new commands.
  *
  *

+ 2 - 1
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.
     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.
     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).
 #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;
 } 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`.
 /// This struct provide MSPI Flash necessary timing related config, should be consistent with that in union in `spi_flash_hal_config_t`.
 typedef struct {
 typedef struct {

+ 1 - 0
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_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_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_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
     uint16_t command;           ///< Command to send
     uint8_t dummy_bitlen;       ///< Basic dummy bits to use
     uint8_t dummy_bitlen;       ///< Basic dummy bits to use
     uint32_t io_mode;           ///< Flash working mode when `SPI_FLASH_IGNORE_BASEIO` is specified.
     uint32_t io_mode;           ///< Flash working mode when `SPI_FLASH_IGNORE_BASEIO` is specified.

+ 1 - 0
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_hold = cfg->cs_hold,
         .cs_setup = cfg->cs_setup,
         .cs_setup = cfg->cs_setup,
         .base_io_mode = cfg->default_io_mode,
         .base_io_mode = cfg->default_io_mode,
+        .freq_mhz = cfg->freq_mhz,
     };
     };
 #if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
 #if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
     if (cfg->using_timing_tuning) {
     if (cfg->using_timing_tuning) {

+ 3 - 0
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_buffer_data(dev, trans->mosi_data, trans->mosi_len);
 
 
     spi_flash_ll_set_miso_bitlen(dev, trans->miso_len * 8);
     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);
     spi_flash_ll_user_start(dev);
     host->driver->poll_cmd_done(host);
     host->driver->poll_cmd_done(host);
     if (trans->miso_len > 0) {
     if (trans->miso_len > 0) {

+ 14 - 1
components/hal/spi_flash_hal_iram.c

@@ -6,11 +6,14 @@
 #include "sdkconfig.h"
 #include "sdkconfig.h"
 
 
 #include "hal/spi_flash_hal.h"
 #include "hal/spi_flash_hal.h"
+
 #if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
 #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_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_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_disable_auto_suspend_mode(spi_flash_host_inst_t *host);
 void spi_flash_hal_setup_auto_resume_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
 #endif //SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
 
 
 #ifndef CONFIG_SPI_FLASH_ROM_IMPL
 #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_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;
     spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host;
     memcpy(&(ctx->sus_cfg), sus_conf, sizeof(spi_flash_sus_cmd_conf));
     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_suspend_cmd_setup(dev, sus_conf->sus_cmd);
     spimem_flash_ll_resume_cmd_setup(dev, sus_conf->res_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);
     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
 #endif // SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
     return ESP_OK;
     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)
 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_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_wait_idle_init(dev, true);
     spimem_flash_ll_auto_suspend_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
 #if SOC_SPI_MEM_SUPPORT_CHECK_SUS
     spimem_flash_ll_sus_check_sus_setup(dev, true);
     spimem_flash_ll_sus_check_sus_setup(dev, true);
 #endif
 #endif

+ 8 - 1
components/soc/esp32c3/include/soc/spi_mem_struct.h

@@ -238,7 +238,14 @@ typedef volatile struct spi_mem_dev_s {
     union {
     union {
         struct {
         struct {
             uint32_t flash_sus:     1;                  /*The status of flash suspend  only used in SPI1.*/
             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;
         uint32_t val;
     } sus_status;
     } sus_status;

+ 0 - 4
components/soc/esp32s2/include/soc/Kconfig.soc_caps.in

@@ -951,10 +951,6 @@ config SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE
     bool
     bool
     default y
     default y
 
 
-config SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
-    bool
-    default y
-
 config SOC_SPI_MEM_SUPPORT_SW_SUSPEND
 config SOC_SPI_MEM_SUPPORT_SW_SUSPEND
     bool
     bool
     default y
     default y

+ 0 - 1
components/soc/esp32s2/include/soc/soc_caps.h

@@ -414,7 +414,6 @@
 
 
 /*-------------------------- SPI MEM CAPS ---------------------------------------*/
 /*-------------------------- SPI MEM CAPS ---------------------------------------*/
 #define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE                (1)
 #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_SW_SUSPEND                    (1)
 #define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE          (1)
 #define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE          (1)
 #define SOC_SPI_MEM_SUPPORT_WRAP                          (1)
 #define SOC_SPI_MEM_SUPPORT_WRAP                          (1)

+ 8 - 0
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"]
     - if: IDF_TARGET in ["esp32c2", "esp32s2", "esp32c6", "esp32h2"]
       temporary: true
       temporary: true
       reason: No runners # IDF-5634
       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

+ 10 - 3
components/spi_flash/Kconfig

@@ -147,17 +147,24 @@ menu "SPI Flash driver"
         help
         help
             Defines how many ticks will be before returning to continue a erasing.
             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
     config SPI_FLASH_AUTO_SUSPEND
         bool "Auto suspend long erase/write operations (READ DOCS FIRST)"
         bool "Auto suspend long erase/write operations (READ DOCS FIRST)"
         default n
         default n
-        depends on IDF_TARGET_ESP32C3 && !SPI_FLASH_ROM_IMPL
+        depends on SPI_FLASH_SUSPEND_QVL_SUPPORTED && !SPI_FLASH_ROM_IMPL
         help
         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
             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)
             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.
             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.
             Also reading auto suspend part in `SPI Flash API` document before you enable this function.
 
 

+ 2 - 21
components/spi_flash/esp_flash_spi_init.c

@@ -97,26 +97,7 @@ esp_flash_t *esp_flash_default_chip = NULL;
     .input_delay_ns = 0,\
     .input_delay_ns = 0,\
     .cs_setup = 1,\
     .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
 #if !CONFIG_SPI_FLASH_AUTO_SUSPEND
 #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \
 #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \
     .host_id = SPI1_HOST,\
     .host_id = SPI1_HOST,\
@@ -137,7 +118,7 @@ esp_flash_t *esp_flash_default_chip = NULL;
     .cs_setup = 1,\
     .cs_setup = 1,\
 }
 }
 #endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND
 #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)
 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)
 {
 {

+ 25 - 1
components/spi_flash/spi_flash_chip_gd.c

@@ -11,6 +11,7 @@
 #include "spi_flash_chip_generic.h"
 #include "spi_flash_chip_generic.h"
 #include "spi_flash_chip_gd.h"
 #include "spi_flash_chip_gd.h"
 #include "spi_flash_defs.h"
 #include "spi_flash_defs.h"
+#include "sdkconfig.h"
 
 
 #define ADDR_32BIT(addr)            (addr >= (1<<24))
 #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) {
     if ((chip->chip_id & 0xFF) >= 0x19) {
         caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT;
         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-suspend is not supported
     // flash read unique id.
     // flash read unique id.
     caps_flags |= SPI_FLASH_CHIP_CAP_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
 #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";
 static const char chip_name[] = "gd";
 
 
 // The issi chip can use the functions for generic chips except from set read mode and probe,
 // 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,
     .read_reg = spi_flash_chip_generic_read_reg,
     .yield = spi_flash_chip_generic_yield,
     .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,
     .read_unique_id = spi_flash_chip_generic_read_unique_id,
     .get_chip_caps = spi_flash_chip_gd_get_caps,
     .get_chip_caps = spi_flash_chip_gd_get_caps,
     .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode,
     .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode,

+ 8 - 13
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 <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
@@ -209,6 +201,7 @@ static esp_err_t spi_flash_command_winbond_program_4B(esp_flash_t *chip, const v
         .address = address,
         .address = address,
         .mosi_len = length,
         .mosi_len = length,
         .mosi_data = buffer,
         .mosi_data = buffer,
+        .flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
     };
     };
     return chip->host->driver->common_command(chip->host, &t);
     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),
         .command = (addr_4b? CMD_SECTOR_ERASE_4B: CMD_SECTOR_ERASE),
         .address_bitlen = (addr_4b? 32: 24),
         .address_bitlen = (addr_4b? 32: 24),
         .address = start_address,
         .address = start_address,
+        .flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
     };
     };
     return chip->host->driver->common_command(chip->host, &t);
     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),
         .command = (addr_4b? CMD_LARGE_BLOCK_ERASE_4B: CMD_LARGE_BLOCK_ERASE),
         .address_bitlen = (addr_4b? 32: 24),
         .address_bitlen = (addr_4b? 32: 24),
         .address = start_address,
         .address = start_address,
+        .flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
     };
     };
     return chip->host->driver->common_command(chip->host, &t);
     return chip->host->driver->common_command(chip->host, &t);
 }
 }

+ 0 - 49
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);
 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)
 static void test_write_protection(const esp_partition_t* part)
 {
 {
     esp_flash_t* chip = part->flash_chip;
     esp_flash_t* chip = part->flash_chip;

+ 0 - 1
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_boya.c
 components/spi_flash/spi_flash_chip_issi.c
 components/spi_flash/spi_flash_chip_issi.c
 components/spi_flash/spi_flash_chip_mxic.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_esp_flash.c
 components/spi_flash/test/test_flash_encryption.c
 components/spi_flash/test/test_flash_encryption.c
 components/spi_flash/test/test_mmap.c
 components/spi_flash/test/test_mmap.c