esp_flash: fix the quad issue for some GD flash chips

The GD flash with product ID 40H, is already used in Wrover-nosufix modules.
This commit is contained in:
Michael (XIAO Xufeng) 2019-09-10 00:56:46 +08:00
parent 1e1d50376b
commit eb104aa16f
9 changed files with 180 additions and 17 deletions

View file

@ -14,7 +14,7 @@ else()
"partition.c"
"spi_flash_rom_patch.c"
)
# New implementation
# New implementation after IDF v4.0
list(APPEND cache_srcs
"esp_flash_api.c"
"esp_flash_spi_init.c"
@ -25,6 +25,7 @@ else()
"spi_flash_chip_drivers.c"
"spi_flash_chip_generic.c"
"spi_flash_chip_issi.c"
"spi_flash_chip_gd.c"
"memspi_host_driver.c"
)
list(APPEND srcs ${cache_srcs})

View file

@ -90,8 +90,23 @@ menu "SPI Flash driver"
bool "ISSI"
default y
help
Enable this to support auto detection of ISSI chips if chip vendor not specified.
This adds support for variant chips, however will extend detecting time.
Enable this to support auto detection of ISSI chips if chip vendor not directly
given by ``chip_drv`` member of the chip struct. This adds support for variant
chips, however will extend detecting time.
config SPI_FLASH_SUPPORT_GD_CHIP
bool "GigaDevice"
default y
help
Enable this to support auto detection of GD (GigaDevice) chips if chip vendor not
directly given by ``chip_drv`` member of the chip struct. If you are using Wrover
modules, please don't disable this, otherwise your flash may not work in 4-bit
mode.
This adds support for variant chips, however will extend detecting time and image
size. Note that the default chip driver supports the GD chips with product ID
60H.
endmenu #auto detect flash chips
endmenu

View file

