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 2020/11/13 07:38:11 UTC

[incubator-nuttx] branch master updated: xtensa/esp32: Add SPI Flash hardware encryption I/O support

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

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


The following commit(s) were added to refs/heads/master by this push:
     new bfb5214  xtensa/esp32: Add SPI Flash hardware encryption I/O support
bfb5214 is described below

commit bfb5214ef8a4ac5e32323908c7865782c21912af
Author: Dong Heng <do...@espressif.com>
AuthorDate: Wed Oct 28 17:59:12 2020 +0800

    xtensa/esp32: Add SPI Flash hardware encryption I/O support
---
 arch/xtensa/src/esp32/esp32_spiflash.c             | 806 +++++++++++++++++----
 arch/xtensa/src/esp32/esp32_spiflash.h             |  16 +
 arch/xtensa/src/esp32/hardware/esp32_dport.h       |   8 +
 arch/xtensa/src/esp32/hardware/esp32_soc.h         |  14 +
 boards/xtensa/esp32/esp32-core/Kconfig             |  16 +
 .../xtensa/esp32/esp32-core/scripts/esp32_rom.ld   |   1 +
 boards/xtensa/esp32/esp32-core/src/esp32-core.h    |  20 +
 boards/xtensa/esp32/esp32-core/src/esp32_bringup.c |   5 +
 .../xtensa/esp32/esp32-core/src/esp32_spiflash.c   | 161 ++++
 9 files changed, 906 insertions(+), 141 deletions(-)

diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c b/arch/xtensa/src/esp32/esp32_spiflash.c
index eb077c7..95611b5 100644
--- a/arch/xtensa/src/esp32/esp32_spiflash.c
+++ b/arch/xtensa/src/esp32/esp32_spiflash.c
@@ -53,6 +53,14 @@
 #define SPI_FLASH_WRITE_BUF_SIZE    (32)
 #define SPI_FLASH_READ_BUF_SIZE     (64)
 
+#define SPI_FLASH_WRITE_WORDS       (SPI_FLASH_WRITE_BUF_SIZE / 4)
+#define SPI_FLASH_READ_WORDS        (SPI_FLASH_READ_BUF_SIZE / 4)
+
+#define SPI_FLASH_MAP_PAGE_SIZE     (0x10000)
+
+#define SPI_FLASH_ENCRYPT_UNIT_SIZE (32)
+#define SPI_FLASH_ENCRYPT_WORDS     (32 / 4)
+
 #define ESP32_MTD_OFFSET            CONFIG_ESP32_MTD_OFFSET
 #define ESP32_MTD_SIZE              CONFIG_ESP32_MTD_SIZE
 
@@ -63,10 +71,26 @@
 #define MTD_BLK2SIZE(_priv, _b)     (MTD_BLKSIZE(_priv) * (_b))
 #define MTD_SIZE2BLK(_priv, _s)     ((_s) / MTD_BLKSIZE(_priv))
 
+#define MMU_ADDR2PAGE(_addr)        ((_addr) / SPI_FLASH_MAP_PAGE_SIZE)
+#define MMU_ADDR2OFF(_addr)         ((_addr) % SPI_FLASH_MAP_PAGE_SIZE)
+#define MMU_BYTES2PAGES(_n)         (((_n) + SPI_FLASH_MAP_PAGE_SIZE - 1) \
+                                     / SPI_FLASH_MAP_PAGE_SIZE)
+
 #ifndef MIN
 #  define  MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif
 
+#define DPORT_INTERRUPT_DISABLE()
+#define DPORT_INTERRUPT_RESTORE()
+
+/* Flash MMU table for PRO CPU */
+
+#define PRO_MMU_TABLE ((volatile uint32_t *)DPORT_PRO_FLASH_MMU_TABLE_REG)
+
+/* Flash MMU table for APP CPU */
+
+#define APP_MMU_TABLE ((volatile uint32_t *)DPORT_APP_FLASH_MMU_TABLE_REG)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -99,6 +123,31 @@ struct esp32_spiflash_s
   uint8_t *dummies;
 };
 
+/* SPI Flash map request data */
+
+struct spiflash_map_req
+{
+  /* Request mapping SPI Flash base address */
+
+  uint32_t  src_addr;
+
+  /* Request mapping SPI Flash size */
+
+  uint32_t  size;
+
+  /* Mapped memory pointer */
+
+  void      *ptr;
+
+  /* Mapped started MMU page index */
+
+  uint32_t  start_page;
+
+  /* Mapped MMU page count */
+
+  uint32_t  page_cnt;
+};
+
 /****************************************************************************
  * ROM function prototypes
  ****************************************************************************/
