]> granicus.if.org Git - esp-idf/commitdiff
feat(psram): config SPI psram pins based on efuse value
authorchenjianqiang <chenjianqiang@espressif.com>
Tue, 7 May 2019 08:36:37 +0000 (16:36 +0800)
committerchenjianqiang <chenjianqiang@espressif.com>
Tue, 28 May 2019 13:25:16 +0000 (21:25 +0800)
components/bootloader_support/include/bootloader_common.h
components/bootloader_support/src/bootloader_common.c
components/bootloader_support/src/bootloader_init.c
components/esp32/Kconfig
components/esp32/sdkconfig.rename
components/esp32/spiram_psram.c

index c7136d4aa5f3086f5ef0fd2a226f7eb9451a2106..eb5864125fc2c9c55a2ddf4e4abe33178200491e 100644 (file)
@@ -136,3 +136,8 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
  *  - ESP_FAIL:              mapping is fail.
  */
 esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
+
+/**
+ * @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
+ */
+void bootloader_common_vddsdio_configure();
index 09c088dfe7bd7c401a651f18263b49decd03b0ef..e584ea3df759dcf6bf5d29e1e7ec2a7aef9cca30 100644 (file)
@@ -27,6 +27,7 @@
 #include "bootloader_common.h"
 #include "soc/gpio_periph.h"
 #include "soc/efuse_reg.h"
+#include "soc/rtc.h"
 #include "esp_image_format.h"
 #include "bootloader_sha.h"
 #include "sys/param.h"
@@ -257,3 +258,18 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
 
     return ESP_OK;
 }
+
+void bootloader_common_vddsdio_configure()
+{
+#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
+    rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
+    if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) {    // 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 // CONFIG_BOOTLOADER_VDDSDIO_BOOST
+}
index ca0f435df3120ebd3a1c7f6d6f5f39850b061a71..77b1d3e8c55ddc140c614fd3b4257b2defb95f18 100644 (file)
@@ -49,6 +49,7 @@
 #include "bootloader_random.h"
 #include "bootloader_config.h"
 #include "bootloader_clock.h"
+#include "bootloader_common.h"
 
 #include "flash_qio_mode.h"
 
@@ -62,7 +63,6 @@ static const char* TAG = "boot";
 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(const esp_image_header_t* pfhdr);
 static void uart_console_configure(void);
 static void wdt_reset_check(void);
@@ -118,7 +118,7 @@ esp_err_t bootloader_init()
 
 static esp_err_t bootloader_main()
 {
-    vddsdio_configure();
+    bootloader_common_vddsdio_configure();
     /* Read and keep flash ID, for further use. */
     g_rom_flashchip.device_id = bootloader_read_flash_id();
     esp_image_header_t fhdr;
@@ -286,21 +286,6 @@ static void print_flash_info(const esp_image_header_t* phdr)
 #endif
 }
 
-static void vddsdio_configure()
-{
-#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
-    rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
-    if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) {    // 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 // CONFIG_BOOTLOADER_VDDSDIO_BOOST
-}
-
 #define FLASH_CLK_IO      6
 #define FLASH_CS_IO       11
 #define FLASH_SPIQ_IO     7
index 1bd63a2c03960ced3d104dc4be5e165adf86cc74..8546448bb8b60526cf9810e819aa6176f164c751 100644 (file)
@@ -233,16 +233,84 @@ menu "ESP32-specific"
                 bool "VSPI host (SPI3)"
         endchoice
 