@ -62,6 +62,7 @@ static const char io_mode_str[][IO_STR_LEN] = {
_Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_io_mode_t defined in spi_flash_ll.h");
esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
/* Static function to notify OS of a new SPI flash operation.
@ -115,6 +116,18 @@ esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip)
return ESP_ERR_INVALID_ARG;
}
//read chip id
uint32_t flash_id;
int retries = 10;
do {
err = esp_flash_read_chip_id(chip, &flash_id);
} while (err == ESP_ERR_FLASH_NOT_INITIALISED && retries-- > 0);
if (err != ESP_OK) {
return err;
}
chip->chip_id = flash_id;
if (!esp_flash_chip_driver_initialized(chip)) {
// Detect chip_drv
err = detect_spi_flash_chip(chip);
@ -175,15 +188,7 @@ esp_err_t IRAM_ATTR esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id
static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip)
{
esp_err_t err;
uint32_t flash_id;
int retries = 10;
do {
err = esp_flash_read_chip_id(chip, &flash_id);
} while (err == ESP_ERR_FLASH_NOT_INITIALISED && retries-- > 0);
if (err != ESP_OK) {
return err;
}
uint32_t flash_id = chip->chip_id;
// Detect the chip and set the chip_drv structure for it
const spi_flash_chip_t **drivers = esp_flash_registered_chips;

View file

@ -65,6 +65,7 @@ struct esp_flash_t {
esp_flash_io_mode_t read_mode; ///< Configured SPI flash read mode. Set before ``esp_flash_init`` is called.
uint32_t size; ///< Size of SPI flash in bytes. If 0, size will be detected during initialisation.
uint32_t chip_id; ///< Detected chip id.
};

View file

@ -0,0 +1,32 @@
// Copyright 2015-2019 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.
#pragma once
#include <stdint.h>
#include "esp_flash.h"
#include "spi_flash_chip_driver.h"
/**
* GD (GigaDevice) SPI flash chip_drv, uses all the above functions for its operations. In
* default autodetection, this is used as a catchall if a more specific chip_drv
* is not found.
*
* Note that this is for GD chips with product ID 40H (GD25Q) and 60H (GD25LQ). The chip diver uses
* different commands to write the SR2 register according to the chip ID. For GD25Q40 - GD25Q16
* chips, and GD25LQ chips, WRSR (01H) command is used; while WRSR2 (31H) is used for GD25Q32 -
* GD25Q127 chips.
*/
extern const spi_flash_chip_t esp_flash_chip_gd;

View file

@ -4,5 +4,6 @@ entries:
spi_flash_rom_patch (noflash_text)
spi_flash_chip_generic (noflash)
spi_flash_chip_issi (noflash)
spi_flash_chip_gd(noflash)
memspi_host_driver (noflash)

View file

@ -16,6 +16,7 @@
#include "spi_flash_chip_driver.h"
#include "spi_flash_chip_generic.h"
#include "spi_flash_chip_issi.h"
#include "spi_flash_chip_gd.h"
#include "sdkconfig.h"
/*
@ -30,6 +31,9 @@
static const spi_flash_chip_t *default_registered_chips[] = {
#ifdef CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP
&esp_flash_chip_issi,
#endif
#ifdef CONFIG_SPI_FLASH_SUPPORT_GD_CHIP
&esp_flash_chip_gd,
#endif
&esp_flash_chip_generic,
NULL,

View file

@ -0,0 +1,108 @@
// Copyright 2015-2019 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.
#include <stdlib.h>
#include "spi_flash_chip_generic.h"
#include "spi_flash_defs.h"
#define FLASH_ID_MASK 0xFF00
#define FLASH_SIZE_MASK 0xFF
#define GD25Q_PRODUCT_ID 0x4000
#define GD25LQ_PRODUCT_ID 0x6000
#define WRSR_16B_REQUIRED(chip_id) (((chip_id) & FLASH_ID_MASK) == GD25LQ_PRODUCT_ID || \
((chip_id) & FLASH_SIZE_MASK) <= 0x15)
/* Driver for GD flash chip */
esp_err_t spi_flash_chip_gd_probe(esp_flash_t *chip, uint32_t flash_id)
{
/* Check manufacturer and product IDs match our desired masks */
const uint8_t MFG_ID = 0xC8;
if (flash_id >> 16 != MFG_ID) {
return ESP_ERR_NOT_FOUND;
}
uint32_t product_id = flash_id & FLASH_ID_MASK;
if (product_id != GD25Q_PRODUCT_ID && product_id != GD25LQ_PRODUCT_ID) {
return ESP_ERR_NOT_FOUND;
}
return ESP_OK;
}
esp_err_t spi_flash_chip_gd_set_io_mode(esp_flash_t *chip)
{
if (WRSR_16B_REQUIRED(chip->chip_id)) {
const uint32_t qe = 1<<9;
return spi_flash_common_set_io_mode(chip,
spi_flash_common_write_status_16b_wrsr,
spi_flash_common_read_status_16b_rdsr_rdsr2,
qe);
} else {
const uint32_t qe = 1<<1;
return spi_flash_common_set_io_mode(chip,
spi_flash_common_write_status_8b_wrsr2,
spi_flash_common_read_status_8b_rdsr2,
qe);
}
}
esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode)
{
/* GD uses bit 1 of SR2 as Quad Enable */
const uint8_t BIT_QE = 1 << 1;
uint32_t sr;
esp_err_t ret = spi_flash_common_read_status_8b_rdsr2(chip, &sr);
if (ret == ESP_OK) {
*out_io_mode = ((sr & BIT_QE)? SPI_FLASH_QOUT: 0);
}
return ret;
}
static const char chip_name[] = "gd";
// The issi chip can use the functions for generic chips except from set read mode and probe,
// So we only replace these two functions.
const spi_flash_chip_t esp_flash_chip_gd = {
.name = chip_name,
.probe = spi_flash_chip_gd_probe,
.reset = spi_flash_chip_generic_reset,
.detect_size = spi_flash_chip_generic_detect_size,
.erase_chip = spi_flash_chip_generic_erase_chip,
.erase_sector = spi_flash_chip_generic_erase_sector,
.erase_block = spi_flash_chip_generic_erase_block,
.sector_size = 4 * 1024,
.block_erase_size = 64 * 1024,
.get_chip_write_protect = spi_flash_chip_generic_get_write_protect,
.set_chip_write_protect = spi_flash_chip_generic_set_write_protect,
// TODO support protected regions on ISSI flash
.num_protectable_regions = 0,
.protectable_regions = NULL,
.get_protected_regions = NULL,
.set_protected_regions = NULL,
.read = spi_flash_chip_generic_read,
.write = spi_flash_chip_generic_write,
.program_page = spi_flash_chip_generic_page_program,
.page_size = 256,
.write_encrypted = spi_flash_chip_generic_write_encrypted,
.wait_idle = spi_flash_chip_generic_wait_idle,
.set_io_mode = spi_flash_chip_gd_set_io_mode,
.get_io_mode = spi_flash_chip_gd_get_io_mode,
};

View file

@ -60,12 +60,8 @@ esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip)
esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size)
{
uint32_t id = 0;
uint32_t id = chip->chip_id;
*size = 0;
esp_err_t err = chip->host->read_id(chip->host, &id);
if (err != ESP_OK) {
return err;
}
/* Can't detect size unless the high byte of the product ID matches the same convention, which is usually 0x40 or
* 0xC0 or similar. */