diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild
index 5efa1dc3..3e03ba91 100644
--- a/components/bootloader/Kconfig.projbuild
+++ b/components/bootloader/Kconfig.projbuild
@@ -1,4 +1,15 @@
 menu "Bootloader config"
+
+config BOOTLOADER_INIT_SPI_FLASH
+    bool "Bootloader init SPI flash"
+    default y
+    help
+        Enable this option, software will initialize SPI flash clock and I/O mode at bootloader instead of at APP.
+        So it will speed up system starting and reduce the time cost at loading firmware.
+
+        If your system bootloader is based on v3.0, the option must not be enable, because the v3.0 bootloader don't support
+        this function.
+
 choice LOG_BOOTLOADER_LEVEL
    bool "Bootloader log verbosity"
    default LOG_BOOTLOADER_LEVEL_INFO
diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c
index a7e518bb..52eea185 100644
--- a/components/bootloader_support/src/bootloader_init.c
+++ b/components/bootloader_support/src/bootloader_init.c
@@ -619,46 +619,26 @@ static esp_err_t bootloader_main()
         return ESP_FAIL;
     }
 
+    update_flash_config(&fhdr);
+
     ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
 
     ESP_LOGI(TAG, "compile time " __TIME__ );
 
     print_flash_info(&fhdr);
 
-    update_flash_config(&fhdr);
-
     return ESP_OK;
 }
 
 static void update_flash_config(const esp_image_header_t* pfhdr)
 {
-    // uint32_t size;
-    // switch(pfhdr->spi_size) {
-    //     case ESP_IMAGE_FLASH_SIZE_1MB:
-    //         size = 1;
-    //         break;
-    //     case ESP_IMAGE_FLASH_SIZE_2MB:
-    //     case ESP_IMAGE_FLASH_SIZE_2MB_C1:
-    //         size = 2;
-    //         break;
-    //     case ESP_IMAGE_FLASH_SIZE_4MB:
-    //     case ESP_IMAGE_FLASH_SIZE_4MB_C1:
-    //         size = 4;
-    //         break;
-    //     case ESP_IMAGE_FLASH_SIZE_8MB:
-    //         size = 8;
-    //         break;
-    //     case ESP_IMAGE_FLASH_SIZE_16MB:
-    //         size = 16;
-    //         break;
-    //     default:
-    //         size = 2;
-    // }
+#ifdef CONFIG_BOOTLOADER_INIT_SPI_FLASH
+    extern void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode);
 
-    // Set flash chip size
-//    esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
-    // TODO: set mode
-    // TODO: set frequency
+    esp_spi_flash_init(pfhdr->spi_speed, pfhdr->spi_mode);
+
+    ESP_LOGD(TAG, "bootloader initialize SPI flash clock and I/O");
+#endif /* CONFIG_BOOTLOADER_INIT_SPI_FLASH */
 }
 
 static void print_flash_info(const esp_image_header_t* phdr)
diff --git a/components/esp8266/include/driver/spi_register.h b/components/esp8266/include/driver/spi_register.h
index 9591c382..48051aa7 100644
--- a/components/esp8266/include/driver/spi_register.h
+++ b/components/esp8266/include/driver/spi_register.h
@@ -256,4 +256,8 @@
 #define PERIPHS_SPI_FLASH_CTRL                  SPI_CTRL(SPI)
 #define PERIPHS_SPI_FLASH_CMD                   SPI_CMD(SPI)
 
+#define SPI0_CLK_EQU_SYSCLK                     BIT8
+
+#define PERIPHS_SPI_FLASH_USRREG                (0x60000200 + 0x1c)
+
 #endif // SPI_REGISTER_H_INCLUDED
diff --git a/components/esp8266/source/chip_boot.c b/components/esp8266/source/chip_boot.c
index 0ca7ff5b..9ced7620 100644
--- a/components/esp8266/source/chip_boot.c
+++ b/components/esp8266/source/chip_boot.c
@@ -13,86 +13,17 @@
 // limitations under the License.
 
 #include "sdkconfig.h"