-        config SPIRAM_PICO_PSRAM_CS_IO
-            int "PSRAM CS IO for ESP32-PICO chip"
-            depends on ESP32_SPIRAM_SUPPORT
+        menu "PSRAM clock and cs IO for ESP32-DOWD"
+
+            config D0WD_PSRAM_CLK_IO
+                int "PSRAM CLK IO number"
+                depends on ESP32_SPIRAM_SUPPORT
+                range 0 33
+                default 17
+                help
+                    The PSRAM CLOCK IO can be any unused GPIO, user can config it based on hardware design. If user use
+                    1.8V flash and 1.8V psram, this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
+
+            config D0WD_PSRAM_CS_IO
+                int "PSRAM CS IO number"
+                depends on ESP32_SPIRAM_SUPPORT
+                range 0 33
+                default 16
+                help
+                    The PSRAM CS IO can be any unused GPIO, user can config it based on hardware design. If user use
+                    1.8V flash and 1.8V psram, this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
+        endmenu
+
+        menu "PSRAM clock and cs IO for ESP32-D2WD"
+
+            config D2WD_PSRAM_CLK_IO
+                int "PSRAM CLK IO number"
+                depends on ESP32_SPIRAM_SUPPORT
+                range 0 33
+                default 9
+                help
+                    User can config it based on hardware design. For ESP32-D2WD chip, the psram can only be 1.8V psram,
+                    so this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
+
+            config D2WD_PSRAM_CS_IO
+                int "PSRAM CS IO number"
+                depends on ESP32_SPIRAM_SUPPORT
+                range 0 33
+                default 10
+                help
+                    User can config it based on hardware design. For ESP32-D2WD chip, the psram can only be 1.8V psram,
+                    so this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
+        endmenu
+
+        menu "PSRAM clock and cs IO for ESP32-PICO"
+
+            config PICO_PSRAM_CS_IO
+                int "PSRAM CS IO number"
+                depends on ESP32_SPIRAM_SUPPORT
+                range 0 33
+                default 10
+                help
+                    The PSRAM CS IO can be any unused GPIO, user can config it based on hardware design.
+
+                    For ESP32-PICO chip, the psram share clock with flash, so user do not need to configure the clock
+                    IO.
+                    For the reference hardware design, please refer to
+                    https://www.espressif.com/sites/default/files/documentation/esp32-pico-d4_datasheet_en.pdf
+
+        endmenu
+
+        config SPIRAM_SPIWP_SD3_PIN
+            int "SPI PSRAM WP(SD3) Pin when customising pins via eFuse (read help)"
+            depends on ESPTOOLPY_FLASHMODE_DIO || ESPTOOLPY_FLASHMODE_DOUT
             range 0 33
-            default 10
+            default 7
             help
-                When ESP32-PICO chip connect a external psram, the clock IO and data IO is fixed, but the CS IO can be
-                any unused GPIO, user can config it based on hardware design.
+                This value is ignored unless flash mode is set to DIO or DOUT and the SPI flash pins have been
+                overriden by setting the eFuses SPI_PAD_CONFIG_xxx.
+
+                When this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka
+                ESP32 pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in eFuse. And the psram only has QPI
+                mode, the WP pin is necessary, so we need to configure this value here.
+
+                When flash mode is set to QIO or QOUT, the PSRAM WP pin will be set as the value configured in
+                bootloader.
+
+                For ESP32-PICO chip, the default value of this config should be 7.
 
-    endmenu
+    endmenu # "SPI RAM config"
 
     config ESP32_MEMMAP_TRACEMEM
         bool
index 15b1a55c0fd99f0befbd1ebcfe2809037877e0af..271b93a6216a87bdb980c745644b7a00506215bd 100644 (file)
@@ -35,4 +35,3 @@ CONFIG_REDUCE_PHY_TX_POWER                              CONFIG_ESP32_REDUCE_PHY_
 
 # SPI RAM config
 CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST           CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
-CONFIG_PICO_PSRAM_CS_IO                                 CONFIG_SPIRAM_PICO_PSRAM_CS_IO
index f6cda3fa3bb965354d16b962cee846d44e5155e8..f7d88c85929bf06ad1c64f633e205d830b0e1fab 100644 (file)
@@ -28,6 +28,7 @@
 #include "esp32/rom/spi_flash.h"
 #include "esp32/rom/gpio.h"
 #include "esp32/rom/cache.h"
+#include "esp32/rom/efuse.h"
 #include "soc/io_mux_reg.h"
 #include "soc/dport_reg.h"
 #include "soc/gpio_sig_map.h"
@@ -35,6 +36,7 @@
 #include "driver/gpio.h"
 #include "driver/spi_common.h"
 #include "driver/periph_ctrl.h"
+#include "bootloader_common.h"
 
 #if CONFIG_ESP32_SPIRAM_SUPPORT
 #include "soc/rtc.h"
