You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2021/03/26 08:19:32 UTC

[incubator-nuttx] branch master updated (653bbde -> 76c02af)

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

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


    from 653bbde  Documentation: add ESP32 and DevKitC docs
     new 4f8ff07  risc-v/esp32c3: Add SPIFlash support
     new 76c02af  esp32c3-devkit: Add board support for SPIFlash

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/risc-v/src/esp32c3/Kconfig                    |  52 ++
 arch/risc-v/src/esp32c3/Make.defs                  |   8 +
 .../src/esp32c3/esp32c3_partition.c}               | 172 ++---
 .../src/esp32c3/esp32c3_partition.h}               |  16 +-
 arch/risc-v/src/esp32c3/esp32c3_spiflash.c         | 745 +++++++++++++++++++++
 arch/risc-v/src/esp32c3/esp32c3_spiflash.h         | 251 +++++++
 .../src/esp32c3/rom/esp32c3_spiflash.h}            |  70 +-
 boards/risc-v/esp32c3/esp32c3-devkit/Kconfig       |  23 +
 .../configs/{timer => spiflash}/defconfig          |  16 +-
 .../esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld  |   1 +
 boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile  |   4 +
 .../esp32c3/esp32c3-devkit/src/esp32c3-devkit.h    |  11 +
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |  19 +
 .../esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c} |  60 +-
 14 files changed, 1270 insertions(+), 178 deletions(-)
 copy arch/{xtensa/src/esp32/esp32_partition.c => risc-v/src/esp32c3/esp32c3_partition.c} (80%)
 copy arch/{xtensa/src/esp32/esp32_partition.h => risc-v/src/esp32c3/esp32c3_partition.h} (83%)
 create mode 100644 arch/risc-v/src/esp32c3/esp32c3_spiflash.c
 create mode 100644 arch/risc-v/src/esp32c3/esp32c3_spiflash.h
 copy arch/{xtensa/src/esp32/rom/esp32_spiflash.h => risc-v/src/esp32c3/rom/esp32c3_spiflash.h} (90%)
 copy boards/risc-v/esp32c3/esp32c3-devkit/configs/{timer => spiflash}/defconfig (79%)
 copy boards/{xtensa/esp32/esp32-wrover-kit/src/esp32_spiflash.c => risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c} (77%)

[incubator-nuttx] 01/02: risc-v/esp32c3: Add SPIFlash support

Posted by ag...@apache.org.
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

commit 4f8ff0765f1e63c4d530f4b399fe673e7439cb56
Author: Alan Carvalho de Assis <al...@espressif.com>
AuthorDate: Sat Mar 20 13:27:56 2021 -0300

    risc-v/esp32c3: Add SPIFlash support
    
    Co-Authored-By: Dong Heng <do...@espressif.com>
    Co-authored-by: Gustavo Henrique Nihei <gu...@espressif.com>
    Co-authored-by: Abdelatif Guettouche <ab...@espressif.com>
---
 arch/risc-v/src/esp32c3/Kconfig                    |  52 ++
 arch/risc-v/src/esp32c3/Make.defs                  |   8 +
 arch/risc-v/src/esp32c3/esp32c3_partition.c        | 678 ++++++++++++++++++
 arch/risc-v/src/esp32c3/esp32c3_partition.h        |  72 ++
 arch/risc-v/src/esp32c3/esp32c3_spiflash.c         | 745 +++++++++++++++++++
 arch/risc-v/src/esp32c3/esp32c3_spiflash.h         | 251 +++++++
 arch/risc-v/src/esp32c3/rom/esp32c3_spiflash.h     | 794 +++++++++++++++++++++
 .../esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld  |   1 +
 8 files changed, 2601 insertions(+)

diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig
index b30ec27..50f052c 100644
--- a/arch/risc-v/src/esp32c3/Kconfig
+++ b/arch/risc-v/src/esp32c3/Kconfig
@@ -216,6 +216,13 @@ config ESP32C3_TIMER1
 	---help---
 		Enables Timer 1
 
+config ESP32C3_SPIFLASH
+	bool "SPI Flash"
+	default n
+	select MTD
+	select MTD_BYTE_WRITE
+	select MTD_PARTITION
+
 config ESP32C3_MWDT0
 	bool "Main System Watchdog Timer (Group 0)"
 	default n
@@ -301,6 +308,13 @@ config ESP32C3_UART1_RXPIN
 
 endif # ESP32C3_UART1
 
+config ESP32C3_PARTITION
+	bool "ESP32-C3 Partition"
+	default n
+	select ESP32C3_SPIFLASH
+	---help---
+		Decode partition file and initialize partition as MTD.
+
 endmenu
 
 menu "Real-Time Timer"
@@ -383,4 +397,42 @@ config ESP32C3_WIFI_FS_MOUNTPT
 
 endmenu # ESP32C3_WIRELESS
 
+menu "SPI Flash configuration"
+	depends on ESP32C3_SPIFLASH
+
+config ESP32C3_MTD_OFFSET
+	hex "MTD base address in SPI Flash"
+	default 0x180000
+	help
+		MTD base address in SPI Flash.
+
+config ESP32C3_MTD_SIZE
+	hex "MTD size in SPI Flash"
+	default 0x100000
+	help
+		MTD size in SPI Flash.
+
+config ESP32C3_SPIFLASH_DEBUG
+	bool "Debug SPI Flash"
+	default n
+	depends on DEBUG_FS_INFO
+	help
+		If this option is enabled, SPI Flash driver read and write functions
+		will output input parameters and return values (if applicable).
+
+endmenu # ESP32C3_SPIFLASH
+
+menu "Partition Configuration"
+        depends on ESP32C3_PARTITION
+
+config ESP32C3_PARTITION_OFFSET
+        hex "Partition offset"
+        default "0x8000"
+
+config ESP32C3_PARTITION_MOUNT
+        string "Partition mount point"
+        default "/dev/esp/partition/"
+
+endmenu # ESP32C3_PARTITION
+
 endif # ARCH_CHIP_ESP32C3
diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index 58b29b8..757ee27 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -63,6 +63,14 @@ ifeq ($(CONFIG_ESP32C3_I2C),y)
 CHIP_CSRCS += esp32c3_i2c.c
 endif
 
+ifeq ($(CONFIG_ESP32C3_SPIFLASH),y)
+CHIP_CSRCS += esp32c3_spiflash.c
+endif
+
+ifeq ($(CONFIG_ESP32C3_PARTITION),y)
+CHIP_CSRCS += esp32c3_partition.c
+endif
+
 ifeq ($(CONFIG_ESP32C3_WDT),y)
 CHIP_CSRCS += esp32c3_wdt.c
 ifeq ($(CONFIG_WATCHDOG),y)