@@ -121,7 +170,6 @@ static inline void spi_set_regbits(struct esp32_spiflash_s *priv,
                                    int offset, uint32_t bits);
 static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
                                      int offset, uint32_t bits);
-static inline void IRAM_ATTR spi_memcpy(void *d, const void *s, uint32_t n);
 
 /* Misc. helpers */
 
@@ -161,12 +209,24 @@ static int esp32_erase(FAR struct mtd_dev_s *dev, off_t startblock,
                        size_t nblocks);
 static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
                           size_t nbytes, FAR uint8_t *buffer);
+static ssize_t esp32_read_decrypt(FAR struct mtd_dev_s *dev,
+                                  off_t offset,
+                                  size_t nbytes,
+                                  FAR uint8_t *buffer);
 static ssize_t esp32_bread(FAR struct mtd_dev_s *dev, off_t startblock,
                            size_t nblocks, FAR uint8_t *buffer);
+static ssize_t esp32_bread_decrypt(FAR struct mtd_dev_s *dev,
+                                   off_t startblock,
+                                   size_t nblocks,
+                                   FAR uint8_t *buffer);
 static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
                            size_t nbytes, FAR const uint8_t *buffer);
 static ssize_t esp32_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
                             size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t esp32_bwrite_encrypt(FAR struct mtd_dev_s *dev,
+                                    off_t startblock,
+                                    size_t nblocks,
+                                    FAR const uint8_t *buffer);
 static int esp32_ioctl(FAR struct mtd_dev_s *dev, int cmd,
                        unsigned long arg);
 
@@ -198,7 +258,26 @@ static struct esp32_spiflash_s g_esp32_spiflash1 =
   .dummies = g_rom_spiflash_dummy_len_plus
 };
 
-/* Ensure exclusive access to the driver */
+static struct esp32_spiflash_s g_esp32_spiflash1_encrypt =
+{
+  .mtd =
+          {
+            .erase  = esp32_erase,
+            .bread  = esp32_bread_decrypt,
+            .bwrite = esp32_bwrite_encrypt,
+            .read   = esp32_read_decrypt,
+            .ioctl  = esp32_ioctl,
+#ifdef CONFIG_MTD_BYTE_WRITE
+            .write  = NULL,
+#endif
+            .name   = "esp32_mainflash_encrypt"
+          },
+  .config = &g_esp32_spiflash1_config,
+  .chip = &g_rom_flashchip,
+  .dummies = g_rom_spiflash_dummy_len_plus
+};
+
+/* Enxusre exculisve access to the driver */
 
 static sem_t g_exclsem = SEM_INITIALIZER(1);
 
@@ -298,35 +377,6 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
 }
 
 /****************************************************************************
- * Name: spi_memcpy
- *
- * Description:
- *   Copy data from one block of memory to another block of memory.
- *   The function must be linked in IRAM not in flash, so add this function
- *   instead of libc memcpy.
- *
- * Input Parameters:
- *   d - destination address
- *   s - source address
- *   n - data bytes
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-static inline void IRAM_ATTR spi_memcpy(void *d, const void *s, uint32_t n)
-{
-  uint8_t *dest = (uint8_t *)d;
-  const uint8_t *src = (const uint8_t *)s;
-
-  while (n--)
-    {
-      *dest++ = *src++;
-    }
-}
-
-/****************************************************************************
  * Name: esp32_spiflash_opstart
  *
  * Description:
@@ -719,7 +769,7 @@ static int esp32_write_status(FAR struct esp32_spiflash_s *priv,
  *
  ****************************************************************************/
 