@@ -94,43 +96,36 @@ typedef enum {
 // WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines
 // hardcode the flash pins as well, making this code incompatible with either a setup
 // that has the flash on non-standard pins or ESP32s with built-in flash.
-#define FLASH_CLK_IO                6
+#define FLASH_CLK_IO               6
 #define FLASH_CS_IO                11
-#define FLASH_SPIQ_SD0_IO           7
-#define FLASH_SPID_SD1_IO           8
-#define FLASH_SPIWP_SD3_IO         10
-#define FLASH_SPIHD_SD2_IO          9
-
-#define PSRAM_CLK_IO               17
-#define PSRAM_CS_IO                16
-#define PSRAM_SPIQ_SD0_IO           7
-#define PSRAM_SPID_SD1_IO           8
+#define PSRAM_SPIQ_SD0_IO          7
+#define PSRAM_SPID_SD1_IO          8
 #define PSRAM_SPIWP_SD3_IO         10
-#define PSRAM_SPIHD_SD2_IO          9
-
-// IO-pins of ESP32-PICO-D4 for PSRAM. PSRAM share clock with flash.
-// The CS IO can be overwrite via menuconfig.
-#define PICO_FLASH_CLK_IO                6
-#define PICO_FLASH_CS_IO                16
-#define PICO_FLASH_SPIQ_SD0_IO          17
-#define PICO_FLASH_SPID_SD1_IO           8
-#define PICO_FLASH_SPIWP_SD3_IO          7
-#define PICO_FLASH_SPIHD_SD2_IO         11
-
-#define PICO_PSRAM_CLK_IO                6
-#define PICO_PSRAM_CS_IO                CONFIG_SPIRAM_PICO_PSRAM_CS_IO
-#define PICO_PSRAM_SPIQ_SD0_IO          17
-#define PICO_PSRAM_SPID_SD1_IO           8
-#define PICO_PSRAM_SPIWP_SD3_IO          7
-#define PICO_PSRAM_SPIHD_SD2_IO         11
+#define PSRAM_SPIHD_SD2_IO         9
+
+#define FLASH_HSPI_CLK_IO          14
+#define FLASH_HSPI_CS_IO           15
+#define PSRAM_HSPI_SPIQ_SD0_IO     12
+#define PSRAM_HSPI_SPID_SD1_IO     13
+#define PSRAM_HSPI_SPIWP_SD3_IO    2
+#define PSRAM_HSPI_SPIHD_SD2_IO    4
+
+// PSRAM clock and cs IO should be configured based on hardware design.
+// For ESP32-WROVER or ESP32-WROVER-B module, the clock IO is IO17, the cs IO is IO16,
+// they are the default value for these two configs.
+#define D0WD_PSRAM_CLK_IO          CONFIG_D0WD_PSRAM_CLK_IO  // Default value is 17
+#define D0WD_PSRAM_CS_IO           CONFIG_D0WD_PSRAM_CS_IO   // Default value is 16
+
+#define D2WD_PSRAM_CLK_IO          CONFIG_D2WD_PSRAM_CLK_IO  // Default value is 9
+#define D2WD_PSRAM_CS_IO           CONFIG_D2WD_PSRAM_CS_IO   // Default value is 10
+
+// For ESP32-PICO chip, the psram share clock with flash. The flash clock pin is fixed, which is IO6.
+#define PICO_PSRAM_CLK_IO          6
+#define PICO_PSRAM_CS_IO           CONFIG_PICO_PSRAM_CS_IO   // Default value is 10
 
 typedef struct {
     uint8_t flash_clk_io;
     uint8_t flash_cs_io;
-    uint8_t flash_spiq_sd0_io;
-    uint8_t flash_spid_sd1_io;
-    uint8_t flash_spiwp_sd3_io;
-    uint8_t flash_spihd_sd2_io;
     uint8_t psram_clk_io;
     uint8_t psram_cs_io;
     uint8_t psram_spiq_sd0_io;
@@ -491,7 +486,6 @@ void psram_set_cs_timing(psram_spi_num_t spi_num, psram_clk_mode_t clk_mode)
 void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
 {
     CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_TRANS_DONE << 5);
-    SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CS_SETUP);
     // SPI_CPOL & SPI_CPHA
     CLEAR_PERI_REG_MASK(SPI_PIN_REG(spi_num), SPI_CK_IDLE_EDGE);
     CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CK_OUT_EDGE);
@@ -508,11 +502,8 @@ void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
     psram_set_cs_timing(spi_num, s_clk_mode);
 }
 
