You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/12/18 19:44:04 UTC

[incubator-nuttx] branch master updated: arch/xtensa/src/esp32/esp32_spiflash.c: Invalidate the cache and writeback PSRAM data if the flash address used has a cache mapping.

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

acassis 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 81a9eb1  arch/xtensa/src/esp32/esp32_spiflash.c: Invalidate the cache and writeback PSRAM data if the flash address used has a cache mapping.
81a9eb1 is described below

commit 81a9eb190d912e96e264613919a747eae08c17d3
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Thu Dec 10 09:15:24 2020 +0000

    arch/xtensa/src/esp32/esp32_spiflash.c: Invalidate the cache and
    writeback PSRAM data if the flash address used has a cache mapping.
    
    Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
 arch/xtensa/src/esp32/esp32_spiflash.c     | 309 +++++++++++++++++++++++------
 arch/xtensa/src/esp32/hardware/esp32_soc.h |   3 +
 2 files changed, 252 insertions(+), 60 deletions(-)

diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c b/arch/xtensa/src/esp32/esp32_spiflash.c
index 95611b5..cde3e6a 100644
--- a/arch/xtensa/src/esp32/esp32_spiflash.c
+++ b/arch/xtensa/src/esp32/esp32_spiflash.c
@@ -41,10 +41,17 @@
 #include "xtensa.h"
 #include "xtensa_attr.h"
 
+#include "rom/esp32_spiflash.h"
+
 #include "hardware/esp32_soc.h"
 #include "hardware/esp32_spi.h"
 #include "hardware/esp32_dport.h"
-#include "rom/esp32_spiflash.h"
+
+#ifdef CONFIG_ESP32_SPIRAM
+#include "esp32_spiram.h"
+#endif
+
+#include "esp32_spiflash.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -56,7 +63,7 @@
 #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_MMU_PAGE_SIZE     (0x10000)
 
 #define SPI_FLASH_ENCRYPT_UNIT_SIZE (32)
 #define SPI_FLASH_ENCRYPT_WORDS     (32 / 4)
@@ -71,10 +78,13 @@
 #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)
+#define MMU_ADDR2PAGE(_addr)        ((_addr) / SPI_FLASH_MMU_PAGE_SIZE)
+#define MMU_ADDR2OFF(_addr)         ((_addr) % SPI_FLASH_MMU_PAGE_SIZE)
+#define MMU_BYTES2PAGES(_n)         (((_n) + SPI_FLASH_MMU_PAGE_SIZE - 1) \
+                                     / SPI_FLASH_MMU_PAGE_SIZE)
+#define MMU_ALIGNUP_SIZE(_s)        (((_s) + SPI_FLASH_MMU_PAGE_SIZE - 1) \
+                                     & ~(SPI_FLASH_MMU_PAGE_SIZE - 1))
+#define MMU_ALIGNDOWN_SIZE(_s)      ((_s) & ~(SPI_FLASH_MMU_PAGE_SIZE - 1))
 
 #ifndef MIN
 #  define  MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -91,6 +101,9 @@
 
 #define APP_MMU_TABLE ((volatile uint32_t *)DPORT_APP_FLASH_MMU_TABLE_REG)
 
+#define PRO_IRAM0_FIRST_PAGE  ((SOC_IRAM_LOW - SOC_DRAM_HIGH) /\
+                               (SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START))
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -148,13 +161,18 @@ struct spiflash_map_req
   uint32_t  page_cnt;
 };
 
+struct spiflash_cachestate_s
+{
+  int cpu;
+  irqstate_t flags;
+  uint32_t val[2];
+};
+
 /****************************************************************************
  * ROM function prototypes
  ****************************************************************************/
 
 void Cache_Flush(int cpu);
-void Cache_Read_Enable(int cpu);
-void Cache_Read_Disable(int cpu);
 
 /****************************************************************************
  * Private Functions Prototypes
@@ -173,10 +191,13 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
 
 /* Misc. helpers */
 
