2019-06-24 00:56:39 -04:00
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
# include "sdkconfig.h"
# include "esp_flash.h"
# include "memspi_host_driver.h"
# include "esp_flash_spi_init.h"
# include "driver/gpio.h"
# include "esp32/rom/spi_flash.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"
2019-09-11 14:41:00 -04:00
# include "esp_flash_internal.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
# 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
# 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
# else
# define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD
# endif
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){ \
. host_id = SPI_HOST , \
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = false , \
. input_delay_ns = 0 , \
}
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){ \
. host_id = SPI_HOST , \
. speed = DEFAULT_FLASH_SPEED , \
. cs_num = 0 , \
. iomux = true , \
. input_delay_ns = 0 , \
}
# endif
2019-09-10 02:34:06 -04:00
esp_flash_t * esp_flash_default_chip = NULL ;
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 ] ;
//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 ) ;
if ( use_iomux ) {
2020-04-07 12:42:46 -04:00
// This requires `gpio_iomux_in` and `gpio_iomux_out` to be in the IRAM.
// `linker.lf` is used fulfill this requirement.
2019-11-27 20:20:00 -05:00
gpio_iomux_in ( cs_io_num , spics_in ) ;
gpio_iomux_out ( cs_io_num , spics_func , false ) ;
2019-06-24 00:56:39 -04:00
} else {
PIN_INPUT_ENABLE ( iomux_reg ) ;
if ( cs_io_num < 32 ) {
GPIO . enable_w1ts = ( 0x1 < < cs_io_num ) ;
} else {
GPIO . enable1_w1ts . data = ( 0x1 < < ( cs_io_num - 32 ) ) ;
}
GPIO . pin [ cs_io_num ] . pad_driver = 0 ;
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
}
PIN_FUNC_SELECT ( iomux_reg , PIN_FUNC_GPIO ) ;
}
chip - > os_func - > end ( chip - > os_func_data ) ;
}
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 ;
}
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 ;
if ( config - > host_id = = SPI_HOST ) caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT ;
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 ;
}
2020-05-11 14:34:53 -04:00
int dev_id = - 1 ;
2019-10-24 07:00:26 -04:00
esp_err_t err = esp_flash_init_os_functions ( chip , config - > host_id , & dev_id ) ;
2020-04-09 01:30:12 -04:00
if ( err = = ESP_ERR_NOT_SUPPORTED ) {
ESP_LOGE ( TAG , " Init os functions failed! No free CS. " ) ;
} else if ( err = = ESP_ERR_INVALID_ARG ) {
ESP_LOGE ( TAG , " Init os functions failed! Bus lock not initialized (check CONFIG_SPI_FLASH_SHARE_SPI1_BUS). " ) ;
}
2019-06-24 00:56:39 -04:00
if ( err ! = ESP_OK ) {
ret = err ;
goto fail ;
}
2020-05-11 14:34:53 -04:00
// When `CONFIG_SPI_FLASH_SHARE_SPI1_BUS` is not enabled on SPI1 bus, the
// `esp_flash_init_os_functions` will not be able to assign a new device ID. In this case, we
// use the `cs_id` in the config structure.
if ( dev_id = = - 1 & & config - > host_id = = SPI_HOST ) {
dev_id = config - > cs_id ;
}
2020-04-07 11:04:41 -04:00
assert ( dev_id < SOC_SPI_PERIPH_CS_NUM ( config - > host_id ) & & 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 ;
}
2019-10-24 07:00:26 -04:00
esp_flash_deinit_os_functions ( chip ) ;
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 ;
# ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
2019-06-24 00:56:39 -04:00
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 ,
} ;
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
{
memspi_host_config_t cfg = ESP_FLASH_HOST_CONFIG_DEFAULT ( ) ;
2020-01-16 01:41:41 -05:00
2020-04-07 11:53:43 -04:00
# ifdef CONFIG_IDF_TARGET_ESP32S2
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
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
2020-05-07 02:46:41 -04:00
err = esp_flash_init ( & default_chip ) ;
2019-06-24 00:56:39 -04:00
if ( err ! = ESP_OK ) {
return err ;
}
if ( default_chip . size < g_rom_flashchip . 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 , g_rom_flashchip . chip_size / 1024 ) ;
return ESP_ERR_FLASH_SIZE_NOT_MATCH ;
} else if ( default_chip . size > g_rom_flashchip . chip_size ) {
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 , g_rom_flashchip . chip_size / 1024 ) ;
default_chip . size = g_rom_flashchip . chip_size ;
}
default_chip . size = g_rom_flashchip . chip_size ;
esp_flash_default_chip = & default_chip ;
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