-static int esp32_enable_write(FAR struct esp32_spiflash_s *priv)
+static int IRAM_ATTR esp32_enable_write(FAR struct esp32_spiflash_s *priv)
 {
   uint32_t flags;
   uint32_t regval;
@@ -772,6 +822,8 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
   int me;
   uint32_t flags;
 
+  esp32_set_write_opt(priv);
+
   if (esp32_wait_idle(priv) != OK)
     {
       return -EIO;
@@ -807,50 +859,110 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
 }
 
 /****************************************************************************
- * Name: esp32_writedata
+ * Name: esp32_writeonce
  *
  * Description:
- *   Write data to SPI Flash at designated address.
+ *   Write max 32 byte data to SPI Flash at designated address.
+ *
+ *   ESP32 can write max 32 byte once transmission by hardware.
  *
  * Input Parameters:
  *   spi    - ESP32 SPI Flash chip data
  *   addr   - target address
  *   buffer - data buffer pointer
- *   size   - data number
+ *   size   - data number by bytes
  *
  * Returned Value:
  *   0 if success or a negative value if fail.
  *
  ****************************************************************************/
 
-static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
-                           const uint8_t *buffer, uint32_t size)
+static int IRAM_ATTR esp32_writeonce(FAR struct esp32_spiflash_s *priv,
+                                     uint32_t addr,
+                                     const uint32_t *buffer,
+                                     uint32_t size)
 {
   uint32_t regval;
   uint32_t i;
-  uint32_t bytes;
-  uint32_t tmp;
-  uint32_t res;
-  const uint8_t  *tmpbuff = buffer;
-  int ret = OK;
-  int me;
-  uint32_t flags;
+
+  if (size > SPI_FLASH_WRITE_BUF_SIZE)
+    {
+      return -EINVAL;
+    }
 
   if (esp32_wait_idle(priv) != OK)
     {
       return -EIO;
     }
 
-  while (size > 0)
+  if (esp32_enable_write(priv) != OK)
     {
-      flags = esp32_spiflash_opstart(priv, &me);
+      return -EIO;
+    }
 
-      if (esp32_enable_write(priv) != OK)
-        {
-          esp32_spiflash_opdone(priv, flags, me);
-          return -EIO;
-        }
+  regval = addr & 0xffffff;
+  regval |= size << ESP_ROM_SPIFLASH_BYTES_LEN;
+  spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+
+  for (i = 0; i < (size / 4); i++)
+    {
+      spi_set_reg(priv, SPI_W0_OFFSET + i * 4, buffer[i]);
+    }
+
+  if (size & 0x3)
+    {
+      memcpy(&regval, &buffer[i], size & 0x3);
+      spi_set_reg(priv, SPI_W0_OFFSET + i * 4, regval);
+    }
+
+  spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+  spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_PP);
+  while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+    {
+      ;
+    }
+
+  if (esp32_wait_idle(priv) != OK)
+    {
+      return -EIO;
+    }
+
+  return OK;
+}
 
+/****************************************************************************
+ * Name: esp32_writedata
+ *
+ * Description:
+ *   Write data to SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv,
+                                     uint32_t addr,
+                                     const uint8_t *buffer,
+                                     uint32_t size)
+{
+  int ret;
+  int me;
+  uint32_t flags;
+  uint32_t off = 0;
+  uint32_t bytes;
+  uint32_t tmp_buf[SPI_FLASH_WRITE_WORDS];
+
+  esp32_set_write_opt(priv);
+
+  while (size > 0)
+    {
       bytes = MTD_BLKSIZE(priv) - addr % MTD_BLKSIZE(priv) ;
       if (!bytes)
         {
@@ -862,38 +974,108 @@ static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
           bytes = MIN(bytes, SPI_FLASH_WRITE_BUF_SIZE);
         }
 
-      regval = addr & 0xffffff;
-      regval |= bytes << ESP_ROM_SPIFLASH_BYTES_LEN;
-      spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+      memcpy(tmp_buf, &buffer[off], bytes);
 
-      for (i = 0; i < bytes; i += 4)
-        {
-          res = MIN(4, bytes - i);
+      flags = esp32_spiflash_opstart(priv, &me);
+      ret = esp32_writeonce(priv, addr, tmp_buf, bytes);
+      esp32_spiflash_opdone(priv, flags, me);
 
-          spi_memcpy(&tmp, tmpbuff, res);
-          spi_set_reg(priv, SPI_W0_OFFSET + i, tmp);
-          tmpbuff += res;
+      if (ret)
+        {
+          return ret;
         }
 
-      spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
-      spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_PP);
-      while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+      addr += bytes;
+      size -= bytes;
+      off += bytes;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_writedata
+ *
+ * Description:
+ *   Write plaintext data to SPI Flash at designated address by SPI Flash
+ *   hardware encryption, and written data in SPI Flash is ciphertext.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_writedata_encrypted(
+  FAR struct esp32_spiflash_s *priv,
+  uint32_t addr,
+  const uint8_t *buffer,
+  uint32_t size)
+{
+  int i;
+  int blocks;
+  int ret = OK;
+  int me;
+  uint32_t flags;
+  uint32_t tmp_buf[SPI_FLASH_ENCRYPT_WORDS];
+
+  if (addr % SPI_FLASH_ENCRYPT_UNIT_SIZE)
+    {
+      ferr("ERROR: address=0x%x is not %d-byte align\n",
+           addr, SPI_FLASH_ENCRYPT_UNIT_SIZE);
+      return -EINVAL;
+    }
+
+  if (size % SPI_FLASH_ENCRYPT_UNIT_SIZE)
+    {
+      ferr("ERROR: size=%u is not %d-byte align\n",
+           size, SPI_FLASH_ENCRYPT_UNIT_SIZE);
+      return -EINVAL;
+    }
+
+  blocks = size / SPI_FLASH_ENCRYPT_UNIT_SIZE;
+
+  for (i = 0; i < blocks; i++)
+    {
+      memcpy(tmp_buf, buffer, SPI_FLASH_ENCRYPT_UNIT_SIZE);
+
+      flags = esp32_spiflash_opstart(priv, &me);
+      esp_rom_spiflash_write_encrypted_enable();
+
+      ret = esp_rom_spiflash_prepare_encrypted_data(addr, tmp_buf);
+      if (ret)
         {
-          ;
+          ferr("ERROR: Failed to prepare encrypted data\n");
+          goto exit;
         }
 
-      if (esp32_wait_idle(priv) != OK)
+      ret = esp32_writeonce(priv, addr, tmp_buf,
+                            SPI_FLASH_ENCRYPT_UNIT_SIZE);
+      if (ret)
         {
-          esp32_spiflash_opdone(priv, flags, me);
-          return -EIO;
+          ferr("ERROR: Failed to write encrypted data @ 0x%x\n", addr);
+          goto exit;
         }
 
-      addr += bytes;
-      size -= bytes;
-
+      esp_rom_spiflash_write_encrypted_disable();
       esp32_spiflash_opdone(priv, flags, me);
+
+      addr += SPI_FLASH_ENCRYPT_UNIT_SIZE;
+      buffer += SPI_FLASH_ENCRYPT_UNIT_SIZE;
+      size -= SPI_FLASH_ENCRYPT_UNIT_SIZE;
     }
 
+  return 0;
+
+exit:
+  esp_rom_spiflash_write_encrypted_disable();
+  esp32_spiflash_opdone(priv, flags, me);
+
   return ret;
 }
 
@@ -901,69 +1083,271 @@ static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
  * Name: esp32_readdata
  *
  * Description:
- *   Read data from SPI Flash at designated address.
+ *   Read max 64 byte data data from SPI Flash at designated address.
+ *
+ *   ESP32 can read max 64 byte once transmission by hardware.
  *
  * Input Parameters:
  *   spi    - ESP32 SPI Flash chip data
  *   addr   - target address
  *   buffer - data buffer pointer
- *   size   - data number
+ *   size   - data number by bytes
  *
  * Returned Value:
  *   OK if success or a negative value if fail.
  *
  ****************************************************************************/
 
