diff --git a/components/bootloader_support/include_priv/flash_qio_mode.h b/components/bootloader_support/include_priv/flash_qio_mode.h index 9efa1313e..98e2fd22a 100644 --- a/components/bootloader_support/include_priv/flash_qio_mode.h +++ b/components/bootloader_support/include_priv/flash_qio_mode.h @@ -24,6 +24,14 @@ extern "C" { */ void bootloader_enable_qio_mode(void); +/** + * @brief Read flash ID by sending 0x9F command + * @return flash raw ID + * mfg_id = (ID >> 16) & 0xFF; + flash_id = ID & 0xffff; + */ +uint32_t bootloader_read_flash_id(); + #ifdef __cplusplus } #endif diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index bed022397..5a1ecd6ab 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -63,7 +63,7 @@ static esp_err_t bootloader_main(); static void print_flash_info(const esp_image_header_t* pfhdr); static void update_flash_config(const esp_image_header_t* pfhdr); static void vddsdio_configure(); -static void flash_gpio_configure(); +static void flash_gpio_configure(const esp_image_header_t* pfhdr); static void uart_console_configure(void); static void wdt_reset_check(void); @@ -118,7 +118,14 @@ esp_err_t bootloader_init() static esp_err_t bootloader_main() { vddsdio_configure(); - flash_gpio_configure(); + /* Read and keep flash ID, for further use. */ + g_rom_flashchip.device_id = bootloader_read_flash_id(); + esp_image_header_t fhdr; + if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) { + ESP_LOGE(TAG, "failed to load bootloader header!"); + return ESP_FAIL; + } + flash_gpio_configure(&fhdr); #if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240) //Check if ESP32 is rated for a CPU frequency of 160MHz only if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) && @@ -132,8 +139,6 @@ static esp_err_t bootloader_main() wdt_reset_check(); ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); - esp_image_header_t fhdr; - ESP_LOGI(TAG, "compile time " __TIME__ ); ets_set_appcpu_boot_addr(0); @@ -158,11 +163,6 @@ static esp_err_t bootloader_main() bootloader_enable_qio_mode(); #endif - if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) { - ESP_LOGE(TAG, "failed to load bootloader header!"); - return ESP_FAIL; - } - print_flash_info(&fhdr); update_flash_config(&fhdr); @@ -295,31 +295,49 @@ static void vddsdio_configure() #define FLASH_SPIHD_IO 9 #define FLASH_IO_MATRIX_DUMMY_40M 1 #define FLASH_IO_MATRIX_DUMMY_80M 2 -static void IRAM_ATTR flash_gpio_configure() +#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3 + +/* + * Bootloader reads SPI configuration from bin header, so that + * the burning configuration can be different with compiling configuration. + */ +static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr) { int spi_cache_dummy = 0; int drv = 2; -#if CONFIG_FLASHMODE_QIO - spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3 -#elif CONFIG_FLASHMODE_QOUT - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7 -#elif CONFIG_FLASHMODE_DIO - spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3 -#elif CONFIG_FLASHMODE_DOUT - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7 -#endif + switch (pfhdr->spi_mode) { + case ESP_IMAGE_SPI_MODE_QIO: + spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; + break; + case ESP_IMAGE_SPI_MODE_DIO: + spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3 + break; + case ESP_IMAGE_SPI_MODE_QOUT: + case ESP_IMAGE_SPI_MODE_DOUT: + default: + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; + break; + } + /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; -#if CONFIG_ESPTOOLPY_FLASHFREQ_40M - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY -#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY - drv = 3; -#endif + switch (pfhdr->spi_speed) { + case ESP_IMAGE_SPI_SPEED_80M: + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, + SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + drv = 3; + break; + case ESP_IMAGE_SPI_SPEED_40M: + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, + SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + break; + default: + break; + } uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t pkg_ver = chip_ver & 0x7; @@ -361,6 +379,19 @@ static void IRAM_ATTR flash_gpio_configure() // set drive ability for clock PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + + #if CONFIG_SPIRAM_TYPE_ESPPSRAM32 + uint32_t flash_id = g_rom_flashchip.device_id; + if (flash_id == FLASH_ID_GD25LQ32C) { + // Set drive ability for 1.8v flash in 80Mhz. + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); + } + #endif } } } diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index 001b76f41..e01ad6a1e 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -114,6 +114,19 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8 /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; +uint32_t bootloader_read_flash_id() +{ + uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; + SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user.usr_addr = 0; + SPIFLASH.user.usr_command = 1; + SPIFLASH.user2.usr_command_bitlen = 7; + uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24); + SPIFLASH.ctrl.val = old_ctrl_reg; + id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); + return id; +} void bootloader_enable_qio_mode(void) { @@ -129,17 +142,12 @@ void bootloader_enable_qio_mode(void) /* Set up some of the SPIFLASH user/ctrl variables which don't change while we're probing using execute_flash_command() */ old_ctrl_reg = SPIFLASH.ctrl.val; - SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 0; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; - raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24); + raw_flash_id = g_rom_flashchip.device_id; ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id); - mfg_id = raw_flash_id & 0xFF; - flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00); + mfg_id = (raw_flash_id >> 16) & 0xFF; + flash_id = raw_flash_id & 0xFFFF; ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id); for (i = 0; i < NUM_CHIPS-1; i++) { diff --git a/components/esp32/include/rom/spi_flash.h b/components/esp32/include/rom/spi_flash.h index 35d010d79..cc9856f45 100644 --- a/components/esp32/include/rom/spi_flash.h +++ b/components/esp32/include/rom/spi_flash.h @@ -117,6 +117,8 @@ extern "C" { #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 FLASH_ID_GD25LQ32C 0xC86016 + typedef enum { ESP_ROM_SPIFLASH_QIO_MODE = 0, ESP_ROM_SPIFLASH_QOUT_MODE, diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index 39bb0a388..279de8d2f 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -37,6 +37,7 @@ #include "driver/periph_ctrl.h" #if CONFIG_SPIRAM_SUPPORT +#include "soc/rtc.h" //Commands for PSRAM chip #define PSRAM_READ 0x03 @@ -79,15 +80,10 @@ #define PSRAM_IO_MATRIX_DUMMY_40M 1 #define PSRAM_IO_MATRIX_DUMMY_80M 2 -#if CONFIG_FLASHMODE_QIO -#define SPI_CACHE_DUMMY SPI0_R_QIO_DUMMY_CYCLELEN //qio 3 -#elif CONFIG_FLASHMODE_QOUT -#define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //qout 7 -#elif CONFIG_FLASHMODE_DIO -#define SPI_CACHE_DUMMY SPI0_R_DIO_DUMMY_CYCLELEN //dio 3 -#elif CONFIG_FLASHMODE_DOUT -#define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //dout 7 -#endif +#define _SPI_CACHE_PORT 0 +#define _SPI_FLASH_PORT 1 +#define _SPI_80M_CLK_DIV 1 +#define _SPI_40M_CLK_DIV 2 static const char* TAG = "psram"; typedef enum { @@ -101,9 +97,7 @@ static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX; /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; - static int extra_dummy = 0; - typedef enum { PSRAM_CMD_QPI, PSRAM_CMD_SPI, @@ -421,8 +415,23 @@ void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode) memset((void*)SPI_W0_REG(spi_num), 0, 16 * 4); } +/* + * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA. + * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode. + */ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) { + int spi_cache_dummy = 0; + uint32_t rd_mode_reg = READ_PERI_REG(SPI_CTRL_REG(0)); + if (rd_mode_reg & (SPI_FREAD_QIO_M | SPI_FREAD_DIO_M)) { + spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; + } else if (rd_mode_reg & (SPI_FREAD_QUAD_M | SPI_FREAD_DUAL_M)) { + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; + } else { + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; + } + // In bootloader, all the signals are already configured, + // We keep the following code in case the bootloader is some older version. gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); gpio_matrix_out(PSRAM_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); gpio_matrix_in(PSRAM_SPIQ_IO, SPIQ_IN_IDX, 0); @@ -436,24 +445,33 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) switch (mode) { case PSRAM_CACHE_F80M_S40M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT); + esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT); //set drive ability for clock SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S); break; case PSRAM_CACHE_F80M_S80M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; + SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT); + esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT); //set drive ability for clock SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S); break; case PSRAM_CACHE_F40M_S40M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_40M; + g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_CACHE_PORT); + esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT); //set drive ability for clock SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 2, FUN_DRV_S); SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S); @@ -549,11 +567,38 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad gpio_matrix_out(PSRAM_CLK_IO, SIG_IN_FUNC225_IDX, 0, 0); break; } + #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V + // For flash 80Mhz, we must update ldo voltage in case older version of bootloader didn't do this. + rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); + if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V + cfg.drefh = 3; + cfg.drefm = 3; + cfg.drefl = 3; + cfg.force = 1; + rtc_vddsdio_set_config(cfg); + ets_delay_us(10); // wait for regulator to become stable + } + #endif CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M); psram_gpio_config(mode); WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO)); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], PIN_FUNC_GPIO); + + uint32_t flash_id = g_rom_flashchip.device_id; + if (flash_id == FLASH_ID_GD25LQ32C) { + #if CONFIG_SPIRAM_TYPE_ESPPSRAM32 + // Set drive ability for 1.8v flash in 80Mhz. + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO], FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S); + #endif + } uint32_t id; psram_read_id(&id); if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) {