-#include "esp_attr.h"
+
+#ifndef CONFIG_BOOTLOADER_INIT_SPI_FLASH
 #include "spi_flash.h"
-#include "esp_log.h"
-#include "esp_system.h"
-#include "esp8266/eagle_soc.h"
-#include "esp8266/rom_functions.h"
-#include "esp_image_format.h"
-
-#define PERIPHS_SPI_FLASH_USRREG        (0x60000200 + 0x1c)
-#define PERIPHS_SPI_FLASH_CTRL          (0x60000200 + 0x08)
-#define PERIPHS_IO_MUX_CONF_U           (0x60000800)
-
-#define SPI0_CLK_EQU_SYSCLK             BIT8
-#define SPI_FLASH_CLK_EQU_SYSCLK        BIT12
-
-static const char *TAG = "chip_boot";
 
 /*
- * @brief initialize the chip including flash I/O and chip cache according to
- *        boot parameters which are stored at the flash
+ * @brief initialize the chip
  */
-void chip_boot(size_t start_addr)
+void chip_boot(void)
 {
-    int ret;
-    uint32_t freqdiv, flash_size;
-    uint32_t freqbits;
-    esp_image_header_t fhdr;
+    extern void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode);
 
-    uint32_t flash_map_table[FALSH_SIZE_MAP_MAX] = {
-        1 * 1024 * 1024,
-        2 * 1024 * 1024,
-        4 * 1024 * 1024,
-        8 * 1024 * 1024,
-        16 * 1024 * 1024
-    };
-    uint32_t flash_map_table_size = sizeof(flash_map_table) / sizeof(flash_map_table[0]);
-
-    extern esp_spi_flash_chip_t flashchip;
-    extern void phy_get_bb_evm(void);
-    extern void cache_init(uint8_t);
-    extern void user_spi_flash_dio_to_qio_pre_init(void);
-
-    phy_get_bb_evm();
-
-    SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_USRREG, BIT5);
-
-    ret = spi_flash_read(start_addr, &fhdr, sizeof(esp_image_header_t));
-    if (ret) {
-        ESP_EARLY_LOGE(TAG, "SPI flash read result %d\n", ret);
-    }
-
-    if (3 > fhdr.spi_speed)
-        freqdiv = fhdr.spi_speed + 2;
-    else if (0x0F == fhdr.spi_speed)
-        freqdiv = 1;
-    else
-        freqdiv = 2;
-
-    if (fhdr.spi_size < flash_map_table_size) {
-        flash_size = flash_map_table[fhdr.spi_size];
-        ESP_EARLY_LOGD(TAG, "SPI flash size is %d\n", flash_size);
-    } else {
-        flash_size = 0; 
-        ESP_EARLY_LOGE(TAG, "SPI size error is %d\n", fhdr.spi_size);
-    }
-    flashchip.chip_size = flash_size;
-
-    if (1 >= freqdiv) {
-        freqbits = SPI_FLASH_CLK_EQU_SYSCLK;
-        SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK);
-        SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK);
-    } else {
-        freqbits = ((freqdiv - 1) << 8) + ((freqdiv / 2 - 1) << 4) + (freqdiv - 1);
-        CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK);
-        CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK);
-    }
-    SET_PERI_REG_BITS(PERIPHS_SPI_FLASH_CTRL, 0xfff, freqbits, 0);
-
-    if (fhdr.spi_mode == ESP_IMAGE_SPI_MODE_QIO) {
-        ESP_EARLY_LOGD(TAG, "SPI flash enable QIO mode\n");
-        user_spi_flash_dio_to_qio_pre_init();
-    }
+    esp_spi_flash_init(CONFIG_SPI_FLASH_FREQ, CONFIG_SPI_FLASH_MODE);
 }