-static int esp32_readdata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
-                          uint8_t *buffer, uint32_t size)
+static int IRAM_ATTR esp32_readonce(FAR struct esp32_spiflash_s *priv,
+                                    uint32_t addr,
+                                    uint32_t *buffer,
+                                    uint32_t size)
 {
   uint32_t regval;
   uint32_t i;
-  uint32_t bytes;
-  uint32_t tmp;
-  uint32_t res;
-  uint8_t  *tmpbuff = buffer;
-  int me;
-  uint32_t flags;
+
+  if (size > SPI_FLASH_READ_BUF_SIZE)
+    {
+      return -EINVAL;
+    }
 
   if (esp32_wait_idle(priv) != OK)
     {
       return -EIO;
     }
 
-  while (size > 0)
+  regval = ((size << 3) - 1) << SPI_USR_MISO_DBITLEN_S;
+  spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, regval);
+
+  regval = addr << 8;
+  spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+
+  spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+  spi_set_reg(priv, SPI_CMD_OFFSET, SPI_USR);
+  while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
     {
-      flags = esp32_spiflash_opstart(priv, &me);
+      ;
+    }
+
+  for (i = 0; i < (size / 4); i++)
+    {
+      buffer[i] = spi_get_reg(priv, SPI_W0_OFFSET + i * 4);
+    }
+
+  if (size & 0x3)
+    {
+      regval = spi_get_reg(priv, SPI_W0_OFFSET + i * 4);
+      memcpy(&buffer[i], &regval, size & 0x3);
+    }
+
+  return OK;
+}
 
