2021-05-10 04:35:07 +02:00
/*
2023-07-18 10:12:46 +08:00
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
2021-05-10 04:35:07 +02:00
*
* SPDX-License-Identifier: Apache-2.0
*/
2016-11-02 10:41:58 +11:00
# include <stddef.h>
2020-07-13 03:23:12 +08:00
# include <bootloader_flash_priv.h>
2016-11-02 10:41:58 +11:00
# include <esp_log.h>
2017-01-26 18:30:32 +11:00
# include <esp_flash_encrypt.h>
2020-03-12 18:20:31 +08:00
# include "sdkconfig.h"
# include "soc/soc_caps.h"
2022-09-23 17:32:16 +08:00
# include "hal/efuse_ll.h"
2023-03-16 16:47:53 +08:00
# include "hal/efuse_hal.h"
2020-03-12 18:20:31 +08:00
# if CONFIG_IDF_TARGET_ESP32
# include "soc / spi_struct.h"
# include "soc / spi_reg.h"
/* SPI flash controller */
# define SPIFLASH SPI1
# else
# include "soc / spi_mem_struct.h"
# include "soc / spi_mem_reg.h"
/* SPI flash controller */
# define SPIFLASH SPIMEM1
# endif
2022-06-27 15:24:07 +08:00
// This dependency will be removed in the future. IDF-5025
# include "esp_flash.h"
2021-09-28 14:12:56 +08:00
# include "esp_rom_spiflash.h"
2016-11-02 10:41:58 +11:00
2021-06-17 07:21:36 +08:00
# ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
2023-03-16 16:47:53 +08:00
# define ENCRYPTION_IS_VIRTUAL (!efuse_hal_flash_encryption_enabled())
2021-06-17 07:21:36 +08:00
# else
# define ENCRYPTION_IS_VIRTUAL 0
# endif
2021-05-07 15:25:06 +08:00
# define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
# define ISSI_ID 0x9D
2021-09-17 15:38:37 +08:00
# define MXIC_ID 0xC2
2021-05-07 15:25:06 +08:00
# define GD_Q_ID_HIGH 0xC8
# define GD_Q_ID_MID 0x40
# define GD_Q_ID_LOW 0x16
# define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
2021-09-17 15:38:37 +08:00
# define ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 BIT1 // QE position when you write 8 bits(for SR2) at one time.
# define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
2016-11-02 10:41:58 +11:00
# ifndef BOOTLOADER_BUILD
2022-06-27 15:24:07 +08:00
/* Normal app version maps to spi_flash_mmap.h operations...
2016-11-02 10:41:58 +11:00
*/
static const char * TAG = " bootloader_mmap " ;
2018-03-15 19:58:02 +08:00
static spi_flash_mmap_handle_t map ;
2016-11-02 10:41:58 +11:00
2019-07-16 16:33:30 +07:00
uint32_t bootloader_mmap_get_free_pages ( void )
2019-06-15 15:13:51 +05:30
{
return spi_flash_mmap_get_free_pages ( SPI_FLASH_MMAP_DATA ) ;
}
2016-11-02 10:41:58 +11:00
const void * bootloader_mmap ( uint32_t src_addr , uint32_t size )
{
if ( map ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " tried to bootloader_mmap twice " ) ;
2016-11-02 10:41:58 +11:00
return NULL ; /* existing mapping in use... */
}
const void * result = NULL ;
2019-05-27 14:29:43 +08:00
uint32_t src_page = src_addr & ~ ( SPI_FLASH_MMU_PAGE_SIZE - 1 ) ;
2017-06-27 17:25:30 +10:00
size + = ( src_addr - src_page ) ;
esp_err_t err = spi_flash_mmap ( src_page , size , SPI_FLASH_MMAP_DATA , & result , & map ) ;
2016-11-02 10:41:58 +11:00
if ( err ! = ESP_OK ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " spi_flash_mmap failed: 0x%x " , err ) ;
2018-03-15 19:58:02 +08:00
return NULL ;
2016-11-02 10:41:58 +11:00
}
2017-06-27 17:25:30 +10:00
return ( void * ) ( ( intptr_t ) result + ( src_addr - src_page ) ) ;
2016-11-02 10:41:58 +11:00
}
2016-11-07 15:45:57 +11:00
void bootloader_munmap ( const void * mapping )
2016-11-02 10:41:58 +11:00
{
2019-05-27 14:29:43 +08:00
if ( mapping & & map ) {
2016-11-02 10:41:58 +11:00
spi_flash_munmap ( map ) ;
}
map = 0 ;
}
2016-11-11 17:00:34 +11:00
esp_err_t bootloader_flash_read ( size_t src , void * dest , size_t size , bool allow_decrypt )
2016-11-02 10:41:58 +11:00
{
2017-01-26 18:30:32 +11:00
if ( allow_decrypt & & esp_flash_encryption_enabled ( ) ) {
2022-06-27 15:24:07 +08:00
return esp_flash_read_encrypted ( NULL , src , dest , size ) ;
2017-01-26 18:30:32 +11:00
} else {
2022-06-27 15:24:07 +08:00
return esp_flash_read ( NULL , dest , src , size ) ;
2017-01-26 18:30:32 +11:00
}
2016-11-02 10:41:58 +11:00
}
2016-11-11 17:00:34 +11:00
esp_err_t bootloader_flash_write ( size_t dest_addr , void * src , size_t size , bool write_encrypted )
{
2021-06-17 07:21:36 +08:00
if ( write_encrypted & & ! ENCRYPTION_IS_VIRTUAL ) {
2022-06-27 15:24:07 +08:00
return esp_flash_write_encrypted ( NULL , dest_addr , src , size ) ;
2016-11-11 17:00:34 +11:00
} else {
2022-06-27 15:24:07 +08:00
return esp_flash_write ( NULL , src , dest_addr , size ) ;
2016-11-11 17:00:34 +11:00
}
}
esp_err_t bootloader_flash_erase_sector ( size_t sector )
{
2022-06-27 15:24:07 +08:00
// Will de-dependency IDF-5025
return esp_flash_erase_region ( NULL , sector * SPI_FLASH_SEC_SIZE , SPI_FLASH_SEC_SIZE ) ;
2016-11-11 17:00:34 +11:00
}
2018-08-24 17:58:04 +05:30
esp_err_t bootloader_flash_erase_range ( uint32_t start_addr , uint32_t size )
{
2022-06-27 15:24:07 +08:00
// Will de-dependency IDF-5025
return esp_flash_erase_region ( NULL , start_addr , size ) ;
2018-08-24 17:58:04 +05:30
}
2021-08-01 14:23:36 +08:00
# else //BOOTLOADER_BUILD
2016-11-02 10:41:58 +11:00
/* Bootloader version, uses ROM functions only */
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2019-12-26 15:25:24 +08:00
# include "esp32/rom/cache.h"
2019-05-27 14:29:43 +08:00
# endif
2021-09-28 14:12:56 +08:00
# include "esp_rom_spiflash.h"
2023-04-15 16:41:22 -03:00
# include "esp_rom_sys.h"
2022-02-11 15:30:54 +08:00
# include "hal/mmu_hal.h"
# include "hal/mmu_ll.h"
# include "hal/cache_hal.h"
2023-09-14 12:14:08 +08:00
# include "hal/cache_ll.h"
2023-04-14 11:37:09 +08:00
# if CONFIG_IDF_TARGET_ESP32S3
# include "esp32s3/rom/opi_flash.h"
# endif
2016-11-02 10:41:58 +11:00
static const char * TAG = " bootloader_flash " ;
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-11 17:00:34 +11:00
/* Use first 50 blocks in MMU for bootloader_mmap,
50th block for bootloader_flash_read
*/
2019-05-27 14:29:43 +08:00
# define MMU_BLOCK0_VADDR SOC_DROM_LOW
2022-07-08 16:46:11 +08:00
# define MMAP_MMU_SIZE (0x320000)
# define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMAP_MMU_SIZE)
# define FLASH_READ_VADDR MMU_BLOCK50_VADDR
2020-11-26 19:56:13 +11:00
# else // !CONFIG_IDF_TARGET_ESP32
2019-05-27 14:29:43 +08:00
/* Use first 63 blocks in MMU for bootloader_mmap,
63th block for bootloader_flash_read
*/
# define MMU_BLOCK0_VADDR SOC_DROM_LOW
2023-10-16 17:18:19 +08:00
# if CONFIG_IDF_TARGET_ESP32S2
/**
* On ESP32S2 we use `(SOC_DRAM0_CACHE_ADDRESS_HIGH - SOC_DRAM0_CACHE_ADDRESS_LOW)`.
* As this code is in bootloader, we keep this on ESP32S2
*/
2023-08-31 12:28:04 +08:00
# define MMAP_MMU_SIZE (SOC_DRAM0_CACHE_ADDRESS_HIGH - SOC_DRAM0_CACHE_ADDRESS_LOW) // This mmu size means that the mmu size to be mapped
2023-10-16 17:18:19 +08:00
# else
# define MMAP_MMU_SIZE (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_DRAM_FLASH_ADDRESS_LOW) // This mmu size means that the mmu size to be mapped
2023-07-27 15:10:50 +08:00
# endif
2022-11-02 19:11:45 +08:00
# define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMAP_MMU_SIZE - SPI_FLASH_MMU_PAGE_SIZE)
2019-08-08 13:44:24 +10:00
# define FLASH_READ_VADDR MMU_BLOCK63_VADDR
2019-05-27 14:29:43 +08:00
# endif
2016-11-11 17:00:34 +11:00
2022-07-08 16:46:11 +08:00
# define MMU_FREE_PAGES (MMAP_MMU_SIZE / CONFIG_MMU_PAGE_SIZE)
2019-12-26 15:25:24 +08:00
2016-11-02 10:41:58 +11:00
static bool mapped ;
2017-06-16 16:30:21 +10:00
// Current bootloader mapping (ab)used for bootloader_read()
2016-11-11 17:00:34 +11:00
static uint32_t current_read_mapping = UINT32_MAX ;
2019-07-16 16:33:30 +07:00
uint32_t bootloader_mmap_get_free_pages ( void )
2019-06-15 15:13:51 +05:30
{
/**
* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
* Since, bootloader_mmap function below assumes it to be 0x320000 (50 pages), we can safely do this.
*/
return MMU_FREE_PAGES ;
}
2022-02-11 15:30:54 +08:00
const void * bootloader_mmap ( uint32_t src_paddr , uint32_t size )
2016-11-02 10:41:58 +11:00
{
if ( mapped ) {
2022-02-11 15:30:54 +08:00
ESP_EARLY_LOGE ( TAG , " tried to bootloader_mmap twice " ) ;
2016-11-02 10:41:58 +11:00
return NULL ; /* can't map twice */
}
2022-07-08 16:46:11 +08:00
if ( size > MMAP_MMU_SIZE ) {
2022-02-11 15:30:54 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_mmap excess size %x " , size ) ;
return NULL ;
}
uint32_t src_paddr_aligned = src_paddr & MMU_FLASH_MASK ;
//The addr is aligned, so we add the mask off length to the size, to make sure the corresponding buses are enabled.
uint32_t size_after_paddr_aligned = ( src_paddr - src_paddr_aligned ) + size ;
/**
* @note 1
* Will add here a check to make sure the vaddr is on read-only and executable buses, since we use others for psram
* Now simply check if it's valid vaddr, didn't check if it's readable, writable or executable.
* TODO: IDF-4710
*/
2023-02-13 19:12:44 +08:00
if ( mmu_ll_check_valid_ext_vaddr_region ( 0 , MMU_BLOCK0_VADDR , size_after_paddr_aligned , MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION ) = = 0 ) {
2022-02-11 15:30:54 +08:00
ESP_EARLY_LOGE ( TAG , " vaddr not valid " ) ;
2016-11-11 17:00:34 +11:00
return NULL ;
}
2016-11-02 10:41:58 +11:00
2022-02-11 15:30:54 +08:00
//-------------stop cache to do the MMU mapping--------------
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-02 10:41:58 +11:00
Cache_Read_Disable ( 0 ) ;
Cache_Flush ( 0 ) ;
2021-10-21 18:09:37 +08:00
# else
2023-09-15 20:11:52 +08:00
cache_hal_disable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2019-05-27 14:29:43 +08:00
# endif
2022-02-11 15:30:54 +08:00
//---------------Do mapping------------------------
ESP_EARLY_LOGD ( TAG , " rodata starts from paddr=0x%08x, size=0x%x, will be mapped to vaddr=0x%08x " , src_paddr , size , MMU_BLOCK0_VADDR ) ;
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2022-02-11 15:30:54 +08:00
uint32_t count = GET_REQUIRED_MMU_PAGES ( size , src_paddr ) ;
int e = cache_flash_mmu_set ( 0 , 0 , MMU_BLOCK0_VADDR , src_paddr_aligned , 64 , count ) ;
2022-06-01 10:14:48 +08:00
ESP_EARLY_LOGV ( TAG , " after mapping, starting from paddr=0x%08x and vaddr=0x%08x, 0x%x bytes are mapped " , src_paddr_aligned , MMU_BLOCK0_VADDR , count * SPI_FLASH_MMU_PAGE_SIZE ) ;
2022-02-11 15:30:54 +08:00
if ( e ! = 0 ) {
ESP_EARLY_LOGE ( TAG , " cache_flash_mmu_set failed: %d \n " , e ) ;
2017-04-05 17:26:37 +08:00
Cache_Read_Enable ( 0 ) ;
return NULL ;
}
2022-02-11 15:30:54 +08:00
# else
/**
* This hal won't return error, it assumes the inputs are valid. The related check should be done in `bootloader_mmap()`.
* See above comments (note 1) about IDF-4710
*/
uint32_t actual_mapped_len = 0 ;
mmu_hal_map_region ( 0 , MMU_TARGET_FLASH0 , MMU_BLOCK0_VADDR , src_paddr_aligned , size_after_paddr_aligned , & actual_mapped_len ) ;
ESP_EARLY_LOGV ( TAG , " after mapping, starting from paddr=0x%08x and vaddr=0x%08x, 0x%x bytes are mapped " , src_paddr_aligned , MMU_BLOCK0_VADDR , actual_mapped_len ) ;
# endif
/**
* If after mapping, your code stucks, it possibly means that some of the buses are not enabled, check `cache_ll_l1_enable_bus()`
* For now, keep this unchanged.
*/
//-------------enable cache--------------
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2017-04-05 17:26:37 +08:00
Cache_Read_Enable ( 0 ) ;
2022-02-11 15:30:54 +08:00
# else
2023-09-14 12:14:08 +08:00
# if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_ll_invalidate_addr ( CACHE_LL_LEVEL_ALL , CACHE_TYPE_ALL , CACHE_LL_ID_ALL , MMU_BLOCK0_VADDR , actual_mapped_len ) ;
2023-07-27 15:10:50 +08:00
# endif
2023-09-15 20:11:52 +08:00
cache_hal_enable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2019-05-27 14:29:43 +08:00
# endif
2016-11-02 10:41:58 +11:00
mapped = true ;
2022-02-11 15:30:54 +08:00
return ( void * ) ( MMU_BLOCK0_VADDR + ( src_paddr - src_paddr_aligned ) ) ;
2016-11-02 10:41:58 +11:00
}
2016-11-07 15:45:57 +11:00
void bootloader_munmap ( const void * mapping )
2016-11-02 10:41:58 +11:00
{
if ( mapped ) {
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-02 10:41:58 +11:00
/* Full MMU reset */
Cache_Read_Disable ( 0 ) ;
Cache_Flush ( 0 ) ;
mmu_init ( 0 ) ;
2022-02-11 15:30:54 +08:00
# else
2023-09-15 20:11:52 +08:00
cache_hal_disable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2023-03-13 11:37:23 +08:00
mmu_hal_unmap_all ( ) ;
2019-05-27 14:29:43 +08:00
# endif
2016-11-02 10:41:58 +11:00
mapped = false ;
2016-11-11 17:00:34 +11:00
current_read_mapping = UINT32_MAX ;
2016-11-02 10:41:58 +11:00
}
}
2017-03-09 10:29:00 +03:00
static esp_err_t spi_to_esp_err ( esp_rom_spiflash_result_t r )
2016-11-02 10:41:58 +11:00
{
2019-05-27 14:29:43 +08:00
switch ( r ) {
2017-03-09 10:29:00 +03:00
case ESP_ROM_SPIFLASH_RESULT_OK :
2016-11-02 10:41:58 +11:00
return ESP_OK ;
2017-03-09 10:29:00 +03:00
case ESP_ROM_SPIFLASH_RESULT_ERR :
2016-11-02 10:41:58 +11:00
return ESP_ERR_FLASH_OP_FAIL ;
2017-03-09 10:29:00 +03:00
case ESP_ROM_SPIFLASH_RESULT_TIMEOUT :
2016-11-02 10:41:58 +11:00
return ESP_ERR_FLASH_OP_TIMEOUT ;
default :
return ESP_FAIL ;
}
}
2016-11-11 17:00:34 +11:00
static esp_err_t bootloader_flash_read_no_decrypt ( size_t src_addr , void * dest , size_t size )
{
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-11 17:00:34 +11:00
Cache_Read_Disable ( 0 ) ;
Cache_Flush ( 0 ) ;
2022-02-11 15:30:54 +08:00
# else
2023-09-15 20:11:52 +08:00
cache_hal_disable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2019-05-27 14:29:43 +08:00
# endif
2022-02-11 15:30:54 +08:00
2017-03-09 10:29:00 +03:00
esp_rom_spiflash_result_t r = esp_rom_spiflash_read ( src_addr , dest , size ) ;
2022-02-11 15:30:54 +08:00
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-11 17:00:34 +11:00
Cache_Read_Enable ( 0 ) ;
2022-02-11 15:30:54 +08:00
# else
2023-09-15 20:11:52 +08:00
cache_hal_enable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2019-05-27 14:29:43 +08:00
# endif
2016-11-11 17:00:34 +11:00
return spi_to_esp_err ( r ) ;
}
static esp_err_t bootloader_flash_read_allow_decrypt ( size_t src_addr , void * dest , size_t size )
{
uint32_t * dest_words = ( uint32_t * ) dest ;
2020-11-17 12:48:35 +08:00
for ( size_t word = 0 ; word < size / 4 ; word + + ) {
2016-11-11 17:00:34 +11:00
uint32_t word_src = src_addr + word * 4 ; /* Read this offset from flash */
uint32_t map_at = word_src & MMU_FLASH_MASK ; /* Map this 64KB block from flash */
uint32_t * map_ptr ;
2022-02-11 15:30:54 +08:00
/* Move the 64KB mmu mapping window to fit map_at */
2016-11-11 17:00:34 +11:00
if ( map_at ! = current_read_mapping ) {
2022-02-11 15:30:54 +08:00
//----------Stop cache for mapping----------------
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-11 17:00:34 +11:00
Cache_Read_Disable ( 0 ) ;
Cache_Flush ( 0 ) ;
2022-02-11 15:30:54 +08:00
# else
2023-09-15 20:11:52 +08:00
cache_hal_disable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2019-05-27 14:29:43 +08:00
# endif
2022-02-11 15:30:54 +08:00
//---------------Do mapping------------------------
ESP_EARLY_LOGD ( TAG , " mmu set block paddr=0x%08x (was 0x%08x) " , map_at , current_read_mapping ) ;
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2022-06-01 10:14:48 +08:00
//Should never fail if we only map a SPI_FLASH_MMU_PAGE_SIZE to the vaddr starting from FLASH_READ_VADDR
2019-08-08 13:44:24 +10:00
int e = cache_flash_mmu_set ( 0 , 0 , FLASH_READ_VADDR , map_at , 64 , 1 ) ;
2022-02-11 15:30:54 +08:00
assert ( e = = 0 ) ;
# else
uint32_t actual_mapped_len = 0 ;
2022-06-01 10:14:48 +08:00
mmu_hal_map_region ( 0 , MMU_TARGET_FLASH0 , FLASH_READ_VADDR , map_at , SPI_FLASH_MMU_PAGE_SIZE - 1 , & actual_mapped_len ) ;
2019-05-27 14:29:43 +08:00
# endif
2016-11-11 17:00:34 +11:00
current_read_mapping = map_at ;
2022-02-11 15:30:54 +08:00
//-------------enable cache-------------------------
2019-05-27 14:29:43 +08:00
# if CONFIG_IDF_TARGET_ESP32
2016-11-11 17:00:34 +11:00
Cache_Read_Enable ( 0 ) ;
2022-02-11 15:30:54 +08:00
# else
2023-09-14 12:14:08 +08:00
# if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_ll_invalidate_addr ( CACHE_LL_LEVEL_ALL , CACHE_TYPE_ALL , CACHE_LL_ID_ALL , MMU_BLOCK0_VADDR , actual_mapped_len ) ;
2023-07-27 15:10:50 +08:00
# endif
2023-09-15 20:11:52 +08:00
cache_hal_enable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2019-05-27 14:29:43 +08:00
# endif
2016-11-11 17:00:34 +11:00
}
2019-08-08 13:44:24 +10:00
map_ptr = ( uint32_t * ) ( FLASH_READ_VADDR + ( word_src - map_at ) ) ;
2016-11-11 17:00:34 +11:00
dest_words [ word ] = * map_ptr ;
}
return ESP_OK ;
}
esp_err_t bootloader_flash_read ( size_t src_addr , void * dest , size_t size , bool allow_decrypt )
{
if ( src_addr & 3 ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_flash_read src_addr 0x%x not 4-byte aligned " , src_addr ) ;
2016-11-11 17:00:34 +11:00
return ESP_FAIL ;
}
if ( size & 3 ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_flash_read size 0x%x not 4-byte aligned " , size ) ;
2016-11-11 17:00:34 +11:00
return ESP_FAIL ;
}
if ( ( intptr_t ) dest & 3 ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_flash_read dest 0x%x not 4-byte aligned " , ( intptr_t ) dest ) ;
2016-11-11 17:00:34 +11:00
return ESP_FAIL ;
}
if ( allow_decrypt ) {
return bootloader_flash_read_allow_decrypt ( src_addr , dest , size ) ;
} else {
return bootloader_flash_read_no_decrypt ( src_addr , dest , size ) ;
}
}
esp_err_t bootloader_flash_write ( size_t dest_addr , void * src , size_t size , bool write_encrypted )
{
esp_err_t err ;
size_t alignment = write_encrypted ? 32 : 4 ;
if ( ( dest_addr % alignment ) ! = 0 ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_flash_write dest_addr 0x%x not %d-byte aligned " , dest_addr , alignment ) ;
2016-11-11 17:00:34 +11:00
return ESP_FAIL ;
}
if ( ( size % alignment ) ! = 0 ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_flash_write size 0x%x not %d-byte aligned " , size , alignment ) ;
2016-11-11 17:00:34 +11:00
return ESP_FAIL ;
}
if ( ( ( intptr_t ) src % 4 ) ! = 0 ) {
2023-01-30 18:04:18 +08:00
ESP_EARLY_LOGE ( TAG , " bootloader_flash_write src 0x%x not 4 byte aligned " , ( intptr_t ) src ) ;
2016-11-11 17:00:34 +11:00
return ESP_FAIL ;
}
2021-05-07 15:25:06 +08:00
err = bootloader_flash_unlock ( ) ;
2016-11-11 17:00:34 +11:00
if ( err ! = ESP_OK ) {
return err ;
}
2021-06-17 07:21:36 +08:00
if ( write_encrypted & & ! ENCRYPTION_IS_VIRTUAL ) {
2017-03-09 10:29:00 +03:00
return spi_to_esp_err ( esp_rom_spiflash_write_encrypted ( dest_addr , src , size ) ) ;
2016-11-11 17:00:34 +11:00
} else {
2017-03-09 10:29:00 +03:00
return spi_to_esp_err ( esp_rom_spiflash_write ( dest_addr , src , size ) ) ;
2016-11-11 17:00:34 +11:00
}
}
esp_err_t bootloader_flash_erase_sector ( size_t sector )
{
2017-03-09 10:29:00 +03:00
return spi_to_esp_err ( esp_rom_spiflash_erase_sector ( sector ) ) ;
2016-11-11 17:00:34 +11:00
}
2018-08-24 17:58:04 +05:30
esp_err_t bootloader_flash_erase_range ( uint32_t start_addr , uint32_t size )
{
if ( start_addr % FLASH_SECTOR_SIZE ! = 0 ) {
return ESP_ERR_INVALID_ARG ;
}
if ( size % FLASH_SECTOR_SIZE ! = 0 ) {
return ESP_ERR_INVALID_SIZE ;
}
size_t start = start_addr / FLASH_SECTOR_SIZE ;
size_t end = start + size / FLASH_SECTOR_SIZE ;
const size_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE ;
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK ;
for ( size_t sector = start ; sector ! = end & & rc = = ESP_ROM_SPIFLASH_RESULT_OK ; ) {
if ( sector % sectors_per_block = = 0 & & end - sector > = sectors_per_block ) {
rc = esp_rom_spiflash_erase_block ( sector / sectors_per_block ) ;
sector + = sectors_per_block ;
} else {
rc = esp_rom_spiflash_erase_sector ( sector ) ;
+ + sector ;
}
}
return spi_to_esp_err ( rc ) ;
}
2020-03-12 18:20:31 +08:00
2023-10-12 11:57:04 +08:00
# if CONFIG_SPI_FLASH_QUAD_32BIT_ADDR_ENABLE || CONFIG_SPI_FLASH_OCTAL_32BIT_ADDR_ENABLE
2023-04-14 11:37:09 +08:00
void bootloader_flash_32bits_address_map_enable ( esp_rom_spiflash_read_mode_t flash_mode )
{
esp_rom_opiflash_spi0rd_t cache_rd = { } ;
switch ( flash_mode ) {
case ESP_ROM_SPIFLASH_DOUT_MODE :
cache_rd . addr_bit_len = 32 ;
cache_rd . dummy_bit_len = 8 ;
cache_rd . cmd = CMD_FASTRD_DUAL_4B ;
cache_rd . cmd_bit_len = 8 ;
break ;
case ESP_ROM_SPIFLASH_DIO_MODE :
cache_rd . addr_bit_len = 32 ;
cache_rd . dummy_bit_len = 4 ;
cache_rd . cmd = CMD_FASTRD_DIO_4B ;
cache_rd . cmd_bit_len = 8 ;
break ;
case ESP_ROM_SPIFLASH_QOUT_MODE :
cache_rd . addr_bit_len = 32 ;
cache_rd . dummy_bit_len = 8 ;
cache_rd . cmd = CMD_FASTRD_QUAD_4B ;
cache_rd . cmd_bit_len = 8 ;
break ;
case ESP_ROM_SPIFLASH_QIO_MODE :
cache_rd . addr_bit_len = 32 ;
cache_rd . dummy_bit_len = 6 ;
cache_rd . cmd = CMD_FASTRD_QIO_4B ;
cache_rd . cmd_bit_len = 8 ;
break ;
2023-10-12 11:57:04 +08:00
case ESP_ROM_SPIFLASH_FASTRD_MODE :
cache_rd . addr_bit_len = 32 ;
cache_rd . dummy_bit_len = 8 ;
cache_rd . cmd = CMD_FASTRD_4B ;
cache_rd . cmd_bit_len = 8 ;
break ;
case ESP_ROM_SPIFLASH_SLOWRD_MODE :
cache_rd . addr_bit_len = 32 ;
cache_rd . dummy_bit_len = 0 ;
cache_rd . cmd = CMD_SLOWRD_4B ;
cache_rd . cmd_bit_len = 8 ;
break ;
2023-04-14 11:37:09 +08:00
default :
assert ( false ) ;
break ;
}
2023-09-15 20:11:52 +08:00
cache_hal_disable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2023-04-14 11:37:09 +08:00
esp_rom_opiflash_cache_mode_config ( flash_mode , & cache_rd ) ;
2023-09-15 20:11:52 +08:00
cache_hal_enable ( CACHE_LL_LEVEL_EXT_MEM , CACHE_TYPE_ALL ) ;
2023-04-14 11:37:09 +08:00
}
# endif
2021-08-01 14:23:36 +08:00
# endif // BOOTLOADER_BUILD
2020-03-12 18:20:31 +08:00
2021-05-07 15:25:06 +08:00
FORCE_INLINE_ATTR bool is_issi_chip ( const esp_rom_spiflash_chip_t * chip )
{
return BYTESHIFT ( chip - > device_id , 2 ) = = ISSI_ID ;
}
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
FORCE_INLINE_ATTR bool is_gd_q_chip ( const esp_rom_spiflash_chip_t * chip )
{
return BYTESHIFT ( chip - > device_id , 2 ) = = GD_Q_ID_HIGH & & BYTESHIFT ( chip - > device_id , 1 ) = = GD_Q_ID_MID & & BYTESHIFT ( chip - > device_id , 0 ) > = GD_Q_ID_LOW ;
}
2021-09-17 15:38:37 +08:00
FORCE_INLINE_ATTR bool is_mxic_chip ( const esp_rom_spiflash_chip_t * chip )
{
return BYTESHIFT ( chip - > device_id , 2 ) = = MXIC_ID ;
}
2021-05-07 15:25:06 +08:00
esp_err_t IRAM_ATTR __attribute__ ( ( weak ) ) bootloader_flash_unlock ( void )
{
2021-09-17 15:38:37 +08:00
// At the beginning status == new_status == status_sr2 == new_status_sr2 == 0.
// If the register doesn't need to be updated, keep them the same (0), so that no command will be actually sent.
2021-05-07 15:25:06 +08:00
uint16_t status = 0 ; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
uint16_t new_status = 0 ;
uint8_t status_sr2 = 0 ; // status_sr2 for SR2.
uint8_t new_status_sr2 = 0 ;
2021-09-17 15:38:37 +08:00
uint8_t sr1_bit_num = 0 ;
2021-05-07 15:25:06 +08:00
esp_err_t err = ESP_OK ;
esp_rom_spiflash_wait_idle ( & g_rom_flashchip ) ;
2021-09-17 15:38:37 +08:00
if ( is_issi_chip ( & g_rom_flashchip ) | | is_mxic_chip ( & g_rom_flashchip ) ) {
// Currently ISSI & MXIC share the same command and register layout, which is different from the default model.
// If any code here needs to be modified, check both chips.
2021-05-07 15:25:06 +08:00
status = bootloader_execute_flash_command ( CMD_RDSR , 0 , 0 , 8 ) ;
/* Clear all bits in the mask.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
2021-09-17 15:38:37 +08:00
sr1_bit_num = 8 ;
2021-05-07 15:25:06 +08:00
new_status = status & ( ~ ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI ) ;
2023-07-18 10:12:46 +08:00
} else if ( is_gd_q_chip ( & g_rom_flashchip ) ) {
2021-05-07 15:25:06 +08:00
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
Use 01H to write SR1 and 31H to write SR2.
*/
status = bootloader_execute_flash_command ( CMD_RDSR , 0 , 0 , 8 ) ;
2021-09-17 15:38:37 +08:00
sr1_bit_num = 8 ;
2021-05-07 15:25:06 +08:00
new_status = 0 ;
status_sr2 = bootloader_execute_flash_command ( CMD_RDSR2 , 0 , 0 , 8 ) ;
2021-09-17 15:38:37 +08:00
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 ;
2021-05-07 15:25:06 +08:00
} else {
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
status = bootloader_execute_flash_command ( CMD_RDSR , 0 , 0 , 8 ) | ( bootloader_execute_flash_command ( CMD_RDSR2 , 0 , 0 , 8 ) < < 8 ) ;
/* Clear all bits except QE, if it is set.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
2021-09-17 15:38:37 +08:00
sr1_bit_num = 16 ;
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE ;
2021-05-07 15:25:06 +08:00
}
2021-09-17 15:38:37 +08:00
// When SR is written, set to true to indicate that WRDI need to be sent to ensure the protection is ON before return.
bool status_written = false ;
// Skip if nothing needs to be changed. Meaningless writing to SR increases the risk during write and wastes time.
2021-05-07 15:25:06 +08:00
if ( status ! = new_status ) {
esp_rom_spiflash_wait_idle ( & g_rom_flashchip ) ;
bootloader_execute_flash_command ( CMD_WREN , 0 , 0 , 0 ) ;
2021-09-17 15:38:37 +08:00
bootloader_execute_flash_command ( CMD_WRSR , new_status , sr1_bit_num , 0 ) ;
status_written = true ;
2021-05-07 15:25:06 +08:00
}
if ( status_sr2 ! = new_status_sr2 ) {
esp_rom_spiflash_wait_idle ( & g_rom_flashchip ) ;
bootloader_execute_flash_command ( CMD_WREN , 0 , 0 , 0 ) ;
2021-09-17 15:38:37 +08:00
bootloader_execute_flash_command ( CMD_WRSR2 , new_status_sr2 , 8 , 0 ) ;
status_written = true ;
}
if ( status_written ) {
//Call esp_rom_spiflash_wait_idle to make sure previous WRSR is completed.
2021-05-07 15:25:06 +08:00
esp_rom_spiflash_wait_idle ( & g_rom_flashchip ) ;
2021-09-17 15:38:37 +08:00
bootloader_execute_flash_command ( CMD_WRDI , 0 , 0 , 0 ) ;
2021-05-07 15:25:06 +08:00
}
return err ;
}
2022-02-25 17:03:45 +08:00
IRAM_ATTR uint32_t bootloader_flash_execute_command_common (
2021-08-01 14:23:36 +08:00
uint8_t command ,
uint32_t addr_len , uint32_t address ,
uint8_t dummy_len ,
uint8_t mosi_len , uint32_t mosi_data ,
uint8_t miso_len )
2020-03-12 18:20:31 +08:00
{
2021-08-01 14:23:36 +08:00
assert ( mosi_len < = 32 ) ;
assert ( miso_len < = 32 ) ;
2020-03-12 18:20:31 +08:00
uint32_t old_ctrl_reg = SPIFLASH . ctrl . val ;
2021-08-18 23:55:39 +08:00
uint32_t old_user_reg = SPIFLASH . user . val ;
2021-08-19 17:02:58 +08:00
uint32_t old_user1_reg = SPIFLASH . user1 . val ;
2023-04-27 16:20:30 +02:00
uint32_t old_user2_reg = SPIFLASH . user2 . val ;
2020-03-12 18:20:31 +08:00
# if CONFIG_IDF_TARGET_ESP32
SPIFLASH . ctrl . val = SPI_WP_REG_M ; // keep WP high while idle, otherwise leave DIO mode
2020-11-26 19:56:13 +11:00
# else
2020-03-12 18:20:31 +08:00
SPIFLASH . ctrl . val = SPI_MEM_WP_REG_M ; // keep WP high while idle, otherwise leave DIO mode
# endif
2021-08-01 14:23:36 +08:00
//command phase
2020-03-12 18:20:31 +08:00
SPIFLASH . user . usr_command = 1 ;
SPIFLASH . user2 . usr_command_bitlen = 7 ;
SPIFLASH . user2 . usr_command_value = command ;
2021-08-01 14:23:36 +08:00
//addr phase
SPIFLASH . user . usr_addr = addr_len > 0 ;
SPIFLASH . user1 . usr_addr_bitlen = addr_len - 1 ;
2020-03-12 18:20:31 +08:00
# if CONFIG_IDF_TARGET_ESP32
2021-08-01 14:23:36 +08:00
SPIFLASH . addr = ( addr_len > 0 ) ? ( address < < ( 32 - addr_len ) ) : 0 ;
2020-11-26 19:56:13 +11:00
# else
2021-08-01 14:23:36 +08:00
SPIFLASH . addr = address ;
2020-03-12 18:20:31 +08:00
# endif
2021-08-01 14:23:36 +08:00
//dummy phase
2022-02-25 17:05:48 +08:00
uint32_t total_dummy = dummy_len ;
2021-08-01 14:23:36 +08:00
if ( miso_len > 0 ) {
2022-02-25 17:05:48 +08:00
total_dummy + = g_rom_spiflash_dummy_len_plus [ 1 ] ;
2021-08-01 14:23:36 +08:00
}
2022-02-25 17:05:48 +08:00
SPIFLASH . user . usr_dummy = total_dummy > 0 ;
SPIFLASH . user1 . usr_dummy_cyclelen = total_dummy - 1 ;
2021-08-01 14:23:36 +08:00
//output data
2020-03-12 18:20:31 +08:00
SPIFLASH . user . usr_mosi = mosi_len > 0 ;
# if CONFIG_IDF_TARGET_ESP32
SPIFLASH . mosi_dlen . usr_mosi_dbitlen = mosi_len ? ( mosi_len - 1 ) : 0 ;
2020-11-26 19:56:13 +11:00
# else
2020-03-12 18:20:31 +08:00
SPIFLASH . mosi_dlen . usr_mosi_bit_len = mosi_len ? ( mosi_len - 1 ) : 0 ;
2016-11-02 10:41:58 +11:00
# endif
2020-03-12 18:20:31 +08:00
SPIFLASH . data_buf [ 0 ] = mosi_data ;
2021-08-01 14:23:36 +08:00
//input data
SPIFLASH . user . usr_miso = miso_len > 0 ;
# if CONFIG_IDF_TARGET_ESP32
SPIFLASH . miso_dlen . usr_miso_dbitlen = miso_len ? ( miso_len - 1 ) : 0 ;
# else
SPIFLASH . miso_dlen . usr_miso_bit_len = miso_len ? ( miso_len - 1 ) : 0 ;
# endif
2020-03-12 18:20:31 +08:00
SPIFLASH . cmd . usr = 1 ;
while ( SPIFLASH . cmd . usr ! = 0 ) {
}
SPIFLASH . ctrl . val = old_ctrl_reg ;
2021-08-18 23:55:39 +08:00
SPIFLASH . user . val = old_user_reg ;
2021-08-19 17:02:58 +08:00
SPIFLASH . user1 . val = old_user1_reg ;
2023-04-27 16:20:30 +02:00
SPIFLASH . user2 . val = old_user2_reg ;
2021-08-01 14:23:36 +08:00
uint32_t ret = SPIFLASH . data_buf [ 0 ] ;
if ( miso_len < 32 ) {
//set unused bits to 0
ret & = ~ ( UINT32_MAX < < miso_len ) ;
}
return ret ;
}
uint32_t IRAM_ATTR bootloader_execute_flash_command ( uint8_t command , uint32_t mosi_data , uint8_t mosi_len , uint8_t miso_len )
{
const uint8_t addr_len = 0 ;
const uint8_t address = 0 ;
const uint8_t dummy_len = 0 ;
return bootloader_flash_execute_command_common ( command , addr_len , address ,
dummy_len , mosi_len , mosi_data , miso_len ) ;
}
// cmd(0x5A) + 24bit address + 8 cycles dummy
uint32_t IRAM_ATTR bootloader_flash_read_sfdp ( uint32_t sfdp_addr , unsigned int miso_byte_num )
{
assert ( miso_byte_num < = 4 ) ;
const uint8_t command = CMD_RDSFDP ;
const uint8_t addr_len = 24 ;
const uint8_t dummy_len = 8 ;
const uint8_t mosi_len = 0 ;
const uint32_t mosi_data = 0 ;
const uint8_t miso_len = miso_byte_num * 8 ;
return bootloader_flash_execute_command_common ( command , addr_len , sfdp_addr ,
dummy_len , mosi_len , mosi_data , miso_len ) ;
2020-03-12 18:20:31 +08:00
}
void bootloader_enable_wp ( void )
{
bootloader_execute_flash_command ( CMD_WRDI , 0 , 0 , 0 ) ; /* Exit OTP mode */
}
2021-08-01 14:23:36 +08:00
uint32_t IRAM_ATTR bootloader_read_flash_id ( void )
{
uint32_t id = bootloader_execute_flash_command ( CMD_RDID , 0 , 0 , 24 ) ;
id = ( ( id & 0xff ) < < 16 ) | ( ( id > > 16 ) & 0xff ) | ( id & 0xff00 ) ;
return id ;
}
2022-06-23 15:19:56 +08:00
void bootloader_spi_flash_reset ( void )
{
bootloader_execute_flash_command ( CMD_RESETEN , 0 , 0 , 0 ) ;
bootloader_execute_flash_command ( CMD_RESET , 0 , 0 , 0 ) ;
}
2021-08-01 14:23:36 +08:00
/*******************************************************************************
* XMC startup flow
******************************************************************************/
# define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
# define XMC_VENDOR_ID 0x20
# if BOOTLOADER_BUILD
2023-01-30 18:04:18 +08:00
# define BOOTLOADER_FLASH_LOG(level, ...) ESP_EARLY_LOG##level(TAG, ##__VA_ARGS__)
2021-08-01 14:23:36 +08:00
# else
static DRAM_ATTR char bootloader_flash_tag [ ] = " bootloader_flash " ;
# define BOOTLOADER_FLASH_LOG(level, ...) ESP_DRAM_LOG##level(bootloader_flash_tag, ##__VA_ARGS__)
# endif
# if XMC_SUPPORT
//strictly check the model
static IRAM_ATTR bool is_xmc_chip_strict ( uint32_t rdid )
{
uint32_t vendor_id = BYTESHIFT ( rdid , 2 ) ;
uint32_t mfid = BYTESHIFT ( rdid , 1 ) ;
uint32_t cpid = BYTESHIFT ( rdid , 0 ) ;
if ( vendor_id ! = XMC_VENDOR_ID ) {
return false ;
}
bool matched = false ;
if ( mfid = = 0x40 ) {
if ( cpid > = 0x13 & & cpid < = 0x20 ) {
matched = true ;
}
} else if ( mfid = = 0x41 ) {
if ( cpid > = 0x17 & & cpid < = 0x20 ) {
matched = true ;
}
} else if ( mfid = = 0x50 ) {
if ( cpid > = 0x15 & & cpid < = 0x16 ) {
matched = true ;
}
}
return matched ;
}
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup ( void )
{
// If the RDID value is a valid XMC one, may skip the flow
const bool fast_check = true ;
if ( fast_check & & is_xmc_chip_strict ( g_rom_flashchip . device_id ) ) {
BOOTLOADER_FLASH_LOG ( D , " XMC chip detected by RDID (%08X), skip. " , g_rom_flashchip . device_id ) ;
return ESP_OK ;
}
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
const int sfdp_mfid_addr = 0x10 ;
uint8_t mf_id = ( bootloader_flash_read_sfdp ( sfdp_mfid_addr , 1 ) & 0xff ) ;
if ( mf_id ! = XMC_VENDOR_ID ) {
BOOTLOADER_FLASH_LOG ( D , " non-XMC chip detected by SFDP Read (%02X), skip. " , mf_id ) ;
return ESP_OK ;
}
BOOTLOADER_FLASH_LOG ( I , " XM25QHxxC startup flow " ) ;
// Enter DPD
bootloader_execute_flash_command ( 0xB9 , 0 , 0 , 0 ) ;
// Enter UDPD
bootloader_execute_flash_command ( 0x79 , 0 , 0 , 0 ) ;
// Exit UDPD
bootloader_execute_flash_command ( 0xFF , 0 , 0 , 0 ) ;
// Delay tXUDPD
esp_rom_delay_us ( 2000 ) ;
// Release Power-down
bootloader_execute_flash_command ( 0xAB , 0 , 0 , 0 ) ;
esp_rom_delay_us ( 20 ) ;
// Read flash ID and check again
g_rom_flashchip . device_id = bootloader_read_flash_id ( ) ;
if ( ! is_xmc_chip_strict ( g_rom_flashchip . device_id ) ) {
BOOTLOADER_FLASH_LOG ( E , " XMC flash startup fail " ) ;
return ESP_FAIL ;
}
return ESP_OK ;
}
# else
//only compare the vendor id
static IRAM_ATTR bool is_xmc_chip ( uint32_t rdid )
{
uint32_t vendor_id = ( rdid > > 16 ) & 0xFF ;
return ( vendor_id = = XMC_VENDOR_ID ) ;
}
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup ( void )
{
if ( is_xmc_chip ( g_rom_flashchip . device_id ) ) {
BOOTLOADER_FLASH_LOG ( E , " XMC chip detected (%08X) while support disabled. " , g_rom_flashchip . device_id ) ;
return ESP_FAIL ;
}
return ESP_OK ;
}
# endif //XMC_SUPPORT
2022-05-30 16:49:19 +08:00
FORCE_INLINE_ATTR void bootloader_mspi_reset ( void )
{
# if CONFIG_IDF_TARGET_ESP32
SPI1 . slave . sync_reset = 0 ;
SPI0 . slave . sync_reset = 0 ;
SPI1 . slave . sync_reset = 1 ;
SPI0 . slave . sync_reset = 1 ;
SPI1 . slave . sync_reset = 0 ;
SPI0 . slave . sync_reset = 0 ;
# else
SPIMEM1 . ctrl2 . sync_reset = 0 ;
SPIMEM0 . ctrl2 . sync_reset = 0 ;
SPIMEM1 . ctrl2 . sync_reset = 1 ;
SPIMEM0 . ctrl2 . sync_reset = 1 ;
SPIMEM1 . ctrl2 . sync_reset = 0 ;
SPIMEM0 . ctrl2 . sync_reset = 0 ;
# endif
}
esp_err_t IRAM_ATTR bootloader_flash_reset_chip ( void )
{
bootloader_mspi_reset ( ) ;
// Seems that sync_reset cannot make host totally idle.'
// Sending an extra(useless) command to make the host idle in order to send reset command.
bootloader_execute_flash_command ( 0x05 , 0 , 0 , 0 ) ;
# if CONFIG_IDF_TARGET_ESP32
if ( SPI1 . ext2 . st ! = 0 )
# else
2022-07-08 16:46:11 +08:00
if ( ! spimem_flash_ll_host_idle ( & SPIMEM1 ) )
2022-05-30 16:49:19 +08:00
# endif
{
return ESP_FAIL ;
}
bootloader_execute_flash_command ( 0x66 , 0 , 0 , 0 ) ;
bootloader_execute_flash_command ( 0x99 , 0 , 0 , 0 ) ;
return ESP_OK ;
}
2022-09-23 17:32:16 +08:00
2023-02-23 12:54:37 +08:00
bool IRAM_ATTR bootloader_flash_is_octal_mode_enabled ( void )
2022-09-23 17:32:16 +08:00
{
# if SOC_SPI_MEM_SUPPORT_OPI_MODE
return efuse_ll_get_flash_type ( ) ;
# else
return false ;
# endif
}
2023-04-14 11:37:09 +08:00
esp_rom_spiflash_read_mode_t bootloader_flash_get_spi_mode ( void )
{
esp_rom_spiflash_read_mode_t spi_mode = ESP_ROM_SPIFLASH_FASTRD_MODE ;
# if CONFIG_IDF_TARGET_ESP32
uint32_t spi_ctrl = REG_READ ( SPI_CTRL_REG ( 0 ) ) ;
if ( spi_ctrl & SPI_FREAD_QIO ) {
spi_mode = ESP_ROM_SPIFLASH_QIO_MODE ;
} else if ( spi_ctrl & SPI_FREAD_QUAD ) {
spi_mode = ESP_ROM_SPIFLASH_QOUT_MODE ;
} else if ( spi_ctrl & SPI_FREAD_DIO ) {
spi_mode = ESP_ROM_SPIFLASH_DIO_MODE ;
} else if ( spi_ctrl & SPI_FREAD_DUAL ) {
spi_mode = ESP_ROM_SPIFLASH_DOUT_MODE ;
} else if ( spi_ctrl & SPI_FASTRD_MODE ) {
spi_mode = ESP_ROM_SPIFLASH_FASTRD_MODE ;
} else {
spi_mode = ESP_ROM_SPIFLASH_SLOWRD_MODE ;
}
# else
uint32_t spi_ctrl = REG_READ ( SPI_MEM_CTRL_REG ( 0 ) ) ;
if ( spi_ctrl & SPI_MEM_FREAD_QIO ) {
spi_mode = ESP_ROM_SPIFLASH_QIO_MODE ;
} else if ( spi_ctrl & SPI_MEM_FREAD_QUAD ) {
spi_mode = ESP_ROM_SPIFLASH_QOUT_MODE ;
} else if ( spi_ctrl & SPI_MEM_FREAD_DIO ) {
spi_mode = ESP_ROM_SPIFLASH_DIO_MODE ;
} else if ( spi_ctrl & SPI_MEM_FREAD_DUAL ) {
spi_mode = ESP_ROM_SPIFLASH_DOUT_MODE ;
} else if ( spi_ctrl & SPI_MEM_FASTRD_MODE ) {
spi_mode = ESP_ROM_SPIFLASH_FASTRD_MODE ;
} else {
spi_mode = ESP_ROM_SPIFLASH_SLOWRD_MODE ;
}
# endif
return spi_mode ;
}