spi_flash: Add GD25LQ255E flash support

This commit is contained in:
Cao Sen Miao
2023-05-12 19:05:43 +08:00
parent d7a141f3ea
commit 1ec55b7d1a
3 changed files with 43 additions and 3 deletions

View File

@@ -41,6 +41,7 @@
#define MXIC_ID 0xC2 #define MXIC_ID 0xC2
#define GD_Q_ID_HIGH 0xC8 #define GD_Q_ID_HIGH 0xC8
#define GD_Q_ID_MID 0x40 #define GD_Q_ID_MID 0x40
#define GD_LQ_ID_MID 0x60
#define GD_Q_ID_LOW 0x16 #define GD_Q_ID_LOW 0x16
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2) #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; 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) FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip)
{ {
return BYTESHIFT(chip->device_id, 2) == MXIC_ID; 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; sr1_bit_num = 8;
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI); 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. /* 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. Use 01H to write SR1 and 31H to write SR2.
*/ */

View File

@@ -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_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_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_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_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_BEYOND_LIMIT, // Means that flash has no capability to meet that condition.
} spi_flash_requirement_t; } spi_flash_requirement_t;
typedef void (*spi_flash_hpm_enable_fn_t)(void); typedef void (*spi_flash_hpm_enable_fn_t)(void);

View File

@@ -26,6 +26,7 @@
* 1. Some flash chips send A3H to enable the HPM. * 1. Some flash chips send A3H to enable the HPM.
* 2. Some flash chips write HPF bit in status register. * 2. Some flash chips write HPF bit in status register.
* 3. Some flash chips adjust dummy cycles. * 3. Some flash chips adjust dummy cycles.
* 4. Some flash chips do nothing.
******************************************************************************/ ******************************************************************************/
#if CONFIG_ESPTOOLPY_FLASHFREQ_120M #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); 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-------------------------------------// //-----------------------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 }, { "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}, { "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}, { "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. // 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}, { "NULL", NULL, NULL, NULL, NULL, spi_flash_hpm_get_dummy_generic},
}; };