|
|
|
@ -15,6 +15,9 @@
|
|
|
|
|
#include "esp_private/spi_flash_os.h"
|
|
|
|
|
#include "esp_rom_caps.h"
|
|
|
|
|
|
|
|
|
|
#define IS_REGION_32BIT(start, len) ((start) + (len) > (1<<24))
|
|
|
|
|
#define IS_ADDR_32BIT(addr) (addr >= (1<<24))
|
|
|
|
|
|
|
|
|
|
typedef struct flash_chip_dummy {
|
|
|
|
|
uint8_t dio_dummy_bitlen;
|
|
|
|
|
uint8_t qio_dummy_bitlen;
|
|
|
|
@ -112,6 +115,41 @@ esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size)
|
|
|
|
|
|
|
|
|
|
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
|
|
|
|
|
|
|
|
|
static esp_err_t spi_flash_command_generic_program_4B(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
|
|
|
|
|
{
|
|
|
|
|
spi_flash_trans_t t = {
|
|
|
|
|
.command = CMD_PROGRAM_PAGE_4B,
|
|
|
|
|
.address_bitlen = 32,
|
|
|
|
|
.address = address,
|
|
|
|
|
.mosi_len = length,
|
|
|
|
|
.mosi_data = buffer,
|
|
|
|
|
.flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
|
|
|
|
|
};
|
|
|
|
|
return chip->host->driver->common_command(chip->host, &t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t spi_flash_command_generic_erase_sector_4B(esp_flash_t *chip, uint32_t start_address)
|
|
|
|
|
{
|
|
|
|
|
spi_flash_trans_t t = {
|
|
|
|
|
.command = CMD_SECTOR_ERASE_4B,
|
|
|
|
|
.address_bitlen = 32,
|
|
|
|
|
.address = start_address,
|
|
|
|
|
.flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
|
|
|
|
|
};
|
|
|
|
|
return chip->host->driver->common_command(chip->host, &t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t spi_flash_command_generic_erase_block_4B(esp_flash_t *chip, uint32_t start_address)
|
|
|
|
|
{
|
|
|
|
|
spi_flash_trans_t t = {
|
|
|
|
|
.command = CMD_LARGE_BLOCK_ERASE_4B,
|
|
|
|
|
.address_bitlen = 32,
|
|
|
|
|
.address = start_address,
|
|
|
|
|
.flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
|
|
|
|
|
};
|
|
|
|
|
return chip->host->driver->common_command(chip->host, &t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id)
|
|
|
|
|
{
|
|
|
|
|
// This is the catch-all probe function, claim the chip always if nothing
|
|
|
|
@ -173,6 +211,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
|
|
|
|
|
|
|
|
|
|
esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_address)
|
|
|
|
|
{
|
|
|
|
|
bool addr_32b = IS_ADDR_32BIT(start_address);
|
|
|
|
|
esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false);
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
|
|
|
@ -180,7 +219,11 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
|
|
|
|
|
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
|
|
|
|
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
|
|
|
|
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
|
|
|
|
|
chip->host->driver->erase_sector(chip->host, start_address);
|
|
|
|
|
if (addr_32b) {
|
|
|
|
|
spi_flash_command_generic_erase_sector_4B(chip, start_address);
|
|
|
|
|
} else {
|
|
|
|
|
chip->host->driver->erase_sector(chip->host, start_address);
|
|
|
|
|
}
|
|
|
|
|
chip->busy = 1;
|
|
|
|
|
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
|
|
|
|
|
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
|
|
|
|
@ -199,6 +242,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
|
|
|
|
|
|
|
|
|
|
esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_address)
|
|
|
|
|
{
|
|
|
|
|
bool addr_32b = IS_ADDR_32BIT(start_address);
|
|
|
|
|
esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false);
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
|
|
|
@ -206,7 +250,11 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a
|
|
|
|
|
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
|
|
|
|
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
|
|
|
|
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
|
|
|
|
|
chip->host->driver->erase_block(chip->host, start_address);
|
|
|
|
|
if (addr_32b) {
|
|
|
|
|
spi_flash_command_generic_erase_block_4B(chip, start_address);
|
|
|
|
|
} else {
|
|
|
|
|
chip->host->driver->erase_block(chip->host, start_address);
|
|
|
|
|
}
|
|
|
|
|
chip->busy = 1;
|
|
|
|
|
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
|
|
|
|
|
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
|
|
|
|
@ -232,6 +280,9 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t
|
|
|
|
|
uint32_t config_io_flags = 0;
|
|
|
|
|
|
|
|
|
|
// Configure the host, and return
|
|
|
|
|
if (IS_REGION_32BIT(address, length)) {
|
|
|
|
|
config_io_flags |= SPI_FLASH_CONFIG_IO_MODE_32B_ADDR;
|
|
|
|
|
}
|
|
|
|
|
err = chip->chip_drv->config_host_io_mode(chip, config_io_flags);
|
|
|
|
|
|
|
|
|
|
if (err == ESP_ERR_NOT_SUPPORTED) {
|
|
|
|
@ -259,12 +310,16 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t
|
|
|
|
|
esp_err_t spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
|
|
|
|
|
{
|
|
|
|
|
esp_err_t err;
|
|
|
|
|
|
|
|
|
|
bool addr_32b = IS_ADDR_32BIT(address);
|
|
|
|
|
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
|
|
|
|
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
|
|
|
|
//The chip didn't accept the previous write command. Ignore this in preparation stage.
|
|
|
|
|
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
|
|
|
|
// Perform the actual Page Program command
|
|
|
|
|
chip->host->driver->program_page(chip->host, buffer, address, length);
|
|
|
|
|
if (addr_32b) {
|
|
|
|
|
spi_flash_command_generic_program_4B(chip, buffer, address, length);
|
|
|
|
|
} else {
|
|
|
|
|
chip->host->driver->program_page(chip->host, buffer, address, length);
|
|
|
|
|
}
|
|
|
|
|
chip->busy = 1;
|
|
|
|
|
|
|
|
|
|
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->page_program_timeout);
|
|
|
|
@ -433,48 +488,48 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t
|
|
|
|
|
uint32_t read_command;
|
|
|
|
|
bool conf_required = false;
|
|
|
|
|
esp_flash_io_mode_t read_mode = chip->read_mode;
|
|
|
|
|
bool addr_32bit = (flags & SPI_FLASH_CONFIG_IO_MODE_32B_ADDR);
|
|
|
|
|
bool is_addr_32bit = (flags & SPI_FLASH_CONFIG_IO_MODE_32B_ADDR);
|
|
|
|
|
|
|
|
|
|
switch (read_mode & 0xFFFF) {
|
|
|
|
|
case SPI_FLASH_QIO:
|
|
|
|
|
//for QIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that.
|
|
|
|
|
addr_bitlen = SPI_FLASH_QIO_ADDR_BITLEN;
|
|
|
|
|
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->qio_dummy_bitlen : rom_flash_chip_dummy->qio_dummy_bitlen);
|
|
|
|
|
read_command = (addr_32bit? CMD_FASTRD_QIO_4B: CMD_FASTRD_QIO);
|
|
|
|
|
read_command = (is_addr_32bit? CMD_FASTRD_QIO_4B: CMD_FASTRD_QIO);
|
|
|
|
|
conf_required = true;
|
|
|
|
|
break;
|
|
|
|
|
case SPI_FLASH_QOUT:
|
|
|
|
|
addr_bitlen = SPI_FLASH_QOUT_ADDR_BITLEN;
|
|
|
|
|
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->qout_dummy_bitlen : rom_flash_chip_dummy->qout_dummy_bitlen);
|
|
|
|
|
read_command = (addr_32bit? CMD_FASTRD_QUAD_4B: CMD_FASTRD_QUAD);
|
|
|
|
|
read_command = (is_addr_32bit? CMD_FASTRD_QUAD_4B: CMD_FASTRD_QUAD);
|
|
|
|
|
break;
|
|
|
|
|
case SPI_FLASH_DIO:
|
|
|
|
|
//for DIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that.
|
|
|
|
|
addr_bitlen = SPI_FLASH_DIO_ADDR_BITLEN;
|
|
|
|
|
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->dio_dummy_bitlen : rom_flash_chip_dummy->dio_dummy_bitlen);
|
|
|
|
|
read_command = (addr_32bit? CMD_FASTRD_DIO_4B: CMD_FASTRD_DIO);
|
|
|
|
|
read_command = (is_addr_32bit? CMD_FASTRD_DIO_4B: CMD_FASTRD_DIO);
|
|
|
|
|
conf_required = true;
|
|
|
|
|
break;
|
|
|
|
|
case SPI_FLASH_DOUT:
|
|
|
|
|
addr_bitlen = SPI_FLASH_DOUT_ADDR_BITLEN;
|
|
|
|
|
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->dout_dummy_bitlen : rom_flash_chip_dummy->dout_dummy_bitlen);
|
|
|
|
|
read_command = (addr_32bit? CMD_FASTRD_DUAL_4B: CMD_FASTRD_DUAL);
|
|
|
|
|
read_command = (is_addr_32bit? CMD_FASTRD_DUAL_4B: CMD_FASTRD_DUAL);
|
|
|
|
|
break;
|
|
|
|
|
case SPI_FLASH_FASTRD:
|
|
|
|
|
addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN;
|
|
|
|
|
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->fastrd_dummy_bitlen : rom_flash_chip_dummy->fastrd_dummy_bitlen);
|
|
|
|
|
read_command = (addr_32bit? CMD_FASTRD_4B: CMD_FASTRD);
|
|
|
|
|
read_command = (is_addr_32bit? CMD_FASTRD_4B: CMD_FASTRD);
|
|
|
|
|
break;
|
|
|
|
|
case SPI_FLASH_SLOWRD:
|
|
|
|
|
addr_bitlen = SPI_FLASH_SLOWRD_ADDR_BITLEN;
|
|
|
|
|
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->slowrd_dummy_bitlen : rom_flash_chip_dummy->slowrd_dummy_bitlen);
|
|
|
|
|
read_command = (addr_32bit? CMD_READ_4B: CMD_READ);
|
|
|
|
|
read_command = (is_addr_32bit? CMD_READ_4B: CMD_READ);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return ESP_ERR_FLASH_NOT_INITIALISED;
|
|
|
|
|
}
|
|
|
|
|
//For W25Q256 chip, the only difference between 4-Byte address command and 3-Byte version is the command value and the address bit length.
|
|
|
|
|
if (addr_32bit) {
|
|
|
|
|
if (is_addr_32bit) {
|
|
|
|
|
addr_bitlen += 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -619,6 +674,7 @@ spi_flash_caps_t spi_flash_chip_generic_get_caps(esp_flash_t *chip)
|
|
|
|
|
// XMC-D support suspend
|
|
|
|
|
if (chip->chip_id >> 16 == 0x46) {
|
|
|
|
|
caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND;
|
|
|
|
|
caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// XMC-D support suspend (some D series flash chip begin with 0x20, difference checked by SFDP)
|
|
|
|
@ -637,6 +693,7 @@ spi_flash_caps_t spi_flash_chip_generic_get_caps(esp_flash_t *chip)
|
|
|
|
|
chip->host->driver->common_command(chip->host, &t);
|
|
|
|
|
if((data & 0x8) == 0x8) {
|
|
|
|
|
caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND;
|
|
|
|
|
caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|