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"
# 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
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 , \
}
esp_flash_t * esp_flash_default_chip = NULL ;
2019-09-05 01:11:36 -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 )
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 ;
int spics_out = spi_periph_signal [ config - > host_id ] . spics_out [ config - > 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-06-01 03:27:18 -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 ;
gpio_matrix_out ( cs_io_num , spics_out , false , false ) ;
if ( config - > cs_id = = 0 ) {
gpio_matrix_in ( cs_io_num , spics_in , false ) ;
}
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 ;
spi_flash_host_driver_t * host = NULL ;
memspi_host_data_t * host_data = NULL ;
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-06-01 03:25:17 -04:00
if ( ! chip ) {
2019-06-24 00:56:39 -04:00
ret = ESP_ERR_NO_MEM ;
goto fail ;
}
2020-06-01 03:25:17 -04:00
host = ( spi_flash_host_driver_t * ) heap_caps_malloc ( sizeof ( spi_flash_host_driver_t ) , caps ) ;
2019-06-24 00:56:39 -04:00
* chip = ( esp_flash_t ) {
. read_mode = config - > io_mode ,
. host = host ,
} ;
2020-06-01 03:25:17 -04:00
if ( ! host ) {
ret = ESP_ERR_NO_MEM ;
goto fail ;
}
host_data = ( memspi_host_data_t * ) heap_caps_malloc ( sizeof ( memspi_host_data_t ) , caps ) ;
host - > driver_data = host_data ;
if ( ! host_data ) {
ret = ESP_ERR_NO_MEM ;
goto fail ;
}
2019-06-24 00:56:39 -04:00
esp_err_t err = esp_flash_init_os_functions ( chip , config - > host_id ) ;
if ( err ! = ESP_OK ) {
ret = err ;
goto fail ;
}
bool use_iomux = spicommon_bus_using_iomux ( config - > host_id ) ;
memspi_host_config_t host_cfg = {
. host_id = config - > host_id ,
. cs_num = config - > cs_id ,
. iomux = use_iomux ,
. input_delay_ns = config - > input_delay_ns ,
. speed = config - > speed ,
} ;
err = memspi_host_init_pointers ( host , host_data , & host_cfg ) ;
if ( err ! = ESP_OK ) {
ret = err ;
goto fail ;
}
cs_initialize ( chip , config , use_iomux ) ;
* out_chip = chip ;
return ret ;
fail :
2020-06-01 03:25:17 -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 ;
}
if ( chip - > host ) {
free ( chip - > host - > driver_data ) ;
free ( chip - > host ) ;
}
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
static DRAM_ATTR memspi_host_data_t default_driver_data ;
2019-09-10 02:34:06 -04:00
static DRAM_ATTR spi_flash_host_driver_t esp_flash_default_host_drv = ESP_FLASH_DEFAULT_HOST_DRIVER ( ) ;
2019-06-24 00:56:39 -04:00
static DRAM_ATTR esp_flash_t default_chip = {
. read_mode = DEFAULT_FLASH_MODE ,
. host = & esp_flash_default_host_drv ,
. 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-06-01 03:27:18 -04:00
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
spi_flash_hal_init ( & default_driver_data , & cfg ) ;
default_chip . host - > driver_data = & default_driver_data ;
// 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
esp_err_t err = esp_flash_init ( & default_chip ) ;
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
{
2019-09-11 14:41:00 -04:00
return esp_flash_app_init_os_functions ( & default_chip ) ;
2019-06-24 00:56:39 -04:00
}
2019-09-10 02:34:06 -04:00
# endif