2021-09-09 03:34:42 -04:00
/*
2022-01-17 21:32:56 -05:00
* SPDX - FileCopyrightText : 2015 - 2022 Espressif Systems ( Shanghai ) CO LTD
2021-09-09 03:34:42 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
2019-06-24 00:56:39 -04:00
# include "sdkconfig.h"
# include "esp_flash.h"
# include "memspi_host_driver.h"
# include "esp_flash_spi_init.h"
# include "driver/gpio.h"
2020-06-19 00:00:58 -04:00
# include "esp_rom_gpio.h"
2020-07-13 09:57:24 -04:00
# include "esp_rom_efuse.h"
2019-06-24 00:56:39 -04:00
# include "esp_log.h"
# include "esp_heap_caps.h"
# include "hal/spi_types.h"
2019-09-03 02:06:26 -04:00
# include "driver/spi_common_internal.h"
2020-06-12 06:52:00 -04:00
# include "hal/spi_flash_hal.h"
2021-03-15 22:55:05 -04:00
# include "hal/gpio_hal.h"
2019-09-11 14:41:00 -04:00
# include "esp_flash_internal.h"
2020-07-29 01:13:51 -04:00
# include "esp_rom_gpio.h"
2021-09-09 03:34:42 -04:00
# include "esp_private/spi_flash_os.h"
2021-09-28 02:12:56 -04:00
# include "esp_rom_spiflash.h"
2019-06-24 00:56:39 -04:00
2019-09-10 02:34:06 -04:00
__attribute__ ( ( unused ) ) static const char TAG [ ] = " spi_flash " ;
2019-06-24 00:56:39 -04:00
2021-08-04 23:40:22 -04:00
/* This pointer is defined in ROM and extern-ed on targets where CONFIG_SPI_FLASH_ROM_IMPL = y*/
# if !CONFIG_SPI_FLASH_ROM_IMPL
esp_flash_t * esp_flash_default_chip = NULL ;
# endif
# ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
2019-06-24 00:56:39 -04:00
# ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M
# define DEFAULT_FLASH_SPEED ESP_FLASH_80MHZ
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_40M
# define DEFAULT_FLASH_SPEED ESP_FLASH_40MHZ
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_26M
# define DEFAULT_FLASH_SPEED ESP_FLASH_26MHZ
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_20M
# define DEFAULT_FLASH_SPEED ESP_FLASH_20MHZ
2021-09-01 03:58:15 -04:00
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_120M
# define DEFAULT_FLASH_SPEED ESP_FLASH_120MHZ
2019-06-24 00:56:39 -04:00
# else
# error Flash frequency not defined! Check the ``CONFIG_ESPTOOLPY_FLASHFREQ_*`` options.
# endif
# if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO)
# define DEFAULT_FLASH_MODE SPI_FLASH_QIO
# elif defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT)
# define DEFAULT_FLASH_MODE SPI_FLASH_QOUT
# elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO)
# define DEFAULT_FLASH_MODE SPI_FLASH_DIO
# elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT)
# define DEFAULT_FLASH_MODE SPI_FLASH_DOUT
2021-09-09 03:34:42 -04:00
# elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR)
2021-09-01 03:58:15 -04:00
# define DEFAULT_FLASH_MODE SPI_FLASH_OPI_STR
2021-09-09 03:34:42 -04:00
# elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR)
2021-09-01 03:58:15 -04:00
# define DEFAULT_FLASH_MODE SPI_FLASH_OPI_DTR
2019-06-24 00:56:39 -04:00
# else
# define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD
# endif
2020-07-26 15:13:07 -04:00
//TODO: modify cs hold to meet requirements of all chips!!!
2020-01-16 01:41:41 -05:00
# if CONFIG_IDF_TARGET_ESP32
2019-09-10 02:34:06 -04:00
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
2021-03-05 03:20:33 -05:00
. host_id = SPI1_HOST , \
2019-09-10 02:34:06 -04:00
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = false , \
. input_delay_ns = 0 , \
2021-05-20 08:51:38 -04:00
. cs_setup = 1 , \
2019-09-10 02:34:06 -04:00
}
2020-01-16 22:47:08 -05:00
# elif CONFIG_IDF_TARGET_ESP32S2
2020-01-16 01:41:41 -05:00
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
2021-03-05 03:20:33 -05:00
. host_id = SPI1_HOST , \
2020-01-16 01:41:41 -05:00
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
2021-05-20 08:51:38 -04:00
. cs_setup = 1 , \
2020-01-16 01:41:41 -05:00
}
2020-07-29 01:13:51 -04:00
# elif CONFIG_IDF_TARGET_ESP32S3
# include "esp32s3/rom/efuse.h"
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
2021-03-05 03:20:33 -05:00
. host_id = SPI1_HOST , \
2020-07-29 01:13:51 -04:00
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
2021-05-20 08:51:38 -04:00
. cs_setup = 1 , \
2020-07-29 01:13:51 -04:00
}
2022-01-17 21:32:56 -05:00
# elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
2020-12-17 23:57:55 -05:00
# if !CONFIG_SPI_FLASH_AUTO_SUSPEND
2020-12-15 22:50:13 -05:00
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
2021-03-05 03:20:33 -05:00
. host_id = SPI1_HOST , \
2020-12-15 22:50:13 -05:00
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
2021-05-20 08:51:38 -04:00
. cs_setup = 1 , \
2020-12-15 22:50:13 -05:00
}
2020-12-17 23:57:55 -05:00
# else
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
2021-03-05 03:20:33 -05:00
. host_id = SPI1_HOST , \
2020-12-17 23:57:55 -05:00
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
. auto_sus_en = true , \
2021-05-20 08:51:38 -04:00
. cs_setup = 1 , \
2020-12-17 23:57:55 -05:00
}
# endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND
2021-06-10 07:47:41 -04:00
# elif CONFIG_IDF_TARGET_ESP32H2
# include "esp32h2/rom/efuse.h"
# if !CONFIG_SPI_FLASH_AUTO_SUSPEND
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
. host_id = SPI1_HOST , \
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
}
# else
# define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
. host_id = SPI1_HOST , \
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
. auto_sus_en = true , \
}
# endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND
2020-01-16 01:41:41 -05:00
# endif
2019-09-10 02:34:06 -04:00
2020-04-07 11:53:43 -04:00
static IRAM_ATTR NOINLINE_ATTR void cs_initialize ( esp_flash_t * chip , const esp_flash_spi_device_config_t * config , bool use_iomux , int cs_id )
2019-06-24 00:56:39 -04:00
{
//Not using spicommon_cs_initialize since we don't want to put the whole
//spi_periph_signal into the DRAM. Copy these data from flash before the
//cache disabling
int cs_io_num = config - > cs_io_num ;
int spics_in = spi_periph_signal [ config - > host_id ] . spics_in ;
2020-04-07 11:53:43 -04:00
int spics_out = spi_periph_signal [ config - > host_id ] . spics_out [ cs_id ] ;
2019-11-27 20:20:00 -05:00
int spics_func = spi_periph_signal [ config - > host_id ] . func ;
2019-06-24 00:56:39 -04:00
uint32_t iomux_reg = GPIO_PIN_MUX_REG [ cs_io_num ] ;
2021-12-30 07:31:38 -05:00
gpio_hal_context_t gpio_hal = {
. dev = GPIO_HAL_GET_HW ( GPIO_PORT_0 )
} ;
2019-06-24 00:56:39 -04:00
//To avoid the panic caused by flash data line conflicts during cs line
//initialization, disable the cache temporarily
chip - > os_func - > start ( chip - > os_func_data ) ;
2020-07-10 14:19:28 -04:00
PIN_INPUT_ENABLE ( iomux_reg ) ;
2019-06-24 00:56:39 -04:00
if ( use_iomux ) {
2021-03-15 22:55:05 -04:00
gpio_hal_iomux_func_sel ( iomux_reg , spics_func ) ;
2019-06-24 00:56:39 -04:00
} else {
2021-12-30 07:31:38 -05:00
gpio_hal_output_enable ( & gpio_hal , cs_io_num ) ;
gpio_hal_od_disable ( & gpio_hal , cs_io_num ) ;
2020-06-19 00:00:58 -04:00
esp_rom_gpio_connect_out_signal ( cs_io_num , spics_out , false , false ) ;
2020-04-07 11:53:43 -04:00
if ( cs_id = = 0 ) {
2020-06-19 00:00:58 -04:00
esp_rom_gpio_connect_in_signal ( cs_io_num , spics_in , false ) ;
2019-06-24 00:56:39 -04:00
}
2021-03-15 22:55:05 -04:00
gpio_hal_iomux_func_sel ( iomux_reg , PIN_FUNC_GPIO ) ;
2019-06-24 00:56:39 -04:00
}
chip - > os_func - > end ( chip - > os_func_data ) ;
}
2022-04-13 05:23:57 -04:00
static bool use_bus_lock ( int host_id )
{
if ( host_id ! = SPI1_HOST ) {
return true ;
}
# if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
return true ;
# else
return false ;
# endif
}
static esp_err_t acquire_spi_device ( const esp_flash_spi_device_config_t * config , int * out_dev_id , spi_bus_lock_dev_handle_t * out_dev_handle )
{
esp_err_t ret = ESP_OK ;
int dev_id = - 1 ;
spi_bus_lock_dev_handle_t dev_handle = NULL ;
if ( use_bus_lock ( config - > host_id ) ) {
spi_bus_lock_handle_t lock = spi_bus_lock_get_by_id ( config - > host_id ) ;
spi_bus_lock_dev_config_t config = { . flags = SPI_BUS_LOCK_DEV_FLAG_CS_REQUIRED } ;
ret = spi_bus_lock_register_dev ( lock , & config , & dev_handle ) ;
if ( ret = = ESP_OK ) {
dev_id = spi_bus_lock_get_dev_id ( dev_handle ) ;
} else if ( ret = = ESP_ERR_NOT_SUPPORTED ) {
ESP_LOGE ( TAG , " No free CS. " ) ;
} else if ( ret = = ESP_ERR_INVALID_ARG ) {
ESP_LOGE ( TAG , " Bus lock not initialized (check CONFIG_SPI_FLASH_SHARE_SPI1_BUS). " ) ;
}
} else {
const bool is_main_flash = ( config - > host_id = = SPI1_HOST & & config - > cs_id = = 0 ) ;
if ( config - > cs_id > = SOC_SPI_PERIPH_CS_NUM ( config - > host_id ) | | config - > cs_id < 0 | | is_main_flash ) {
ESP_LOGE ( TAG , " Not valid CS. " ) ;
ret = ESP_ERR_INVALID_ARG ;
} else {
dev_id = config - > cs_id ;
assert ( dev_handle = = NULL ) ;
}
}
* out_dev_handle = dev_handle ;
* out_dev_id = dev_id ;
return ret ;
}
2019-06-24 00:56:39 -04:00
esp_err_t spi_bus_add_flash_device ( esp_flash_t * * out_chip , const esp_flash_spi_device_config_t * config )
{
if ( out_chip = = NULL ) {
return ESP_ERR_INVALID_ARG ;
}
2020-12-16 01:21:06 -05:00
if ( ! GPIO_IS_VALID_OUTPUT_GPIO ( config - > cs_io_num ) ) {
return ESP_ERR_INVALID_ARG ;
}
2019-06-24 00:56:39 -04:00
esp_flash_t * chip = NULL ;
2020-05-07 02:46:41 -04:00
memspi_host_inst_t * host = NULL ;
2019-06-24 00:56:39 -04:00
esp_err_t ret = ESP_OK ;
uint32_t caps = MALLOC_CAP_DEFAULT ;
2021-03-05 03:20:33 -05:00
if ( config - > host_id = = SPI1_HOST ) caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT ;
2019-06-24 00:56:39 -04:00
chip = ( esp_flash_t * ) heap_caps_malloc ( sizeof ( esp_flash_t ) , caps ) ;
2020-04-07 11:04:41 -04:00
if ( ! chip ) {
2019-06-24 00:56:39 -04:00
ret = ESP_ERR_NO_MEM ;
goto fail ;
}
2020-05-07 02:46:41 -04:00
host = ( memspi_host_inst_t * ) heap_caps_malloc ( sizeof ( memspi_host_inst_t ) , caps ) ;
2019-06-24 00:56:39 -04:00
* chip = ( esp_flash_t ) {
. read_mode = config - > io_mode ,
2020-05-07 02:46:41 -04:00
. host = ( spi_flash_host_inst_t * ) host ,
2019-06-24 00:56:39 -04:00
} ;
2020-04-07 11:04:41 -04:00
if ( ! host ) {
ret = ESP_ERR_NO_MEM ;
goto fail ;
}
2022-04-13 05:23:57 -04:00
int dev_id ;
spi_bus_lock_dev_handle_t dev_handle ;
esp_err_t err = acquire_spi_device ( config , & dev_id , & dev_handle ) ;
2019-06-24 00:56:39 -04:00
if ( err ! = ESP_OK ) {
ret = err ;
goto fail ;
}
2022-04-13 05:23:57 -04:00
err = esp_flash_init_os_functions ( chip , config - > host_id , dev_handle ) ;
if ( err ! = ESP_OK ) {
ret = err ;
goto fail ;
2020-05-11 14:34:53 -04:00
}
2019-06-24 00:56:39 -04:00
2022-04-13 05:23:57 -04:00
//avoid conflicts with main flash
assert ( config - > host_id ! = SPI1_HOST | | dev_id ! = 0 ) ;
2019-06-24 00:56:39 -04:00
bool use_iomux = spicommon_bus_using_iomux ( config - > host_id ) ;
memspi_host_config_t host_cfg = {
. host_id = config - > host_id ,
2019-10-24 07:00:26 -04:00
. cs_num = dev_id ,
2019-06-24 00:56:39 -04:00
. iomux = use_iomux ,
. input_delay_ns = config - > input_delay_ns ,
. speed = config - > speed ,
} ;
2020-05-07 02:46:41 -04:00
err = memspi_host_init_pointers ( host , & host_cfg ) ;
2019-06-24 00:56:39 -04:00
if ( err ! = ESP_OK ) {
ret = err ;
goto fail ;
}
2020-04-07 11:53:43 -04:00
// The cs_id inside `config` is deprecated, use the `dev_id` provided by the bus lock instead.
cs_initialize ( chip , config , use_iomux , dev_id ) ;
2019-06-24 00:56:39 -04:00
* out_chip = chip ;
return ret ;
fail :
2020-04-07 11:04:41 -04:00
// The memory allocated are free'd in the `spi_bus_remove_flash_device`.
2019-06-24 00:56:39 -04:00
spi_bus_remove_flash_device ( chip ) ;
return ret ;
}
esp_err_t spi_bus_remove_flash_device ( esp_flash_t * chip )
{
if ( chip = = NULL ) {
return ESP_ERR_INVALID_ARG ;
}
2022-04-13 05:23:57 -04:00
spi_bus_lock_dev_handle_t dev_handle = NULL ;
esp_flash_deinit_os_functions ( chip , & dev_handle ) ;
if ( dev_handle ) {
spi_bus_lock_unregister_dev ( dev_handle ) ;
}
2020-05-07 02:46:41 -04:00
free ( chip - > host ) ;
2019-06-24 00:56:39 -04:00
free ( chip ) ;
return ESP_OK ;
}
2019-09-10 02:34:06 -04:00
/* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */
extern const esp_flash_os_functions_t esp_flash_noos_functions ;
2020-05-07 02:46:41 -04:00
static DRAM_ATTR memspi_host_inst_t esp_flash_default_host ;
2019-06-24 00:56:39 -04:00
static DRAM_ATTR esp_flash_t default_chip = {
. read_mode = DEFAULT_FLASH_MODE ,
2020-05-07 02:46:41 -04:00
. host = ( spi_flash_host_inst_t * ) & esp_flash_default_host ,
2019-06-24 00:56:39 -04:00
. os_func = & esp_flash_noos_functions ,
} ;
2020-12-17 23:57:55 -05:00
extern esp_err_t esp_flash_suspend_cmd_init ( esp_flash_t * chip ) ;
2019-07-16 05:33:30 -04:00
esp_err_t esp_flash_init_default_chip ( void )
2019-06-24 00:56:39 -04:00
{
2020-12-15 22:50:13 -05:00
const esp_rom_spiflash_chip_t * legacy_chip = & g_rom_flashchip ;
2019-06-24 00:56:39 -04:00
memspi_host_config_t cfg = ESP_FLASH_HOST_CONFIG_DEFAULT ( ) ;
2020-01-16 01:41:41 -05:00
2022-01-17 21:32:56 -05:00
# if !CONFIG_IDF_TARGET_ESP32 && !CONFIG_IDF_TARGET_ESP32C2
2020-01-16 01:41:41 -05:00
// For esp32s2 spi IOs are configured as from IO MUX by default
2020-07-13 09:57:24 -04:00
cfg . iomux = esp_rom_efuse_get_flash_gpio_info ( ) = = 0 ? true : false ;
2020-01-16 01:41:41 -05:00
# endif
2021-09-01 03:58:15 -04:00
# if CONFIG_ESPTOOLPY_OCT_FLASH
cfg . octal_mode_en = 1 ;
cfg . default_io_mode = DEFAULT_FLASH_MODE ;
# endif
// For chips need time tuning, get value directely from system here.
# if SOC_SPI_MEM_SUPPORT_TIME_TUNING
2021-10-19 00:25:08 -04:00
if ( spi_timing_is_tuned ( ) ) {
2021-09-01 03:58:15 -04:00
cfg . using_timing_tuning = 1 ;
spi_timing_get_flash_timing_param ( & cfg . timing_reg ) ;
}
# endif // SOC_SPI_MEM_SUPPORT_TIME_TUNING
2019-06-24 00:56:39 -04:00
//the host is already initialized, only do init for the data and load it to the host
2020-05-07 02:46:41 -04:00
esp_err_t err = memspi_host_init_pointers ( & esp_flash_default_host , & cfg ) ;
if ( err ! = ESP_OK ) {
return err ;
}
2019-06-24 00:56:39 -04:00
// ROM TODO: account for non-standard default pins in efuse
// ROM TODO: to account for chips which are slow to power on, maybe keep probing in a loop here
2021-09-01 03:58:15 -04:00
err = esp_flash_init_main ( & default_chip ) ;
2019-06-24 00:56:39 -04:00
if ( err ! = ESP_OK ) {
return err ;
}
2020-12-15 22:50:13 -05:00
if ( default_chip . size < legacy_chip - > chip_size ) {
ESP_EARLY_LOGE ( TAG , " Detected size(%dk) smaller than the size in the binary image header(%dk). Probe failed. " , default_chip . size / 1024 , legacy_chip - > chip_size / 1024 ) ;
2019-06-24 00:56:39 -04:00
return ESP_ERR_FLASH_SIZE_NOT_MATCH ;
2020-12-16 18:28:03 -05:00
}
if ( default_chip . size > legacy_chip - > chip_size ) {
2020-12-15 22:50:13 -05:00
ESP_EARLY_LOGW ( TAG , " Detected size(%dk) larger than the size in the binary image header(%dk). Using the size in the binary image header. " , default_chip . size / 1024 , legacy_chip - > chip_size / 1024 ) ;
2019-06-24 00:56:39 -04:00
}
2020-12-16 18:28:03 -05:00
default_chip . size = legacy_chip - > chip_size ;
2019-06-24 00:56:39 -04:00
esp_flash_default_chip = & default_chip ;
2020-12-17 23:57:55 -05:00
# ifdef CONFIG_SPI_FLASH_AUTO_SUSPEND
err = esp_flash_suspend_cmd_init ( & default_chip ) ;
if ( err ! = ESP_OK ) {
return err ;
}
# endif
2019-06-24 00:56:39 -04:00
return ESP_OK ;
}
2019-07-16 05:33:30 -04:00
esp_err_t esp_flash_app_init ( void )
2019-06-24 00:56:39 -04:00
{
2020-04-09 01:30:12 -04:00
esp_err_t err = ESP_OK ;
# if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
err = esp_flash_init_main_bus_lock ( ) ;
if ( err ! = ESP_OK ) return err ;
# endif
err = esp_flash_app_enable_os_functions ( & default_chip ) ;
return err ;
2019-06-24 00:56:39 -04:00
}
2019-09-10 02:34:06 -04:00
2020-04-09 01:30:12 -04:00
# endif //!CONFIG_SPI_FLASH_USE_LEGACY_IMPL