diff --git a/arch/risc-v/src/esp32c3/esp32c3_partition.c b/arch/risc-v/src/esp32c3/esp32c3_partition.c
new file mode 100644
index 0000000..c0ae63d
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_partition.c
@@ -0,0 +1,678 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_partition.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>
+#include <stdint.h>
+#include <string.h>
+#include <debug.h>
+#include <stdio.h>
+#include <sys/errno.h>
+
+#include <nuttx/kmalloc.h>
+
+#include "esp32c3_spiflash.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Partition table max size */
+
+#define PARTITION_MAX_SIZE    (0xc00)
+
+/* Partition table header magic value */
+
+#define PARTITION_MAGIC       (0x50aa)
+
+/* Partition table member label length */
+
+#define PARTITION_LABEL_LEN   (16)
+
+/* OTA data offset in OTA partition */
+
+#define OTA_DATA_OFFSET       (4096)
+
+/* OTA data number */
+
+#define OTA_DATA_NUM          (2)
+
+/* Partition offset in SPI Flash */
+
+#define ESP32C3_PARTITION_OFFSET CONFIG_ESP32C3_PARTITION_OFFSET
+
+/* Partition MTD device mount point */
+
+#define ESP32C3_PARTITION_MOUNT CONFIG_ESP32C3_PARTITION_MOUNT
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* OTA image operation code */
+
+enum ota_img_ctrl_e
+{
+  OTA_IMG_GET_BOOT        = 0xe1,
+  OTA_IMG_SET_BOOT        = 0xe2
+};
+
+/* OTA image state */
+
+enum ota_img_state_e
+{
+  /**
+   *  Monitor the first boot. In bootloader of esp-idf this state is changed
+   *  to ESP_OTA_IMG_PENDING_VERIFY if this bootloader enable app rollback.
+   *
+   *  So this driver doesn't use this state currently.
+   */
+
+  OTA_IMG_NEW             = 0x0,
+
+  /**
+   * First boot for this app was. If while the second boot this state is then
+   * it will be changed to ABORTED if this bootloader enable app rollback.
+   *
+   * So this driver doesn't use this state currently.
+   */
+
+  OTA_IMG_PENDING_VERIFY  = 0x1,
+
+  /* App was confirmed as workable. App can boot and work without limits. */
+
+  OTA_IMG_VALID           = 0x2,
+
+  /* App was confirmed as non-workable. This app will not selected to boot. */
+
+  OTA_IMG_INVALID         = 0x3,
+
+  /**
+   * App could not confirm the workable or non-workable. In bootloader
+   * IMG_PENDING_VERIFY state will be changed to IMG_ABORTED. This app will
+   * not selected to boot at all if this bootloader enable app rollback.
+   *
+   * So this driver doesn't use this state currently.
+   */
+
+  OTA_IMG_ABORTED         = 0x4,
+
+  /**
+   * Undefined. App can boot and work without limits in esp-idf.
+   *
+   * This state is not used.
+   */
+
+  OTA_IMG_UNDEFINED       = 0xffffffff,
+};
+
+/* OTA image boot sequency */
+
+enum ota_img_bootseq_e
+{
+  OTA_IMG_BOOT_FACTORY    = 0,
+  OTA_IMG_BOOT_OTA_0      = 1,
+  OTA_IMG_BOOT_OTA_1      = 2,
+  OTA_IMG_BOOT_SEQ_MAX
+};
+
+/* Partition information data */
+
+struct partition_info_priv_s
+{
+  uint16_t magic;                       /* Partition magic */
+  uint8_t  type;                        /* Partition type */
+  uint8_t  subtype;                     /* Partition sub-type */
+
+  uint32_t offset;                      /* Offset in SPI Flash */
+  uint32_t size;                        /* Size by byte */
+
+  uint8_t  label[PARTITION_LABEL_LEN];  /* Partition label */
+
+  uint32_t flags;                       /* Partition flags */
+};
+
+/* Partition device data */
+
+struct mtd_dev_priv_s
+{
+  struct mtd_dev_s mtd;                 /* MTD data */
+
+  uint8_t  type;                        /* Partition type */
+  uint8_t  subtype;                     /* Partition sub-type */
+  uint32_t flags;                       /* Partition flags */
+
+  struct mtd_dev_s  *ll_mtd;            /* Low-level MTD data */
+  struct mtd_dev_s  *part_mtd;          /* Partition MTD data */
+};
+
+/* OTA data entry */
+
+struct ota_data_entry_s
+{
+  uint32_t ota_seq;                     /* Boot sequence */
+  uint8_t  seq_label[20];               /* Boot sequence label */
+  uint32_t ota_state;                   /* Boot entry state */
+  uint32_t crc;                         /* Boot ota_seq CRC32 */
+};
+
+/****************************************************************************
+ * External Function Prototypes
+ ****************************************************************************/
+
+extern uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ota_is_valid
+ *
+ * Description:
+ *   Check if OTA data is valid
+ *
+ * Input Parameters:
+ *   ota_data - OTA data
+ *
+ * Returned Value:
+ *   true if checking success or false if fail
+ *
+ ****************************************************************************/
+
+static bool ota_is_valid(struct ota_data_entry_s *ota_data)
+{
+  if ((ota_data->ota_seq >= OTA_IMG_BOOT_SEQ_MAX) ||
+      (ota_data->ota_state != OTA_IMG_VALID) ||
+      (ota_data->crc != crc32_le(UINT32_MAX, (uint8_t *)ota_data, 4)))
+    {
+      return false;
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: ota_get_bootseq
+ *
+ * Description:
+ *   Get boot sequence
+ *
+ * Input Parameters:
+ *   dev - Partition private MTD data
+ *   num - boot sequence buffer
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int ota_get_bootseq(struct mtd_dev_priv_s *dev, int *num)
+{
+  int i;
+  int ret;
+  struct ota_data_entry_s ota_data;
+  int size = sizeof(struct ota_data_entry_s);
+
+  /* Each OTA data locates in independent sector */
+
+  for (i = 0; i < OTA_DATA_NUM; i++)
+    {
+      ret = MTD_READ(dev->part_mtd, i * OTA_DATA_OFFSET,
+                     size, (uint8_t *)&ota_data);
+      if (ret != size)
+        {
+          ferr("ERROR: Failed to read OTA%d data error=%d\n", i, ret);
+          return -EIO;
+        }
+
+      if (ota_is_valid(&ota_data))
+        {
+          *num = i + OTA_IMG_BOOT_OTA_0;
+          break;
+        }
+    }
+
+  if (i >= 2)
+    {
+      *num = OTA_IMG_BOOT_FACTORY;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: ota_set_bootseq
+ *
+ * Description:
+ *   Set boot sequence
+ *
+ * Input Parameters:
+ *   dev - Partition private MTD data
+ *   num - boot sequence buffer
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int ota_set_bootseq(struct mtd_dev_priv_s *dev, int num)
+{
+  int ret;
+  int id;
+  int old_id;
+  struct ota_data_entry_s ota_data;
+  int size = sizeof(struct ota_data_entry_s);
+
+  finfo("INFO: num=%d\n", num);
+
+  switch (num)
+    {
+      case OTA_IMG_BOOT_FACTORY:
+
+        /* Erase all OTA data to force use factory app */
+
+        ret = MTD_ERASE(dev->part_mtd, 0, OTA_DATA_NUM);
+        if (ret != OTA_DATA_NUM)
+          {
+            ferr("ERROR: Failed to erase OTA data error=%d\n", ret);
+            return -EIO;
+          }
+
+        break;
+      case OTA_IMG_BOOT_OTA_0:
+      case OTA_IMG_BOOT_OTA_1:
+        {
+          id = num - 1;
+          old_id = num == OTA_IMG_BOOT_OTA_0 ? OTA_IMG_BOOT_OTA_1 - 1:
+                                               OTA_IMG_BOOT_OTA_0 - 1;
+
+          ret = MTD_ERASE(dev->part_mtd, id, 1);
+          if (ret != 1)
+            {
+              ferr("ERROR: Failed to erase OTA%d data error=%d\n", id, ret);
+              return -EIO;
+            }
+
+          ota_data.ota_state = OTA_IMG_VALID;
+          ota_data.ota_seq = num;
+          ota_data.crc = crc32_le(UINT32_MAX, (uint8_t *)&ota_data, 4);
+          ret = MTD_WRITE(dev->part_mtd, id * OTA_DATA_OFFSET,
+                          size, (uint8_t *)&ota_data);
+          if (ret != size)
+            {
+              ferr("ERROR: Failed to write OTA%d data error=%d\n",
+                   id, ret);
+              return -1;
+            }
+
+          /* Erase old OTA data to force new OTA bin */
+
+          ret = MTD_ERASE(dev->part_mtd, old_id, 1);
+          if (ret != 1)
+            {
+              ferr("ERROR: Failed to erase OTA%d data error=%d\n",
+                   old_id, ret);
+              return -EIO;
+            }
+        }
+
+        break;
+      default:
+        ferr("ERROR: num=%d is error\n", num);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+/****************************************************************************
+ * Name: esp32c3_part_erase
+ *
+ * Description:
+ *   Erase SPI Flash designated sectors.
+ *
+ * Input Parameters:
+ *   dev        - ESP32-C3 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 esp32c3_part_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                            size_t nblocks)
+{
+  struct mtd_dev_priv_s *mtd_priv = (struct mtd_dev_priv_s *)dev;
+
+  return MTD_ERASE(mtd_priv->ll_mtd, startblock, nblocks);
+}
+
+/****************************************************************************
+ * Name: esp32c3_part_read
+ *
+ * Description:
+ *   Read data from SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   dev    - ESP32-C3 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 esp32c3_part_read(FAR struct mtd_dev_s *dev, off_t offset,
+                               size_t nbytes, FAR uint8_t *buffer)
+{
+  struct mtd_dev_priv_s *mtd_priv = (struct mtd_dev_priv_s *)dev;
+
+  return MTD_READ(mtd_priv->ll_mtd, offset, nbytes, buffer);
+}
+
+/****************************************************************************
+ * Name: esp32c3_part_bread
+ *
+ * Description:
+ *   Read data from designated blocks.
+ *
+ * Input Parameters:
+ *   dev        - ESP32-C3 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 esp32c3_part_bread(FAR struct mtd_dev_s *dev,
+                                  off_t startblock, size_t nblocks,
+                                  FAR uint8_t *buffer)
+{
+  struct mtd_dev_priv_s *mtd_priv = (struct mtd_dev_priv_s *)dev;
+
+  return MTD_BREAD(mtd_priv->ll_mtd, startblock, nblocks, buffer);
+}
+
+/****************************************************************************
+ * Name: esp32c3_part_write
+ *
+ * Description:
+ *   write data to SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   dev    - ESP32-C3 MTD device data
+ *   offset - target address offset
+ *   nbytes - data number
+ *   buffer - data buffer pointer
+ *
+ * Returned Value:
+ *   Written bytes if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32c3_part_write(FAR struct mtd_dev_s *dev, off_t offset,
+                                size_t nbytes, FAR const uint8_t *buffer)
+{
+  struct mtd_dev_priv_s *mtd_priv = (struct mtd_dev_priv_s *)dev;
+
+  return MTD_WRITE(mtd_priv->ll_mtd, offset, nbytes, buffer);
+}
+
+/****************************************************************************
+ * Name: esp32c3_part_bwrite
+ *
+ * Description:
+ *   Write data to designated blocks.
+ *
+ * Input Parameters:
+ *   dev        - ESP32-C3 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:
+ *   Written block number if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32c3_part_bwrite(FAR struct mtd_dev_s *dev,
+                                   off_t startblock, size_t nblocks,
+                                   FAR const uint8_t *buffer)
+{
+  struct mtd_dev_priv_s *mtd_priv = (struct mtd_dev_priv_s *)dev;
+
+  return MTD_BWRITE(mtd_priv->ll_mtd, startblock, nblocks, buffer);
+}
+
+/****************************************************************************
+ * Name: esp32c3_part_ioctl
+ *
+ * Description:
+ *   Set/Get option to/from ESP32-C3 SPI Flash MTD device data.
+ *
+ * Input Parameters:
+ *   dev - ESP32-C3 MTD device data
+ *   cmd - operation command
+ *   arg - operation argument
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32c3_part_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg)
+{
+  int ret;
+  struct mtd_dev_priv_s *mtd_priv = (struct mtd_dev_priv_s *)dev;
+
+  finfo("INFO: cmd=%d(0x%x) arg=0x%" PRIx32 "\n", cmd, cmd, arg);
+
+  if (!_MTDIOCVALID(cmd))
+    {
+      ferr("ERROR: cmd=%d(0x%x) is error\n", cmd, cmd);
+      return -EINVAL;
+    }
+
+  switch (_IOC_NR(cmd))
+    {
+      case OTA_IMG_GET_BOOT:
+        {
+          int *num = (int *)arg;
+
+          ret = ota_get_bootseq(mtd_priv, num);
+          if (ret < 0)
+            {
+              ferr("ERROR: Failed to get boot img\n");
+            }
+        }
+
+        break;
+      case OTA_IMG_SET_BOOT:
+        {
+          ret = ota_set_bootseq(mtd_priv, arg);
+          if (ret < 0)
+            {
+              ferr("ERROR: Failed to set boot img\n");
+            }
+        }
+
+        break;
+      default:
+        {
+          ret = MTD_IOCTL(mtd_priv->ll_mtd, cmd, arg);
+        }
+
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_partition_init
+ * 
+ *   Initialize ESP32-C3 partition. Read partition information, and use
+ *   these data for creating MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+int esp32c3_partition_init(void)
+{
+  int i;
+  struct partition_info_priv_s *info;
+  uint8_t *pbuf;
+  struct mtd_dev_s *mtd;
+  struct mtd_dev_s *mtd_part;
+  struct mtd_geometry_s geo;
+  struct mtd_dev_priv_s *mtd_priv;
+  int ret = 0;
+  const int num = PARTITION_MAX_SIZE / sizeof(struct partition_info_priv_s);
+  const char path_base[] = ESP32C3_PARTITION_MOUNT;
+  char label[PARTITION_LABEL_LEN + 1];
+  char path[PARTITION_LABEL_LEN + sizeof(path_base)];
+
+  pbuf = kmm_malloc(PARTITION_MAX_SIZE);
+  if (pbuf == NULL)
+    {
+      ferr("ERROR: Failed to allocate %d byte\n", PARTITION_MAX_SIZE);
+      ret = -ENOMEM;
+      goto errout_with_malloc;
+    }
+
+  mtd = esp32c3_spiflash_mtd();
+  if (mtd == NULL)
+    {
+      ferr("ERROR: Failed to get SPI flash MTD\n");
+      ret = -EIO;
+      goto errout_with_mtd;
+    }
+
+  ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)&geo);
+  if (ret < 0)
+    {
+      ferr("ERROR: Failed to get info from MTD\n");
+      ret = -EIO;
+      goto errout_with_mtd;
+    }
+
+  ret = MTD_READ(mtd, ESP32C3_PARTITION_OFFSET,
+                 PARTITION_MAX_SIZE, pbuf);
+  if (ret != PARTITION_MAX_SIZE)
+    {
+      ferr("ERROR: Failed to get read data from MTD\n");
+      ret = -EIO;
+      goto errout_with_mtd;
+    }
+
+  info = (struct partition_info_priv_s *)pbuf;
+
+  for (i = 0; i < num; i++)
+    {
+      if (info->magic != PARTITION_MAGIC)
+        {
+          break;
+        }
+
+      strncpy(label, (char *)info->label, PARTITION_LABEL_LEN);
+      label[PARTITION_LABEL_LEN] = '\0';
+      sprintf(path, "%s%s", path_base, label);
+
+      finfo("INFO: [label]:   %s\n", label);
+      finfo("INFO: [type]:    %d\n", info->type);
+      finfo("INFO: [subtype]: %d\n", info->subtype);
+      finfo("INFO: [offset]:  0x%08" PRIx32 "\n", info->offset);
+      finfo("INFO: [size]:    0x%08" PRIx32 "\n", info->size);
+      finfo("INFO: [flags]:   0x%08" PRIx32 "\n", info->flags);
+      finfo("INFO: [mount]:   %s\n", path);
+
+      mtd_priv = kmm_malloc(sizeof(struct mtd_dev_priv_s));
+      if (!mtd_priv)
+        {
+          ferr("ERROR: Failed to allocate %d byte\n",
+               sizeof(struct mtd_dev_priv_s));
+          ret = -1;
+          goto errout_with_mtd;
+        }
+
+      mtd_priv->ll_mtd = mtd;
+      mtd_priv->mtd.bread  = esp32c3_part_bread;
+      mtd_priv->mtd.bwrite = esp32c3_part_bwrite;
+      mtd_priv->mtd.erase  = esp32c3_part_erase;
+      mtd_priv->mtd.ioctl  = esp32c3_part_ioctl;
+      mtd_priv->mtd.read   = esp32c3_part_read;
+      mtd_priv->mtd.write  = esp32c3_part_write;
+      mtd_priv->mtd.name   = label;
+
+      mtd_part = mtd_partition(&mtd_priv->mtd,
+                               info->offset / geo.blocksize,
+                               info->size / geo.blocksize);
+      if (!mtd_part)
+        {
+          ferr("ERROR: Failed to create MTD partition\n");
+          kmm_free(mtd_priv);
+          ret = -1;
+          goto errout_with_mtd;
+        }
+
+      mtd_priv->part_mtd = mtd_part;
+
+      ret = register_mtddriver(path, mtd_part, 0777, NULL);
+      if (ret < 0)
+        {
+          ferr("ERROR: Failed to regitser MTD @ %s\n", path);
+          kmm_free(mtd_priv);
+          ret = -1;
+          goto errout_with_mtd;
+        }
+
+      info++;
+    }
+
+  ret = 0;
+
+errout_with_mtd:
+  kmm_free(pbuf);
+
+errout_with_malloc:
+  return ret;
+}
diff --git a/arch/risc-v/src/esp32c3/esp32c3_partition.h b/arch/risc-v/src/esp32c3/esp32c3_partition.h
new file mode 100644
index 0000000..0334113
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_partition.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_partition.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_RISCV_SRC_ESP32C3_ESP32C3_PARTITION_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_PARTITION_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: esp32c3_partition_init
+ *
+ * Description:
+ *   Initialize ESP32-C3 partition. Read partition information
+ *   and use these data for creating MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+int esp32c3_partition_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_PARTITION_H */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_spiflash.c b/arch/risc-v/src/esp32c3/esp32c3_spiflash.c
new file mode 100644
index 0000000..918c349
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_spiflash.c
@@ -0,0 +1,745 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_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>
+
+#include <stdint.h>
+#include <debug.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/init.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/mtd/mtd.h>
+
+#include "esp32c3_spiflash.h"
+#include "rom/esp32c3_spiflash.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SPI_FLASH_BLK_SIZE          256
+#define SPI_FLASH_ERASE_SIZE        4096
+#define SPI_FLASH_SIZE              (4 * 1024 * 1024)
+
+#define ESP32C3_MTD_OFFSET          CONFIG_ESP32C3_MTD_OFFSET
+#define ESP32C3_MTD_SIZE            CONFIG_ESP32C3_MTD_SIZE
+
+#define MTD2PRIV(_dev)              ((FAR struct esp32c3_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))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* ESP32-C3 SPI Flash device private data  */
+
+struct esp32c3_spiflash_s
+{
+  struct mtd_dev_s mtd;
+
+  /* SPI Flash data */
+
+  esp32c3_spiflash_chip_t *chip;
+};
+
+/****************************************************************************
+ * Private Functions Prototypes
+ ****************************************************************************/
+
+/* MTD driver methods */
+
+static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
+                         size_t nblocks);
+static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
+                            size_t nbytes, uint8_t *buffer);
+static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
+                                    off_t offset,
+                                    size_t nbytes,
+                                    uint8_t *buffer);
+static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
+                             size_t nblocks, uint8_t *buffer);
+static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
+                                     off_t startblock,
+                                     size_t nblocks,
+                                     uint8_t *buffer);
+static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, const uint8_t *buffer);
+static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, const uint8_t *buffer);
+static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
+                                      off_t startblock,
+                                      size_t nblocks,
+                                      const uint8_t *buffer);
+static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
+                         unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct esp32c3_spiflash_s g_esp32c3_spiflash =
+{
+  .mtd =
+          {
+            .erase  = esp32c3_erase,
+            .bread  = esp32c3_bread,
+            .bwrite = esp32c3_bwrite,
+            .read   = esp32c3_read,
+            .ioctl  = esp32c3_ioctl,
+#ifdef CONFIG_MTD_BYTE_WRITE
+            .write  = esp32c3_write,
+#endif
+            .name   = "esp32c3_spiflash"
+          },
+  .chip = &g_rom_flashchip,
+};
+
+static struct esp32c3_spiflash_s g_esp32c3_spiflash_encrypt =
+{
+  .mtd =
+          {
+            .erase  = esp32c3_erase,
+            .bread  = esp32c3_bread_decrypt,
+            .bwrite = esp32c3_bwrite_encrypt,
+            .read   = esp32c3_read_decrypt,
+            .ioctl  = esp32c3_ioctl,
+#ifdef CONFIG_MTD_BYTE_WRITE
+            .write  = NULL,
+#endif
+            .name   = "esp32c3_spiflash_encrypt"
+          }
+};
+
+/* Ensure exclusive access to the driver */
+
+static sem_t g_exclsem = SEM_INITIALIZER(1);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
+                         size_t nblocks)
+{
+  ssize_t ret;
+  uint32_t offset = startblock * SPI_FLASH_ERASE_SIZE;
+  uint32_t nbytes = nblocks * SPI_FLASH_ERASE_SIZE;
+
+  if ((offset > SPI_FLASH_SIZE) || ((offset + nbytes) > SPI_FLASH_SIZE))
+    {
+      return -EINVAL;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("(%p, %d, %d)\n", dev, startblock, nblocks);
+#endif
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("spi_flash_erase_range(%p, 0x%x, %d)\n", dev, offset, nbytes);
+#endif
+
+  ret = spi_flash_erase_range(offset, nbytes);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nblocks;
+    }
+  else
+    {
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+      finfo("Failed to erase the flash range!\n");
+#endif
+      ret = -1;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_read(struct mtd_dev_s *dev, off_t offset,
+                          size_t nbytes, uint8_t *buffer)
+{
+  ssize_t ret;
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
+#endif
+
+  /* Acquire the semaphore. */
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      goto error_with_buffer;
+    }
+
+  ret = spi_flash_read(offset, buffer, nbytes);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nbytes;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+error_with_buffer:
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
+                           size_t nblocks, uint8_t *buffer)
+{
+  ssize_t ret;
+  uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
+  uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
+        buffer);
+#endif
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = spi_flash_read(addr, buffer, size);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_read_decrypt(struct mtd_dev_s *dev,
+                                  off_t offset,
+                                  size_t nbytes,
+                                  uint8_t *buffer)
+{
+  ssize_t ret;
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
+#endif
+
+  /* Acquire the semaphore. */
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = spi_flash_read_encrypted(offset, buffer, nbytes);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nbytes;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_bread_decrypt(struct mtd_dev_s *dev,
+                                   off_t startblock,
+                                   size_t nblocks,
+                                   uint8_t *buffer)
+{
+  ssize_t ret;
+  uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
+  uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
+        buffer);
+#endif
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = spi_flash_read_encrypted(addr, buffer, size);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_write(struct mtd_dev_s *dev, off_t offset,
+                           size_t nbytes, const uint8_t *buffer)
+{
+  int ret;
+
+  ASSERT(buffer);
+
+  if ((offset > SPI_FLASH_SIZE) || ((offset + nbytes) > SPI_FLASH_SIZE))
+    {
+      return -EINVAL;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
+#endif
+
+  /* Acquire the semaphore. */
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      goto error_with_buffer;
+    }
+
+  ret = spi_flash_write(offset, buffer, nbytes);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nbytes;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+error_with_buffer:
+
+  return (ssize_t)ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
+                            size_t nblocks, const uint8_t *buffer)
+{
+  ssize_t ret;
+  uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
+  uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
+        nblocks, buffer);
+#endif
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = spi_flash_write(addr, buffer, size);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
+                                      off_t startblock,
+                                      size_t nblocks,
+                                      const uint8_t *buffer)
+{
+  ssize_t ret;
+  uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
+  uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
+        nblocks, buffer);
+#endif
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      goto error_with_buffer;
+    }
+
+  ret = spi_flash_write_encrypted(addr, buffer, size);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
+  finfo("%s()=%d\n", __func__, ret);
+#endif
+
+error_with_buffer:
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_ioctl
+ *
+ * Description:
+ *   Set/Get option to/from ESP32-C3 SPI Flash MTD device data.
+ *
+ * Input Parameters:
+ *   dev - ESP32-C3 MTD device data
+ *   cmd - operation command
+ *   arg - operation argument
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
+                         unsigned long arg)
+{
+  int ret = OK;
+  struct mtd_geometry_s *geo;
+
+  finfo("cmd: %d \n", cmd);
+
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        {
+          geo = (struct mtd_geometry_s *)arg;
+          if (geo)
+            {
+              geo->blocksize    = SPI_FLASH_BLK_SIZE;
+              geo->erasesize    = SPI_FLASH_ERASE_SIZE;
+              geo->neraseblocks = SPI_FLASH_SIZE / SPI_FLASH_ERASE_SIZE;
+              ret               = OK;
+
+              finfo("blocksize: %" PRId32 " erasesize: %" PRId32 \
+                    " neraseblocks: %" PRId32 "\n",
+                    geo->blocksize, geo->erasesize, geo->neraseblocks);
+            }
+        }
+        break;
+
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  finfo("return %d\n", ret);
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_alloc_mtdpart
+ *
+ * Description:
+ *   Allocate SPI Flash MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   SPI Flash MTD data pointer if success or NULL if fail.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32c3_spiflash_alloc_mtdpart(void)
+{
+  struct esp32c3_spiflash_s *priv = &g_esp32c3_spiflash;
+  esp32c3_spiflash_chip_t *chip = priv->chip;
+  FAR struct mtd_dev_s *mtd_part;
+  uint32_t blocks;
+  uint32_t startblock;
+  uint32_t size;
+
+  ASSERT((ESP32C3_MTD_OFFSET + ESP32C3_MTD_SIZE) <= chip->chip_size);
+  ASSERT((ESP32C3_MTD_OFFSET % chip->sector_size) == 0);
+  ASSERT((ESP32C3_MTD_SIZE % chip->sector_size) == 0);
+
+  finfo("ESP32 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);
+
+#if ESP32C3_MTD_SIZE == 0
+  size = chip->chip_size - ESP32C3_MTD_OFFSET;
+#else
+  size = ESP32C3_MTD_SIZE;
+#endif
+
+  finfo("\tMTD offset = 0x%x\n", ESP32C3_MTD_OFFSET);
+  finfo("\tMTD size = 0x%" PRIx32 "\n", size);
+
+  startblock = MTD_SIZE2BLK(priv, ESP32C3_MTD_OFFSET);
+  blocks = MTD_SIZE2BLK(priv, size);
+
+  mtd_part = mtd_partition(&priv->mtd, startblock, blocks);
+  if (!mtd_part)
+    {
+      ferr("ERROR: Failed to create MTD partition\n");
+      return NULL;
+    }
+
+  return mtd_part;
+}
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_mtd
+ *
+ * Description:
+ *   Get SPI Flash MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32-C3 SPI Flash MTD pointer.
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s *esp32c3_spiflash_mtd(void)
+{
+  struct esp32c3_spiflash_s *priv = &g_esp32c3_spiflash;
+
+  return &priv->mtd;
+}
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_encrypt_mtd
+ *
+ * Description:
+ *   Get SPI Flash encryption MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   SPI Flash encryption MTD pointer.
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s *esp32c3_spiflash_encrypt_mtd(void)
+{
+  struct esp32c3_spiflash_s *priv = &g_esp32c3_spiflash_encrypt;
+
+  return &priv->mtd;
+}
diff --git a/arch/risc-v/src/esp32c3/esp32c3_spiflash.h b/arch/risc-v/src/esp32c3/esp32c3_spiflash.h
new file mode 100644
index 0000000..f274c1c
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_spiflash.h
@@ -0,0 +1,251 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_SPIFLASH_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_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: esp32c3_spiflash_mtd
+ *
+ * Description:
+ *   Get ESP32-C3 SPI Flash MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32-C3 SPI Flash MTD pointer.
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s *esp32c3_spiflash_mtd(void);
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_alloc_mtdpart
+ *
+ * Description:
+ *   Alloc ESP32-C3 SPI Flash MTD
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32-C3 SPI Flash MTD data pointer if success or NULL if fail
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32c3_spiflash_alloc_mtdpart(void);
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_encrypt_mtd
+ *
+ * Description:
+ *   Get ESP32-C3 SPI Flash encryption MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32-C3 SPI Flash encryption MTD pointer.
+ *
+ ****************************************************************************/
+
+struct mtd_dev_s *esp32c3_spiflash_encrypt_mtd(void);
+
+/****************************************************************************
+ * Name: spi_flash_write_encrypted
+ *
+ * Description:
+ *   Write data encrypted to Flash.
+ *
+ *   Flash encryption must be enabled for this function to work.
+ *
+ *   Flash encryption must be enabled when calling this function.
+ *   If flash encryption is disabled, the function returns
+ *   ESP_ERR_INVALID_STATE.  Use esp_flash_encryption_enabled()
+ *   function to determine if flash encryption is enabled.
+ *
+ *   Both dest_addr and size must be multiples of 16 bytes. For
+ *   absolute best performance, both dest_addr and size arguments should
+ *   be multiples of 32 bytes.
+ *
+ * Input Parameters:
+ *   dest_addr - Destination address in Flash. Must be a multiple of 16
+ *               bytes.
+ *   src       - Pointer to the source buffer.
+ *   size      - Length of data, in bytes. Must be a multiple of 16 bytes.
+ *
+ * Returned Values:
+ *   Zero (OK) is returned or a negative error.
+ *
+ ****************************************************************************/
+
+int spi_flash_write_encrypted(uint32_t dest_addr, const void *src,
+                              uint32_t size);
+
+/****************************************************************************
+ * Name: spi_flash_write
+ *
+ * Description:
+ *
+ *   Write data to Flash.
+ *
+ *   Note: For fastest write performance, write a 4 byte aligned size at a
+ *   4 byte aligned offset in flash from a source buffer in DRAM. Varying
+ *   any of these parameters will still work, but will be slower due to
+ *   buffering.
+ *
+ *   Writing more than 8KB at a time will be split into multiple
+ *   write operations to avoid disrupting other tasks in the system.
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+int spi_flash_write(uint32_t dest_addr, const void *src, uint32_t size);
+
+/****************************************************************************
+ * 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:
+ *   src   - source address of the data in Flash.
+ *   dest  - pointer to the destination buffer
+ *   size  - length of data
+ *
+ * Returned Values: esp_err_t
+ *
+ ****************************************************************************/
+
+int spi_flash_read_encrypted(uint32_t src, void *dest, uint32_t size);
+
+/****************************************************************************
+ * Name: spi_flash_read
+ *
+ * Description:
+ *   Read data from Flash.
+ *
+ *   Note: For fastest read performance, all parameters should be
+ *   4 byte aligned. If source address and read size are not 4 byte
+ *   aligned, read may be split into multiple flash operations. If
+ *   destination buffer is not 4 byte aligned, a temporary buffer will
+ *   be allocated on the stack.
+ *
+ *   Reading more than 16KB of data at a time will be split
+ *   into multiple reads to avoid disruption to other tasks in the
+ *   system. Consider using spi_flash_mmap() to read large amounts
+ *   of data.
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+int spi_flash_read(uint32_t src_addr, void *dest, uint32_t size);
+
+/****************************************************************************
+ * 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.
+ *
+ ****************************************************************************/
+
+int spi_flash_erase_sector(uint32_t sector);
+
+/****************************************************************************
+ * 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.
+ *
+ ****************************************************************************/
+
+int spi_flash_erase_range(uint32_t start_address, uint32_t size);
+
+#ifdef __cplusplus
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_SPIFLASH_H */
diff --git a/arch/risc-v/src/esp32c3/rom/esp32c3_spiflash.h b/arch/risc-v/src/esp32c3/rom/esp32c3_spiflash.h
new file mode 100644
index 0000000..f7f8bcf
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/rom/esp32c3_spiflash.h
@@ -0,0 +1,794 @@
+/*****************************************************************************
+ * arch/risc-v/src/esp32c3/rom/esp32c3_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
+
+/*****************************************************************************
+ * 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;
+} esp32c3_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:
+ *   esp32c3_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(esp32c3_spiflash_chip_t *spi,
+                             uint32_t *status);
+
+/*****************************************************************************
+ * Name: esp32c3_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:
+ *   esp32c3_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
+esp32c3_spiflash_read_statushigh(esp32c3_spiflash_chip_t *spi,
+                               uint32_t *status);
+
+/*****************************************************************************
+ * Name: esp32c3_spiflash_write_status
+ *
+ * Description:
+ *   Write status to Falsh status register.
+ *
+ *   Please do not call this function in SDK.
+ *
+ * Input Parameters:
+ *   esp32c3_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
+esp32c3_spiflash_write_status(esp32c3_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:
+ *   esp32c3_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(esp32c3_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 esp32c3_spiflash_chip_t structure used by ROM functions */
+
+extern esp32c3_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/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
index c9680ca..f35761d 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
@@ -173,6 +173,7 @@ PROVIDE( Enable_QMode = 0x40000228 );
 /* Data (.data, .bss, .rodata) */
 PROVIDE( rom_spiflash_legacy_funcs = 0x3fcdfff4 );
 PROVIDE( rom_spiflash_legacy_data = 0x3fcdfff0 );
+PROVIDE( g_rom_flashchip = 0x3fcdf730 );
 PROVIDE( g_flash_guard_ops = 0x3fcdfff8 );
 
 

[incubator-nuttx] 02/02: esp32c3-devkit: Add board support for SPIFlash

Posted by ag...@apache.org.
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

commit 76c02afc4802e5f74ab6d7dfe15bbdca93e56981
Author: Alan Carvalho de Assis <al...@espressif.com>
AuthorDate: Sat Mar 20 13:29:55 2021 -0300

    esp32c3-devkit: Add board support for SPIFlash
    
    Co-authored-by: Abdelatif Guettouche <ab...@espressif.com>
---
 arch/risc-v/src/esp32c3/esp32c3_partition.c        |   2 +-
 boards/risc-v/esp32c3/esp32c3-devkit/Kconfig       |  23 ++
 .../esp32c3-devkit/configs/spiflash/defconfig      |  54 +++++
 boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile  |   4 +
 .../esp32c3/esp32c3-devkit/src/esp32c3-devkit.h    |  11 +
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |  19 ++
 .../esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c  | 262 +++++++++++++++++++++
 7 files changed, 374 insertions(+), 1 deletion(-)

diff --git a/arch/risc-v/src/esp32c3/esp32c3_partition.c b/arch/risc-v/src/esp32c3/esp32c3_partition.c
index c0ae63d..1c9cc78 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_partition.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_partition.c
@@ -544,7 +544,7 @@ static int esp32c3_part_ioctl(FAR struct mtd_dev_s *dev, int cmd,
 
 /****************************************************************************
  * Name: esp32c3_partition_init
- * 
+ *
  *   Initialize ESP32-C3 partition. Read partition information, and use
  *   these data for creating MTD.
  *
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig b/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
index 978934d..6259575 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
@@ -10,4 +10,27 @@ config ESP32C3_DEVKIT_RUN_IRAM
 	default n
 	---help---
 
+choice
+  prompt "SPIFLASH File System"
+  default ESP32C3_SPIFLASH_SMARTFS
+  depends on ESP32C3_SPIFLASH
+
+  config ESP32C3_SPIFLASH_SMARTFS
+	bool "SmartFS"
+	depends on FS_SMARTFS
+
+  config ESP32C3_SPIFLASH_NXFFS
+	bool "NXFFS"
+	depends on FS_NXFFS
+
+  config ESP32C3_SPIFLASH_SPIFFS
+	bool "SPIFFS"
+	depends on FS_SPIFFS
+
+  config ESP32C3_SPIFLASH_LITTLEFS
+	bool "LittleFS"
+	depends on FS_LITTLEFS
+
+endchoice
+
 endif # ARCH_BOARD_ESP32C3_DEVKIT
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/spiflash/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/spiflash/defconfig
new file mode 100644
index 0000000..5386f3e
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/spiflash/defconfig
@@ -0,0 +1,54 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c3-devkit"
+CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32c3"
+CONFIG_ARCH_CHIP_ESP32C3=y
+CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
+CONFIG_ARCH_INTERRUPTSTACK=1536
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILTIN=y
+CONFIG_DEV_ZERO=y
+CONFIG_ESP32C3_MTD_OFFSET=0x110000
+CONFIG_ESP32C3_MTD_SIZE=0xf0000
+CONFIG_ESP32C3_SPIFLASH=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_SMARTFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_MAX_TASKS=8
+CONFIG_MTD_SMART=y
+CONFIG_NAME_MAX=48
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_LOSMART=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_SMARTFS_MAXNAMLEN=48
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_FLASH_ERASEALL=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_FSTEST=y
+CONFIG_TESTING_FSTEST_MOUNTPT="/mnt"
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile b/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile
index bf0565d..b216b51 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile
@@ -34,6 +34,10 @@ endif
 
 endif
 
+ifeq ($(CONFIG_ESP32C3_SPIFLASH),y)
+CSRCS += esp32c3_spiflash.c
+endif
+
 ifeq ($(CONFIG_DEV_GPIO),y)
 CSRCS += esp32c3_gpio.c
 endif
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h
index 3e8cc79..08c3ba3 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h
@@ -135,5 +135,16 @@ int board_tim_init(void);
 int board_bmp180_initialize(int devno, int busno);
 #endif
 
+/****************************************************************************
+ * Name: esp32c3_spiflash_init
+ *
+ * Description:
+ *   Initialize the SPIFLASH and register the MTD device.
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPIFLASH
+int esp32c3_spiflash_init(void);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_SRC_ESP32C3_DEVKIT_H */
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
index 401eae0..e0b11e9 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
@@ -88,6 +88,25 @@ int esp32c3_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32C3_SPIFLASH
+  ret = esp32c3_spiflash_init();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n");
+      return ret;
+    }
+#endif
+
+#ifdef CONFIG_ESP32C3_PARTITION
+  ret = esp32c3_partition_init();
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize partition error=%d\n",
+             ret);
+      return ret;
+    }
+#endif
+
 #ifdef CONFIG_DEV_GPIO
   ret = esp32c3_gpio_init();
   if (ret < 0)
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c
new file mode 100644
index 0000000..ea7f1df
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c
@@ -0,0 +1,262 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_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>
+
+#include <sys/mount.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/fs/nxffs.h>
+
+#include "esp32c3_spiflash.h"
+#include "esp32c3-devkit.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_init
+ *
+ * Description:
+ *   Initialize the SPIFLASH and register the MTD device.
+ ****************************************************************************/
+
+int esp32c3_spiflash_init(void)
+{
+  FAR struct mtd_dev_s *mtd;
+  int ret = ERROR;
+
+  mtd = esp32c3_spiflash_alloc_mtdpart();
+
+#if defined (CONFIG_ESP32C3_SPIFLASH_SMARTFS)
+  ret = smart_initialize(0, 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(0, mtd, NULL);
+      if (ret < 0)
+        {
+          ferr("ERROR: smart_initialize failed: %d\n", ret);
+          return ret;
+        }
+    }
+
+#elif defined (CONFIG_ESP32C3_SPIFLASH_NXFFS)
+  ret = nxffs_initialize(mtd);
+  if (ret < 0)
+    {
+      ferr("ERROR: NXFFS init failed: %d\n", ret);
+      return ret;
+    }
+
+#else
+  ret = register_mtddriver("/dev/esp32c3flash", mtd, 0755, NULL);
+  if (ret < 0)
+    {
+      ferr("ERROR: Register MTD failed: %d\n", ret);
+      return ret;
+    }
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_spiflash_encrypt_test
+ *
+ * Description:
+ *   Test ESP32-C3 SPI Flash driver read/write with encryption.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_ENCRYPTION_TEST
+
+void esp32c3_spiflash_encrypt_test(void)
+{
+  int i;
+  int ret;
+  uint8_t *wbuf;
+  uint8_t *rbuf;
+  struct mtd_geometry_s geo;
+  uint32_t erase_block;
+  uint32_t erase_nblocks;
+  uint32_t rw_block;
+  uint32_t rw_nblocks;
+  struct mtd_dev_s *mtd = esp32c3_spiflash_get_mtd();
+  struct mtd_dev_s *enc_mtd = esp32c3_spiflash_encrypt_get_mtd();
+  const uint32_t address = CONFIG_ESP32C3_SPIFLASH_TEST_ADDRESS;
+  const uint32_t size = 4096;
+
+  ret = MTD_IOCTL(enc_mtd, MTDIOC_GEOMETRY,
+                  (unsigned long)(uintptr_t)&geo);
+  if (ret < 0)
+    {
+      ferr("ERROR: Failed to get GEO errno =%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  wbuf = kmm_malloc(size);
+  if (!wbuf)
+    {
+      ferr("ERROR: Failed to alloc %d heap\n", size);
+      DEBUGASSERT(0);
+    }
+
+  rbuf = kmm_malloc(size);
+  if (!rbuf)
+    {
+      ferr("ERROR: Failed to alloc %d heap\n", size);
+      DEBUGASSERT(0);
+    }
+
+  for (i = 0; i < size; i++)
+    {
+      wbuf[i] = (uint8_t)random();
+    }
+
+  erase_block = address / geo.erasesize;
+  erase_nblocks = size / geo.erasesize;
+
+  rw_block = address / geo.blocksize;
+  rw_nblocks = size / geo.blocksize;
+
+  ret = MTD_ERASE(enc_mtd, erase_block, erase_nblocks);
+  if (ret != erase_nblocks)
+    {
+      ferr("ERROR: Failed to erase block errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  ret = MTD_BWRITE(enc_mtd, rw_block, rw_nblocks, wbuf);
+  if (ret != rw_nblocks)
+    {
+      ferr("ERROR: Failed to encrypt write errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  memset(rbuf, 0, size);
+  ret = MTD_BREAD(enc_mtd, rw_block, rw_nblocks, rbuf);
+  if (ret != rw_nblocks)
+    {
+      ferr("ERROR: Failed to decrypt read errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  if (memcmp(wbuf, rbuf, size))
+    {
+      ferr("ASSERT: Encrypted and decrypted data is not same\n");
+      DEBUGASSERT(0);
+    }
+
+  memset(rbuf, 0, size);
+  ret = MTD_BREAD(mtd, rw_block, rw_nblocks, rbuf);
+  if (ret != rw_nblocks)
+    {
+      ferr("ERROR: Failed to read errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  if (!memcmp(wbuf, rbuf, size))
+    {
+      ferr("ASSERT: Encrypted and normal data is same\n");
+      DEBUGASSERT(0);
+    }
+
+  for (i = 0; i < size; i++)
+    {
+      wbuf[i] = (uint8_t)random();
+    }
+
+  ret = MTD_ERASE(enc_mtd, erase_block, erase_nblocks);
+  if (ret != erase_nblocks)
+    {
+      ferr("ERROR: Failed to erase errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  ret = MTD_BWRITE(mtd, rw_block, rw_nblocks, wbuf);
+  if (ret != rw_nblocks)
+    {
+      ferr("ERROR: Failed to write errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  memset(rbuf, 0, size);
+  ret = MTD_BREAD(enc_mtd, rw_block, rw_nblocks, rbuf);
+  if (ret != rw_nblocks)
+    {
+      ferr("ERROR: Failed to decrypt read errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  if (!memcmp(wbuf, rbuf, size))
+    {
+      ferr("ASSERT: Normal and decrypted data is same\n");
+      DEBUGASSERT(0);
+    }
+
+  memset(rbuf, 0, size);
+  ret = MTD_BREAD(mtd, rw_block, rw_nblocks, rbuf);
+  if (ret != rw_nblocks)
+    {
+      ferr("ERROR: Failed to read errno=%d\n", ret);
+      DEBUGASSERT(0);
+    }
+
+  if (memcmp(wbuf, rbuf, size))
+    {
+      ferr("ASSERT: Normal and normal data is not same\n");
+      DEBUGASSERT(0);
+    }
+
+  kmm_free(wbuf);
+  kmm_free(rbuf);
+
+  finfo("INFO: SPI Flash encryption test success\n");
+}
+
+#endif /* CONFIG_ESP32C3_SPIFLASH_ENCRYPTION_TEST */