-static inline irqstate_t IRAM_ATTR esp32_spiflash_opstart(
-  FAR struct esp32_spiflash_s *priv, int *cpu);
-static inline void IRAM_ATTR esp32_spiflash_opdone(
-  FAR struct esp32_spiflash_s *priv, irqstate_t flags, int cpu);
+static inline void IRAM_ATTR
+  esp32_spiflash_opstart(FAR struct spiflash_cachestate_s *state);
+static inline void IRAM_ATTR
+  esp32_spiflash_opdone(FAR const struct spiflash_cachestate_s *state);
+
+static bool IRAM_ATTR spiflash_pagecached(uint32_t phypage);
+static void IRAM_ATTR spiflash_flushmapped(size_t start, size_t size);
 
 /* Flash helpers */
 
@@ -377,6 +398,85 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
 }
 
 /****************************************************************************
+ * Name: spiflash_disable_cache
+ ****************************************************************************/
+
+static void IRAM_ATTR spi_disable_cache(int cpu, uint32_t *state)
+{
+  const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */
+  uint32_t regval;
+  uint32_t ret = 0;
+
+  if (cpu == 0)
+    {
+      ret |= (getreg32(DPORT_PRO_CACHE_CTRL1_REG) & cache_mask);
+      while (((getreg32(DPORT_PRO_DCACHE_DBUG0_REG) >>
+                      DPORT_PRO_CACHE_STATE_S) & DPORT_PRO_CACHE_STATE) != 1)
+        {
+          ;
+        }
+
+      regval  = getreg32(DPORT_PRO_CACHE_CTRL_REG);
+      regval &= ~DPORT_PRO_CACHE_ENABLE_M;
+      putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
+    }
+#ifdef CONFIG_SMP
+  else
+    {
+      ret |= (getreg32(DPORT_APP_CACHE_CTRL1_REG) & cache_mask);
+      while (((getreg32(DPORT_APP_DCACHE_DBUG0_REG) >>
+                      DPORT_APP_CACHE_STATE_S) & DPORT_APP_CACHE_STATE) != 1)
+        {
+          ;
+        }
+
+      regval  = getreg32(DPORT_APP_CACHE_CTRL_REG);
+      regval &= ~DPORT_APP_CACHE_ENABLE_M;
+      putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
+    }
+
+#endif
+  *state = ret;
+}
+
+/****************************************************************************
+ * Name: spiflash_enable_cache
+ ****************************************************************************/
+
+static void IRAM_ATTR spi_enable_cache(int cpu, uint32_t state)
+{
+  const uint32_t cache_mask = 0x3f;  /* Caches' bits in CTRL1_REG */
+  uint32_t regval;
+  uint32_t ctrlreg;
+  uint32_t ctrl1reg;
+  uint32_t ctrlmask;
+
+  if (cpu == 0)
+    {
+      ctrlreg = DPORT_PRO_CACHE_CTRL_REG;
+      ctrl1reg = DPORT_PRO_CACHE_CTRL1_REG;
+      ctrlmask = DPORT_PRO_CACHE_ENABLE_M;
+    }
+#ifdef CONFIG_SMP
+  else
+    {
+      ctrlreg = DPORT_APP_CACHE_CTRL_REG;
+      ctrl1reg = DPORT_APP_CACHE_CTRL1_REG;
+      ctrlmask = DPORT_APP_CACHE_ENABLE_M;
+    }
+#endif
+
+  regval  = getreg32(ctrlreg);
+  regval |= ctrlmask;
+  putreg32(regval, ctrlreg);
+
+  regval  = getreg32(ctrl1reg);
+  regval &= ~cache_mask;
+  regval |= state;
+  putreg32(regval, ctrl1reg);
+}
+
+/****************************************************************************
  * Name: esp32_spiflash_opstart
  *
  * Description:
@@ -384,32 +484,29 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
  *
  ****************************************************************************/
 
