diff --git a/arch/xtensa/src/esp32s2/Kconfig b/arch/xtensa/src/esp32s2/Kconfig index 9fa5f828ee8..3119a762a3d 100644 --- a/arch/xtensa/src/esp32s2/Kconfig +++ b/arch/xtensa/src/esp32s2/Kconfig @@ -158,6 +158,10 @@ config ESP32S2_FLASH_8M bool default n +config ESP32S2_FLASH_16M + bool + default n + config ESP32S2_PSRAM_2M bool default n @@ -749,6 +753,35 @@ config ESP32S2_OTA_SCRATCH_DEVPATH endif +if ESP32S2_SPIFLASH + +comment "General storage MTD configuration" + +config ESP32S2_MTD + bool "MTD driver" + default y + select MTD + select MTD_BYTE_WRITE + select MTD_PARTITION + ---help--- + Initialize an MTD driver for the ESP32-S2 SPI Flash, which will + add an entry at /dev for application access from userspace. + +config ESP32S2_SPIFLASH_MTD_BLKSIZE + int "Storage MTD block size" + default 256 + depends on ESP32S2_MTD + +config ESP32S2_STORAGE_MTD_DEBUG + bool "Storage MTD Debug" + default n + depends on ESP32S2_MTD && DEBUG_FS_INFO + ---help--- + If this option is enabled, Storage MTD driver read and write functions + will output input parameters and return values (if applicable). + +endif # ESP32S2_SPIFLASH + endmenu # SPI Flash Configuration menu "SPI RAM Configuration" diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs index 12fea11818f..1a61d1a5a4a 100644 --- a/arch/xtensa/src/esp32s2/Make.defs +++ b/arch/xtensa/src/esp32s2/Make.defs @@ -68,6 +68,22 @@ ifeq ($(CONFIG_ESP32S2_SPI),y) CHIP_CSRCS += esp32s2_spi.c endif +#ifeq ($(CONFIG_ESP32S2_SPIFLASH),y) +#CHIP_CSRCS += esp32s2_spicache.c +#CHIP_CSRCS += esp32s2_spiflash.c +#endif + +ifeq ($(CONFIG_ESP32S2_SPIFLASH),y) +CHIP_CSRCS += esp32s2_spiflash.c +ifeq ($(CONFIG_ESP32S2_MTD),y) +CHIP_CSRCS += esp32s2_spiflash_mtd.c +endif +endif + +ifeq ($(CONFIG_ESP32S2_PARTITION_TABLE),y) +CHIP_CSRCS += esp32_partition.c +endif + ifeq ($(CONFIG_ESP32S2_TIMER),y) CHIP_CSRCS += esp32s2_tim.c ifeq ($(CONFIG_TIMER),y) diff --git a/arch/xtensa/src/esp32s2/esp32s2_spiflash.c b/arch/xtensa/src/esp32s2/esp32s2_spiflash.c new file mode 100644 index 00000000000..6c1e8e879f3 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_spiflash.c @@ -0,0 +1,876 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_spiflash.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ESP32S2_SPIFLASH + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "xtensa.h" +#include "xtensa_attr.h" +#include "hardware/esp32s2_spi_mem_reg.h" +#include "rom/esp32s2_spiflash.h" +#include "rom/esp32s2_opi_flash.h" +#include "esp32s2_irq.h" +#include "esp32s2_spiflash.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Used in spiflash_cachestate_s structure */ + +#define SPI_FLASH_WRITE_BUF_SIZE (32) +#define SPI_FLASH_READ_BUF_SIZE (64) + +#define SPI_FLASH_ERASED_STATE (0xff) + +#define SPI_FLASH_WRITE_WORDS (SPI_FLASH_WRITE_BUF_SIZE / 4) +#define SPI_FLASH_READ_WORDS (SPI_FLASH_READ_BUF_SIZE / 4) + +#define SPI_FLASH_MMU_PAGE_SIZE (0x10000) + +/* MMU base virtual mapped address */ + +#define SPI_FLASH_ENCRYPT_MIN_SIZE (16) + +/* Flash MMU table for CPU */ + +#define MMU_TABLE ((volatile uint32_t *)DR_REG_MMU_TABLE) + +#define MMU_ADDR2PAGE(_addr) ((_addr) / SPI_FLASH_MMU_PAGE_SIZE) +#define MMU_ADDR2OFF(_addr) ((_addr) % SPI_FLASH_MMU_PAGE_SIZE) +#define MMU_BYTES2PAGES(_n) (((_n) + SPI_FLASH_MMU_PAGE_SIZE - 1) / \ + SPI_FLASH_MMU_PAGE_SIZE) + +/* SPI port number */ + +# define SPI_PORT (1) + +/* SPI buffer size */ + +# define SPI_BUFFER_WORDS (16) +# define SPI_BUFFER_BYTES (SPI_BUFFER_WORDS * 4) + +/* SPI flash hardware definition */ + +# define FLASH_SECTOR_SIZE (4096) + +/* SPI flash command */ + +# define FLASH_CMD_WRDI ROM_FLASH_CMD_WRDI +# define FLASH_CMD_WREN ROM_FLASH_CMD_WREN +# define FLASH_CMD_RDSR ROM_FLASH_CMD_RDSR +# define FLASH_CMD_SE4B ROM_FLASH_CMD_SE4B +# define FLASH_CMD_SE ROM_FLASH_CMD_ERASE_SEC +# define FLASH_CMD_PP4B ROM_FLASH_CMD_PP4B +# define FLASH_CMD_PP 0x02 +# define FLASH_CMD_FSTRD4B ROM_FLASH_CMD_FSTRD4B +# define FLASH_CMD_FSTRD 0x0B + +/* SPI flash SR1 bits */ + +# define FLASH_SR1_BUSY ESP_ROM_SPIFLASH_BUSY_FLAG +# define FLASH_SR1_WREN ESP_ROM_SPIFLASH_WRENABLE_FLAG + +/* SPI flash operation */ + +#ifdef CONFIG_ESP32S2S_SPI_FLASH_USE_32BIT_ADDRESS +# define ADDR_BITS(addr) (((addr) & 0xff000000) ? 32 : 24) +# define READ_CMD(addr) (ADDR_BITS(addr) == 32 ? FLASH_CMD_FSTRD4B : \ + FLASH_CMD_FSTRD) +# define WRITE_CMD(addr) (ADDR_BITS(addr) == 32 ? FLASH_CMD_PP4B : \ + FLASH_CMD_PP) +# define ERASE_CMD(addr) (ADDR_BITS(addr) == 32 ? FLASH_CMD_SE4B : \ + FLASH_CMD_SE) +# define READ_DUMMY(addr) (8) +#else +# define ADDR_BITS(addr) 24 +# define READ_CMD(addr) FLASH_CMD_FSTRD +# define WRITE_CMD(addr) FLASH_CMD_PP +# define ERASE_CMD(addr) FLASH_CMD_SE +# define READ_DUMMY(addr) (8) +#endif + +# define SEND_CMD8_TO_FLASH(cmd) \ + esp32s2_spi_trans((cmd), 8, \ + 0, 0, \ + NULL, 0, \ + NULL, 0, \ + 0, \ + false) + +# define READ_SR1_FROM_FLASH(cmd, status) \ + esp32s2_spi_trans((cmd), 8, \ + 0, 0, \ + NULL, 0, \ + (status), 1, \ + 0, \ + false) + +# define ERASE_FLASH_SECTOR(addr) \ + esp32s2_spi_trans(ERASE_CMD(addr), 8, \ + (addr), ADDR_BITS(addr), \ + NULL, 0, \ + NULL, 0, \ + 0, \ + true) + +# define WRITE_DATA_TO_FLASH(addr, buffer, size) \ + esp32s2_spi_trans(WRITE_CMD(addr), 8, \ + (addr), ADDR_BITS(addr), \ + buffer, size, \ + NULL, 0, \ + 0, \ + true) + +# define READ_DATA_FROM_FLASH(addr, buffer, size) \ + esp32s2_spi_trans(READ_CMD(addr), 8, \ + (addr), ADDR_BITS(addr), \ + NULL, 0, \ + buffer, size, \ + READ_DUMMY(addr), \ + false) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* SPI Flash map request data */ + +struct spiflash_map_req +{ + /* Request mapping SPI Flash base address */ + + uint32_t src_addr; + + /* Request mapping SPI Flash size */ + + uint32_t size; + + /* Mapped memory pointer */ + + void *ptr; + + /* Mapped started MMU page index */ + + uint32_t start_page; + + /* Mapped MMU page count */ + + uint32_t page_cnt; +}; + +struct spiflash_cachestate_s +{ + irqstate_t flags; + uint32_t value; +}; + +/**************************************************************************** + * Private Functions Declaration + ****************************************************************************/ + +extern void cache_flush(int cpu); +extern uint32_t cache_suspend_icache(void); +extern uint32_t cache_suspend_dcache(void); + +static inline void IRAM_ATTR + spiflash_start(void); + +static inline void IRAM_ATTR + spiflash_end(void); + +/**************************************************************************** + * Public Functions Declaration + ****************************************************************************/ + +extern uint32_t cache_suspend_icache(void); +extern uint32_t cache_suspend_dcache(void); +extern void cache_resume_icache(uint32_t val); +extern void cache_resume_dcache(uint32_t val); +extern int cache_invalidate_addr(uint32_t addr, uint32_t size); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct spiflash_cachestate_s g_state; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_set_reg + * + * Description: + * Set the content of the SPI register at offset + * + * Input Parameters: + * priv - Private SPI device structure + * offset - Offset to the register of interest + * value - Value to be written + * + * Returned Value: + * None + * + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_set_regbits + * + * Description: + * Set the bits of the SPI register at offset + * + * Input Parameters: + * priv - Private SPI device structure + * offset - Offset to the register of interest + * bits - Bits to be set + * + * Returned Value: + * None + * + ****************************************************************************/ + +/**************************************************************************** + * Name: spiflash_start + * + * Description: + * Prepare for an SPIFLASH operartion. + * + ****************************************************************************/ + +static inline void IRAM_ATTR +spiflash_start(void) +{ + g_state.flags = enter_critical_section(); + + g_state.value = cache_suspend_icache() << 16; + g_state.value |= cache_suspend_dcache(); +} + +/**************************************************************************** + * Name: spiflash_end + * + * Description: + * Undo all the steps of start. + * + ****************************************************************************/ + +static inline void IRAM_ATTR + spiflash_end(void) +{ + cache_resume_icache(g_state.value >> 16); + cache_resume_dcache(g_state.value & 0xffff); + + leave_critical_section(g_state.flags); +} + +/**************************************************************************** + * Name: esp32s2_spi_trans + * + * Description: + * Transmit given command, address and data. + * + * Input Parameters: + * command - command value + * command_bits - command bits + * address - address value + * address_bits - address bits + * tx_buffer - write buffer + * tx_bytes - write buffer size + * rx_buffer - read buffer + * rx_bytes - read buffer size + * dummy_bits - dummy bits + * is_program - true if operation is program or erase + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static IRAM_ATTR void esp32s2_spi_trans(uint32_t command, + uint32_t command_bits, + uint32_t address, + uint32_t address_bits, + uint32_t *tx_buffer, + uint32_t tx_bytes, + uint32_t *rx_buffer, + uint32_t rx_bytes, + uint32_t dummy_bits, + bool is_program) +{ + uint32_t regval; + uint32_t cmd_reg; + uint32_t user1_reg = getreg32(SPI_MEM_USER1_REG(SPI_PORT)); + uint32_t user_reg = getreg32(SPI_MEM_USER_REG(SPI_PORT)); + + /* Initiliaze SPI user register */ + + user_reg &= ~(SPI_MEM_USR_ADDR_M | SPI_MEM_USR_DUMMY_M | + SPI_MEM_USR_MOSI_M | SPI_MEM_USR_MISO_M); + user_reg |= SPI_MEM_USR_COMMAND_M; + + /* Wait until SPI is idle */ + + do + { + cmd_reg = getreg32(SPI_MEM_CMD_REG(SPI_PORT)); + } + while ((cmd_reg & SPI_MEM_USR_M) != 0); + + /* Set command bits and value, and command is always needed */ + + regval = getreg32(SPI_MEM_USER2_REG(SPI_PORT)); + regval &= ~(SPI_MEM_USR_COMMAND_BITLEN_M | SPI_MEM_USR_COMMAND_VALUE_M); + regval |= ((command_bits - 1) << SPI_MEM_USR_COMMAND_BITLEN_S) | + (command << SPI_MEM_USR_COMMAND_VALUE_S); + putreg32(regval, SPI_MEM_USER2_REG(SPI_PORT)); + + /* Set address bits and value */ + + if (address_bits) + { + user1_reg &= ~SPI_MEM_USR_ADDR_BITLEN_M; + user1_reg |= (address_bits - 1) << SPI_MEM_USR_ADDR_BITLEN_S; + + putreg32(address, SPI_MEM_ADDR_REG(SPI_PORT)); + + user_reg |= SPI_MEM_USR_ADDR_M; + + regval = getreg32(SPI_MEM_CACHE_FCTRL_REG(SPI_PORT)); + if (address_bits > 24) + { + regval |= SPI_MEM_CACHE_USR_CMD_4BYTE_M; + } + else + { + regval &= ~SPI_MEM_CACHE_USR_CMD_4BYTE_M; + } + + putreg32(regval, SPI_MEM_CACHE_FCTRL_REG(SPI_PORT)); + } + + /* Set dummy */ + + if (dummy_bits) + { + user1_reg &= ~SPI_MEM_USR_DUMMY_CYCLELEN_M; + user1_reg |= (dummy_bits - 1) << SPI_MEM_USR_DUMMY_CYCLELEN_S; + + user_reg |= SPI_MEM_USR_DUMMY_M; + } + + /* Set TX data */ + + if (tx_bytes) + { + putreg32(tx_bytes * 8 - 1, SPI_MEM_MOSI_DLEN_REG(SPI_PORT)); + for (uint32_t i = 0; i < tx_bytes; i += 4) + { + putreg32(tx_buffer[i / 4], SPI_MEM_W0_REG(SPI_PORT) + i); + } + + user_reg |= SPI_MEM_USR_MOSI_M; + } + + /* Set RX data */ + + if (rx_bytes) + { + putreg32(rx_bytes * 8 - 1, SPI_MEM_MISO_DLEN_REG(SPI_PORT)); + + user_reg |= SPI_MEM_USR_MISO_M; + } + + putreg32(user_reg, SPI_MEM_USER_REG(SPI_PORT)); + putreg32(user1_reg, SPI_MEM_USER1_REG(SPI_PORT)); + + /* Set I/O mode */ + + regval = getreg32(SPI_MEM_CTRL_REG(SPI_PORT)); + regval &= ~(SPI_MEM_FREAD_QIO_M | SPI_MEM_FREAD_DIO_M | + SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_DUAL_M | + SPI_MEM_FCMD_OCT_M | SPI_MEM_FCMD_QUAD_M | + SPI_MEM_FCMD_DUAL_M | SPI_MEM_FADDR_OCT_M | + SPI_MEM_FDIN_OCT_M | SPI_MEM_FDOUT_OCT_M | + SPI_MEM_FDUMMY_OUT_M | SPI_MEM_RESANDRES_M | + SPI_MEM_WP_REG_M | SPI_MEM_WRSR_2B_M); + regval |= SPI_MEM_FASTRD_MODE_M; + putreg32(regval, SPI_MEM_CTRL_REG(SPI_PORT)); + + /* Set clock and delay */ + + /* FIXME */ + + regval = SPI_MEM_FLASH_PES_EN_M | + SPI_MEM_FLASH_PES_EN_M; + putreg32(regval, SPI_MEM_FLASH_SUS_CMD_REG(SPI_PORT)); + putreg32(0, SPI_MEM_CLOCK_GATE_REG(SPI_PORT)); + + /* Set if this is program or erase operation */ + + if (is_program) + { + cmd_reg |= SPI_MEM_FLASH_PE_M; + } + + /* Start transmision */ + + cmd_reg |= SPI_MEM_USR_M; + putreg32(cmd_reg, SPI_MEM_CMD_REG(SPI_PORT)); + + /* Wait until transmission is done */ + + while ((getreg32(SPI_MEM_CMD_REG(SPI_PORT)) & SPI_MEM_USR_M) != 0) + { + ; + } + + /* Get read data */ + + if (rx_bytes) + { + for (uint32_t i = 0; i < rx_bytes; i += 4) + { + rx_buffer[i / 4] = getreg32(SPI_MEM_W0_REG(SPI_PORT) + i); + } + } +} + +/**************************************************************************** + * Name: wait_flash_idle + * + * Description: + * Wait until flash enters idle state + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void wait_flash_idle(void) +{ + uint32_t status; + + do + { + READ_SR1_FROM_FLASH(FLASH_CMD_RDSR, &status); + if ((status & FLASH_SR1_BUSY) == 0) + { + break; + } + } + while (1); +} + +/**************************************************************************** + * Name: enable_flash_write + * + * Description: + * Enable Flash write mode + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void enable_flash_write(void) +{ + uint32_t status; + + do + { + SEND_CMD8_TO_FLASH(FLASH_CMD_WREN); + READ_SR1_FROM_FLASH(FLASH_CMD_RDSR, &status); + if ((status & FLASH_SR1_WREN) != 0) + { + break; + } + } + while (1); +} + +/**************************************************************************** + * Name: disable_flash_write + * + * Description: + * Disable Flash write mode + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void disable_flash_write(void) +{ + uint32_t status; + + do + { + SEND_CMD8_TO_FLASH(FLASH_CMD_WRDI); + READ_SR1_FROM_FLASH(FLASH_CMD_RDSR, &status); + if ((status & FLASH_SR1_WREN) == 0) + { + break; + } + } + while (1); +} + +/**************************************************************************** + * Name: esp32s2_mmap + * + * Description: + * Mapped SPI Flash address to ESP32S2's address bus, so that software + * can read SPI Flash data by reading data from memory access. + * + * If SPI Flash hardware encryption is enable, the read from mapped + * address is decrypted. + * + * Input Parameters: + * req - SPI Flash mapping requesting parameters + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static int IRAM_ATTR esp32s2_mmap(struct spiflash_map_req *req) +{ + int ret; + int i; + int start_page; + int flash_page; + int page_cnt; + + spiflash_start(); + + for (start_page = DROM0_PAGES_START; + start_page < DROM0_PAGES_END; + ++start_page) + { + if (MMU_TABLE[start_page] == INVALID_MMU_VAL) + { + break; + } + } + + flash_page = MMU_ADDR2PAGE(req->src_addr); + page_cnt = MMU_BYTES2PAGES(MMU_ADDR2OFF(req->src_addr) + req->size); + + if (start_page + page_cnt < DROM0_PAGES_END) + { + for (i = 0; i < page_cnt; i++) + { + MMU_TABLE[start_page + i] = flash_page + i; + } + + req->start_page = start_page; + req->page_cnt = page_cnt; + req->ptr = (void *)(VADDR0_START_ADDR + + start_page * SPI_FLASH_MMU_PAGE_SIZE + + MMU_ADDR2OFF(req->src_addr)); + ret = 0; + } + else + { + ret = -ENOBUFS; + } + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_ummap + * + * Description: + * Unmap SPI Flash address in ESP32S2's address bus, and free resource. + * + * Input Parameters: + * spi - ESP32S2 SPI Flash chip data + * req - SPI Flash mapping requesting parameters + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void esp32s2_ummap(const struct spiflash_map_req *req) +{ + int i; + + spiflash_start(); + + for (i = req->start_page; i < req->start_page + req->page_cnt; ++i) + { + MMU_TABLE[i] = INVALID_MMU_VAL; + } + + spiflash_end(); +} + +/**************************************************************************** + * Name: spi_flash_read_encrypted + * + * Description: + * Read decrypted data from SPI Flash at designated address when + * enable SPI Flash hardware encryption. + * + * Input Parameters: + * spi - ESP32S2 SPI Flash chip data + * addr - target address + * buffer - data buffer pointer + * size - data number + * + * Returned Value: + * OK if success or a negative value if fail. + * + ****************************************************************************/ + +int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size) +{ + int ret; + struct spiflash_map_req req = + { + .src_addr = addr, + .size = size + }; + + ret = esp32s2_mmap(&req); + if (ret) + { + return ret; + } + + memcpy(buffer, req.ptr, size); + + esp32s2_ummap(&req); + + return OK; +} + +/**************************************************************************** + * Name: spi_flash_erase_sector + * + * Description: + * Erase the Flash sector. + * + * Parameters: + * sector - Sector number, the count starts at sector 0, 4KB per sector. + * + * Returned Values: esp_err_t + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_erase_sector(uint32_t sector) +{ + int ret = OK; + uint32_t addr = sector * FLASH_SECTOR_SIZE; + + spiflash_start(); + + wait_flash_idle(); + enable_flash_write(); + + ERASE_FLASH_SECTOR(addr); + + wait_flash_idle(); + disable_flash_write(); + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: spi_flash_erase_range + * + * Description: + * Erase a range of flash sectors + * + * Parameters: + * start_address - Address where erase operation has to start. + * Must be 4kB-aligned + * size - Size of erased range, in bytes. Must be divisible by + * 4kB. + * + * Returned Values: + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_erase_range(uint32_t start_address, uint32_t size) +{ + int ret = OK; + uint32_t addr = start_address; + + spiflash_start(); + + for (uint32_t i = 0; i < size; i += FLASH_SECTOR_SIZE) + { + wait_flash_idle(); + enable_flash_write(); + + ERASE_FLASH_SECTOR(addr); + addr += FLASH_SECTOR_SIZE; + } + + wait_flash_idle(); + disable_flash_write(); + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: spi_flash_write + * + * Description: + * Write data to Flash. + * + * Parameters: + * dest_addr - Destination address in Flash. + * src - Pointer to the source buffer. + * size - Length of data, in bytes. + * + * Returned Values: + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_write(uint32_t dest_addr, + const void *buffer, + uint32_t size) +{ + int ret = OK; + const uint8_t *tx_buf = (const uint8_t *)buffer; + uint32_t tx_bytes = size; + uint32_t tx_addr = dest_addr; + + spiflash_start(); + + for (int i = 0; i < size; i += SPI_BUFFER_BYTES) + { + uint32_t spi_buffer[SPI_BUFFER_WORDS]; + uint32_t n = MIN(tx_bytes, SPI_BUFFER_BYTES); + + memcpy(spi_buffer, tx_buf, n); + + wait_flash_idle(); + enable_flash_write(); + + WRITE_DATA_TO_FLASH(tx_addr, spi_buffer, n); + + tx_bytes -= n; + tx_buf += n; + tx_addr += n; + } + + wait_flash_idle(); + disable_flash_write(); + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: spi_flash_read + * + * Description: + * Read data from Flash. + * + * Parameters: + * src_addr - source address of the data in Flash. + * dest - pointer to the destination buffer + * size - length of data + * + * Returned Values: + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_read(uint32_t src_addr, void *dest, uint32_t size) +{ + int ret = OK; + uint8_t *rx_buf = (uint8_t *)dest; + uint32_t rx_bytes = size; + uint32_t rx_addr = src_addr; + + spiflash_start(); + + for (uint32_t i = 0; i < size; i += SPI_BUFFER_BYTES) + { + uint32_t spi_buffer[SPI_BUFFER_WORDS]; + uint32_t n = MIN(rx_bytes, SPI_BUFFER_BYTES); + + READ_DATA_FROM_FLASH(rx_addr, spi_buffer, n); + + memcpy(rx_buf, spi_buffer, n); + rx_bytes -= n; + rx_buf += n; + rx_addr += n; + } + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_spiflash_init + * + * Description: + * Initialize ESP32-S2 SPI flash driver. + * + * Returned Value: + * OK if success or a negative value if fail. + * + ****************************************************************************/ + +int esp32s2_spiflash_init(void) +{ + return OK; +} + +#endif /* CONFIG_ESP32S2_SPIFLASH */ diff --git a/arch/xtensa/src/esp32s2/esp32s2_spiflash.h b/arch/xtensa/src/esp32s2/esp32s2_spiflash.h new file mode 100644 index 00000000000..4af4888d431 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_spiflash.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_spiflash.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIFLASH_H +#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIFLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_flash_read_encrypted + * + * Description: + * + * Read data from Encrypted Flash. + * + * If flash encryption is enabled, this function will transparently + * decrypt data as it is read. + * If flash encryption is not enabled, this function behaves the same as + * spi_flash_read(). + * + * See esp_flash_encryption_enabled() for a function to check if flash + * encryption is enabled. + * + * Parameters: + * addr - source address of the data in Flash. + * buffer - pointer to the destination buffer + * size - length of data + * + * Returned Values: esp_err_t + * + ****************************************************************************/ + +int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size); + +/**************************************************************************** + * Name: esp32s2_spiflash_init + * + * Description: + * Initialize ESP32-S3 SPI flash driver. + * + * Returned Value: + * OK if success or a negative value if fail. + * + ****************************************************************************/ + +int esp32s2_spiflash_init(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIFLASH_H */ diff --git a/arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.c b/arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.c new file mode 100644 index 00000000000..2d1067c0b44 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.c @@ -0,0 +1,792 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hardware/esp32s2_soc.h" + +#include "xtensa_attr.h" +#include "esp32s2_spiflash.h" + +#include "rom/esp32s2_spiflash.h" +#include "esp32s2_spiflash_mtd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MTD_BLK_SIZE CONFIG_ESP32S2_SPIFLASH_MTD_BLKSIZE +#define MTD_ERASE_SIZE 4096 +#define MTD_ERASED_STATE (0xff) + +#define MTD2PRIV(_dev) ((struct esp32s2_mtd_dev_s *)_dev) +#define MTD_SIZE(_priv) ((_priv)->chip->chip_size) +#define MTD_BLK2SIZE(_priv, _b) (MTD_BLK_SIZE * (_b)) +#define MTD_SIZE2BLK(_priv, _s) ((_s) / MTD_BLK_SIZE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* ESP32-S3 SPI Flash device private data */ + +struct esp32s2_mtd_dev_s +{ + struct mtd_dev_s mtd; + + /* SPI Flash data */ + + esp32s2_spiflash_chip_t *chip; +}; + +/**************************************************************************** + * Private Functions Prototypes + ****************************************************************************/ + +/* MTD driver methods */ + +static int esp32s2_erase(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks); +static ssize_t esp32s2_read(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, uint8_t *buffer); +static ssize_t esp32s2_read_decrypt(struct mtd_dev_s *dev, + off_t offset, + size_t nbytes, + uint8_t *buffer); +static ssize_t esp32s2_bread(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, uint8_t *buffer); +static ssize_t esp32s2_bread_decrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + uint8_t *buffer); +static ssize_t esp32s2_write(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, const uint8_t *buffer); +static ssize_t esp32s2_bwrite(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, const uint8_t *buffer); +static ssize_t esp32s2_bwrite_encrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + const uint8_t *buffer); +static int esp32s2_ioctl(struct mtd_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct esp32s2_mtd_dev_s g_esp32s2_spiflash = +{ + .mtd = + { + .erase = esp32s2_erase, + .bread = esp32s2_bread, + .bwrite = esp32s2_bwrite, + .read = esp32s2_read, + .ioctl = esp32s2_ioctl, +#ifdef CONFIG_MTD_BYTE_WRITE + .write = esp32s2_write, +#endif + .name = "esp32s2_spiflash" + }, + .chip = &g_rom_flashchip, +}; + +static const struct esp32s2_mtd_dev_s g_esp32s2_spiflash_encrypt = +{ + .mtd = + { + .erase = esp32s2_erase, + .bread = esp32s2_bread_decrypt, + .bwrite = esp32s2_bwrite_encrypt, + .read = esp32s2_read_decrypt, + .ioctl = esp32s2_ioctl, +#ifdef CONFIG_MTD_BYTE_WRITE + .write = NULL, +#endif + .name = "esp32s2_spiflash_encrypt" + }, + .chip = &g_rom_flashchip, +}; + +/* Ensure exclusive access to the driver */ + +static mutex_t g_lock = NXMUTEX_INITIALIZER; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_erase + * + * Description: + * Erase SPI Flash designated sectors. + * + * Input Parameters: + * dev - MTD device data + * startblock - start block number, it is not equal to SPI Flash's block + * nblocks - Number of blocks + * + * Returned Value: + * Erased blocks if success or a negative value if fail. + * + ****************************************************************************/ + +static int esp32s2_erase(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks) +{ + ssize_t ret; + uint32_t offset = startblock * MTD_ERASE_SIZE; + uint32_t nbytes = nblocks * MTD_ERASE_SIZE; + struct esp32s2_mtd_dev_s *priv = (struct esp32s2_mtd_dev_s *)dev; + + if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv))) + { + return -EINVAL; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d)\n", __func__, dev, startblock, nblocks); + + finfo("spi_flash_erase_range(0x%x, %d)\n", offset, nbytes); +#endif + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_erase_range(offset, nbytes); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nblocks; + } + else + { +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("Failed to erase the flash range!\n"); +#endif + ret = -1; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_read + * + * Description: + * Read data from SPI Flash at designated address. + * + * Input Parameters: + * dev - MTD device data + * offset - target address offset + * nbytes - data number + * buffer - data buffer pointer + * + * Returned Value: + * Read data bytes if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_read(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, uint8_t *buffer) +{ + ssize_t ret; + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer); + + finfo("spi_flash_read(0x%x, %p, %d)\n", offset, buffer, nbytes); +#endif + + /* Acquire the mutex. */ + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_read(offset, buffer, nbytes); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nbytes; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_bread + * + * Description: + * Read data from designated blocks. + * + * Input Parameters: + * dev - MTD device data + * startblock - start block number, it is not equal to SPI Flash's block + * nblocks - blocks number + * buffer - data buffer pointer + * + * Returned Value: + * Read block number if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_bread(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, uint8_t *buffer) +{ + ssize_t ret; + uint32_t addr = startblock * MTD_BLK_SIZE; + uint32_t size = nblocks * MTD_BLK_SIZE; + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks, + buffer); + + finfo("spi_flash_read(0x%x, %p, %d)\n", addr, buffer, size); +#endif + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_read(addr, buffer, size); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_read_decrypt + * + * Description: + * Read encrypted data and decrypt automatically from SPI Flash + * at designated address. + * + * Input Parameters: + * dev - MTD device data + * offset - target address offset + * nbytes - data number + * buffer - data buffer pointer + * + * Returned Value: + * Read data bytes if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_read_decrypt(struct mtd_dev_s *dev, + off_t offset, + size_t nbytes, + uint8_t *buffer) +{ + ssize_t ret; + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer); + + finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", offset, buffer, + nbytes); +#endif + + /* Acquire the mutex. */ + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_read_encrypted(offset, buffer, nbytes); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nbytes; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_bread_decrypt + * + * Description: + * Read encrypted data and decrypt automatically from designated blocks. + * + * Input Parameters: + * dev - MTD device data + * startblock - start block number, it is not equal to SPI Flash's block + * nblocks - blocks number + * buffer - data buffer pointer + * + * Returned Value: + * Read block number if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_bread_decrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + uint8_t *buffer) +{ + ssize_t ret; + uint32_t addr = startblock * MTD_BLK_SIZE; + uint32_t size = nblocks * MTD_BLK_SIZE; + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks, + buffer); + + finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", addr, buffer, size); +#endif + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_read_encrypted(addr, buffer, size); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + return ret; +} + +/**************************************************************************** + * Name: esp32s2_write + * + * Description: + * write data to SPI Flash at designated address. + * + * Input Parameters: + * dev - MTD device data + * offset - target address offset + * nbytes - data number + * buffer - data buffer pointer + * + * Returned Value: + * Writen bytes if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_write(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, const uint8_t *buffer) +{ + ssize_t ret; + struct esp32s2_mtd_dev_s *priv = (struct esp32s2_mtd_dev_s *)dev; + + ASSERT(buffer); + + if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv))) + { + return -EINVAL; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer); + + finfo("spi_flash_write(0x%x, %p, %d)\n", offset, buffer, nbytes); +#endif + + /* Acquire the mutex. */ + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_write(offset, buffer, nbytes); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nbytes; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + return ret; +} + +/**************************************************************************** + * Name: esp32s2_bwrite_encrypt + * + * Description: + * Write data to designated blocks by SPI Flash hardware encryption. + * + * Input Parameters: + * dev - MTD device data + * startblock - start MTD block number, + * it is not equal to SPI Flash's block + * nblocks - blocks number + * buffer - data buffer pointer + * + * Returned Value: + * Writen block number if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_bwrite_encrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + const uint8_t *buffer) +{ + ssize_t ret; + uint32_t addr = startblock * MTD_BLK_SIZE; + uint32_t size = nblocks * MTD_BLK_SIZE; + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, + nblocks, buffer); + + finfo("spi_flash_write_encrypted(0x%x, %p, %d)\n", addr, buffer, size); +#endif + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_write_encrypted(addr, buffer, size); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + return ret; +} + +/**************************************************************************** + * Name: esp32s2_bwrite + * + * Description: + * Write data to designated blocks. + * + * Input Parameters: + * dev - MTD device data + * startblock - start MTD block number, + * it is not equal to SPI Flash's block + * nblocks - blocks number + * buffer - data buffer pointer + * + * Returned Value: + * Writen block number if success or a negative value if fail. + * + ****************************************************************************/ + +static ssize_t esp32s2_bwrite(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, const uint8_t *buffer) +{ + ssize_t ret; + uint32_t addr = startblock * MTD_BLK_SIZE; + uint32_t size = nblocks * MTD_BLK_SIZE; + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, + nblocks, buffer); + + finfo("spi_flash_write(0x%x, %p, %d)\n", addr, buffer, size); +#endif + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_write(addr, buffer, size); + nxmutex_unlock(&g_lock); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESP32S2_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_ioctl + * + * Description: + * Set/Get option to/from ESP32-S3 SPI Flash MTD device data. + * + * Input Parameters: + * dev - ESP32-S3 MTD device data + * cmd - operation command + * arg - operation argument + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static int esp32s2_ioctl(struct mtd_dev_s *dev, int cmd, + unsigned long arg) +{ + int ret = OK; + finfo("cmd: %d\n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + struct esp32s2_mtd_dev_s *priv = (struct esp32s2_mtd_dev_s *)dev; + struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg; + if (geo) + { + memset(geo, 0, sizeof(*geo)); + + geo->blocksize = MTD_BLK_SIZE; + geo->erasesize = MTD_ERASE_SIZE; + geo->neraseblocks = MTD_SIZE(priv) / MTD_ERASE_SIZE; + ret = OK; + + finfo("blocksize: %" PRId32 " erasesize: %" PRId32 \ + " neraseblocks: %" PRId32 "\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case BIOC_PARTINFO: + { + struct esp32s2_mtd_dev_s *priv = (struct esp32s2_mtd_dev_s *)dev; + struct partition_info_s *info = (struct partition_info_s *)arg; + if (info != NULL) + { + info->numsectors = MTD_SIZE(priv) / MTD_BLK_SIZE; + info->sectorsize = MTD_BLK_SIZE; + info->startsector = 0; + info->parent[0] = '\0'; + } + } + break; + + case MTDIOC_ERASESTATE: + { + uint8_t *result = (uint8_t *)arg; + *result = MTD_ERASED_STATE; + + ret = OK; + } + break; + + default: + ret = -ENOTTY; + break; + } + + finfo("return %d\n", ret); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_spiflash_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from the ESP32-S3 SPI Flash. + * + * Input Parameters: + * mtd_offset - MTD Partition offset from the base address in SPI Flash. + * mtd_size - Size for the MTD partition. + * encrypted - Flag indicating whether the newly allocated partition will + * have its content encrypted. + * + * Returned Value: + * ESP32-S3 SPI Flash MTD data pointer if success or NULL if fail. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s2_spiflash_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size, + bool encrypted) +{ + const struct esp32s2_mtd_dev_s *priv; + const esp32s2_spiflash_chip_t *chip; + struct mtd_dev_s *mtd_part; + uint32_t blocks; + uint32_t startblock; + uint32_t size; + + if (encrypted) + { + priv = &g_esp32s2_spiflash_encrypt; + } + else + { + priv = &g_esp32s2_spiflash; + } + + chip = priv->chip; + + finfo("ESP32-S2 SPI Flash information:\n"); + finfo("\tID = 0x%" PRIx32 "\n", chip->device_id); + finfo("\tStatus mask = 0x%" PRIx32 "\n", chip->status_mask); + finfo("\tChip size = %" PRId32 " KB\n", chip->chip_size / 1024); + finfo("\tPage size = %" PRId32 " B\n", chip->page_size); + finfo("\tSector size = %" PRId32 " KB\n", chip->sector_size / 1024); + finfo("\tBlock size = %" PRId32 " KB\n", chip->block_size / 1024); + + ASSERT((mtd_offset + mtd_size) <= chip->chip_size); + ASSERT((mtd_offset % chip->sector_size) == 0); + ASSERT((mtd_size % chip->sector_size) == 0); + + if (mtd_size == 0) + { + size = chip->chip_size - mtd_offset; + } + else + { + size = mtd_size; + } + + finfo("\tMTD offset = 0x%" PRIx32 "\n", mtd_offset); + finfo("\tMTD size = 0x%" PRIx32 "\n", size); + + startblock = MTD_SIZE2BLK(priv, mtd_offset); + blocks = MTD_SIZE2BLK(priv, size); + + mtd_part = mtd_partition((struct mtd_dev_s *)&priv->mtd, startblock, + blocks); + if (!mtd_part) + { + ferr("ERROR: Failed to create MTD partition\n"); + return NULL; + } + + return mtd_part; +} + +/**************************************************************************** + * Name: esp32s2_spiflash_mtd + * + * Description: + * Get SPI Flash MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * ESP32-S3 SPI Flash MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s2_spiflash_mtd(void) +{ + struct esp32s2_mtd_dev_s *priv = + (struct esp32s2_mtd_dev_s *)&g_esp32s2_spiflash; + + return &priv->mtd; +} + +/**************************************************************************** + * Name: esp32s2_spiflash_encrypt_mtd + * + * Description: + * Get SPI Flash encryption MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * SPI Flash encryption MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s2_spiflash_encrypt_mtd(void) +{ + struct esp32s2_mtd_dev_s *priv = + (struct esp32s2_mtd_dev_s *)&g_esp32s2_spiflash_encrypt; + + return &priv->mtd; +} diff --git a/arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.h b/arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.h new file mode 100644 index 00000000000..ad5ffa087c2 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_spiflash_mtd.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIFLASH_MTD_H +#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIFLASH_MTD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_spiflash_mtd + * + * Description: + * Get SPI Flash MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * ESP32-S3 SPI Flash MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s2_spiflash_mtd(void); + +/**************************************************************************** + * Name: esp32s2_spiflash_encrypt_mtd + * + * Description: + * Get SPI Flash encryption MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * SPI Flash encryption MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s2_spiflash_encrypt_mtd(void); + +/**************************************************************************** + * Name: esp32s2_spiflash_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from the ESP32-S3 SPI Flash. + * + * Input Parameters: + * mtd_offset - MTD Partition offset from the base address in SPI Flash. + * mtd_size - Size for the MTD partition. + * encrypted - Flag indicating whether the newly allocated partition will + * have its content encrypted. + * + * Returned Value: + * SPI Flash MTD data pointer if success or NULL if fail. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s2_spiflash_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size, + bool encrypted); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIFLASH_MTD_H */ diff --git a/arch/xtensa/src/esp32s2/hardware/esp32s2_spi_mem_reg.h b/arch/xtensa/src/esp32s2/hardware/esp32s2_spi_mem_reg.h index ebf0f7bbebc..3d2903cbe11 100644 --- a/arch/xtensa/src/esp32s2/hardware/esp32s2_spi_mem_reg.h +++ b/arch/xtensa/src/esp32s2/hardware/esp32s2_spi_mem_reg.h @@ -34,6 +34,8 @@ extern "C" #define REG_SPI_MEM_BASE(i) (DR_REG_SPI0_BASE - (i) * 0x1000) +#define SPI_MEM_CMD_REG(i) (REG_SPI_MEM_BASE(i) + 0x0) + /* SPI_MEM_FLASH_READ : R/W/SC ;bitpos:[31] ;default: 1'b0 ; */ /* Description: Read flash enable. Read flash operation will be triggered diff --git a/arch/xtensa/src/esp32s2/hardware/esp32s2_system.h b/arch/xtensa/src/esp32s2/hardware/esp32s2_system.h index 60351db7ad6..cfad41ab6ea 100644 --- a/arch/xtensa/src/esp32s2/hardware/esp32s2_system.h +++ b/arch/xtensa/src/esp32s2/hardware/esp32s2_system.h @@ -115,6 +115,13 @@ #define SYSTEM_CLK_EN_DEDICATED_GPIO_V 0x00000001 #define SYSTEM_CLK_EN_DEDICATED_GPIO_S 7 +/* SYSTEM_CLK_EN_ASSIST_DEBUG : R/W ;bitpos:[6] ;default: 0 */ + +#define SYSTEM_CLK_EN_ASSIST_DEBUG (BIT(6)) +#define SYSTEM_CLK_EN_ASSIST_DEBUG_M (BIT(6)) +#define SYSTEM_CLK_EN_ASSIST_DEBUG_V 0x1 +#define SYSTEM_CLK_EN_ASSIST_DEBUG_S 6 + /* SYSTEM_CPU_PERI_RST_EN_REG register * CPU peripheral reset register */ @@ -130,6 +137,13 @@ #define SYSTEM_RST_EN_DEDICATED_GPIO_V 0x00000001 #define SYSTEM_RST_EN_DEDICATED_GPIO_S 7 +/* SYSTEM_RST_EN_ASSIST_DEBUG : R/W ;bitpos:[6] ;default: 1 ; */ + +#define SYSTEM_RST_EN_ASSIST_DEBUG (BIT(6)) +#define SYSTEM_RST_EN_ASSIST_DEBUG_M (BIT(6)) +#define SYSTEM_RST_EN_ASSIST_DEBUG_V 0x1 +#define SYSTEM_RST_EN_ASSIST_DEBUG_S 6 + /* SYSTEM_CPU_PER_CONF_REG register * CPU peripheral clock configuration register */ @@ -1101,6 +1115,20 @@ #define SYSTEM_LPCLK_SEL_RTC_SLOW_V 0x00000001 #define SYSTEM_LPCLK_SEL_RTC_SLOW_S 24 +/* SYSTEM_BT_LPCK_DIV_A : R/W ;bitpos:[23:12] ;default: 1 */ + +#define SYSTEM_BT_LPCK_DIV_A 0x00000FFF +#define SYSTEM_BT_LPCK_DIV_A_M ((SYSTEM_BT_LPCK_DIV_A_V)<<(SYSTEM_BT_LPCK_DIV_A_S)) +#define SYSTEM_BT_LPCK_DIV_A_V 0xFFF +#define SYSTEM_BT_LPCK_DIV_A_S 12 + +/* SYSTEM_BT_LPCK_DIV_B : R/W ;bitpos:[11:0] ;default: 1 */ + +#define SYSTEM_BT_LPCK_DIV_B 0x00000FFF +#define SYSTEM_BT_LPCK_DIV_B_M ((SYSTEM_BT_LPCK_DIV_B_V)<<(SYSTEM_BT_LPCK_DIV_B_S)) +#define SYSTEM_BT_LPCK_DIV_B_V 0xFFF +#define SYSTEM_BT_LPCK_DIV_B_S 0 + /* SYSTEM_CPU_INTR_FROM_CPU_0_REG register * CPU interrupt controlling register 0 */ @@ -1200,6 +1228,7 @@ #define SYSTEM_RSA_MEM_PD_M (SYSTEM_RSA_MEM_PD_V << SYSTEM_RSA_MEM_PD_S) #define SYSTEM_RSA_MEM_PD_V 0x00000001 #define SYSTEM_RSA_MEM_PD_S 0 +#define SYSTEM_RSA_PD SYSTEM_RSA_MEM_PD /* SYSTEM_BUSTOEXTMEM_ENA_REG register * EDMA enable register diff --git a/arch/xtensa/src/esp32s2/rom/esp32s2_spiflash.h b/arch/xtensa/src/esp32s2/rom/esp32s2_spiflash.h index 87d862214c9..8dad19f18ec 100644 --- a/arch/xtensa/src/esp32s2/rom/esp32s2_spiflash.h +++ b/arch/xtensa/src/esp32s2/rom/esp32s2_spiflash.h @@ -143,17 +143,6 @@ typedef struct uint16_t data; } esp_rom_spiflash_common_cmd_t; -/** - * Global ROM spiflash data, as used by legacy SPI flash functions - */ - -struct spiflash_legacy_data_s -{ - esp32s2_spiflash_chip_t chip; - uint8_t dummy_len_plus[3]; - uint8_t sig_matrix; -}; - /** * Structure holding SPI flash access critical sections management functions. * @@ -484,7 +473,7 @@ esp_rom_spiflash_config_clk(uint8_t freqdiv, * * Please do not call this function in SDK. * - * Input Paramater: + * Input Parameter: * esp_rom_spiflash_common_cmd_t *cmd : A struct to show the action of a * command. * @@ -1011,7 +1000,10 @@ void spi_flash_enable_cache(uint32_t cpuid); * Public Data *****************************************************************************/ -extern const struct spiflash_legacy_data_s *rom_spiflash_legacy_data; +/* Global esp32s2_spiflash_chip_t structure used by ROM functions */ + +extern esp32s2_spiflash_chip_t g_rom_flashchip; +extern uint8_t g_rom_spiflash_dummy_len_plus[]; #ifdef __cplusplus } diff --git a/boards/xtensa/esp32s2/common/Kconfig b/boards/xtensa/esp32s2/common/Kconfig index ae760d6949a..a6ea5f07f5b 100644 --- a/boards/xtensa/esp32s2/common/Kconfig +++ b/boards/xtensa/esp32s2/common/Kconfig @@ -12,6 +12,47 @@ config ESP32S2_MERGE_BINS This is only useful when the path to binary files (e.g. bootloader) is provided via the ESPTOOL_BINDIR variable. +choice ESP32S2_SPIFLASH_FS + prompt "Mount SPI Flash MTD on bring-up" + default ESP32S2_SPIFLASH_SMARTFS + depends on ESP32S2_SPIFLASH + optional + ---help--- + Mount the SPI Flash MTD with the selected File System format on board + bring-up. + If not selected, the MTD will be registered as a device node on /dev. + + config ESP32S2_SPIFLASH_SMARTFS + bool "SmartFS" + select FS_SMARTFS + select MTD_SMART + depends on !ESP32S2_SECURE_FLASH_ENC_ENABLED + + comment "SmartFS not supported with Flash Encryption" + depends on ESP32S2_SECURE_FLASH_ENC_ENABLED + + config ESP32S2_SPIFLASH_NXFFS + bool "NXFFS" + select FS_NXFFS + depends on !ESP32S2_SECURE_FLASH_ENC_ENABLED + + comment "NXFFS not supported with Flash Encryption" + depends on ESP32S2_SECURE_FLASH_ENC_ENABLED + + config ESP32S2_SPIFLASH_SPIFFS + bool "SPIFFS" + select FS_SPIFFS + depends on !ESP32S2_SECURE_FLASH_ENC_ENABLED + + comment "SPIFFS not supported with Flash Encryption" + depends on ESP32S2_SECURE_FLASH_ENC_ENABLED + + config ESP32S2_SPIFLASH_LITTLEFS + bool "LittleFS" + select FS_LITTLEFS + +endchoice + config ESP32S2_LCD_OVERCLOCK bool "Run LCD at higher clock speed than allowed" default n diff --git a/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld b/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld index 51fba7b788b..3924ed7dc31 100644 --- a/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld +++ b/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld @@ -76,7 +76,7 @@ PROVIDE ( Cache_Lock_ICache_Items = 0x40018950 ); PROVIDE ( Cache_Mask_All = 0x40018458 ); PROVIDE ( cache_memory_baseaddrs = 0x3ffaf020 ); PROVIDE ( Cache_MMU_Init = 0x40018dd8 ); -PROVIDE ( Cache_Resume_DCache = 0x40018d3c ); +PROVIDE ( cache_resume_dcache = 0x40018d3c ); PROVIDE ( Cache_Resume_DCache_Autoload = 0x4001850c ); PROVIDE ( cache_resume_icache = 0x40018cdc ); PROVIDE ( Cache_Resume_ICache_Autoload = 0x400184c4 ); @@ -85,7 +85,7 @@ PROVIDE ( Cache_Set_Default_Mode = 0x4001810c ); PROVIDE ( cache_set_icache_mode = 0x4001803c ); PROVIDE ( Cache_Start_DCache_Preload = 0x400185c4 ); PROVIDE ( Cache_Start_ICache_Preload = 0x40018530 ); -PROVIDE ( Cache_Suspend_DCache = 0x40018d04 ); +PROVIDE ( cache_suspend_dcache = 0x40018d04 ); PROVIDE ( Cache_Suspend_DCache_Autoload = 0x400184e0 ); PROVIDE ( cache_suspend_icache = 0x40018ca4 ); PROVIDE ( Cache_Suspend_ICache_Autoload = 0x40018498 ); @@ -348,7 +348,7 @@ PROVIDE ( ets_write_char_uart = 0x4000f998 ); PROVIDE ( exc_cause_table = 0x3ffacbe8 ); PROVIDE ( FilePacketSendDeflatedReqMsgProc = 0x40011ed8 ); PROVIDE ( FilePacketSendReqMsgProc = 0x40011bd8 ); -PROVIDE ( flashchip = 0x3ffffd38 ); +PROVIDE ( g_rom_flashchip = 0x3ffffd38 ); PROVIDE ( FlashDwnLdDeflatedStartMsgProc = 0x40011e80 ); PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x40011cc0 ); PROVIDE ( FlashDwnLdStartMsgProc = 0x40011b74 ); diff --git a/boards/xtensa/esp32s2/common/src/Make.defs b/boards/xtensa/esp32s2/common/src/Make.defs index 3599a831fd8..f7335a4f9c4 100644 --- a/boards/xtensa/esp32s2/common/src/Make.defs +++ b/boards/xtensa/esp32s2/common/src/Make.defs @@ -24,6 +24,10 @@ ifeq ($(CONFIG_WATCHDOG),y) CSRCS += esp32s2_board_wdt.c endif +ifeq ($(CONFIG_ESP32S2_SPIFLASH),y) + CSRCS += esp32s2_board_spiflash.c +endif + ifeq ($(CONFIG_SENSORS_MAX6675),y) CSRCS += esp32s2_max6675.c endif diff --git a/boards/xtensa/esp32s2/common/src/esp32s2_board_spiflash.c b/boards/xtensa/esp32s2/common/src/esp32s2_board_spiflash.c new file mode 100644 index 00000000000..64131350fb1 --- /dev/null +++ b/boards/xtensa/esp32s2/common/src/esp32s2_board_spiflash.c @@ -0,0 +1,367 @@ +/**************************************************************************** + * boards/xtensa/esp32s2/common/src/esp32s2_board_spiflash.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "inttypes.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifdef CONFIG_BCH +#include +#endif + +#include "esp32s2_spiflash.h" +#include "esp32s2_spiflash_mtd.h" +#include "esp32s2-saola-1.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_ESP32S2_STORAGE_MTD_OFFSET +# define CONFIG_ESP32S2_STORAGE_MTD_OFFSET 0x10000 +#endif + +#ifndef CONFIG_ESP32S2_STORAGE_MTD_SIZE +# define CONFIG_ESP32S2_STORAGE_MTD_SIZE 0x100000 +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setup_smartfs + * + * Description: + * Provide a block driver wrapper around MTD partition and mount a + * SMART FS over it. + * + * Parameters: + * smartn - Number used to register the mtd partition: /dev/smartx, where + * x = smartn. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESP32S2_SPIFLASH_SMARTFS) +static int setup_smartfs(int smartn, struct mtd_dev_s *mtd, + const char *mnt_pt) +{ + int ret = OK; + char path[22]; + + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + finfo("smart_initialize failed, Trying to erase first...\n"); + ret = mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + if (ret < 0) + { + ferr("ERROR: ioctl(BULKERASE) failed: %d\n", ret); + return ret; + } + + finfo("Erase successful, initializing it again.\n"); + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + ferr("ERROR: smart_initialize failed: %d\n", ret); + return ret; + } + } + + if (mnt_pt != NULL) + { + snprintf(path, sizeof(path), "/dev/smart%d", smartn); + + ret = nx_mount(path, mnt_pt, "smartfs", 0, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} + +#endif + +/**************************************************************************** + * Name: setup_littlefs + * + * Description: + * Register a mtd driver and mount a Little FS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESP32S2_SPIFLASH_LITTLEFS) +static int setup_littlefs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, NULL); + if (ret < 0) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, "forceformat"); + if (ret < 0) + { + ferr("ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: setup_spiffs + * + * Description: + * Register a mtd driver and mount a SPIFFS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESP32S2_SPIFLASH_SPIFFS) +static int setup_spiffs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "spiffs", 0, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_nxffs + * + * Description: + * Register a mtd driver and mount a SPIFFS over it. + * + * Parameters: + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESP32S2_SPIFLASH_NXFFS) +static int setup_nxffs(struct mtd_dev_s *mtd, const char *mnt_pt) +{ + int ret = OK; + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + ferr("ERROR: NXFFS init failed: %d\n", ret); + return ret; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(NULL, mnt_pt, "nxffs", 0, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: init_storage_partition + * + * Description: + * Initialize partition that is dedicated to general use. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int init_storage_partition(void) +{ + int ret = OK; + struct mtd_dev_s *mtd; + + mtd = esp32s2_spiflash_alloc_mtdpart(CONFIG_ESP32S2_STORAGE_MTD_OFFSET, + CONFIG_ESP32S2_STORAGE_MTD_SIZE, + false); + if (!mtd) + { + ferr("ERROR: Failed to alloc MTD partition of SPI Flash\n"); + return ERROR; + } + +#if defined (CONFIG_ESP32S2_SPIFLASH_SMARTFS) + + ret = setup_smartfs(0, mtd, "/data"); + if (ret < 0) + { + ferr("ERROR: Failed to setup smartfs\n"); + return ret; + } + +#elif defined (CONFIG_ESP32S2_SPIFLASH_NXFFS) + + ret = setup_nxffs(mtd, "/data"); + if (ret < 0) + { + ferr("ERROR: Failed to setup nxffs\n"); + return ret; + } + +#elif defined (CONFIG_ESP32S2_SPIFLASH_LITTLEFS) + + const char *path = "/dev/esp32s2flash"; + ret = setup_littlefs(path, mtd, "/data", 0755); + if (ret < 0) + { + ferr("ERROR: Failed to setup littlefs\n"); + return ret; + } + +#elif defined (CONFIG_ESP32S2_SPIFLASH_SPIFFS) + + const char *path = "/dev/esp32s2flash"; + ret = setup_spiffs(path, mtd, "/data", 0755); + if (ret < 0) + { + ferr("ERROR: Failed to setup spiffs\n"); + return ret; + } + +#else + + ret = register_mtddriver("/dev/esp32s2flash", mtd, 0755, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +#endif + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPIFLASH and register the MTD device. + * + ****************************************************************************/ + +int board_spiflash_init(void) +{ + int ret = OK; + + ret = esp32s2_spiflash_init(); + if (ret < 0) + { + return ret; + } + + ret = init_storage_partition(); + if (ret < 0) + { + return ret; + } + + return ret; +} + diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h index 2598df49dd2..decf704ef79 100644 --- a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h @@ -81,6 +81,18 @@ int esp32s2_bringup(void); +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPIFLASH and register the MTD device. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32S2_SPIFLASH +int board_spiflash_init(void); +#endif + /**************************************************************************** * Name: esp32s2_gpio_init * diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c index f41d44ef385..eb46a0fe38a 100644 --- a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c @@ -145,6 +145,14 @@ int esp32s2_bringup(void) } #endif /* CONFIG_ESP32S2_LEDC */ +#ifdef CONFIG_ESP32S2_SPIFLASH + ret = board_spiflash_init(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n"); + } +#endif + #ifdef CONFIG_DEV_GPIO ret = esp32s2_gpio_init(); if (ret < 0)