This is an automated email from the ASF dual-hosted git repository.

aguettouche pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new c06d3e1  xtensa/esp32: Add SPI Flash device driver
c06d3e1 is described below

commit c06d3e1b0a2bd459ea46f5b4946838831c841023
Author: Alan C. Assis <acas...@gmail.com>
AuthorDate: Fri Jul 31 11:16:48 2020 -0300

    xtensa/esp32: Add SPI Flash device driver
    
    ESP32 runs code in a SPI Flash, so users can also use it to store
    data directly or mount some parts into a filesystem.
    
    The SPI Flash usually use SPI0.
    
    This driver was implemented by Dong Heng dongh...@espressif.com
    and modified to fix coding style by Alan Carvalho de Assis.
---
 arch/xtensa/src/esp32/Kconfig                      |   31 +
 arch/xtensa/src/esp32/Make.defs                    |    4 +
 arch/xtensa/src/esp32/esp32_spiflash.c             | 1194 ++++++++++++++++++++
 arch/xtensa/src/esp32/esp32_spiflash.h             |   87 ++
 arch/xtensa/src/esp32/rom/esp32_spiflash.h         |  826 ++++++++++++++
 .../xtensa/esp32/esp32-core/scripts/esp32_flash.ld |    3 +
 .../xtensa/esp32/esp32-core/scripts/esp32_rom.ld   |    5 +
 7 files changed, 2150 insertions(+)

diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index de18d2f..f460bb4 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -82,6 +82,13 @@ config ESP32_SPI
        bool
        default n
 
+config ESP32_SPIFLASH
+       bool
+       default n
+       select MTD
+       select MTD_BYTE_WRITE
+       select MTD_PARTITION
+
 config ESP32_SPI2
        bool "SPI 2"
        default n
@@ -405,4 +412,28 @@ endif # ESP32_SPI3
 
 endmenu # ESP32_SPI
 
+menu "SPI Flash configuration"
+       depends on ESP32_SPIFLASH
+
+config ESP32_MTD_OFFSET
+       hex "MTD base address in SPI Flash"
+       default 0x180000
+       help
+               MTD base address in SPI Flash.
+
+config ESP32_MTD_SIZE
+       hex "MTD size in SPI Flash"
+       default 0x100000
+       help
+               MTD size in SPI Flash.
+
+config ESP32_SPIFLASH_DEBUG
+       bool "Debug SPI Flash"
+       default n
+       depends on DEBUG_FS_INFO
+       help
+               Enable this option, read and write of SPI Flash
+               will show input arguments and result.
+
+endmenu # ESP32_SPIFLASH
 endif # ARCH_CHIP_ESP32
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 86998d3..557956d 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -111,6 +111,10 @@ CHIP_CSRCS += esp32_spi.c
   endif
 endif
 
+ifeq ($(CONFIG_ESP32_SPIFLASH),y)
+CHIP_CSRCS += esp32_spiflash.c
+endif
+
 # Configuration-dependent ESP32 files
 
 ifeq ($(CONFIG_SMP),y)
diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c 
b/arch/xtensa/src/esp32/esp32_spiflash.c
new file mode 100644
index 0000000..c9402f8
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_spiflash.c
@@ -0,0 +1,1194 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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 <nuttx/config.h>
+
+#ifdef CONFIG_ESP32_SPIFLASH
+
+#include <stdint.h>
+#include <debug.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <nuttx/mtd/mtd.h>
+
+#include "xtensa.h"
+#include "hardware/esp32_spi.h"
+#include "rom/esp32_spiflash.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SPI_FLASH_WRITE_BUF_SIZE    (32)
+#define SPI_FLASH_READ_BUF_SIZE     (64)
+
+#define ESP32_MTD_OFFSET            CONFIG_ESP32_MTD_OFFSET
+#define ESP32_MTD_SIZE              CONFIG_ESP32_MTD_SIZE
+
+#define MTD2PRIV(_dev)              ((FAR struct esp32_spiflash_s *)_dev)
+#define MTD_SIZE(_priv)             ((_priv)->chip->chip_size)
+#define MTD_BLKSIZE(_priv)          ((_priv)->chip->page_size)
+#define MTD_ERASESIZE(_priv)        ((_priv)->chip->sector_size)
+#define MTD_BLK2SIZE(_priv, _b)     (MTD_BLKSIZE(_priv) * (_b))
+#define MTD_SIZE2BLK(_priv, _s)     ((_s) / MTD_BLKSIZE(_priv))
+
+#ifndef MIN
+#  define  MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* SPI Flash device hardware configuration */
+
+struct esp32_spiflash_config_s
+{
+  /* SPI register base address */
+
+  uint32_t reg_base;
+};
+
+/* SPI Flash device private data  */
+
+struct esp32_spiflash_s
+{
+  struct mtd_dev_s mtd;
+
+  /* Port configuration */
+
+  const struct esp32_spiflash_config_s *config;
+
+  /* SPI Flash data */
+
+  esp32_spiflash_chip_t *chip;
+
+  /* SPI Flash communication dummy number */
+
+  uint8_t *dummies;
+};
+
+/****************************************************************************
+ * Private Functions Prototypes
+ ****************************************************************************/
+
+static int esp32_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                       size_t nblocks);
+
+static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
+                          size_t nbytes, FAR uint8_t *buffer);
+
+static ssize_t esp32_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                           size_t nblocks, FAR uint8_t *buffer);
+
+static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
+                           size_t nbytes, FAR const uint8_t *buffer);
+
+static ssize_t esp32_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                            size_t nblocks, FAR const uint8_t *buffer);
+
+static int esp32_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                       unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct esp32_spiflash_config_s s_esp32_spiflash1_config =
+{
+  .reg_base = REG_SPI_BASE(1)
+};
+
+static struct esp32_spiflash_s s_esp32_spiflash1 =
+{
+  .mtd =
+          {
+            .erase  = esp32_erase,
+            .bread  = esp32_bread,
+            .bwrite = esp32_bwrite,
+            .read   = esp32_read,
+            .ioctl  = esp32_ioctl,
+#if defined(CONFIG_MTD_BYTE_WRITE)
+            .write  = esp32_write,
+#endif
+            .name   = "esp32_mainflash"
+          },
+  .config = &s_esp32_spiflash1_config,
+  .chip = &g_rom_flashchip,
+  .dummies = g_rom_spiflash_dummy_len_plus
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spi_set_reg
+ *
+ * Description:
+ *   Set the contents 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
+ *
+ ****************************************************************************/
+
+static inline void spi_set_reg(struct esp32_spiflash_s *priv,
+                               int offset, uint32_t value)
+{
+  putreg32(value, priv->config->reg_base + offset);
+}
+
+/****************************************************************************
+ * Name: spi_get_reg
+ *
+ * Description:
+ *   Get the contents of the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - Private SPI device structure
+ *   offset - Offset to the register of interest
+ *
+ * Returned Value:
+ *   The contents of the register
+ *
+ ****************************************************************************/
+
+static inline uint32_t spi_get_reg(struct esp32_spiflash_s *priv,
+                                   int offset)
+{
+  return getreg32(priv->config->reg_base + offset);
+}
+
+/****************************************************************************
+ * 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
+ *
+ ****************************************************************************/
+
+static inline void spi_set_regbits(struct esp32_spiflash_s *priv,
+                                   int offset, uint32_t bits)
+{
+  uint32_t tmp = getreg32(priv->config->reg_base + offset);
+
+  putreg32(tmp | bits, priv->config->reg_base + offset);
+}
+
+/****************************************************************************
+ * Name: spi_reset_regbits
+ *
+ * Description:
+ *   Clear 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 cleared
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
+                                     int offset, uint32_t bits)
+{
+  uint32_t tmp = getreg32(priv->config->reg_base + offset);
+
+  putreg32(tmp & (~bits), priv->config->reg_base + offset);
+}
+
+/****************************************************************************
+ * Name: spi_memcpy
+ *
+ * Description:
+ *   Copy data from one block of memory to another block of memory.
+ *   The function must be linked in IRAM not in flash, so add this function
+ *   instead of libc memcpy.
+ *
+ * Input Parameters:
+ *   d - destination address
+ *   s - source address
+ *   n - data bytes
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void spi_memcpy(void *d, const void *s, uint32_t n)
+{
+  uint8_t *dest = (uint8_t *)d;
+  const uint8_t *src = (const uint8_t *)s;
+
+  while (n--)
+    *dest++ = *src++;
+}
+
+/****************************************************************************
+ * Name: esp32_set_read_opt
+ *
+ * Description:
+ *   Set SPI Flash to be direct read mode. Due to different SPI I/O mode
+ *   including DIO, QIO and so on. Different command and communication
+ *   timing sequence are needed.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32_set_read_opt(FAR struct esp32_spiflash_s *priv)
+{
+  uint32_t regval;
+  uint32_t ctrl;
+  uint32_t mode;
+  uint32_t cmd;
+  uint32_t cycles = 0;
+  uint32_t addrbits = 0;
+  uint32_t dummy = 0;
+
+  ctrl = spi_get_reg(priv, SPI_CTRL_OFFSET);
+  mode = ctrl & (SPI_FREAD_QIO | SPI_FASTRD_MODE);
+  if (mode == (SPI_FREAD_QIO | SPI_FASTRD_MODE))
+    {
+      cycles = SPI1_R_QIO_DUMMY_CYCLELEN + priv->dummies[1];
+      dummy = 1;
+      addrbits = SPI1_R_QIO_ADDR_BITSLEN;
+      cmd = (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xeb;
+    }
+  else if (mode == SPI_FASTRD_MODE)
+    {
+      if (ctrl & SPI_FREAD_DIO)
+        {
+          if (priv->dummies[1] == 0)
+            {
+              addrbits = SPI1_R_DIO_ADDR_BITSLEN;
+              cmd = (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xbb;
+            }
+          else
+            {
+              cycles = priv->dummies[1] - 1;
+              dummy = 1;
+              addrbits = SPI1_R_DIO_ADDR_BITSLEN;
+              cmd = 0xbb;
+            }
+        }
+      else
+        {
+          if (ctrl & SPI_FREAD_QUAD)
+            {
+              cmd = (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x6b;
+            }
+          else if (ctrl & SPI_FREAD_DUAL)
+            {
+              cmd = (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x3b;
+            }
+          else
+            {
+              cmd = (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x0b;
+            }
+
+          cycles = SPI1_R_FAST_DUMMY_CYCLELEN + priv->dummies[1];
+          dummy = 1;
+          addrbits = SPI1_R_DIO_ADDR_BITSLEN;
+        }
+    }
+  else
+    {
+      if (priv->dummies[1] != 0)
+        {
+          cycles = priv->dummies[1] - 1;
+          dummy = 1;
+        }
+
+      addrbits = SPI1_R_SIO_ADDR_BITSLEN ;
+      cmd = (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x03;
+    }
+
+  regval = spi_get_reg(priv, SPI_USER_OFFSET);
+  regval &= ~SPI_USR_MOSI;
+  regval = SPI_USR_MISO | SPI_USR_ADDR;
+  if (dummy)
+    {
+      regval |= SPI_USR_DUMMY;
+    }
+  else
+    {
+      regval &= ~SPI_USR_DUMMY;
+    }
+
+  spi_set_regbits(priv, SPI_USER_OFFSET, regval);
+
+  regval = spi_get_reg(priv, SPI_USER1_OFFSET);
+  regval &= ~SPI_USR_DUMMY_CYCLELEN_M;
+  regval |= cycles << SPI_USR_DUMMY_CYCLELEN_S;
+  regval &= ~SPI_USR_ADDR_BITLEN_M;
+  regval |= addrbits << SPI_USR_ADDR_BITLEN_S;
+  spi_set_reg(priv, SPI_USER1_OFFSET, regval);
+
+  regval = spi_get_reg(priv, SPI_USER2_OFFSET);
+  regval &= ~SPI_USR_COMMAND_VALUE;
+  regval |= cmd;
+  spi_set_reg(priv, SPI_USER2_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: esp32_set_read_opt
+ *
+ * Description:
+ *   Set SPI Flash to be direct read mode. Due to different SPI I/O mode
+ *   including DIO, QIO and so on. Different command and communication
+ *   timing sequence are needed.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void esp32_set_write_opt(struct esp32_spiflash_s *priv)
+{
+  uint32_t addrbits;
+  uint32_t regval;
+
+  spi_reset_regbits(priv, SPI_USER_OFFSET, SPI_USR_DUMMY);
+
+  addrbits = ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN;
+  regval = spi_get_reg(priv, SPI_USER1_OFFSET);
+  regval &= ~SPI_USR_ADDR_BITLEN_M;
+  regval |= addrbits << SPI_USR_ADDR_BITLEN_S;
+  spi_set_reg(priv, SPI_USER1_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: esp32_read_status
+ *
+ * Description:
+ *   Read SPI Flash status regitser value.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   status - status buffer pointer
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_read_status(FAR struct esp32_spiflash_s *priv,
+                             uint32_t *status)
+{
+  esp32_spiflash_chip_t *chip = priv->chip;
+  uint32_t regval;
+  uint32_t flags;
+  bool direct = priv->dummies[1] == 0;
+
+  if (priv->dummies[1] == 0)
+    {
+      direct = true;
+    }
+  else
+    {
+      direct = false;
+    }
+
+  do
+    {
+      if (direct)
+        {
+          spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+          spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_RDSR);
+          while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+            {
+              ;
+            }
+
+          regval = spi_get_reg(priv, SPI_RD_STATUS_OFFSET);
+          regval &= chip->status_mask;
+          flags = regval & ESP_ROM_SPIFLASH_BUSY_FLAG;
+        }
+      else
+        {
+          if (esp_rom_spiflash_read_user_cmd(&regval, 0x05))
+            {
+              return -EIO;
+            }
+
+          flags = regval & ESP_ROM_SPIFLASH_BUSY_FLAG;
+        }
+    }
+  while (flags == ESP_ROM_SPIFLASH_BUSY_FLAG);
+
+  *status = regval;
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_wait_idle
+ *
+ * Description:
+ *   Wait for SPI Flash to be idle state.
+ *
+ * Input Parameters:
+ *   spi - ESP32 SPI Flash chip data
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_wait_idle(FAR struct esp32_spiflash_s *priv)
+{
+  uint32_t status;
+
+  while (spi_get_reg(priv, SPI_EXT2_OFFSET) & SPI_ST)
+    {
+      ;
+    }
+
+  while (getreg32(SPI_EXT2_REG(0)) & SPI_ST)
+    {
+      ;
+    }
+
+  if (esp32_read_status(priv, &status))
+    {
+      return -EIO;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_read_highstatus
+ *
+ * Description:
+ *   Read SPI Flash high status regitser value.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   status - status buffer pointer
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+int esp32_read_highstatus(FAR struct esp32_spiflash_s *priv,
+                          uint32_t *status)
+{
+  uint32_t regval;
+
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  if (esp_rom_spiflash_read_user_cmd(&regval, 0x35))
+    {
+      return -EIO;
+    }
+
+  *status = regval << 8;
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_write_status
+ *
+ * Description:
+ *   Write status value to SPI Flash status regitser.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   status - status data
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+int esp32_write_status(FAR struct esp32_spiflash_s *priv, uint32_t status)
+{
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  spi_set_reg(priv, SPI_RD_STATUS_OFFSET, status);
+  spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_WRSR);
+  while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+    {
+      ;
+    }
+
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_enable_write
+ *
+ * Description:
+ *   Drive SPI flash entering into write mode.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_enable_write(FAR struct esp32_spiflash_s *priv)
+{
+  uint32_t flags;
+  uint32_t regval;
+
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+  spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_WREN);
+  while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+    {
+      ;
+    }
+
+  do
+    {
+      if (esp32_read_status(priv, &regval))
+        {
+          return -EIO;
+        }
+
+      flags = regval & ESP_ROM_SPIFLASH_WRENABLE_FLAG;
+    }
+  while (flags != ESP_ROM_SPIFLASH_WRENABLE_FLAG);
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_erasesector
+ *
+ * Description:
+ *   Erase SPI Flash sector at designated address.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - erasing address
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_erasesector(FAR struct esp32_spiflash_s *priv,
+                             uint32_t addr, uint32_t size)
+{
+  int ret;
+  uint32_t offset;
+
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  for (offset = 0; offset < size; offset += MTD_ERASESIZE(priv))
+    {
+      ret = esp32_enable_write(priv);
+      if (ret)
+        {
+          return -EIO;
+        }
+
+      spi_set_reg(priv, SPI_ADDR_OFFSET, (addr + offset) & 0xffffff);
+      spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_SE);
+      while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+        {
+          ;
+        }
+
+      if (esp32_wait_idle(priv))
+        {
+          return -EIO;
+        }
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_writedata
+ *
+ * Description:
+ *   Write data to SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
+                           const uint8_t *buffer, uint32_t size)
+{
+  uint32_t regval;
+  uint32_t i;
+  uint32_t bytes;
+  uint32_t tmp;
+  uint32_t res;
+
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  while (size > 0)
+    {
+      if (esp32_enable_write(priv))
+        {
+          return -EIO;
+        }
+
+      bytes = MTD_BLKSIZE(priv) - addr % MTD_BLKSIZE(priv) ;
+      if (!bytes)
+        {
+          bytes = MIN(size, SPI_FLASH_WRITE_BUF_SIZE);
+        }
+      else
+        {
+          bytes = MIN(bytes, size);
+          bytes = MIN(bytes, SPI_FLASH_WRITE_BUF_SIZE);
+        }
+
+      regval = addr & 0xffffff;
+      regval |= bytes << ESP_ROM_SPIFLASH_BYTES_LEN;
+      spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+
+      for (i = 0; i < bytes; i += 4)
+        {
+          res = MIN(4, bytes - i);
+
+          spi_memcpy(&tmp, buffer, res);
+          spi_set_reg(priv, SPI_W0_OFFSET + i, tmp);
+          buffer += res;
+        }
+
+      spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+      spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_PP);
+      while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+        {
+          ;
+        }
+
+      if (esp32_wait_idle(priv))
+        {
+          return -EIO;
+        }
+
+      addr += bytes;
+      size -= bytes;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_readdata
+ *
+ * Description:
+ *   Read data from SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_readdata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
+                          uint8_t *buffer, uint32_t size)
+{
+  uint32_t regval;
+  uint32_t i;
+  uint32_t bytes;
+  uint32_t tmp;
+  uint32_t res;
+
+  if (esp32_wait_idle(priv))
+    {
+      return -EIO;
+    }
+
+  while (size > 0)
+    {
+      bytes = MIN(size, SPI_FLASH_READ_BUF_SIZE);
+      regval = ((bytes << 3) - 1) << SPI_USR_MISO_DBITLEN_S;
+      spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, regval);
+
+      regval = addr << 8;
+      spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+
+      spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+      spi_set_reg(priv, SPI_CMD_OFFSET, SPI_USR);
+      while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+        {
+          ;
+        }
+
+      for (i = 0; i < bytes; i += 4)
+        {
+          res = MIN(4, bytes - i);
+
+          tmp = spi_get_reg(priv, SPI_W0_OFFSET + i);
+          spi_memcpy(buffer, &tmp, res);
+          buffer += res;
+        }
+
+      addr += bytes;
+      size -= bytes;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_erase
+ *
+ * Description:
+ *   Erase SPI Flash designated sectors.
+ *
+ * Input Parameters:
+ *   dev        - ESP32 MTD device data
+ *   startblock - start block number, it is not equal to SPI Flash's block
+ *   nblocks    - blocks number
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                       size_t nblocks)
+{
+  int ret;
+  uint32_t flags;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+  uint32_t addr = startblock * MTD_ERASESIZE(priv);
+  uint32_t size = nblocks * MTD_ERASESIZE(priv);
+
+  if ((addr >= MTD_SIZE(priv)) || (addr + size > MTD_SIZE(priv)))
+    {
+      return -EINVAL;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_erase(%p, %d, %d)\n", dev, startblock, nblocks);
+#endif
+
+  flags = enter_critical_section();
+
+  esp32_set_write_opt(priv);
+  ret = esp32_erasesector(priv, addr, size);
+
+  leave_critical_section(flags);
+
+  if (!ret)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_erase()=%d\n", ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_read
+ *
+ * Description:
+ *   Read data from SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   dev    - ESP32 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 esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
+                          size_t nbytes, FAR uint8_t *buffer)
+{
+  int ret;
+  uint32_t flags;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_read(%p, 0x%x, %d, %p)\n", dev, offset, nbytes, buffer);
+#endif
+
+  flags = enter_critical_section();
+
+  esp32_set_read_opt(priv);
+  ret = esp32_readdata(priv, offset, buffer, nbytes);
+
+  leave_critical_section(flags);
+
+  if (!ret)
+    {
+      ret = nbytes;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_read()=%d\n", ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_bread
+ *
+ * Description:
+ *   Read data from designated blocks.
+ *
+ * Input Parameters:
+ *   dev        - ESP32 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 esp32_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                           size_t nblocks, FAR uint8_t *buffer)
+{
+  int ret;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+  uint32_t addr = MTD_BLK2SIZE(priv, startblock);
+  uint32_t size = MTD_BLK2SIZE(priv, nblocks);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bread(%p, 0x%x, %d, %p)\n",
+        dev, startblock, nblocks, buffer);
+#endif
+
+  ret = esp32_read(dev, addr, size, buffer);
+  if (ret == size)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bread()=%d\n", ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_write
+ *
+ * Description:
+ *   write data to SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   dev    - ESP32 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 esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
+                           size_t nbytes, FAR const uint8_t *buffer)
+{
+  int ret;
+  uint32_t flags;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+
+  ASSERT(buffer);
+
+  if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv)))
+    {
+      return -EINVAL;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_write(%p, 0x%x, %d, %p)\n", dev, offset, nbytes, buffer);
+#endif
+
+  flags = enter_critical_section();
+
+  esp32_set_write_opt(priv);
+
+  ret = esp32_writedata(priv, offset, buffer, nbytes);
+
+  leave_critical_section(flags);
+
+  if (!ret)
+    {
+      ret = nbytes;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_write()=%d\n", ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_bwrite
+ *
+ * Description:
+ *   Write data to designated blocks.
+ *
+ * Input Parameters:
+ *   dev        - ESP32 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 esp32_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                            size_t nblocks, FAR const uint8_t *buffer)
+{
+  ssize_t ret;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+  uint32_t addr = MTD_BLK2SIZE(priv, startblock);
+  uint32_t size = MTD_BLK2SIZE(priv, nblocks);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bwrite(%p, 0x%x, %d, %p)\n",
+        dev, startblock, nblocks, buffer);
+#endif
+
+  ret = esp32_write(dev, addr, size, buffer);
+  if (ret == size)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bwrite()=%d\n", ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_ioctl
+ *
+ * Description:
+ *   Set/Get option to/from ESP32 SPI Flash MTD device data.
+ *
+ * Input Parameters:
+ *   dev - ESP32 MTD device data
+ *   cmd - operation command
+ *   arg - operation argument
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                       unsigned long arg)
+{
+  int ret = -EINVAL;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+  FAR struct mtd_geometry_s *geo;
+
+  finfo("cmd: %d \n", cmd);
+
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        {
+          geo = (FAR struct mtd_geometry_s *)arg;
+          if (geo)
+            {
+              geo->blocksize    = MTD_BLKSIZE(priv);
+              geo->erasesize    = MTD_ERASESIZE(priv);
+              geo->neraseblocks = MTD_SIZE(priv) / MTD_ERASESIZE(priv);
+              ret               = OK;
+
+              finfo("blocksize: %d erasesize: %d neraseblocks: %d\n",
+                    geo->blocksize, geo->erasesize, geo->neraseblocks);
+            }
+        }
+        break;
+
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  finfo("return %d\n", ret);
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_spiflash_alloc_mtdpart
+ *
+ * Description:
+ *   Alloc ESP32 SPI Flash MTD
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32 SPI Flash MTD data pointer if success or NULL if fail
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_alloc_mtdpart(void)
+{
+  struct esp32_spiflash_s *priv = &s_esp32_spiflash1;
+  esp32_spiflash_chip_t *chip = priv->chip;
+  FAR struct mtd_dev_s *mtd_part;
+  uint32_t blocks;
+  uint32_t startblock;
+  uint32_t size;
+
+  ASSERT((ESP32_MTD_OFFSET + ESP32_MTD_SIZE) <= chip->chip_size);
+  ASSERT((ESP32_MTD_OFFSET % chip->sector_size) == 0);
+  ASSERT((ESP32_MTD_SIZE % chip->sector_size) == 0);
+
+  finfo("ESP32 SPI Flash information:\n");
+  finfo("\tID = 0x%x\n", chip->device_id);
+  finfo("\tStatus mask = %x\n", chip->status_mask);
+  finfo("\tChip size = %d KB\n", chip->chip_size / 1024);
+  finfo("\tPage size = %d B\n", chip->page_size);
+  finfo("\tSector size = %d KB\n", chip->sector_size / 1024);
+  finfo("\tBlock size = %d KB\n", chip->block_size / 1024);
+
+#if ESP32_MTD_SIZE == 0
+  size = chip->chip_size - ESP32_MTD_OFFSET;
+#else
+  size = ESP32_MTD_SIZE;
+#endif
+
+  finfo("\tMTD offset = 0x%x\n", ESP32_MTD_OFFSET);
+  finfo("\tMTD size = 0x%x\n", size);
+
+  startblock = MTD_SIZE2BLK(priv, ESP32_MTD_OFFSET);
+  blocks = MTD_SIZE2BLK(priv, size);
+
+  mtd_part = mtd_partition(&priv->mtd, startblock, blocks);
+  if (!mtd_part)
+    {
+      ferr("ERROR: create MTD partition");
+      return NULL;
+    }
+
+  return mtd_part;
+}
+
+/****************************************************************************
+ * Name: esp32_spiflash_get_mtd
+ *
+ * Description:
+ *   Get ESP32 SPI Flash raw MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32 SPI Flash raw MTD data pointer.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_get_mtd(void)
+{
+  struct esp32_spiflash_s *priv = &s_esp32_spiflash1;
+
+  return &priv->mtd;
+}
+
+#endif /* CONFIG_ESP32_SPIFLASH */
diff --git a/arch/xtensa/src/esp32/esp32_spiflash.h 
b/arch/xtensa/src/esp32/esp32_spiflash.h
new file mode 100644
index 0000000..1b3702d
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_spiflash.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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_ESP32_ESP32_SPIFLASH_H
+#define __ARCH_XTENSA_SRC_ESP32_ESP32_SPIFLASH_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <nuttx/mtd/mtd.h>
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_spiflash_init
+ *
+ * Description:
+ *   Alloc ESP32 SPI Flash MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32 SPI Flash MTD data pointer if success or NULL if fail.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_alloc_mtdpart(void);
+
+/****************************************************************************
+ * Name: esp32_spiflash_get_mtd
+ *
+ * Description:
+ *   Get ESP32 SPI Flash raw MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32 SPI Flash raw MTD data pointer.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_get_mtd(void);
+
+#ifdef __cplusplus
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_SPIFLASH_H */
diff --git a/arch/xtensa/src/esp32/rom/esp32_spiflash.h 
b/arch/xtensa/src/esp32/rom/esp32_spiflash.h
new file mode 100644
index 0000000..2e0eb47
--- /dev/null
+++ b/arch/xtensa/src/esp32/rom/esp32_spiflash.h
@@ -0,0 +1,826 @@
+/*****************************************************************************
+ * arch/xtensa/src/esp32/rom/esp32_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 _ROM_SPI_FLASH_H_
+#define _ROM_SPI_FLASH_H_
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* spi_flash_apis, spi flash operation related apis */
+
+/*****************************************************************************
+ *                            Note
+ *****************************************************************************
+ * 1. ESP32 chip have 4 SPI slave/master, however, SPI0 is
+ *    used as an SPI master to access Flash and ext-SRAM by
+ *    Cache module. It will support Decryto read for Flash,
+ *    read/write for ext-SRAM. And SPI1 is also used as an
+ *    SPI master for Flash read/write and ext-SRAM read/write.
+ *    It will support Encrypto write for Flash.
+ * 2. As an SPI master, SPI support Highest clock to 80M,
+ *    however, Flash with 80M Clock should be configured
+ *    for different Flash chips. If you want to use 80M
+ *    clock We should use the SPI that is certified by
+ *    Espressif. However, the certification is not started
+ *    at the time, so please use 40M clock at the moment.
+ * 3. SPI Flash can use 2 lines or 4 lines mode. If you
+ *    use 2 lines mode, you can save two pad SPIHD and
+ *    SPIWP for gpio. ESP32 support configured SPI pad for
+ *    Flash, the configuration is stored in efuse and flash.
+ *    However, the configurations of pads should be certified
+ *    by Espressif. If you use this function, please use 40M
+ *    clock at the moment.
+ * 4. ESP32 support to use Common SPI command to configure
+ *    Flash to QIO mode, if you failed to configure with fix
+ *    command. With Common SPI Command, ESP32 can also provide
+ *    a way to use same Common SPI command groups on different
+ *    Flash chips.
+ * 5. This functions are not protected by packeting, Please use the
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+#define PERIPHS_SPI_FLASH_CMD                 SPI_CMD_REG(1)
+#define PERIPHS_SPI_FLASH_ADDR                SPI_ADDR_REG(1)
+#define PERIPHS_SPI_FLASH_CTRL                SPI_CTRL_REG(1)
+#define PERIPHS_SPI_FLASH_CTRL1               SPI_CTRL1_REG(1)
+#define PERIPHS_SPI_FLASH_STATUS              SPI_RD_STATUS_REG(1)
+#define PERIPHS_SPI_FLASH_USRREG              SPI_USER_REG(1)
+#define PERIPHS_SPI_FLASH_USRREG1             SPI_USER1_REG(1)
+#define PERIPHS_SPI_FLASH_USRREG2             SPI_USER2_REG(1)
+#define PERIPHS_SPI_FLASH_C0                  SPI_W0_REG(1)
+#define PERIPHS_SPI_FLASH_C1                  SPI_W1_REG(1)
+#define PERIPHS_SPI_FLASH_C2                  SPI_W2_REG(1)
+#define PERIPHS_SPI_FLASH_C3                  SPI_W3_REG(1)
+#define PERIPHS_SPI_FLASH_C4                  SPI_W4_REG(1)
+#define PERIPHS_SPI_FLASH_C5                  SPI_W5_REG(1)
+#define PERIPHS_SPI_FLASH_C6                  SPI_W6_REG(1)
+#define PERIPHS_SPI_FLASH_C7                  SPI_W7_REG(1)
+#define PERIPHS_SPI_FLASH_TX_CRC              SPI_TX_CRC_REG(1)
+
+#define SPI0_R_QIO_DUMMY_CYCLELEN             3
+#define SPI0_R_QIO_ADDR_BITSLEN               31
+#define SPI0_R_FAST_DUMMY_CYCLELEN            7
+#define SPI0_R_DIO_DUMMY_CYCLELEN             1
+#define SPI0_R_DIO_ADDR_BITSLEN               27
+#define SPI0_R_FAST_ADDR_BITSLEN              23
+#define SPI0_R_SIO_ADDR_BITSLEN               23
+
+#define SPI1_R_QIO_DUMMY_CYCLELEN             3
+#define SPI1_R_QIO_ADDR_BITSLEN               31
+#define SPI1_R_FAST_DUMMY_CYCLELEN            7
+#define SPI1_R_DIO_DUMMY_CYCLELEN             3
+#define SPI1_R_DIO_ADDR_BITSLEN               31
+#define SPI1_R_FAST_ADDR_BITSLEN              23
+#define SPI1_R_SIO_ADDR_BITSLEN               23
+
+#define ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN   23
+
+#define ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN   SPI_WRSR_2B
+
+/* SPI address register */
+
+#define ESP_ROM_SPIFLASH_BYTES_LEN            24
+#define ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM  32
+#define ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM   64
+#define ESP_ROM_SPIFLASH_BUFF_BYTE_READ_BITS  0x3f
+
+/* SPI status register */
+
+#define ESP_ROM_SPIFLASH_BUSY_FLAG            BIT0
+#define ESP_ROM_SPIFLASH_WRENABLE_FLAG        BIT1
+#define ESP_ROM_SPIFLASH_BP0                  BIT2
+#define ESP_ROM_SPIFLASH_BP1                  BIT3
+#define ESP_ROM_SPIFLASH_BP2                  BIT4
+#define ESP_ROM_SPIFLASH_WR_PROTECT           (ESP_ROM_SPIFLASH_BP0|\
+                                               ESP_ROM_SPIFLASH_BP1|\
+                                               ESP_ROM_SPIFLASH_BP2)
+#define ESP_ROM_SPIFLASH_QE                   BIT9
+
+/* Extra dummy for flash read */
+
+#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M   0
+#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M   1
+#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M   2
+
+#define FLASH_ID_GD25LQ32C  0xC86016
+
+/*****************************************************************************
+ * Public Types
+ *****************************************************************************/
+
+typedef enum
+{
+    ESP_ROM_SPIFLASH_QIO_MODE = 0,
+    ESP_ROM_SPIFLASH_QOUT_MODE,
+    ESP_ROM_SPIFLASH_DIO_MODE,
+    ESP_ROM_SPIFLASH_DOUT_MODE,
+    ESP_ROM_SPIFLASH_FASTRD_MODE,
+    ESP_ROM_SPIFLASH_SLOWRD_MODE
+} esp_rom_spiflash_read_mode_t;
+
+typedef enum
+{
+    ESP_ROM_SPIFLASH_RESULT_OK,
+    ESP_ROM_SPIFLASH_RESULT_ERR,
+    ESP_ROM_SPIFLASH_RESULT_TIMEOUT
+} esp_rom_spiflash_result_t;
+
+typedef struct
+{
+    uint32_t device_id;
+    uint32_t chip_size;    /* chip size in bytes */
+    uint32_t block_size;
+    uint32_t sector_size;
+    uint32_t page_size;
+    uint32_t status_mask;
+} esp32_spiflash_chip_t;
+
+typedef struct
+{
+    uint8_t  data_length;
+    uint8_t  read_cmd0;
+    uint8_t  read_cmd1;
+    uint8_t  write_cmd;
+    uint16_t data_mask;
+    uint16_t data;
+} esp_rom_spiflash_common_cmd_t;
+
+/*****************************************************************************
+ * Public Function Prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_fix_dummylen
+ *
+ * Description:
+ *   Fix the bug in SPI hardware communication with Flash/Ext-SRAM in High
+ *   Speed.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint8_t spi: 0 for SPI0(Cache Access), 1 for SPI1(Flash read/write).
+ *
+ *   uint8_t freqdiv: Pll is 80M, 4 for 20M, 3 for 26.7M, 2 for 40M,
+ *                    1 for 80M.
+ *
+ * Returned Value:
+ *   None
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_fix_dummylen(uint8_t spi, uint8_t freqdiv);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_select_qiomode
+ *
+ * Description:
+ *   Select SPI Flash to QIO mode when WP pad is read from Flash.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint8_t wp_gpio_num: WP gpio number.
+ *
+ *   uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
+ *                    else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid,
+ *                    bit[23:18] spics0, bit[29:24] spihd
+ *
+ * Returned Value:
+ *   None
+ *****************************************************************************/
+
+void esp_rom_spiflash_select_qiomode(uint8_t wp_gpio_num,
+                                     uint32_t ishspi);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_set_drvs
+ *
+ * Description:
+ *   Set SPI Flash pad drivers.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint8_t wp_gpio_num: WP gpio number.
+ *
+ *   uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
+ *                    else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid,
+ *                    bit[23:18] spics0, bit[29:24] spihd
+ *
+ *   uint8_t *drvs:   drvs[0]-bit[3:0] for cpiclk, bit[7:4] for spiq,
+ *                    drvs[1]-bit[3:0] for spid, drvs[1]-bit[7:4] for spid
+ *                    drvs[2]-bit[3:0] for spihd, drvs[2]-bit[7:4] for spiwp.
+ *                    Values usually read from flash by rom code, function
+ *                    usually callde by rom code.
+ *                    if value with bit(3) set, the value is valid, bit[2:0]
+ *                    is the real value.
+ *
+ * Returned Value:
+ *   None
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_set_drvs(uint8_t wp_gpio_num,
+                               uint32_t ishspi,
+                               uint8_t *drvs);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_select_padsfunc
+ *
+ * Description:
+ *   Select SPI Flash function for pads.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
+ *                    else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid,
+ *                    bit[23:18] spics0, bit[29:24] spihd
+ *
+ * Returned Value:
+ *   None
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_select_padsfunc(uint32_t ishspi);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_attach
+ *
+ * Description:
+ *   SPI Flash init, clock divisor is 4, use 1 line Slow read mode.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
+ *                    else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid,
+ *                    bit[23:18] spics0, bit[29:24] spihd
+ *
+ *   uint8_t legacy: In legacy mode, more SPI command is used in line.
+ *
+ * Returned Value:
+ *   None
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_attach(uint32_t ishspi, bool legacy);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_read_status
+ *
+ * Description:
+ *   SPI Read Flash status register. We use CMD 0x05 (RDSR).
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   esp32_spiflash_chip_t *spi : The information for Flash, which is exported
+ *                                from ld file.
+ *
+ *   uint32_t *status : The pointer to which to return the Flash status value.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : read OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : read error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : read timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_read_status(esp32_spiflash_chip_t *spi,
+                             uint32_t *status);
+
+/*****************************************************************************
+ * Name: esp32_spiflash_read_statushigh
+ *
+ * Description:
+ *   SPI Read Flash status register bits 8-15. We use CMD 0x35 (RDSR2).
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   esp32_spiflash_chip_t *spi : The information for Flash, which is exported
+ *                                from ld file.
+ *
+ *   uint32_t *status : The pointer to which to return the Flash status value.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : read OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : read error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : read timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp32_spiflash_read_statushigh(esp32_spiflash_chip_t *spi,
+                               uint32_t *status);
+
+/*****************************************************************************
+ * Name: esp32_spiflash_write_status
+ *
+ * Description:
+ *   Write status to Falsh status register.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   esp32_spiflash_chip_t *spi : The information for Flash, which is exported
+ *                                from ld file.
+ *
+ *   uint32_t status_value : Value to .
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : write OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : write error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : write timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp32_spiflash_write_status(esp32_spiflash_chip_t *spi,
+                            uint32_t status_value);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_read_user_cmd
+ *
+ * Description:
+ *   Use a command to Read Flash status register.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   esp32_spiflash_chip_t *spi : The information for Flash, which is exported
+ *                                from ld file.
+ *
+ *   uint32_t*status : The pointer to which to return the Flash status value.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : read OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : read error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : read timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_read_user_cmd(uint32_t *status,
+                               uint8_t cmd);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_config_readmode
+ *
+ * Description:
+ *   Config SPI Flash read mode when init.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameter:
+ *   esp_rom_spiflash_read_mode_t mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
+ *
+ *   This function does not try to set the QIO Enable bit in the status
+ *   register, caller is responsible for this.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : config OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : config error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_config_clk
+ *
+ * Description:
+ *   Config SPI Flash clock divisor.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint8_t freqdiv: clock divisor.
+ *
+ *   uint8_t spi: 0 for SPI0, 1 for SPI1.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : config OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : config error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_config_clk(uint8_t freqdiv,
+                            uint8_t spi);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_common_cmd
+ *
+ * Description:
+ *   Send CommonCmd to Flash so that is can go into QIO mode, some Flash use
+ *   different CMD.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Paramater:
+ *   esp_rom_spiflash_common_cmd_t *cmd : A struct to show the action of a
+ *                                        command.
+ *
+ * Returned Value:
+ *   uint16_t  0 : do not send command any more.
+ *             1 : go to the next command.
+ *             n > 1 : skip (n - 1) commands.
+ *
+ *****************************************************************************/
+
+uint16_t esp_rom_spiflash_common_cmd(esp_rom_spiflash_common_cmd_t *cmd);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_unlock
+ *
+ * Description:
+ *   Unlock SPI write protect.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Value:
+ *   None.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Unlock OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Unlock error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Unlock timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_lock
+ *
+ * Description:
+ *   SPI write protect.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameter:
+ *   None.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Lock OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Lock error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Lock timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t esp_rom_spiflash_lock(void);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_config_param
+ *
+ * Description:
+ *   Update SPI Flash parameter.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t deviceId : Device ID read from SPI, the low 32 bit.
+ *
+ *   uint32_t chip_size : The Flash size.
+ *
+ *   uint32_t block_size : The Flash block size.
+ *
+ *   uint32_t sector_size : The Flash sector size.
+ *
+ *   uint32_t page_size : The Flash page size.
+ *
+ *   uint32_t status_mask : The Mask used when read status from Flash
+ *                          (use single CMD).
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Update OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Update error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Update timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_config_param(uint32_t deviceid,
+                              uint32_t chip_size,
+                              uint32_t block_size,
+                              uint32_t sector_size,
+                              uint32_t page_size,
+                              uint32_t status_mask);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_erase_chip
+ *
+ * Description:
+ *   Erase whole flash chip.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameter:
+ *   None
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip(void);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_erase_block
+ *
+ * Description:
+ *   Erase a 64KB block of flash
+ *   Uses SPI flash command D8H.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameter:
+ *   uint32_t block_num : Which block to erase.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block_num);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_erase_sector
+ *
+ * Description:
+ *   Erase a sector of flash.
+ *   Uses SPI flash command 20H.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t sector_num : Which sector to erase.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector_num);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_erase_area
+ *
+ * Description:
+ *   Erase some sectors.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t start_addr : Start addr to erase, should be sector aligned.
+ *
+ *   uint32_t area_len : Length to erase, should be sector aligned.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_erase_area(uint32_t start_addr,
+                            uint32_t area_len);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_write
+ *
+ * Description:
+ *  Write Data to Flash, you should Erase it yourself if need.
+ *
+ *  Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t dest_addr : Address to write, should be 4 bytes aligned.
+ *
+ *   const uint32_t *src : The pointer to data which is to write.
+ *
+ *   uint32_t len : Length to write, should be 4 bytes aligned.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Write OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Write error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Write timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_write(uint32_t dest_addr,
+                       const uint32_t *src,
+                       int32_t len);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_read
+ *
+ * Description:
+ *   Read Data from Flash, you should Erase it yourself if need.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Values:
+ *   uint32_t src_addr : Address to read, should be 4 bytes aligned.
+ *
+ *   uint32_t *dest : The buf to read the data.
+ *
+ *   uint32_t len : Length to read, should be 4 bytes aligned.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Read OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Read error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Read timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_read(uint32_t src_addr,
+                      uint32_t *dest,
+                      int32_t len);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_write_encrypted_enable
+ *
+ * Description:
+ *   SPI1 go into encrypto mode.
+ *
+ *   Please do not call this function in SDK.
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_write_encrypted_enable(void);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_prepare_encrypted_data
+ *
+ * Description:
+ *   Prepare 32 Bytes data to encrpto writing, you should Erase it yourself
+ *   if need.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t flash_addr : Address to write, should be 32 bytes aligned.
+ *
+ *   uint32_t *data : The pointer to data which is to write.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Prepare OK.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Prepare error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Prepare timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_prepare_encrypted_data(uint32_t flash_addr,
+                                        uint32_t *data);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_write_encrypted_disable
+ *
+ * Description:
+ *   SPI1 go out of encrypto mode.
+ *
+ *   Please do not call this function in SDK.
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_write_encrypted_disable(void);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_write_encrypted
+ *
+ * Description:
+ *   Write data to flash with transparent encryption.
+ *   Sectors to be written should already be erased.
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   uint32_t flash_addr : Address to write, should be 32 byte aligned.
+ *
+ *   uint32_t *data : The pointer to data to write. Note, this pointer must
+ *                    be 32 bit aligned and the content of the data will be
+ *                    modified by the encryption function.
+ *
+ *   uint32_t len : Length to write, should be 32 bytes aligned.
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Data written successfully.
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Encryption write error.
+ *   ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Encrypto write timeout.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t
+esp_rom_spiflash_write_encrypted(uint32_t flash_addr,
+                                 uint32_t *data,
+                                 uint32_t len);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_wait_idle
+ *
+ * Description:
+ *   Wait until SPI flash write operation is complete
+ *
+ *   Please do not call this function in SDK.
+ *
+ *   Reads the Write In Progress bit of the SPI flash status register,
+ *   repeats until this bit is zero (indicating write complete).
+ *
+ * Returned Value:
+ *   ESP_ROM_SPIFLASH_RESULT_OK : Write is complete
+ *   ESP_ROM_SPIFLASH_RESULT_ERR : Error while reading status.
+ *
+ *****************************************************************************/
+
+esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp32_spiflash_chip_t
+                                                     *spi);
+
+/*****************************************************************************
+ * Name: esp_rom_spiflash_select_qio_pins
+ *
+ * Description:
+ *   Enable Quad I/O pin functions
+ *
+ *   Please do not call this function in SDK.
+ *
+ *   Sets the HD & WP pin functions for Quad I/O modes, based on the
+ *   efuse SPI pin configuration.
+ *
+ * Input Parameters:
+ *   wp_gpio_num - Number of the WP pin to reconfigure for quad I/O.
+ *   spiconfig   - Pin configuration, as returned from
+ *                 ets_efuse_get_spiconfig().
+ *               - If this parameter is 0, default SPI pins are used and
+ *                 wp_gpio_num parameter is ignored.
+ *               - If this parameter is 1, default HSPI pins are used and
+ *                 wp_gpio_num parameter is ignored.
+ *               - For other values, this parameter encodes the HD pin number
+ *                 and also the CLK pin number. CLK pin selection is used to
+ *                 determine if HSPI or SPI peripheral will be used (use HSPI
+ *                 if CLK pin is the HSPI clock pin, otherwise use SPI).
+ *   Both HD & WP pins are configured via GPIO matrix to map to the selected
+ *   peripheral.
+ *
+ *****************************************************************************/
+
+void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num,
+                                      uint32_t spiconfig);
+
+/* Global esp32_spiflash_chip_t structure used by ROM functions */
+
+extern esp32_spiflash_chip_t g_rom_flashchip;
+
+extern uint8_t g_rom_spiflash_dummy_len_plus[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ROM_SPI_FLASH_H_ */
diff --git a/boards/xtensa/esp32/esp32-core/scripts/esp32_flash.ld 
b/boards/xtensa/esp32/esp32-core/scripts/esp32_flash.ld
index bccf2aa..1634509 100644
--- a/boards/xtensa/esp32/esp32-core/scripts/esp32_flash.ld
+++ b/boards/xtensa/esp32/esp32-core/scripts/esp32_flash.ld
@@ -58,6 +58,7 @@ SECTIONS
     *librtc.a:(.literal .text .literal.* .text.*)
     *libpp.a:(.literal .text .literal.* .text.*)
     *libhal.a:(.literal .text .literal.* .text.*)
+    *libarch.a:esp32_spiflash.*(.literal .text .literal.* .text.*)
     _iram_text_end = ABSOLUTE(.);
 
     /* Module text area starts at the end of iram0_0_seg */
@@ -87,6 +88,7 @@ SECTIONS
     *(.share.mem)
     *(.gnu.linkonce.b.*)
     *(COMMON)
+    *libarch.a:esp32_spiflash.*(.bss  .bss.*  COMMON)
     . = ALIGN(8);
     _ebss = ABSOLUTE(.);
 
@@ -112,6 +114,7 @@ SECTIONS
     KEEP (*(.gnu.linkonce.s2.*))
     KEEP (*(.jcr))
     *(.dram1 .dram1.*)
+    *libarch.a:esp32_spiflash.*(.rodata  .rodata.*)
     . = ALIGN(4);
     _edata = ABSOLUTE(.);
 
diff --git a/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld 
b/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
index 60af005..6541caa 100644
--- a/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
+++ b/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
@@ -1844,3 +1844,8 @@ PROVIDE ( _xtos_syscall_handler = 0x40000790 );
 PROVIDE ( _xtos_unhandled_exception = 0x4000c024 );
 PROVIDE ( _xtos_unhandled_interrupt = 0x4000c01c );
 PROVIDE ( _xtos_vpri_enabled = 0x3ffe0654 );
+PROVIDE ( g_rom_flashchip = 0x3ffae270 );
+PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 );
+PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 );
+PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 );
+PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );

Reply via email to