-static inline irqstate_t IRAM_ATTR esp32_spiflash_opstart(
-  FAR struct esp32_spiflash_s *priv, int *cpu)
+static inline void IRAM_ATTR
+  esp32_spiflash_opstart(FAR struct spiflash_cachestate_s *state)
 {
-  irqstate_t flags;
 #ifdef CONFIG_SMP
   int other;
 #endif
 
-  flags = enter_critical_section();
+  state->flags = enter_critical_section();
 
-  *cpu = up_cpu_index();
+  state->cpu = up_cpu_index();
 #ifdef CONFIG_SMP
-  other = *cpu ? 0 : 1;
+  other = state->cpu ? 0 : 1;
 #endif
 
-  DEBUGASSERT(*cpu == 0 || *cpu == 1);
+  DEBUGASSERT(state->cpu == 0 || state->cpu == 1);
 #ifdef CONFIG_SMP
   DEBUGASSERT(other == 0 || other == 1);
 #endif
 
-  Cache_Read_Disable(*cpu);
+  spi_disable_cache(state->cpu, &state->val[state->cpu]);
 #ifdef CONFIG_SMP
-  Cache_Read_Disable(other);
+  spi_disable_cache(state->cpu, &state->val[other]);
 #endif
-
-  return flags;
 }
 
 /****************************************************************************
@@ -420,30 +517,108 @@ static inline irqstate_t IRAM_ATTR esp32_spiflash_opstart(
  *
  ****************************************************************************/
 
