flash: support EON flash qaud mode

This commit is contained in:
chenjianqiang 2021-02-26 11:36:23 +08:00
parent 8c9f5876be
commit acd3c945d2
3 changed files with 47 additions and 21 deletions

View File

@ -66,10 +66,10 @@ static void write_status_8b_wrsr2(unsigned new_status);
/* Write 16 bit status using WRSR */
static void write_status_16b_wrsr(unsigned new_status);
/* Read 8 bit status of XM25QU64A */
static unsigned read_status_8b_xmc25qu64a();
/* Write 8 bit status of XM25QU64A */
static void write_status_8b_xmc25qu64a(unsigned new_status);
/* Read 8 bit status using RDSR command in otp mode */
static unsigned read_status_8b_rdsr_otp(void);
/* Write 8 bit status using WRSR command in otp mode */
static void write_status_8b_wrsr_otp(unsigned new_status);
#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
@ -95,7 +95,8 @@ const static qio_info_t chip_data[] = {
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "XM25QU64A", 0x20, 0x3817, 0xFFFF, read_status_8b_xmc25qu64a, write_status_8b_xmc25qu64a, 6 },
{ "XM25QU64A", 0x20, 0x3817, 0xFFFF, read_status_8b_rdsr_otp, write_status_8b_wrsr_otp, 6 },
{ "EON", 0x1C, 0x7000, 0xFF00, read_status_8b_rdsr_otp, write_status_8b_wrsr_otp, 6 }, /* EN25QH sereils: IDs 0x70xx */
/* Final entry is default entry, if no other IDs have matched.
@ -253,7 +254,7 @@ static void write_status_16b_wrsr(unsigned new_status)
execute_flash_command(CMD_WRSR, new_status, 16, 0);
}
static unsigned read_status_8b_xmc25qu64a()
static unsigned read_status_8b_rdsr_otp(void)
{
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
@ -262,7 +263,7 @@ static unsigned read_status_8b_xmc25qu64a()
return read_status;
}
static void write_status_8b_xmc25qu64a(unsigned new_status)
static void write_status_8b_wrsr_otp(unsigned new_status)
{
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
esp_rom_spiflash_wait_idle(&g_rom_flashchip);

View File

@ -121,6 +121,7 @@ extern "C" {
#define ESP_ROM_SPIFLASH_BP2 BIT4
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
#define ESP_ROM_SPIFLASH_QE BIT9
#define ESP_ROM_SPIFLASH_BP_MASK_EON (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2)
//Extra dummy for flash read
#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M 0

View File

@ -24,6 +24,11 @@
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
static inline bool is_eon_chip(const esp_rom_spiflash_chip_t* chip)
{
return ((((chip->device_id >> 16)&0xff)) == 0x1C && (((chip->device_id >> 8)&0xff) == 0x70));
}
esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi)
{
uint32_t status;
@ -53,33 +58,52 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp
about interrupts, CPU coordination, flash mapping. However some of
the functions in esp_spi_flash.c call it.
*/
esp_rom_spiflash_result_t esp_rom_spiflash_unlock()
esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void)
{
uint32_t status;
uint32_t new_status;
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
if (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if (is_eon_chip(&g_rom_spiflash_chip)) {
// Eon chips have different QE position
/* Clear all bits except QIE, if it is set.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
status &= ESP_ROM_SPIFLASH_QE;
if (esp_rom_spiflash_read_status(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
/* Clear all bits in the mask.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
new_status = status & (~ESP_ROM_SPIFLASH_BP_MASK_EON);
// Skip if nothing needs to be cleared. Otherwise will waste time waiting for the flash to clear nothing.
if (new_status == status) return ESP_ROM_SPIFLASH_RESULT_OK;
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
} else {
if (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
/* Clear all bits except QE, if it is set.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
new_status = status & ESP_ROM_SPIFLASH_QE;
SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
}
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN);
while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
}
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
esp_rom_spiflash_result_t ret = esp_rom_spiflash_write_status(&g_rom_spiflash_chip, new_status);
// WEL bit should be cleared after operations regardless of writing succeed or not.
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WRDI);
while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
}
return ESP_ROM_SPIFLASH_RESULT_OK;
return ret;
}