-/*
- * 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_io_t psram_io, psram_cache_mode_t mode)
+//psram gpio init , different working frequency we have different solutions
+static void IRAM_ATTR psram_gpio_config(psram_io_t *psram_io, psram_cache_mode_t mode)
 {
     int spi_cache_dummy = 0;
     uint32_t rd_mode_reg = READ_PERI_REG(SPI_CTRL_REG(0));
@@ -523,17 +514,6 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
     } 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(psram_io.flash_cs_io, SPICS0_OUT_IDX, 0, 0);
-    gpio_matrix_out(psram_io.psram_spiq_sd0_io, SPIQ_OUT_IDX, 0, 0);
-    gpio_matrix_in(psram_io.psram_spiq_sd0_io, SPIQ_IN_IDX, 0);
-    gpio_matrix_out(psram_io.psram_spid_sd1_io, SPID_OUT_IDX, 0, 0);
-    gpio_matrix_in(psram_io.psram_spid_sd1_io, SPID_IN_IDX, 0);
-    gpio_matrix_out(psram_io.psram_spiwp_sd3_io, SPIWP_OUT_IDX, 0, 0);
-    gpio_matrix_in(psram_io.psram_spiwp_sd3_io, SPIWP_IN_IDX, 0);
-    gpio_matrix_out(psram_io.psram_spihd_sd2_io, SPIHD_OUT_IDX, 0, 0);
-    gpio_matrix_in(psram_io.psram_spihd_sd2_io, SPIHD_IN_IDX, 0);
 
     switch (mode) {
         case PSRAM_CACHE_F80M_S40M:
@@ -544,8 +524,8 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
             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(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
-            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
             break;
         case PSRAM_CACHE_F80M_S80M:
             extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
@@ -555,8 +535,8 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
             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(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
-            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV, 3, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV, 3, FUN_DRV_S);
             break;
         case PSRAM_CACHE_F40M_S40M:
             extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
@@ -566,36 +546,54 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
             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(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV, 2, FUN_DRV_S);
-            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV, 2, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
             break;
         default:
             break;
     }
-    SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy en
+    SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy enable
 
+    // In bootloader, all the signals are already configured,
+    // We keep the following code in case the bootloader is some older version.
+    gpio_matrix_out(psram_io->flash_cs_io, SPICS0_OUT_IDX, 0, 0);
+    gpio_matrix_out(psram_io->psram_cs_io, SPICS1_OUT_IDX, 0, 0);
+    gpio_matrix_out(psram_io->psram_spiq_sd0_io, SPIQ_OUT_IDX, 0, 0);
+    gpio_matrix_in(psram_io->psram_spiq_sd0_io, SPIQ_IN_IDX, 0);
+    gpio_matrix_out(psram_io->psram_spid_sd1_io, SPID_OUT_IDX, 0, 0);
+    gpio_matrix_in(psram_io->psram_spid_sd1_io, SPID_IN_IDX, 0);
+    gpio_matrix_out(psram_io->psram_spiwp_sd3_io, SPIWP_OUT_IDX, 0, 0);
+    gpio_matrix_in(psram_io->psram_spiwp_sd3_io, SPIWP_IN_IDX, 0);
+    gpio_matrix_out(psram_io->psram_spihd_sd2_io, SPIHD_OUT_IDX, 0, 0);
+    gpio_matrix_in(psram_io->psram_spihd_sd2_io, SPIHD_IN_IDX, 0);
+    
     //select pin function gpio
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spiq_sd0_io],  PIN_FUNC_GPIO);
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spid_sd1_io],  PIN_FUNC_GPIO);
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spihd_sd2_io], PIN_FUNC_GPIO);
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spiwp_sd3_io], PIN_FUNC_GPIO);
-    //flash clock signal should come from IO MUX.
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUNC_SD_CLK_SPICLK);
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_cs_io],  PIN_FUNC_GPIO);
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.psram_cs_io],  PIN_FUNC_GPIO);
-    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], PIN_FUNC_GPIO);
+    if ((psram_io->flash_clk_io == FLASH_CLK_IO) && (psram_io->flash_clk_io != psram_io->psram_clk_io)) {
+        //flash clock signal should come from IO MUX.
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUNC_SD_CLK_SPICLK);
+    } else {
+        //flash clock signal should come from GPIO matrix.
+        PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], PIN_FUNC_GPIO);
+    }
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->flash_cs_io],  PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_cs_io],  PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spiq_sd0_io],  PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spid_sd1_io],  PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spihd_sd2_io], PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spiwp_sd3_io], PIN_FUNC_GPIO);
 
     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(GPIO_PIN_MUX_REG[psram_io.flash_spiq_sd0_io],  FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spid_sd1_io],  FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spihd_sd2_io], FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spiwp_sd3_io], FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_cs_io],  FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_cs_io],  FUN_DRV_V, 3, FUN_DRV_S);
-        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_cs_io],  FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_cs_io],  FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spiq_sd0_io],  FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spid_sd1_io],  FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spihd_sd2_io], FUN_DRV_V, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spiwp_sd3_io], FUN_DRV_V, 3, FUN_DRV_S);
     }
 }
 
@@ -612,15 +610,24 @@ psram_size_t psram_get_size()
     }
 }
 
-//psram gpio init , different working frequency we have different solutions
+/*
+ * 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.
+ */
 esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
 {
     psram_io_t psram_io;
     uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
     uint32_t pkg_ver = chip_ver & 0x7;
     if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
-        ESP_EARLY_LOGE(TAG, "ESP32D2WD do not support psram yet");
-        return ESP_FAIL;
+        ESP_EARLY_LOGI(TAG, "This chip is ESP32-D2WD");
+        rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
+        if (cfg.tieh != RTC_VDDSDIO_TIEH_1_8V) {
+            ESP_EARLY_LOGE(TAG, "VDDSDIO is not 1.8V");
+            return ESP_FAIL;
+        }
+        psram_io.psram_clk_io = D2WD_PSRAM_CLK_IO;
+        psram_io.psram_cs_io  = D2WD_PSRAM_CS_IO;
     } else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
         ESP_EARLY_LOGI(TAG, "This chip is ESP32-PICO");
         rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