-static inline void IRAM_ATTR esp32_spiflash_opdone(
-  FAR struct esp32_spiflash_s *priv, irqstate_t flags, int cpu)
+static inline void IRAM_ATTR
+  esp32_spiflash_opdone(FAR const struct spiflash_cachestate_s *state)
 {
 #ifdef CONFIG_SMP
   int other;
 #endif
 
 #ifdef CONFIG_SMP
-  other = cpu ? 0 : 1;
+  other = state->cpu ? 0 : 1;
 #endif
 
-  DEBUGASSERT(cpu == 0 || cpu == 1);
+  DEBUGASSERT(state->cpu == 0 || state->cpu == 1);
 #ifdef CONFIG_SMP
   DEBUGASSERT(other == 0 || other == 1);
 #endif
 
-  Cache_Flush(cpu);
-  Cache_Read_Enable(cpu);
+  spi_enable_cache(state->cpu, state->val[state->cpu]);
 #ifdef CONFIG_SMP
-  Cache_Flush(other);
-  Cache_Read_Enable(other);
+  spi_enable_cache(other, state->val[other]);
 #endif
 
-  leave_critical_section(flags);
+  leave_critical_section(state->flags);
+}
+
+/****************************************************************************
+ * Name: spiflash_pagecached
+ *
+ * Description:
+ *   Check if the given page is cached.
+ *
+ ****************************************************************************/
+
+static bool IRAM_ATTR spiflash_pagecached(uint32_t phypage)
+{
+  int start[2];
+  int end[2];
+  int i;
+  int j;
+
+  /* Data ROM start and end pages */
+
+  start[0] = DROM0_PAGES_START;
+  end[0]   = DROM0_PAGES_END;
+
+  /* Instruction RAM start and end pages */
+
+  start[1] = PRO_IRAM0_FIRST_PAGE;
+  end[1]   = IROM0_PAGES_END;
+
+  for (i = 0; i < 2; i++)
+    {
+      for (j = start[i]; j < end[i]; j++)
+        {
+          if (PRO_MMU_TABLE[j] == phypage)
+            {
+              return true;
+            }
+        }
+    }
+
+  return false;
+}
+
+/****************************************************************************
+ * Name: spiflash_flushmapped
+ *
+ * Description:
+ *   Writeback PSRAM data and invalidate the cache if the address is mapped.
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR spiflash_flushmapped(size_t start, size_t size)
+{
+  uint32_t page_start;
+  uint32_t addr;
+  uint32_t page;
+
+  page_start = MMU_ALIGNDOWN_SIZE(size);
+  size += (start - page_start);
+  size = MMU_ALIGNUP_SIZE(size);
+
+  for (addr = page_start; addr < page_start + size;
+       addr += SPI_FLASH_MMU_PAGE_SIZE)
+    {
+      page = addr / SPI_FLASH_MMU_PAGE_SIZE;
+
+      if (page >= 256)
+        {
+          return;
+        }
+
+      if (spiflash_pagecached(page))
+        {
+#ifdef CONFIG_ESP32_SPIRAM
+          esp_spiram_writeback_cache();
+#endif
+          Cache_Flush(0);
+#ifndef CONFIG_SMP
+          Cache_Flush(1);
+        }
+#endif
+    }
 }
 
 /****************************************************************************
@@ -819,8 +994,7 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
                                        uint32_t addr, uint32_t size)
 {
   uint32_t offset;
-  int me;
-  uint32_t flags;
+  struct spiflash_cachestate_s state;
 
   esp32_set_write_opt(priv);
 
@@ -831,11 +1005,11 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
 
   for (offset = 0; offset < size; offset += MTD_ERASESIZE(priv))
     {
-      flags = esp32_spiflash_opstart(priv, &me);
+      esp32_spiflash_opstart(&state);
 
       if (esp32_enable_write(priv) != OK)
         {
-          esp32_spiflash_opdone(priv, flags, me);
+          esp32_spiflash_opdone(&state);
           return -EIO;
         }
 
@@ -848,13 +1022,17 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
 
       if (esp32_wait_idle(priv) != OK)
         {
-          esp32_spiflash_opdone(priv, flags, me);
+          esp32_spiflash_opdone(&state);
           return -EIO;
         }
 
-      esp32_spiflash_opdone(priv, flags, me);
+      esp32_spiflash_opdone(&state);
     }
 
+  esp32_spiflash_opstart(&state);
+  spiflash_flushmapped(addr, size);
+  esp32_spiflash_opdone(&state);
+
   return 0;
 }
 
@@ -953,11 +1131,10 @@ static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv,
                                      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];
+  struct spiflash_cachestate_s state;
 
   esp32_set_write_opt(priv);
 
@@ -976,9 +1153,9 @@ static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv,
 
       memcpy(tmp_buf, &buffer[off], bytes);
 
-      flags = esp32_spiflash_opstart(priv, &me);
+      esp32_spiflash_opstart(&state);
       ret = esp32_writeonce(priv, addr, tmp_buf, bytes);
-      esp32_spiflash_opdone(priv, flags, me);
+      esp32_spiflash_opdone(&state);
 
       if (ret)
         {
@@ -990,6 +1167,10 @@ static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv,
       off += bytes;
     }
 
+  esp32_spiflash_opstart(&state);
+  spiflash_flushmapped(addr, size);
+  esp32_spiflash_opdone(&state);
+
   return OK;
 }
 
@@ -1020,9 +1201,8 @@ static int IRAM_ATTR esp32_writedata_encrypted(
   int i;
   int blocks;
   int ret = OK;
-  int me;
-  uint32_t flags;
   uint32_t tmp_buf[SPI_FLASH_ENCRYPT_WORDS];
+  struct spiflash_cachestate_s state;
 
   if (addr % SPI_FLASH_ENCRYPT_UNIT_SIZE)
     {
@@ -1044,7 +1224,7 @@ static int IRAM_ATTR esp32_writedata_encrypted(
     {
       memcpy(tmp_buf, buffer, SPI_FLASH_ENCRYPT_UNIT_SIZE);
 
-      flags = esp32_spiflash_opstart(priv, &me);
+      esp32_spiflash_opstart(&state);
       esp_rom_spiflash_write_encrypted_enable();
 
       ret = esp_rom_spiflash_prepare_encrypted_data(addr, tmp_buf);
@@ -1063,18 +1243,22 @@ static int IRAM_ATTR esp32_writedata_encrypted(
         }
 
       esp_rom_spiflash_write_encrypted_disable();
-      esp32_spiflash_opdone(priv, flags, me);
+      esp32_spiflash_opdone(&state);
 
       addr += SPI_FLASH_ENCRYPT_UNIT_SIZE;
       buffer += SPI_FLASH_ENCRYPT_UNIT_SIZE;
       size -= SPI_FLASH_ENCRYPT_UNIT_SIZE;
     }
 
+  esp32_spiflash_opstart(&state);
+  spiflash_flushmapped(addr, size);
+  esp32_spiflash_opdone(&state);
+
   return 0;
 
 exit:
   esp_rom_spiflash_write_encrypted_disable();
-  esp32_spiflash_opdone(priv, flags, me);
+  esp32_spiflash_opdone(&state);
 
   return ret;
 }
@@ -1166,19 +1350,18 @@ static int IRAM_ATTR esp32_readdata(FAR struct esp32_spiflash_s *priv,
                                     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];
+  struct spiflash_cachestate_s state;
 
   while (size > 0)
     {
       bytes = MIN(size, SPI_FLASH_READ_BUF_SIZE);
 
-      flags = esp32_spiflash_opstart(priv, &me);
+      esp32_spiflash_opstart(&state);
       ret = esp32_readonce(priv, addr, tmp_buf, bytes);
-      esp32_spiflash_opdone(priv, flags, me);
+      esp32_spiflash_opdone(&state);
 
       if (ret)
         {
@@ -1219,13 +1402,12 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv,
 {
   int ret;
   int i;
-  int me;
   int start_page;
   int flash_page;
   int page_cnt;
-  uint32_t flags;
+  struct spiflash_cachestate_s state;
 
-  flags = esp32_spiflash_opstart(priv, &me);
+  esp32_spiflash_opstart(&state);
 
   for (start_page = DROM0_PAGES_START;
        start_page < DROM0_PAGES_END;
@@ -1257,7 +1439,7 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv,
       req->start_page = start_page;
       req->page_cnt = page_cnt;
       req->ptr = (void *)(VADDR0_START_ADDR +
-                          start_page * SPI_FLASH_MAP_PAGE_SIZE +
+                          start_page * SPI_FLASH_MMU_PAGE_SIZE +
                           MMU_ADDR2OFF(req->src_addr));
 
       ret = 0;
@@ -1267,7 +1449,11 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv,
       ret = -ENOBUFS;
     }
 
-  esp32_spiflash_opdone(priv, flags, me);
+  Cache_Flush(0);
+#ifdef CONFIG_SMP
+  Cache_Flush(1);
+#endif
+  esp32_spiflash_opdone(&state);
 
   return ret;
 }
@@ -1290,11 +1476,10 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv,
 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;
+  struct spiflash_cachestate_s state;
 
-  flags = esp32_spiflash_opstart(priv, &me);
+  esp32_spiflash_opstart(&state);
 
   for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
     {
@@ -1304,7 +1489,11 @@ static void IRAM_ATTR esp32_ummap(FAR struct esp32_spiflash_s *priv,
 #endif
     }
 
-  esp32_spiflash_opdone(priv, flags, me);
+  Cache_Flush(0);
+#ifdef CONFIG_SMP
+  Cache_Flush(1);
+#endif
+  esp32_spiflash_opdone(&state);
 }
 
 /****************************************************************************
diff --git a/arch/xtensa/src/esp32/hardware/esp32_soc.h b/arch/xtensa/src/esp32/hardware/esp32_soc.h
index f0bb7e6..e361c72 100644
--- a/arch/xtensa/src/esp32/hardware/esp32_soc.h
+++ b/arch/xtensa/src/esp32/hardware/esp32_soc.h
@@ -785,6 +785,9 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add,
 #define DROM0_PAGES_START           0
 #define DROM0_PAGES_END             64
 
+#define IROM0_PAGES_START           64
+#define IROM0_PAGES_END             256
+
 /* MMU invaild value */
 
 #define INVALID_MMU_VAL             0x100