Skip to content

Commit

Permalink
spi_flash: Add auto suspend mode on esp32c3
Browse files Browse the repository at this point in the history
  • Loading branch information
mythbuster5 committed Jan 25, 2021
1 parent 1f37a5f commit 9905da4
Show file tree
Hide file tree
Showing 30 changed files with 759 additions and 170 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
#define CMD_WRAP 0x77 /* Set burst with wrap command */
#define CMD_RESUME 0x7A /* Resume command to clear flash suspend bit */


/* Provide a Flash API for bootloader_support code,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ static void IRAM_ATTR bootloader_init_flash_configure(void)
bootloader_flash_cs_timing_config();
}

static void bootloader_spi_flash_resume(void)
{
bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
}

static esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
Expand All @@ -204,6 +210,7 @@ static esp_err_t bootloader_init_spi_flash(void)
}
#endif

bootloader_spi_flash_resume();
esp_rom_spiflash_unlock();

#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
Expand Down
45 changes: 0 additions & 45 deletions components/hal/esp32/include/hal/spi_flash_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,51 +117,6 @@ static inline void spi_flash_ll_erase_block(spi_dev_t *dev)
dev->cmd.flash_be = 1;
}

/**
* Suspend erase/program operation.
*
* @param dev Beginning address of the peripheral registers.
*/
static inline void spi_flash_ll_suspend(spi_dev_t *dev)
{
dev->cmd.flash_pes = 1;
}

/**
* Resume suspended erase/program operation.
*
* @param dev Beginning address of the peripheral registers.
*/
static inline void spi_flash_ll_resume(spi_dev_t *dev)
{
dev->cmd.flash_per = 1;
}

/**
* Initialize auto wait idle mode. (work only for ESP32-S2)
*
* @param dev Beginning address of the peripheral registers.
* @param auto_sus Enable/disable Flash Auto-Suspend.
*/
#define spi_flash_ll_auto_wait_idle_init(...) ()

/**
* Initialize auto wait idle mode (work only for ESP32-S2)
*
* @param dev Beginning address of the peripheral registers.
* @param auto_waiti Enable/disable auto wait-idle function
*/
#define spi_flash_ll_auto_suspend_init(...) ()

/**
* Return the suspend status of erase or program operations. (work only for ESP32-S2)
*
* @param dev Beginning address of the peripheral registers.
*
* @return true if suspended, otherwise false.
*/
#define spi_flash_ll_sus_status(...) ({false;})

/**
* Enable/disable write protection for the flash chip.
*
Expand Down
141 changes: 141 additions & 0 deletions components/hal/esp32c3/include/hal/spimem_flash_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,147 @@ static inline void spimem_flash_ll_erase_block(spi_mem_dev_t *dev)
dev->cmd.flash_be = 1;
}

/**
* Suspend erase/program operation.
*
* @param dev Beginning address of the peripheral registers.
*/
static inline void spimem_flash_ll_suspend(spi_mem_dev_t *dev)
{
dev->flash_sus_ctrl.flash_pes = 1;
}

/**
* Resume suspended erase/program operation.
*
* @param dev Beginning address of the peripheral registers.
*/
static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev)
{
dev->flash_sus_ctrl.flash_per = 1;
}

/**
* Initialize auto suspend mode, and esp32c3 doesn't support disable auto-suspend.
*
* @param dev Beginning address of the peripheral registers.
* @param auto_sus Enable/disable Flash Auto-Suspend.
*/
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;
}

/**
* Initialize auto resume mode
*
* @param dev Beginning address of the peripheral registers.
* @param auto_res Enable/Disable Flash Auto-Resume.
*
*/
static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool auto_res)
{
dev->flash_sus_ctrl.pes_per_en = auto_res;
}

/**
* Setup the flash suspend command, may vary from chips to chips.
*
* @param dev Beginning address of the peripheral registers.
* @param sus_cmd Flash suspend command.
*
*/
static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd)
{
dev->flash_sus_cmd.flash_pes_command = sus_cmd;
}