@@ -628,36 +635,46 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
             ESP_EARLY_LOGE(TAG, "VDDSDIO is not 3.3V");
             return ESP_FAIL;
         }
-        psram_io.flash_clk_io       = PICO_FLASH_CLK_IO;
-        psram_io.flash_cs_io        = PICO_FLASH_CS_IO;
-        psram_io.flash_spiq_sd0_io  = PICO_FLASH_SPIQ_SD0_IO;
-        psram_io.flash_spid_sd1_io  = PICO_FLASH_SPID_SD1_IO;
-        psram_io.flash_spiwp_sd3_io = PICO_FLASH_SPIWP_SD3_IO;
-        psram_io.flash_spihd_sd2_io = PICO_FLASH_SPIHD_SD2_IO;
-        psram_io.psram_clk_io       = PICO_PSRAM_CLK_IO;
-        psram_io.psram_cs_io        = PICO_PSRAM_CS_IO;
-        psram_io.psram_spiq_sd0_io  = PICO_PSRAM_SPIQ_SD0_IO;
-        psram_io.psram_spid_sd1_io  = PICO_PSRAM_SPID_SD1_IO;
-        psram_io.psram_spiwp_sd3_io = PICO_PSRAM_SPIWP_SD3_IO;
-        psram_io.psram_spihd_sd2_io = PICO_PSRAM_SPIHD_SD2_IO;
-
         s_clk_mode = PSRAM_CLK_MODE_NORM;
-    } else {
+        psram_io.psram_clk_io = PICO_PSRAM_CLK_IO;
+        psram_io.psram_cs_io  = PICO_PSRAM_CS_IO;
+    } else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5)){
+        ESP_EARLY_LOGI(TAG, "This chip is ESP32-D0WD");
+        psram_io.psram_clk_io = D0WD_PSRAM_CLK_IO;
+        psram_io.psram_cs_io  = D0WD_PSRAM_CS_IO;
+    }
+
+    const uint32_t spiconfig = ets_efuse_get_spiconfig();
+    if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
         psram_io.flash_clk_io       = FLASH_CLK_IO;
         psram_io.flash_cs_io        = FLASH_CS_IO;
-        psram_io.flash_spiq_sd0_io  = FLASH_SPIQ_SD0_IO;
-        psram_io.flash_spid_sd1_io  = FLASH_SPID_SD1_IO;
-        psram_io.flash_spiwp_sd3_io = FLASH_SPIWP_SD3_IO;
-        psram_io.flash_spihd_sd2_io = FLASH_SPIHD_SD2_IO;
-        psram_io.psram_clk_io       = PSRAM_CLK_IO;
-        psram_io.psram_cs_io        = PSRAM_CS_IO;
         psram_io.psram_spiq_sd0_io  = PSRAM_SPIQ_SD0_IO;
         psram_io.psram_spid_sd1_io  = PSRAM_SPID_SD1_IO;
         psram_io.psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO;
         psram_io.psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO;
