mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
spi_flash: Add several flash chips HPM(120M) support
This commit is contained in:
parent
9c09372132
commit
7e1c632d8b
@ -29,6 +29,7 @@ typedef struct {
|
||||
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_requirement_t;
|
||||
@ -41,7 +42,7 @@ typedef spi_flash_requirement_t (*spi_flash_hpm_chip_requirement_check_t)(uint32
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
const char *manufacturer; /* Flash vendor */
|
||||
const char *method; /* Flash HPM method */
|
||||
spi_flash_hpm_probe_fn_t probe;
|
||||
spi_flash_hpm_chip_requirement_check_t chip_hpm_requirement_check;
|
||||
spi_flash_hpm_enable_fn_t flash_hpm_enable;
|
||||
|
@ -48,6 +48,8 @@ extern uint32_t bootloader_flash_execute_command_common(
|
||||
uint8_t mosi_len, uint32_t mosi_data,
|
||||
uint8_t miso_len);
|
||||
|
||||
extern uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
|
||||
|
||||
//-----------------For flash chips which enter HPM via command-----------------------//
|
||||
|
||||
/**
|
||||
@ -61,7 +63,14 @@ static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id)
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0xC84016:
|
||||
case 0xC84017:
|
||||
break;
|
||||
// Read BYTE4 in SFDP, 0 means C series, 6 means E series
|
||||
uint32_t gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
|
||||
if (gd_sfdp == 0x0) {
|
||||
break;
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
@ -75,18 +84,10 @@ static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_cmd
|
||||
(void)voltage_mv;
|
||||
(void)temperautre;
|
||||
spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0xC84016:
|
||||
case 0xC84017:
|
||||
if (freq_mhz > 80) {
|
||||
chip_cap = SPI_FLASH_HPM_CMD_NEEDED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
break;
|
||||
if (freq_mhz > 80) {
|
||||
chip_cap = SPI_FLASH_HPM_CMD_NEEDED;
|
||||
}
|
||||
ESP_EARLY_LOGD(HPM_TAG, "HPM with command, status is %d", chip_cap);
|
||||
return chip_cap;
|
||||
}
|
||||
|
||||
@ -130,6 +131,17 @@ static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
|
||||
case 0x204017:
|
||||
case 0x204018:
|
||||
break;
|
||||
// GD chips.
|
||||
case 0xC84017:
|
||||
case 0xC84018:
|
||||
// Read BYTE4 in SFDP, 0 means C series, 6 means E series
|
||||
uint32_t gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
|
||||
if (gd_sfdp == 0x6) {
|
||||
break;
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
@ -143,18 +155,11 @@ static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_dum
|
||||
(void)voltage_mv;
|
||||
(void)temperautre;
|
||||
spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0x204017:
|
||||
case 0x204018:
|
||||
if (freq_mhz >= 104) {
|
||||
chip_cap = SPI_FLASH_HPM_DUMMY_NEEDED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
break;
|
||||
|
||||
if (freq_mhz >= 104) {
|
||||
chip_cap = SPI_FLASH_HPM_DUMMY_NEEDED;
|
||||
}
|
||||
ESP_EARLY_LOGD(HPM_TAG, "HPM with dummy, status is %d", chip_cap);
|
||||
return chip_cap;
|
||||
}
|
||||
|
||||
@ -194,6 +199,53 @@ static void spi_flash_hpm_get_dummy_xmc(spi_flash_hpm_dummy_conf_t *dummy_conf)
|
||||
dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
|
||||
}
|
||||
|
||||
//-----------------For flash chips which enter HPM via write status register-----------------------//
|
||||
|
||||
/**
|
||||
* @brief Probe the chip whether to write status register to enable HPM mode. Take ZB as an example:
|
||||
* Write status register bits to enable HPM mode of the flash. If ZB works under 80MHz, the register value
|
||||
* would be 0, but when works under 120MHz, the register value would be 1.
|
||||
*/
|
||||
static esp_err_t spi_flash_hpm_probe_chip_with_write_hpf_bit_5(uint32_t flash_id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM by adjusting dummy cycles */
|
||||
// ZB chips.
|
||||
case 0x5E4016:
|
||||
break;
|
||||
default:
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static spi_flash_requirement_t spi_flash_hpm_chip_require_check_hpf_bit_5(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;
|
||||
|
||||
if (freq_mhz >= 104) {
|
||||
chip_cap = SPI_FLASH_HPM_WRITE_SR_NEEDED;
|
||||
}
|
||||
ESP_EARLY_LOGD(HPM_TAG, "HPM with dummy, status is %d", chip_cap);
|
||||
return chip_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write bit 5 in status 3
|
||||
*/
|
||||
static void spi_flash_turn_high_performance_write_hpf_bit_5(void)
|
||||
{
|
||||
uint8_t old_status_3 = bootloader_read_status_8b_rdsr3();
|
||||
uint8_t new_status = (old_status_3 | 0x10);
|
||||
bootloader_execute_flash_command(CMD_WRENVSR, 0, 0, 0);
|
||||
bootloader_write_status_8b_wrsr3(new_status);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
}
|
||||
|
||||
//-----------------------generic functions-------------------------------------//
|
||||
|
||||
@ -212,8 +264,9 @@ void __attribute__((weak)) spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_c
|
||||
|
||||
const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
|
||||
/* vendor, chip_id, freq_threshold, temperature threshold, operation for setting high performance, reading HPF status, get dummy */
|
||||
{ "GD", 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 },
|
||||
{ "XMC", 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},
|
||||
{ "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_require_check_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},
|
||||
// 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},
|
||||
};
|
||||
@ -250,8 +303,8 @@ esp_err_t spi_flash_enable_high_performance_mode(void)
|
||||
}
|
||||
|
||||
hpm_requirement_check = chip_hpm->chip_hpm_requirement_check(flash_chip_id, flash_freq, voltage, temperature);
|
||||
if ((hpm_requirement_check == SPI_FLASH_HPM_CMD_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED)) {
|
||||
ESP_EARLY_LOGI(HPM_TAG, "Enabling high speed mode for chip %s", chip_hpm->manufacturer);
|
||||
if ((hpm_requirement_check == SPI_FLASH_HPM_CMD_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_WRITE_SR_NEEDED)) {
|
||||
ESP_EARLY_LOGI(HPM_TAG, "Enabling flash high speed mode by %s", chip_hpm->method);
|
||||
chip_hpm->flash_hpm_enable();
|
||||
ESP_EARLY_LOGD(HPM_TAG, "Checking whether HPM has been executed");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user