+/****************************************************************************
+ * Name: esp32_readdata
+ *
+ * Description:
+ *   Read data from SPI Flash at designated address.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   OK if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_readdata(FAR struct esp32_spiflash_s *priv,
+                                    uint32_t addr,
+                                    uint8_t *buffer,
+                                    uint32_t size)
+{
+  int ret;
+  int me;
+  uint32_t flags;
+  uint32_t off = 0;
+  uint32_t bytes;
+  uint32_t tmp_buf[SPI_FLASH_READ_WORDS];
+
+  while (size > 0)
+    {
       bytes = MIN(size, SPI_FLASH_READ_BUF_SIZE);
-      regval = ((bytes << 3) - 1) << SPI_USR_MISO_DBITLEN_S;
-      spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, regval);
 
-      regval = addr << 8;
-      spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+      flags = esp32_spiflash_opstart(priv, &me);
+      ret = esp32_readonce(priv, addr, tmp_buf, bytes);
+      esp32_spiflash_opdone(priv, flags, me);
 
-      spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
-      spi_set_reg(priv, SPI_CMD_OFFSET, SPI_USR);
-      while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+      if (ret)
         {
-          ;
+          return ret;
         }
 
-      for (i = 0; i < bytes; i += 4)
+      memcpy(&buffer[off], tmp_buf, bytes);
+
+      addr += bytes;
+      size -= bytes;
+      off += bytes;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_mmap
+ *
+ * Description:
+ *   Mapped SPI Flash address to ESP32's address bus, so that software
+ *   can read SPI Flash data by reading data from memory access.
+ *
+ *   If SPI Flash hardware encryption is enable, the read from mapped
+ *   address is decrypted.
+ *
+ * Input Parameters:
+ *   spi - ESP32 SPI Flash chip data
+ *   req - SPI Flash mapping requesting parameters
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv,
+                                struct spiflash_map_req *req)
+{
+  int ret;
+  int i;
+  int me;
+  int start_page;
+  int flash_page;
+  int page_cnt;
+  uint32_t flags;
+
+  flags = esp32_spiflash_opstart(priv, &me);
+
+  for (start_page = DROM0_PAGES_START;
+       start_page < DROM0_PAGES_END;
+       ++start_page)
+    {
+      if (PRO_MMU_TABLE[start_page] == INVALID_MMU_VAL
+#ifdef CONFIG_SMP
+          && APP_MMU_TABLE[start_page] == INVALID_MMU_VAL
+#endif
+          )
         {
-          res = MIN(4, bytes - i);
+          break;
+        }
+    }
 
-          tmp = spi_get_reg(priv, SPI_W0_OFFSET + i);
-          spi_memcpy(tmpbuff, &tmp, res);
-          tmpbuff += res;
+  flash_page = MMU_ADDR2PAGE(req->src_addr);
+  page_cnt = MMU_BYTES2PAGES(req->size);
+
+  if (start_page + page_cnt < DROM0_PAGES_END)
+    {
+      for (i = 0; i < page_cnt; i++)
+        {
+          PRO_MMU_TABLE[start_page + i] = flash_page + i;
+#ifdef CONFIG_SMP
+          APP_MMU_TABLE[start_page + i] = flash_page + i;
+#endif
         }
 
-      addr += bytes;
-      size -= bytes;
+      req->start_page = start_page;
+      req->page_cnt = page_cnt;
+      req->ptr = (void *)(VADDR0_START_ADDR +
+                          start_page * SPI_FLASH_MAP_PAGE_SIZE +
+                          MMU_ADDR2OFF(req->src_addr));
 
-      esp32_spiflash_opdone(priv, flags, me);
+      ret = 0;
+    }
+  else
+    {
+      ret = -ENOBUFS;
+    }
+
+  esp32_spiflash_opdone(priv, flags, me);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_ummap
+ *
+ * Description:
+ *   Unmap SPI Flash address in ESP32's address bus, and free resource.
+ *
+ * Input Parameters:
+ *   spi - ESP32 SPI Flash chip data
+ *   req - SPI Flash mapping requesting paramters
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32_ummap(FAR struct esp32_spiflash_s *priv,
+                                  const struct spiflash_map_req *req)
+{
+  uint32_t flags;
+  int me;
+  int i;
+
+  flags = esp32_spiflash_opstart(priv, &me);
+
+  for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
+    {
+      PRO_MMU_TABLE[i] = INVALID_MMU_VAL;
+#ifdef CONFIG_SMP
+      APP_MMU_TABLE[i] = INVALID_MMU_VAL;
+#endif
     }
 
+  esp32_spiflash_opdone(priv, flags, me);
+}
+
+/****************************************************************************
+ * Name: esp32_readdata_encrypted
+ *
+ * Description:
+ *   Read decrypted data from SPI Flash at designated address when
+ *   enable SPI Flash hardware encryption.
+ *
+ * Input Parameters:
+ *   spi    - ESP32 SPI Flash chip data
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   OK if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_readdata_encrypted(
+  FAR struct esp32_spiflash_s *priv,
+  uint32_t addr,
+  uint8_t *buffer,
+  uint32_t size)
+{
+  int ret;
+  struct spiflash_map_req req =
+    {
+      .src_addr = addr,
+      .size = size
+    };
+
+  ret = esp32_mmap(priv, &req);
+  if (ret)
+    {
+      return ret;
+    }
+
+  memcpy(buffer, req.ptr, size);
+
+  esp32_ummap(priv, &req);
+
   return OK;
 }
 
@@ -1006,7 +1390,6 @@ static int esp32_erase(FAR struct mtd_dev_s *dev, off_t startblock,
       return ret;
     }
 
-  esp32_set_write_opt(priv);
   ret = esp32_erasesector(priv, addr, size);
 
   nxsem_post(&g_exclsem);
@@ -1044,24 +1427,12 @@ static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
                           size_t nbytes, FAR uint8_t *buffer)
 {
   int ret;
-  uint8_t *tmpbuff = buffer;
   FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
 
 #ifdef CONFIG_ESP32_SPIFLASH_DEBUG
   finfo("esp32_read(%p, 0x%x, %d, %p)\n", dev, offset, nbytes, buffer);
 #endif
 
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
-  if (esp32_ptr_extram(buffer))
-    {
-      tmpbuff = xtensa_imm_malloc(nbytes);
-      if (tmpbuff == NULL)
-        {
-          return (ssize_t)-ENOMEM;
-        }
-    }
-#endif
-
   /* Acquire the semaphore. */
 
   ret = nxsem_wait(&g_exclsem);