/**
* Setup the flash resume command, may vary from chips to chips.
*
* @param dev Beginning address of the peripheral registers.
* @param res_cmd Flash resume command.
*
*/
static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd)
{
dev->flash_sus_cmd.flash_per_command = res_cmd;
}

/**
* Setup the flash read suspend status command, may vary from chips to chips.
*
* @param dev Beginning address of the peripheral registers.
* @param pesr_cmd Flash read suspend status command.
*
*/
static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd)
{
dev->flash_sus_cmd.wait_pesr_command = pesr_cmd;
}

/**
* Setup to check SUS/SUS1/SUS2 to ensure the suspend status of flashs.
*
* @param dev Beginning address of the peripheral registers.
* @param sus_check_sus_en 1: enable, 0: disable.
*
*/
static inline void spimem_flash_ll_sus_check_sus_setup(spi_mem_dev_t *dev, bool sus_check_sus_en)
{
dev->flash_sus_ctrl.sus_timeout_cnt = 5;
dev->flash_sus_ctrl.pes_end_en = sus_check_sus_en;
}

/**
* Setup to check SUS/SUS1/SUS2 to ensure the resume status of flashs.
*
* @param dev Beginning address of the peripheral registers.
* @param sus_check_sus_en 1: enable, 0: disable.
*
*/
static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool res_check_sus_en)
{
dev->flash_sus_ctrl.sus_timeout_cnt = 5;
dev->flash_sus_ctrl.per_end_en = res_check_sus_en;
}

/**
* Set 8 bit command to read suspend status
*
* @param dev Beginning address of the peripheral registers.
*/
static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf)
{
dev->flash_sus_ctrl.frd_sus_2b = 0;
dev->flash_sus_ctrl.pesr_end_msk = sus_conf;
}

/**
* Initialize auto wait idle mode
*
* @param dev Beginning address of the peripheral registers.
* @param auto_waiti Enable/disable auto wait-idle function
*/
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
{
dev->flash_waiti_ctrl.waiti_cmd = 0x05;
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
}

/**
* Return the suspend status of erase or program operations.
*
* @param dev Beginning address of the peripheral registers.
*
* @return true if suspended, otherwise false.
*/
static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev)
{
return dev->sus_status.flash_sus;
}

/**
* Enable/disable write protection for the flash chip.
*
Expand Down
5 changes: 0 additions & 5 deletions components/hal/esp32s2/include/hal/spi_flash_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ typedef union {
#define spi_flash_ll_erase_chip(dev) spimem_flash_ll_erase_chip((spi_mem_dev_t*)dev)
#define spi_flash_ll_erase_sector(dev) spimem_flash_ll_erase_sector((spi_mem_dev_t*)dev)
#define spi_flash_ll_erase_block(dev) spimem_flash_ll_erase_block((spi_mem_dev_t*)dev)
#define spi_flash_ll_suspend(dev) spimem_flash_ll_suspend((spi_mem_dev_t*)dev)
#define spi_flash_ll_resume(dev) spimem_flash_ll_resume((spi_mem_dev_t*)dev)
#define spi_flash_ll_set_write_protect(dev, wp) spimem_flash_ll_set_write_protect((spi_mem_dev_t*)dev, wp)
#define spi_flash_ll_get_buffer_data(dev, buffer, read_len) spimem_flash_ll_get_buffer_data((spi_mem_dev_t*)dev, buffer, read_len)
#define spi_flash_ll_set_buffer_data(dev, buffer, len) spimem_flash_ll_set_buffer_data((spi_mem_dev_t*)dev, buffer, len)
Expand All @@ -105,9 +103,6 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
#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_auto_wait_idle_init(dev, auto_waiti) spimem_flash_ll_auto_wait_idle_init((spi_mem_dev_t*)dev, auto_waiti)
#define spi_flash_ll_auto_suspend_init(dev, auto_sus) spimem_flash_ll_auto_suspend_init((spi_mem_dev_t*)dev, auto_sus)
#define spi_flash_ll_sus_status(dev) spimem_flash_ll_sus_status((spi_mem_dev_t*)dev)

#endif

Expand Down
94 changes: 85 additions & 9 deletions components/hal/esp32s2/include/hal/spimem_flash_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,24 +122,100 @@ static inline void spimem_flash_ll_suspend(spi_mem_dev_t *dev)
*/
static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev)
{
dev->misc.auto_per = 0; // Must disable Hardware Auto-Resume (should not be enabled, ESP32-S2 has bugs).
dev->flash_sus_cmd.flash_per = 1;
while (dev->flash_sus_cmd.flash_per) { };
}

