diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index 9458d3dfb9..99a2cf05c0 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -41,6 +41,7 @@ #define MXIC_ID 0xC2 #define GD_Q_ID_HIGH 0xC8 #define GD_Q_ID_MID 0x40 +#define GD_LQ_ID_MID 0x60 #define GD_Q_ID_LOW 0x16 #define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2) @@ -467,6 +468,11 @@ FORCE_INLINE_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip) return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW; } +FORCE_INLINE_ATTR bool is_gd_lq_chip(const esp_rom_spiflash_chip_t* chip) +{ + return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_LQ_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW; +} + FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip) { return BYTESHIFT(chip->device_id, 2) == MXIC_ID; @@ -494,7 +500,7 @@ esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void) */ sr1_bit_num = 8; new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI); - } else if (is_gd_q_chip(&g_rom_flashchip)) { + } else if (is_gd_q_chip(&g_rom_flashchip) || is_gd_lq_chip(&g_rom_flashchip)) { /* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit. Use 01H to write SR1 and 31H to write SR2. */ diff --git a/components/spi_flash/include/spi_flash_override.h b/components/spi_flash/include/spi_flash_override.h index 4384d629cf..09c2a80aba 100644 --- a/components/spi_flash/include/spi_flash_override.h +++ b/components/spi_flash/include/spi_flash_override.h @@ -30,8 +30,8 @@ typedef enum { SPI_FLASH_HPM_CMD_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode by command. SPI_FLASH_HPM_DUMMY_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode by adjusting dummy. SPI_FLASH_HPM_WRITE_SR_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode by writing status register. - SPI_FLASH_HPM_UNNEEDED, // Means that flash doesn't need to enter the high performance mode. - SPI_FLASH_HPM_BEYOND_LIMIT, // Means that flash has no capability to meet that condition. + SPI_FLASH_HPM_UNNEEDED, // Means that flash doesn't need to enter the high performance mode. + SPI_FLASH_HPM_BEYOND_LIMIT, // Means that flash has no capability to meet that condition. } spi_flash_requirement_t; typedef void (*spi_flash_hpm_enable_fn_t)(void); diff --git a/components/spi_flash/spi_flash_hpm_enable.c b/components/spi_flash/spi_flash_hpm_enable.c index cf114c58c0..bd42b71502 100644 --- a/components/spi_flash/spi_flash_hpm_enable.c +++ b/components/spi_flash/spi_flash_hpm_enable.c @@ -26,6 +26,7 @@ * 1. Some flash chips send A3H to enable the HPM. * 2. Some flash chips write HPF bit in status register. * 3. Some flash chips adjust dummy cycles. + * 4. Some flash chips do nothing. ******************************************************************************/ #if CONFIG_ESPTOOLPY_FLASHFREQ_120M @@ -251,6 +252,38 @@ static void spi_flash_turn_high_performance_write_hpf_bit_5(void) esp_rom_spiflash_wait_idle(&g_rom_flashchip); } +//-----------------For flash chips which enter HPM with doing nothing-----------------------// + +/** + * @brief Probe the chip whether to write status register to enable HPM mode. Take a GD chip as an example: + * This chip (GD25LQ255E) supports maximum frequency to 133MHz by default. So, we don't need to do any extra + * thing. + */ +static esp_err_t spi_flash_hpm_probe_chip_with_doing_nothing(uint32_t flash_id) +{ + esp_err_t ret = ESP_OK; + switch (flash_id) { + /* The flash listed here should enter the HPM by doing nothing */ + // GD25LQ255E. + case 0xC86019: + break; + default: + ret = ESP_ERR_NOT_FOUND; + break; + } + return ret; +} + +static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_doing_nothing(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre) +{ + // voltage and temperature are not been used now, to be completed in the future. + (void)voltage_mv; + (void)temperautre; + spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED; + ESP_EARLY_LOGD(HPM_TAG, "HPM by default, chip caps is %d", chip_cap); + return chip_cap; +} + //-----------------------generic functions-------------------------------------// /** @@ -271,6 +304,7 @@ const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = { { "command", spi_flash_hpm_probe_chip_with_cmd, spi_flash_hpm_chip_hpm_requirement_check_with_cmd, spi_flash_enable_high_performance_send_cmd, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic }, { "dummy", spi_flash_hpm_probe_chip_with_dummy, spi_flash_hpm_chip_hpm_requirement_check_with_dummy, spi_flash_turn_high_performance_reconfig_dummy, spi_flash_high_performance_check_dummy_sr, spi_flash_hpm_get_dummy_xmc}, { "write sr3-bit5", spi_flash_hpm_probe_chip_with_write_hpf_bit_5, spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5, spi_flash_turn_high_performance_write_hpf_bit_5, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic}, + { "noting-to-do", spi_flash_hpm_probe_chip_with_doing_nothing, spi_flash_hpm_chip_hpm_requirement_check_with_doing_nothing, NULL, NULL, spi_flash_hpm_get_dummy_generic}, // default: do nothing, but keep the dummy get function. The first item with NULL as its probe will be the fallback. { "NULL", NULL, NULL, NULL, NULL, spi_flash_hpm_get_dummy_generic}, };