@@ -1071,7 +1442,7 @@ static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
     }
 
   esp32_set_read_opt(priv);
-  ret = esp32_readdata(priv, offset, tmpbuff, nbytes);
+  ret = esp32_readdata(priv, offset, buffer, nbytes);
 
   nxsem_post(&g_exclsem);
 
@@ -1085,13 +1456,6 @@ static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
 #endif
 
 error_with_buffer:
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
-  if (esp32_ptr_extram(buffer))
-    {
-      memcpy(buffer, tmpbuff, (ret == OK) ? nbytes : 0);
-      xtensa_imm_free(tmpbuff);
-    }
-#endif
 
   return (ssize_t)ret;
 }
@@ -1140,6 +1504,109 @@ static ssize_t esp32_bread(FAR struct mtd_dev_s *dev, off_t startblock,
 }
 
 /****************************************************************************
+ * Name: esp32_read_decrypt
+ *
+ * Description:
+ *   Read encrypted data and decrypt automatically from SPI Flash
+ *   at designated address.
+ *
+ * Input Parameters:
+ *   dev    - ESP32 MTD device data
+ *   offset - target address offset
+ *   nbytes - data number
+ *   buffer - data buffer pointer
+ *
+ * Returned Value:
+ *   Read data bytes if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32_read_decrypt(FAR struct mtd_dev_s *dev,
+                                  off_t offset,
+                                  size_t nbytes,
+                                  FAR uint8_t *buffer)
+{
+  int ret;
+  uint8_t *tmpbuff = buffer;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_read_decrypt(%p, 0x%x, %d, %p)\n",
+        dev, offset, nbytes, buffer);
+#endif
+
+  /* Acquire the semaphore. */
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      goto error_with_buffer;
+    }
+
+  ret = esp32_readdata_encrypted(priv, offset, tmpbuff, nbytes);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nbytes;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_read_decrypt()=%d\n", ret);
+#endif
+
+error_with_buffer:
+
+  return (ssize_t)ret;
+}
+
+/****************************************************************************
+ * Name: esp32_bread_decrypt
+ *
+ * Description:
+ *   Read encrypted data and decrypt automatically from designated blocks.
+ *
+ * Input Parameters:
+ *   dev        - ESP32 MTD device data
+ *   startblock - start block number, it is not equal to SPI Flash's block
+ *   nblocks    - blocks number
+ *   buffer     - data buffer pointer
+ *
+ * Returned Value:
+ *   Read block number if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32_bread_decrypt(FAR struct mtd_dev_s *dev,
+                                   off_t startblock,
+                                   size_t nblocks,
+                                   FAR uint8_t *buffer)
+{
+  int ret;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+  uint32_t addr = MTD_BLK2SIZE(priv, startblock);
+  uint32_t size = MTD_BLK2SIZE(priv, nblocks);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bread_decrypt(%p, 0x%x, %d, %p)\n",
+        dev, startblock, nblocks, buffer);
+#endif
+
+  ret = esp32_read_decrypt(dev, addr, size, buffer);
+  if (ret == size)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bread_decrypt()=%d\n", ret);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
  * Name: esp32_write
  *
  * Description:
@@ -1160,7 +1627,6 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
                            size_t nbytes, FAR const uint8_t *buffer)
 {
   int ret;
-  uint8_t *tmpbuff = (uint8_t *)buffer;
   FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
 
   ASSERT(buffer);
@@ -1170,19 +1636,6 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
       return -EINVAL;
     }
 
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
-  if (esp32_ptr_extram(buffer))
-    {
-      tmpbuff = xtensa_imm_malloc(nbytes);
-      if (tmpbuff == NULL)
-        {
-          return (ssize_t)-ENOMEM;
-        }
-
-      memcpy(tmpbuff, buffer, nbytes);
-    }
-#endif
-
 #ifdef CONFIG_ESP32_SPIFLASH_DEBUG
   finfo("esp32_write(%p, 0x%x, %d, %p)\n", dev, offset, nbytes, buffer);
 #endif
@@ -1195,8 +1648,7 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
       goto error_with_buffer;
     }
 
-  esp32_set_write_opt(priv);
-  ret = esp32_writedata(priv, offset, tmpbuff, nbytes);
+  ret = esp32_writedata(priv, offset, buffer, nbytes);
 
   nxsem_post(&g_exclsem);
 
@@ -1210,12 +1662,6 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
 #endif
 
 error_with_buffer:
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
-  if (esp32_ptr_extram(buffer))
-    {
-      xtensa_imm_free(tmpbuff);
-    }
-#endif
 
   return (ssize_t)ret;
 }
@@ -1265,6 +1711,63 @@ static ssize_t esp32_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
 }
 
 /****************************************************************************
+ * Name: esp32_bwrite_encrypt
+ *
+ * Description:
+ *   Write data to designated blocks by SPI Flash hardware encryption.
+ *
+ * Input Parameters:
+ *   dev        - ESP32 MTD device data
+ *   startblock - start MTD block number,
+ *                it is not equal to SPI Flash's block
+ *   nblocks    - blocks number
+ *   buffer     - data buffer pointer
+ *
+ * Returned Value:
+ *   Writen block number if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32_bwrite_encrypt(FAR struct mtd_dev_s *dev,
+                                    off_t startblock,
+                                    size_t nblocks,
+                                    FAR const uint8_t *buffer)
+{
+  ssize_t ret;
+  FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+  uint32_t addr = MTD_BLK2SIZE(priv, startblock);
+  uint32_t size = MTD_BLK2SIZE(priv, nblocks);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bwrite_encrypt(%p, 0x%x, %d, %p)\n",
+        dev, startblock, nblocks, buffer);
+#endif
+
+  ret = nxsem_wait(&g_exclsem);
+  if (ret < 0)
+    {
+      goto error_with_buffer;
+    }
+
+  ret = esp32_writedata_encrypted(priv, addr, buffer, size);
+
+  nxsem_post(&g_exclsem);
+
+  if (ret == OK)
+    {
+      ret = nblocks;
+    }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+  finfo("esp32_bwrite_encrypt()=%d\n", ret);
+#endif
+
+error_with_buffer:
+
+  return ret;
+}
+
+/****************************************************************************
  * Name: esp32_ioctl
  *
  * Description:
@@ -1398,4 +1901,25 @@ FAR struct mtd_dev_s *esp32_spiflash_get_mtd(void)
   return &priv->mtd;
 }
 
+/****************************************************************************
+ * Name: esp32_spiflash_get_mtd
+ *
+ * Description:
+ *   Get ESP32 SPI Flash encryption raw MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32 SPI Flash encryption raw MTD data pointer.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void)
+{
+  struct esp32_spiflash_s *priv = &g_esp32_spiflash1_encrypt;
+
+  return &priv->mtd;
+}
+
 #endif /* CONFIG_ESP32_SPIFLASH */