/**
* Initialize auto wait idle mode
* Initialize auto suspend mode
*
* @param dev Beginning address of the peripheral registers.
* @param auto_sus Enable/disable Flash Auto-Suspend.
*/
static inline void spimem_flash_ll_auto_suspend_init(spi_mem_dev_t *dev, bool auto_sus)
{
dev->flash_sus_ctrl.flash_pes_command = 0x75; // Set auto suspend command, usually 0x75
dev->flash_sus_ctrl.flash_per_command = 0x7A; // Set auto resume command, usually 0x7A
// SET_PERI_REG_MASK(SPI_MEM_FLASH_SUS_CMD_REG(1), SPI_MEM_PES_PER_EN_M); // Only on S3 chip
// SET_PERI_REG_MASK(SPI_MEM_FLASH_SUS_CMD_REG(1), SPI_MEM_PESR_IDLE_EN_M); // MUST SET 1, to avoid missing Resume (Only on S3 chip)
dev->flash_sus_ctrl.flash_pes_en = auto_sus; // enable Flash Auto-Suspend.
dev->flash_sus_ctrl.flash_pes_en = auto_sus;
}

/**
* Initialize auto resume mode
*
* @param dev Beginning address of the peripheral registers.
* @param auto_res Enable/Disable Flash Auto-Resume.
*
*/
static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool auto_res)
{
dev->misc.auto_per = 0; // Must disable Hardware Auto-Resume (should not be enabled, ESP32-S2 has bugs).
}

/**
* Set 8 bit command to read suspend status
*
* @param dev Beginning address of the peripheral registers.
*/
static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_mask)
{
abort();// Not supported on esp32s2
}

/**
* Setup the flash suspend command, may vary from chips to chips.
*
* @param dev Beginning address of the peripheral registers.
* @param sus_cmd Flash suspend command.
*
*/
static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd)
{
dev->flash_sus_ctrl.flash_pes_command = sus_cmd;
}

/**
* Setup the flash resume command, may vary from chips to chips.
*
* @param dev Beginning address of the peripheral registers.
* @param res_cmd Flash resume command.
*
*/
static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd)
{
dev->flash_sus_ctrl.flash_per_command = res_cmd;
}

/**
* Setup the flash read suspend status command, may vary from chips to chips.
*
* @param dev Beginning address of the peripheral registers.
* @param pesr_cmd Flash read suspend status command.
*
*/
static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd)
{
abort();// Not supported on esp32s2
}

/**
* Setup to check SUS/SUS1/SUS2 to ensure the suspend status of flashs.
*
* @param dev Beginning address of the peripheral registers.
* @param sus_check_sus_en 1: enable, 0: disable.
*
*/
static inline void spimem_flash_ll_sus_check_sus_setup(spi_mem_dev_t *dev, bool sus_check_sus_en)
{
abort();// Not supported on esp32s2
}

/**
* Setup to check SUS/SUS1/SUS2 to ensure the resume status of flashs.
*
* @param dev Beginning address of the peripheral registers.
* @param sus_check_sus_en 1: enable, 0: disable.
*
*/
static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool res_check_sus_en)
{
abort();// Not supported on esp32s2
}

/**
Expand All @@ -161,7 +237,7 @@ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool
*
* @return true if suspended, otherwise false.
*/
static inline bool spimem_flash_ll_sus_status(const spi_mem_dev_t *dev)
static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev)
{
return dev->sus_status.flash_sus;
}
Expand Down
Loading

0 comments on commit 9905da4

Please sign in to comment.