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/nuttx.git

commit 5865d2a8ff5bda14497ac65571c2f9d0bccb4964
Author: Eren Terzioglu <eren.terzio...@espressif.com>
AuthorDate: Mon Jan 13 10:52:17 2025 +0100

    esp32[s2|s3]: Enhance SPIRAM/PSRAM support
    Add esp_spiram_writeback_range function to flush some areas of spiram cache
    
    Signed-off-by: Eren Terzioglu <eren.terzio...@espressif.com>
---
 arch/xtensa/src/esp32/esp32_spiram.c               | 118 +++++++++++++++++++++
 arch/xtensa/src/esp32/esp32_spiram.h               |  18 ++++
 arch/xtensa/src/esp32s2/esp32s2_spiram.c           |  22 ++++
 arch/xtensa/src/esp32s2/esp32s2_spiram.h           |  18 ++++
 arch/xtensa/src/esp32s3/esp32s3_spiram.c           |  22 ++++
 arch/xtensa/src/esp32s3/esp32s3_spiram.h           |  18 ++++
 .../esp32s2/common/scripts/esp32s2_aliases.ld      |  12 +++
 .../esp32s3/common/scripts/esp32s3_rom_aliases.ld  |   2 +
 8 files changed, 230 insertions(+)

diff --git a/arch/xtensa/src/esp32/esp32_spiram.c 
b/arch/xtensa/src/esp32/esp32_spiram.c
index 0b94d27490..d9ff290df4 100644
--- a/arch/xtensa/src/esp32/esp32_spiram.c
+++ b/arch/xtensa/src/esp32/esp32_spiram.c
@@ -34,6 +34,7 @@
 #include <sys/param.h>
 #include <nuttx/spinlock.h>
 #include <nuttx/init.h>
+#include <nuttx/nuttx.h>
 
 #include "esp32_spiram.h"
 #include "esp32_spicache.h"
@@ -533,6 +534,123 @@ void IRAM_ATTR esp_spiram_writeback_cache(void)
 #endif
 }
 