diff --git a/arch/xtensa/src/esp32/esp32_spiflash.h b/arch/xtensa/src/esp32/esp32_spiflash.h
index 1b3702d..3c9099a 100644
--- a/arch/xtensa/src/esp32/esp32_spiflash.h
+++ b/arch/xtensa/src/esp32/esp32_spiflash.h
@@ -78,6 +78,22 @@ FAR struct mtd_dev_s *esp32_spiflash_alloc_mtdpart(void);
 
 FAR struct mtd_dev_s *esp32_spiflash_get_mtd(void);
 
+/****************************************************************************
+ * Name: esp32_spiflash_get_mtd
+ *
+ * Description:
+ *   Get ESP32 SPI Flash encryption raw MTD.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   ESP32 SPI Flash encryption raw MTD data pointer.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h
index f81b6de..d5a74be 100644
--- a/arch/xtensa/src/esp32/hardware/esp32_dport.h
+++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h
@@ -4387,4 +4387,12 @@
 #define DPORT_DATE_S  0
 #define DPORT_DPORT_DATE_VERSION 0x1605190
 
+/* SPI Flash MMU table regitser base address for PRO CPU */
+
+#define DPORT_PRO_FLASH_MMU_TABLE_REG       (DR_REG_DPORT_BASE + 0x10000)
+
+/* SPI Flash MMU table regitser base address for APP CPU */
+
+#define DPORT_APP_FLASH_MMU_TABLE_REG       (DR_REG_DPORT_BASE + 0x12000)
+
 #endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_DPORT_H */