+#endif /* CONFIG_BOOTLOADER_INIT_SPI_FLASH */
diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c
index a9be9235..994393cb 100644
--- a/components/esp8266/source/startup.c
+++ b/components/esp8266/source/startup.c
@@ -33,7 +33,7 @@
 #define FLASH_MAP_ADDR 0x40200000
 #define FLASH_MAP_SIZE 0x00100000
 
-extern void chip_boot(size_t start_addr);
+extern void chip_boot(void);
 extern int rtc_init(void);
 extern int mac_init(void);
 extern int base_gpio_init(void);
@@ -41,6 +41,7 @@ extern int watchdog_init(void);
 extern int wifi_timer_init(void);
 extern int wifi_nvs_init(void);
 extern esp_err_t esp_pthread_init(void);
+extern void phy_get_bb_evm(void);
 
 static void user_init_entry(void *param)
 {
@@ -55,6 +56,8 @@ static void user_init_entry(void *param)
     for (func = &__init_array_start; func < &__init_array_end; func++)
         func[0]();
 
+    phy_get_bb_evm();
+
     assert(nvs_flash_init() == 0);
     assert(wifi_nvs_init() == 0);
     assert(rtc_init() == 0);
@@ -108,7 +111,9 @@ void call_user_start(size_t start_addr)
         "wsr        a0, vecbase\n"
         : : :"memory");
 
-    chip_boot(start_addr);
+#ifndef CONFIG_BOOTLOADER_INIT_SPI_FLASH
+    chip_boot();
+#endif
 
     /* clear bss data */
     for (p = &_bss_start; p < &_bss_end; p++)
diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild
index 7b29f4e3..63ff90c3 100644
--- a/components/esptool_py/Kconfig.projbuild
+++ b/components/esptool_py/Kconfig.projbuild
@@ -63,6 +63,14 @@ config FLASHMODE_DOUT
 	bool "DOUT"
 endchoice
 
+config FLASHMODE_SWITCH_TO_QIO
+	bool "Try to switch to QIO mode at startup"
+	default y
+	depends on FLASHMODE_DIO
+	help
+        If users use SPI flash DIO mode to download firmware, bootloader or application 
+        can switch to QIO mode by enable this option.
+
 # Note: we use esptool.py to flash bootloader in
 # dio mode for QIO/QOUT, bootloader then upgrades
 # itself to quad mode during initialisation
@@ -73,6 +81,13 @@ config ESPTOOLPY_FLASHMODE
 	default "dio" if FLASHMODE_DIO
 	default "dout" if FLASHMODE_DOUT
 
+config SPI_FLASH_MODE
+	hex
+	default 0x0 if FLASHMODE_QIO
+	default 0x1 if FLASHMODE_QOUT
+	default 0x2 if FLASHMODE_DIO
+	default 0x3 if FLASHMODE_DOUT	
+
 choice ESPTOOLPY_FLASHFREQ
 	prompt "Flash SPI speed"
 	default ESPTOOLPY_FLASHFREQ_40M
@@ -96,6 +111,12 @@ config ESPTOOLPY_FLASHFREQ
 	default "26m" if ESPTOOLPY_FLASHFREQ_26M
 	default "20m" if ESPTOOLPY_FLASHFREQ_20M
 
+config SPI_FLASH_FREQ
+	hex
+	default 0xf if ESPTOOLPY_FLASHFREQ_80M
+	default 0x0 if ESPTOOLPY_FLASHFREQ_40M
+	default 0x1 if ESPTOOLPY_FLASHFREQ_26M
+	default 0x2 if ESPTOOLPY_FLASHFREQ_20M
 
 choice ESPTOOLPY_FLASHSIZE
 	prompt "Flash size"
@@ -122,6 +143,14 @@ config ESPTOOLPY_FLASHSIZE
 	default "8MB" if ESPTOOLPY_FLASHSIZE_8MB
 	default "16MB" if ESPTOOLPY_FLASHSIZE_16MB
 