+    } else if (spiconfig == EFUSE_SPICONFIG_HSPI_DEFAULTS) {
+        psram_io.flash_clk_io       = FLASH_HSPI_CLK_IO;
+        psram_io.flash_cs_io        = FLASH_HSPI_CS_IO;
+        psram_io.psram_spiq_sd0_io  = PSRAM_HSPI_SPIQ_SD0_IO;
+        psram_io.psram_spid_sd1_io  = PSRAM_HSPI_SPID_SD1_IO;
+        psram_io.psram_spiwp_sd3_io = PSRAM_HSPI_SPIWP_SD3_IO;
+        psram_io.psram_spihd_sd2_io = PSRAM_HSPI_SPIHD_SD2_IO;
+    } else {
+        psram_io.flash_clk_io       = EFUSE_SPICONFIG_RET_SPICLK(spiconfig);
+        psram_io.flash_cs_io        = EFUSE_SPICONFIG_RET_SPICS0(spiconfig);
+        psram_io.psram_spiq_sd0_io  = EFUSE_SPICONFIG_RET_SPIQ(spiconfig);
+        psram_io.psram_spid_sd1_io  = EFUSE_SPICONFIG_RET_SPID(spiconfig);
+        psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig);
+
+        // If flash mode is set to QIO or QOUT, the WP pin is equal the value configured in bootloader.
+        // If flash mode is set to DIO or DOUT, the WP pin should config it via menuconfig.
+        #if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
+        psram_io.psram_spiwp_sd3_io = CONFIG_BOOTLOADER_SPI_WP_PIN;
+        #else
+        psram_io.psram_spiwp_sd3_io = CONFIG_SPIRAM_SPIWP_SD3_PIN;
+        #endif
     }
 
-    WRITE_PERI_REG(GPIO_ENABLE_W1TC_REG, BIT(psram_io.psram_clk_io) | BIT(psram_io.psram_cs_io));   //DISABLE OUPUT FOR IO16/17
     assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
     s_psram_mode = mode;
 
@@ -666,7 +683,6 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
 
     psram_spi_init(PSRAM_SPI_1, mode);
     
-    gpio_matrix_out(psram_io.psram_cs_io, SPICS1_OUT_IDX, 0, 0);
     switch (mode) {
         case PSRAM_CACHE_F80M_S80M:
             gpio_matrix_out(psram_io.psram_clk_io, SPICLK_OUT_IDX, 0, 0);
@@ -691,25 +707,16 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
             }
             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 == RTC_VDDSDIO_TIEH_1_8V) {    // 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
+
+    // Rise VDDSIO for 1.8V psram.
+    bootloader_common_vddsdio_configure();
     // GPIO related settings
-    psram_gpio_config(psram_io, mode);
+    psram_gpio_config(&psram_io, mode);
     psram_read_id(&s_psram_id);
     if (!PSRAM_IS_VALID(s_psram_id)) {
         return ESP_FAIL;
     }
-    
+
     if (PSRAM_IS_32MBIT_VER0(s_psram_id)) {
         s_clk_mode = PSRAM_CLK_MODE_DCLK;
         if (mode == PSRAM_CACHE_F80M_S80M) {
@@ -776,42 +783,43 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
             CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div
             break;
     }
-    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M);     // cache write command enable
+
+    CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M);       //disable dio mode for cache command
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M);         //enable qio mode for cache command
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M);  //enable cache read command
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M);  //enable cache write command
     SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_ADDR_BITLEN_V, 23, SPI_SRAM_ADDR_BITLEN_S); //write address for cache command.
-    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M);     //enable qio mode for cache command
-    CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M);     //disable dio mode for cache command
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M);    //enable cache read dummy
 
-    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M);   //enable cache read dummy
-    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
+    //config sram cache r/w command
+    SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
+            SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
+    SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
+            SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0xEB
     SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
             SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
     SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
             SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
-    SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
-            SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
-    SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
-            SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
     SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
-            SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
+            SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy; 80m--+2dummy
 
-    //config sram cache r/w command
     switch (psram_cache_mode) {
         case PSRAM_CACHE_F80M_S80M: //in this mode , no delay is needed
             break;
-        case PSRAM_CACHE_F80M_S40M: //is sram is @40M, need 2 cycles of delay
+        case PSRAM_CACHE_F80M_S40M: //if sram is @40M, need 2 cycles of delay
         case PSRAM_CACHE_F40M_S40M:
         default:
             if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
                 SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
                         SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache
                 SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ_QUAD) << 8),
-                        SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
+                        SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0xEB, read command value,(0x00 for delay,0xeb for cmd)
                 SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
                         SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache)
                 SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
                         SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
                 SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
-                        SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
+                        SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy; 80m--+2dummy
             }
             break;
     }