+/****************************************************************************
+ * Name: esp_spiram_writeback_range
+ *
+ * Description:
+ *   Writeback the Cache items (also clean the dirty bit) in the region from
+ *   DCache. If the region is not in DCache addr room, nothing will be done.
+ *
+ * Input Parameters:
+ *   addr - writeback region start address
+ *   size - writeback region size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_spiram_writeback_range(uint32_t addr, uint32_t size)
+{
+  int x;
+  uint32_t regval;
+  uint32_t start_len;
+  uint32_t end_len;
+  uint32_t start = addr;
+  uint32_t end = addr + size;
+  uint32_t dcache_line_size = 32;
+  volatile int i = 0;
+  volatile uint8_t *psram = (volatile uint8_t *)SOC_EXTRAM_DATA_LOW;
+  int cache_was_disabled = 0;
+
+  if (!spiram_inited)
+    {
+      return;
+    }
+
+  /* We need cache enabled for this to work. Re-enable it if needed; make
+   * sure we disable it again on exit as well.
+   */
+
+  regval = getreg32(DPORT_PRO_CACHE_CTRL_REG);
+
+  if ((regval & DPORT_PRO_CACHE_ENABLE) == 0)
+    {
+      cache_was_disabled |= (1 << 0);
+      regval  = getreg32(DPORT_PRO_CACHE_CTRL_REG);
+      regval |= (1 << DPORT_PRO_CACHE_ENABLE_S);
+      putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
+    }
+
+#ifdef CONFIG_SMP
+  regval = getreg32(DPORT_APP_CACHE_CTRL_REG);
+
+  if ((regval & DPORT_APP_CACHE_ENABLE) == 0)
+    {
+      cache_was_disabled |= (1 << 1);
+      regval  = getreg32(DPORT_APP_CACHE_CTRL_REG);
+      regval |= 1 << DPORT_APP_CACHE_ENABLE_S;
+      putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
+    }
+#endif
+
+  /* the start address is unaligned */
+
+  if (start & (dcache_line_size -1))
+    {
+      addr = ALIGN_UP_MASK(start, dcache_line_size);
+      start_len = addr - start;
+      size = (size < start_len) ? 0 : (size - start_len);
+      i += psram[start_len];
+    }
+
+  /* the end address is unaligned */
+
+  if ((end & (dcache_line_size -1)) && (size != 0))
+    {
+      end = ALIGN_DOWN_MASK(end, dcache_line_size);
+      end_len = addr + size - end;
+      size = (size - end_len);
+      i += psram[end_len];
+    }
+
+  if (size != 0)
+    {
+      for (x = addr; x < addr + size; x += 32)
+        {
+          i += psram[x];
+        }
+    }
+
+  if (cache_was_disabled & (1 << 0))
+    {
+      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 &= ~(1 << DPORT_PRO_CACHE_ENABLE_S);
+      putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
+    }
+
+#ifdef CONFIG_SMP
+  if (cache_was_disabled & (1 << 1))
+    {
+      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 &= ~(1 << DPORT_APP_CACHE_ENABLE_S);
+      putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
+    }
+#endif
+}
+
 /* If SPI RAM(PSRAM) has been initialized
  *
  * Return:
diff --git a/arch/xtensa/src/esp32/esp32_spiram.h 
b/arch/xtensa/src/esp32/esp32_spiram.h
index 4d2b2b863b..065c538998 100644
--- a/arch/xtensa/src/esp32/esp32_spiram.h
+++ b/arch/xtensa/src/esp32/esp32_spiram.h
@@ -145,6 +145,24 @@ size_t esp_spiram_get_size(void);
 
 void esp_spiram_writeback_cache(void);
 
+/****************************************************************************
+ * Name: esp_spiram_writeback_range
+ *
+ * Description:
+ *   Writeback the Cache items (also clean the dirty bit) in the region from
+ *   DCache. If the region is not in DCache addr room, nothing will be done.
+ *
+ * Input Parameters:
+ *   addr - writeback region start address
+ *   size - writeback region size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_spiram_writeback_range(uint32_t addr, uint32_t size);
+
 /* Description: Reserve a pool of internal memory for specific DMA/internal
  *              allocations.
  *
diff --git a/arch/xtensa/src/esp32s2/esp32s2_spiram.c 
b/arch/xtensa/src/esp32s2/esp32s2_spiram.c
index 8a8c09357b..e3941bcbac 100644
--- a/arch/xtensa/src/esp32s2/esp32s2_spiram.c
+++ b/arch/xtensa/src/esp32s2/esp32s2_spiram.c
@@ -40,6 +40,7 @@
 #include "hardware/esp32s2_soc.h"
 #include "hardware/esp32s2_cache_memory.h"
 #include "hardware/esp32s2_iomux.h"
+#include "hal/cache_hal.h"
 
 #include "soc/extmem_reg.h"
 #include "soc/ext_mem_defs.h"
@@ -361,6 +362,27 @@ void IRAM_ATTR esp_spiram_writeback_cache(void)
   cache_writeback_all();
 }
 
+/****************************************************************************
+ * Name: esp_spiram_writeback_range
+ *
+ * Description:
+ *   Writeback the Cache items (also clean the dirty bit) in the region from
+ *   DCache. If the region is not in DCache addr room, nothing will be done.
+ *
+ * Input Parameters:
+ *   addr - writeback region start address
+ *   size - writeback region size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_spiram_writeback_range(uint32_t addr, uint32_t size)
+{
+  cache_hal_writeback_addr(addr, size);
+}
+
 /* If SPI RAM(PSRAM) has been initialized
  *
  * Return true SPI RAM has been initialized successfully
diff --git a/arch/xtensa/src/esp32s2/esp32s2_spiram.h 
b/arch/xtensa/src/esp32s2/esp32s2_spiram.h
index fe9e077db1..7d61683595 100644
--- a/arch/xtensa/src/esp32s2/esp32s2_spiram.h
+++ b/arch/xtensa/src/esp32s2/esp32s2_spiram.h
@@ -87,6 +87,24 @@ size_t esp_spiram_get_size(void);
 
 void esp_spiram_writeback_cache(void);
 
+/****************************************************************************
+ * Name: esp_spiram_writeback_range
+ *
+ * Description:
+ *   Writeback the Cache items (also clean the dirty bit) in the region from
+ *   DCache. If the region is not in DCache addr room, nothing will be done.
+ *
+ * Input Parameters:
+ *   addr - writeback region start address
+ *   size - writeback region size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_spiram_writeback_range(uint32_t addr, uint32_t size);
+
 /* If SPI RAM(PSRAM) has been initialized
  *
  * Return
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiram.c 
b/arch/xtensa/src/esp32s3/esp32s3_spiram.c
index aba0956b00..079ba4ce0c 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spiram.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_spiram.c
@@ -42,6 +42,7 @@
 #include "hardware/esp32s3_soc.h"
 #include "hardware/esp32s3_cache_memory.h"
 #include "hardware/esp32s3_iomux.h"
+#include "hal/cache_hal.h"
 
 #include "soc/extmem_reg.h"
 
@@ -697,6 +698,27 @@ void IRAM_ATTR esp_spiram_writeback_cache(void)
   cache_writeback_all();
 }
 
+/****************************************************************************
+ * Name: esp_spiram_writeback_range
+ *
+ * Description:
+ *   Writeback the Cache items (also clean the dirty bit) in the region from
+ *   DCache. If the region is not in DCache addr room, nothing will be done.
+ *
+ * Input Parameters:
+ *   addr - writeback region start address
+ *   size - writeback region size
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_spiram_writeback_range(uint32_t addr, uint32_t size)
+{
+  cache_hal_writeback_addr(addr, size);
+}
+
 /* If SPI RAM(PSRAM) has been initialized
  *
  * Return true SPI RAM has been initialized successfully
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiram.h 
b/arch/xtensa/src/esp32s3/esp32s3_spiram.h
index 043398788d..788e2e8701 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spiram.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_spiram.h
@@ -105,6 +105,24 @@ size_t esp_spiram_get_size(void);
 
 void esp_spiram_writeback_cache(void);
 
+/****************************************************************************
+ * Name: esp_spiram_writeback_range
+ *
+ * Description:
+ *   Writeback the Cache items (also clean the dirty bit) in the region from
+ *   DCache. If the region is not in DCache addr room, nothing will be done.
+ *
+ * Input Parameters:
+ *   addr - writeback region start address
+ *   size - writeback region size
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp_spiram_writeback_range(uint32_t addr, uint32_t size);
+
 /* If SPI RAM(PSRAM) has been initialized
  *
  *  Return
diff --git a/boards/xtensa/esp32s2/common/scripts/esp32s2_aliases.ld 
b/boards/xtensa/esp32s2/common/scripts/esp32s2_aliases.ld
index 4a52404933..0208cb53fa 100644
--- a/boards/xtensa/esp32s2/common/scripts/esp32s2_aliases.ld
+++ b/boards/xtensa/esp32s2/common/scripts/esp32s2_aliases.ld
@@ -36,3 +36,15 @@ PROVIDE( rom_i2c_readreg = rom_i2c_readReg );
 PROVIDE( rom_i2c_readreg_mask = rom_i2c_readReg_Mask );
 PROVIDE( rom_i2c_writereg = rom_i2c_writeReg );
 PROVIDE( rom_i2c_writereg_mask = rom_i2c_writeReg_Mask );
+PROVIDE( cache_dbus_mmu_set = Cache_Dbus_MMU_Set );
+PROVIDE( cache_ibus_mmu_set = Cache_Ibus_MMU_Set );
+PROVIDE( cache_invalidate_addr = Cache_Invalidate_Addr );
+PROVIDE( cache_invalidate_dcache_all = Cache_Invalidate_DCache_All );
+PROVIDE( cache_occupy_addr = Cache_Occupy_Addr );
+PROVIDE( cache_set_idrom_mmu_info = Cache_Set_IDROM_MMU_Info );
+PROVIDE( cache_set_idrom_mmu_size = Cache_Set_IDROM_MMU_Size );
+PROVIDE( cache_writeback_all = Cache_WriteBack_All );
+PROVIDE( cache_writeback_items = Cache_WriteBack_Items );
+PROVIDE( cache_writeback_addr = Cache_WriteBack_Addr );
+PROVIDE( cache_set_dcache_mode = Cache_Set_DCache_Mode );
+PROVIDE( cache_enable_dcache = Cache_Enable_DCache );
diff --git a/boards/xtensa/esp32s3/common/scripts/esp32s3_rom_aliases.ld 
b/boards/xtensa/esp32s3/common/scripts/esp32s3_rom_aliases.ld
index 27d70ec783..245e941f9f 100644
--- a/boards/xtensa/esp32s3/common/scripts/esp32s3_rom_aliases.ld
+++ b/boards/xtensa/esp32s3/common/scripts/esp32s3_rom_aliases.ld
@@ -37,3 +37,5 @@ PROVIDE( cache_set_idrom_mmu_size = Cache_Set_IDROM_MMU_Size 
);
 PROVIDE( cache_suspend_dcache = Cache_Suspend_DCache );
 PROVIDE( cache_suspend_icache = Cache_Suspend_ICache );
 PROVIDE( cache_writeback_all = Cache_WriteBack_All );
+PROVIDE( cache_writeback_items = Cache_WriteBack_Items );
+PROVIDE( cache_writeback_addr = Cache_WriteBack_Addr );

Reply via email to