+config SPI_FLASH_SIZE
+	hex
+	default 0x100000 if ESPTOOLPY_FLASHSIZE_1MB
+	default 0x200000 if ESPTOOLPY_FLASHSIZE_2MB
+	default 0x400000 if ESPTOOLPY_FLASHSIZE_4MB
+	default 0x800000 if ESPTOOLPY_FLASHSIZE_8MB
+	default 0x1000000 if ESPTOOLPY_FLASHSIZE_16MB
+
 choice ESPTOOLPY_BEFORE
     prompt "Before flashing"
     default ESPTOOLPY_BEFORE_RESET
diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk
index 6ec0f676..3172f3eb 100644
--- a/components/spi_flash/component.mk
+++ b/components/spi_flash/component.mk
@@ -2,8 +2,10 @@
 # Component Makefile
 #
 
-ifndef IS_BOOTLOADER_BUILD
 COMPONENT_SRCDIRS := src
+
+ifdef IS_BOOTLOADER_BUILD
+COMPONENT_OBJS := src/spi_flash.o src/spi_flash_raw.o
 endif
 
 CFLAGS += -DPARTITION_QUEUE_HEADER=\"sys/queue.h\"
diff --git a/components/spi_flash/src/spi_flash.c b/components/spi_flash/src/spi_flash.c
index c82be03d..22aeec04 100644
--- a/components/spi_flash/src/spi_flash.c
+++ b/components/spi_flash/src/spi_flash.c
@@ -15,6 +15,8 @@
 #include <string.h>
 
 #include "spi_flash.h"
+#include "driver/spi_register.h"
+#include "esp8266/pin_mux_register.h"
 #include "priv/esp_spi_flash_raw.h"
 
 #include "esp_attr.h"
@@ -43,9 +45,15 @@
 #define SPI_FLASH_RDSR2      0x35
 #define SPI_FLASH_PROTECT_STATUS                (BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(14))
 
+#ifndef BOOTLOADER_BUILD
 #define FLASH_INTR_DECLARE(t)
 #define FLASH_INTR_LOCK(t)                      vPortEnterCritical()
 #define FLASH_INTR_UNLOCK(t)                    vPortExitCritical()
+#else
+#define FLASH_INTR_DECLARE(t)
+#define FLASH_INTR_LOCK(t)
+#define FLASH_INTR_UNLOCK(t)
+#endif
 
 #define FLASH_ALIGN_BYTES                       4
 #define FLASH_ALIGN(addr)                       ((((size_t)addr) + (FLASH_ALIGN_BYTES - 1)) & (~(FLASH_ALIGN_BYTES - 1)))
@@ -61,7 +69,7 @@ extern void vPortExitCritical(void);
 
 esp_spi_flash_chip_t flashchip = {
     0x1640ef,
-    (32 / 8) * 1024 * 1024,
+    CONFIG_SPI_FLASH_SIZE,
     64 * 1024,
     4 * 1024,
     256,
@@ -720,3 +728,33 @@ esp_err_t spi_flash_erase_range(size_t start_address, size_t size)
 
     return ret;
 }
+
+void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode)
+{
+    uint32_t freqdiv, freqbits;
+
+    SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_USRREG, BIT5);
+
+    if (spi_speed < 3)
+        freqdiv = spi_speed + 2;
+    else if (0x0F == spi_speed)
+        freqdiv = 1;
+    else
+        freqdiv = 2;
+
+    if (1 >= freqdiv) {
+        freqbits = SPI_FLASH_CLK_EQU_SYSCLK;
+        SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK);
+        SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK);
+    } else {
+        freqbits = ((freqdiv - 1) << 8) + ((freqdiv / 2 - 1) << 4) + (freqdiv - 1);
+        CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK);
+        CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK);
+    }
+    SET_PERI_REG_BITS(PERIPHS_SPI_FLASH_CTRL, 0xfff, freqbits, 0);      
+
+#ifndef CONFIG_FLASHMODE_SWITCH_TO_QIO
+    if (spi_mode == 0)
+#endif
+        user_spi_flash_dio_to_qio_pre_init();
+}