diff --git a/arch/xtensa/src/esp32/hardware/esp32_soc.h b/arch/xtensa/src/esp32/hardware/esp32_soc.h
index 2109315..214108e 100644
--- a/arch/xtensa/src/esp32/hardware/esp32_soc.h
+++ b/arch/xtensa/src/esp32/hardware/esp32_soc.h
@@ -275,6 +275,11 @@
 #define SOC_EXTRAM_DATA_LOW     0x3f800000
 #define SOC_EXTRAM_DATA_HIGH    0x3fc00000
 
+/* Virtual address 0 */
+
+#define VADDR0_START_ADDR       SOC_DROM_LOW
+#define VADDR0_END_ADDR         (SOC_DROM_HIGH - 1)
+
 /* Interrupt hardware source table
  * This table is decided by hardware, don't touch this.
  */
@@ -776,6 +781,15 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add,
 #define FE2_TX_INF_FORCE_PD_V       1
 #define FE2_TX_INF_FORCE_PD_S       9
 
+/* RO data page in MMU index */
+
+#define DROM0_PAGES_START           0
+#define DROM0_PAGES_END             64
+
+/* MMU invaild value */
+
+#define INVALID_MMU_VAL             0x100
+
 /****************************************************************************
  * Inline Functions
  ****************************************************************************/
diff --git a/boards/xtensa/esp32/esp32-core/Kconfig b/boards/xtensa/esp32/esp32-core/Kconfig
index e6a5e29..9a42a5d 100644
--- a/boards/xtensa/esp32/esp32-core/Kconfig
+++ b/boards/xtensa/esp32/esp32-core/Kconfig
@@ -63,6 +63,22 @@ choice
         depends on FS_LITTLEFS
 endchoice
 
+config ESP32_SPIFLASH_ENCRYPTION_TEST
+	bool "SPI Flash encryption test"
+	default n
+	depends on ESP32_SPIFLASH
+	select DEBUG_ASSERTIONS
+	help
+		Enable SPI Flash encryption test. This option will also select
+		DEBUG_ASSERTIONS to enable kernel assert macro.
+
+config ESP32_SPIFLASH_TEST_ADDRESS
+	hex "SPI Flash test address"
+	default 0x180000
+	depends on ESP32_SPIFLASH_ENCRYPTION_TEST
+	help
+		SPI Flash encryption test read/write address.
+
 if PM
 
 config PM_ALARM_SEC
diff --git a/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld b/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
index 870c405..306f4ef 100644
--- a/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
+++ b/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
@@ -1851,6 +1851,7 @@ PROVIDE ( g_rom_flashchip = 0x3ffae270 );
 PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 );
 PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 );
 PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 );
+PROVIDE ( esp_rom_spiflash_write_encrypted_disable = 0x40062e60 );
 PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );
 
 PROVIDE ( esp_rom_printf   = ets_printf );
diff --git a/boards/xtensa/esp32/esp32-core/src/esp32-core.h b/boards/xtensa/esp32/esp32-core/src/esp32-core.h
index 0bce83f..3627b23 100644
--- a/boards/xtensa/esp32/esp32-core/src/esp32-core.h
+++ b/boards/xtensa/esp32/esp32-core/src/esp32-core.h
@@ -118,5 +118,25 @@ int esp32_timer_driver_init(void);
 int esp32_wtd_driver_init(void);
 #endif
 
+/****************************************************************************
+ * Name: esp32_spiflash_encrypt_test
+ *
+ * Description:
+ *   Test ESP32 SPI Flash driver read/write with encryption.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST
+
+void esp32_spiflash_encrypt_test(void);
+
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_XTENSA_ESP32_ESP32_CORE_SRC_ESP32_CORE_H */
diff --git a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c
index c337c06..867ac4a 100644
--- a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c
@@ -162,6 +162,11 @@ int esp32_bringup(void)
 #endif
 
 #ifdef CONFIG_ESP32_SPIFLASH
+
+#ifdef CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST
+  esp32_spiflash_encrypt_test();
+#endif 
+
   ret = esp32_spiflash_init();
   if (ret)
     {
diff --git a/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c b/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c
index 3ac6ca6..7407117 100644
--- a/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c
+++ b/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c
@@ -99,3 +99,164 @@ int esp32_spiflash_init(void)
   return ret;
 }
 
+/****************************************************************************
+ * Name: esp32_spiflash_encrypt_test
+ *
+ * Description:
+ *   Test ESP32 SPI Flash driver read/write with encryption.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST
+
+void esp32_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 = esp32_spiflash_get_mtd();
+  struct mtd_dev_s *enc_mtd = esp32_spiflash_encrypt_get_mtd();
+  const uint32_t address = CONFIG_ESP32_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: ESP32 SPI Flash encryption test successfully\n");
+}
+
+#endif /* CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST */