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

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


The following commit(s) were added to refs/heads/master by this push:
     new 38ba0abc491 arch/tricore: support cache function
38ba0abc491 is described below

commit 38ba0abc4919c83861177aa17aca9384ad4f88ab
Author: makejian <[email protected]>
AuthorDate: Thu Dec 5 16:02:35 2024 +0800

    arch/tricore: support cache function
    
    Add cache operation support for TriCore architecture including:
    - Instruction cache (I-Cache) enable/disable functionality
    - Data cache (D-Cache) enable/disable functionality
    - Cache configuration and management interfaces
    - Performance events integration with cache operations
    
    Signed-off-by: makejian <[email protected]>
    Signed-off-by: zhangyuan29 <[email protected]>
---
 arch/tricore/Kconfig                         |   7 +
 arch/tricore/src/common/CMakeLists.txt       |   1 +
 arch/tricore/src/common/Make.defs            |   1 +
 arch/tricore/src/common/tricore_cache.c      | 523 +++++++++++++++++++++++++++
 arch/tricore/src/common/tricore_initialize.c |   9 +
 5 files changed, 541 insertions(+)

diff --git a/arch/tricore/Kconfig b/arch/tricore/Kconfig
index 25885ded5d9..a6bc0f06477 100644
--- a/arch/tricore/Kconfig
+++ b/arch/tricore/Kconfig
@@ -45,6 +45,13 @@ config ARCH_CHIP_TC397
        ---help---
                AURIX TC39x family: TC397
 
+config ARCH_DCACHE_ADDR
+       hex "AURIX Dcache base address"
+       default 0x7003C000
+       ---help---
+               AURIX Dcache base address, dcache line clear and invalidate need
+               use the address.
+
 if ARCH_TC3XX
 source "arch/tricore/src/tc3xx/Kconfig"
 endif
diff --git a/arch/tricore/src/common/CMakeLists.txt 
b/arch/tricore/src/common/CMakeLists.txt
index f3023df661b..23a705543b0 100644
--- a/arch/tricore/src/common/CMakeLists.txt
+++ b/arch/tricore/src/common/CMakeLists.txt
@@ -22,6 +22,7 @@
 
 set(SRCS
     tricore_allocateheap.c
+    tricore_cache.c
     tricore_checkstack.c
     tricore_createstack.c
     tricore_csa.c
diff --git a/arch/tricore/src/common/Make.defs 
b/arch/tricore/src/common/Make.defs
index 5c0f5c8f785..51e8a5d7fdb 100644
--- a/arch/tricore/src/common/Make.defs
+++ b/arch/tricore/src/common/Make.defs
@@ -23,6 +23,7 @@
 HEAD_CSRC += tricore_doirq.c
 
 CMN_CSRCS += tricore_allocateheap.c
+CMN_CSRCS += tricore_cache.c
 CMN_CSRCS += tricore_checkstack.c
 CMN_CSRCS += tricore_createstack.c
 CMN_CSRCS += tricore_csa.c
diff --git a/arch/tricore/src/common/tricore_cache.c 
b/arch/tricore/src/common/tricore_cache.c
new file mode 100644
index 00000000000..f713960d07f
--- /dev/null
+++ b/arch/tricore/src/common/tricore_cache.c
@@ -0,0 +1,523 @@
+/****************************************************************************
+ * arch/tricore/src/common/tricore_cache.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 "tricore_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define tc_invalidate_cache_byaddr(addr) \
+  __asm__ __volatile__("cachea.i [%0]0"::"a"(addr))
+#define tc_clear_cache_byaddr(addr) \
+  __asm__ __volatile__("cachea.w [%0]0"::"a"(addr))
+#define tc_flush_cache_byaddr(addr) \
+  __asm__ __volatile__("cachea.wi [%0]0"::"a"(addr))
+#define tc_invalidate_cache_byline(line) \
+  __asm__ __volatile__("cachei.i [%0]0"::"a"(line))
+#define tc_clear_cache_byline(line) \
+  __asm__ __volatile__("cachei.w [%0]0"::"a"(line))
+#define tc_flush_cache_byline(line) \
+  __asm__ __volatile__("cachei.wi [%0]0"::"a"(line))
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ICACHE
+/****************************************************************************
+ * Name: up_get_icache_linesize
+ *
+ * Description:
+ *   Get icache linesize
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Cache line size
+ *
+ ****************************************************************************/
+
+size_t up_get_icache_linesize(void)
+{
+  return IFXCPU_PCACHE_LINE_SIZE / 8;
+}
+
+/****************************************************************************
+ * Name: up_get_icache_size
+ *
+ * Description:
+ *   Get icache size
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Cache size
+ *
+ ****************************************************************************/
+
+size_t up_get_icache_size(void)
+{
+  Ifx_CPU_PCON2 pcon2;
+
+  pcon2.U = __mfcr(CPU_PCON2);
+  return pcon2.B.PCACHE_SZE * 1000;
+}
+
+/****************************************************************************
+ * Name: up_enable_icache
+ *
+ * Description:
+ *   Enable the I-Cache
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ * Caution:
+ *   The writable global variables aren't initialized yet.
+ *
+ ****************************************************************************/
+
+void up_enable_icache(void)
+{
+  Ifx_CPU_PCON0 pcon0;
+
+  pcon0.B.PCBYP = 0;
+  __mtcr(CPU_PCON0, pcon0.U);
+
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_disable_icache
+ *
+ * Description:
+ *   Disable the I-Cache
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_disable_icache(void)
+{
+  Ifx_CPU_PCON0 pcon0;
+
+  pcon0.U       = 0;
+  pcon0.B.PCBYP = 1;
+  __mtcr(CPU_PCON0, pcon0.U);
+
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_invalidate_icache
+ *
+ * Description:
+ *   Invalidate the instruction cache within the specified region.
+ *
+ * Input Parameters:
+ *   start - virtual start address of region
+ *   end   - virtual end address of region + 1
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_invalidate_icache(uintptr_t start, uintptr_t end)
+{
+  up_invalidate_icache_all();
+}
+
+/****************************************************************************
+ * Name: up_invalidate_icache_all
+ *
+ * Description:
+ *   Invalidate the entire contents of I cache.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_invalidate_icache_all(void)
+{
+  Ifx_CPU_PCON1 pcon1;
+
+  pcon1.U       = 0;
+  pcon1.B.PCINV = 1;
+  __mtcr(CPU_PCON1, pcon1.U);
+
+  __isync();
+}
+#endif
+
+#ifdef CONFIG_ARCH_DCACHE
+/****************************************************************************
+ * Name: up_get_dcache_linesize
+ *
+ * Description:
+ *   Get dcache linesize
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Cache line size
+ *
+ ****************************************************************************/
+
+size_t up_get_dcache_linesize(void)
+{
+  return IFXCPU_DCACHE_LINE_SIZE / 8;
+}
+
+/****************************************************************************
+ * Name: up_get_dcache_size
+ *
+ * Description:
+ *   Get dcache size
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Cache size
+ *
+ ****************************************************************************/
+
+size_t up_get_dcache_size(void)
+{
+  Ifx_CPU_DCON2 dcon2;
+
+  dcon2.U = __mfcr(CPU_DCON2);
+  return dcon2.B.DCACHE_SZE * 1000;
+}
+
+/****************************************************************************
+ * Name: up_enable_dcache
+ *
+ * Description:
+ *   Enable the D-Cache
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ * Caution:
+ *   The writable global variables aren't initialized yet.
+ *
+ ****************************************************************************/
+
+void up_enable_dcache(void)
+{
+  Ifx_CPU_DCON0 dcon0;
+
+  /* Check if the D-Cache is enabled */
+
+  dcon0.U = __mfcr(CPU_DCON0);
+  if (dcon0.B.DCBYP == 0)
+    {
+      return;
+    }
+
+  up_invalidate_dcache_all();
+
+  dcon0.U       = 0;
+  dcon0.B.DCBYP = 0;
+  __mtcr(CPU_DCON0, dcon0.U);
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_disable_dcache
+ *
+ * Description:
+ *   Disable the D-Cache
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_disable_dcache(void)
+{
+  Ifx_CPU_DCON0 dcon0;
+
+  dcon0.B.DCBYP = 1;
+  __mtcr(CPU_DCON0, dcon0.U);
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_invalidate_dcache
+ *
+ * Description:
+ *   Invalidate the data cache within the specified region; we will be
+ *   performing a DMA operation in this region and we want to purge old data
+ *   in the cache.
+ *
+ * Input Parameters:
+ *   start - virtual start address of region
+ *   end   - virtual end address of region + 1
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_invalidate_dcache(uintptr_t start, uintptr_t end)
+{
+  size_t line_size = up_get_dcache_linesize();
+
+  if ((start & (line_size - 1)) != 0)
+    {
+      start &= ~(line_size - 1);
+      tc_flush_cache_byaddr(start);
+      start += line_size;
+    }
+
+  while (start < end)
+    {
+      if (start + line_size <= end)
+        {
+          tc_invalidate_cache_byaddr(start);
+        }
+      else
+        {
+          tc_flush_cache_byaddr(start);
+        }
+
+      start += line_size;
+    }
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_invalidate_dcache_all
+ *
+ * Description:
+ *   Invalidate the entire contents of D cache.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_invalidate_dcache_all(void)
+{
+  Ifx_CPU_DCON1 dcon1;
+
+  dcon1.U       = 0;
+  dcon1.B.DCINV = 1;
+  __mtcr(CPU_DCON1, dcon1.U);
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_clean_dcache
+ *
+ * Description:
+ *   Clean the data cache within the specified region by flushing the
+ *   contents of the data cache to memory.
+ *
+ * Input Parameters:
+ *   start - virtual start address of region
+ *   end   - virtual end address of region + 1
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_clean_dcache(uintptr_t start, uintptr_t end)
+{
+  size_t line_size = up_get_dcache_linesize();
+
+  start &= ~(line_size - 1);
+
+  while (start < end)
+    {
+      tc_clear_cache_byaddr(start);
+      start += line_size;
+    }
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_clean_dcache_all
+ *
+ * Description:
+ *   Clean the entire data cache within the specified region by flushing the
+ *   contents of the data cache to memory.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_clean_dcache_all(void)
+{
+  uintptr_t cache_addr = CONFIG_ARCH_DCACHE_ADDR;
+  size_t line_size = up_get_dcache_linesize();
+  size_t line_cnt = up_get_dcache_size() / line_size;
+  size_t i;
+
+  for (i = 0; i < line_cnt; i++)
+    {
+      tc_clear_cache_byline(cache_addr);
+      cache_addr += line_size;
+    }
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_flush_dcache
+ *
+ * Description:
+ *   Flush the data cache within the specified region by cleaning and
+ *   invalidating the D cache.
+ *
+ * Input Parameters:
+ *   start - virtual start address of region
+ *   end   - virtual end address of region + 1
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_flush_dcache(uintptr_t start, uintptr_t end)
+{
+  size_t line_size = up_get_dcache_linesize();
+
+  start &= ~(line_size - 1);
+
+  while (start < end)
+    {
+      tc_flush_cache_byaddr(start);
+      start += line_size;
+    }
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_flush_dcache_all
+ *
+ * Description:
+ *   Flush the entire data cache by cleaning and invalidating the D cache.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_flush_dcache_all(void)
+{
+  uintptr_t cache_addr = CONFIG_ARCH_DCACHE_ADDR;
+  size_t line_size = up_get_dcache_linesize();
+  size_t line_cnt = up_get_dcache_size() / line_size;
+  size_t i;
+
+  for (i = 0; i < line_cnt; i++)
+    {
+      tc_flush_cache_byline(cache_addr);
+      cache_addr += line_size;
+    }
+
+  __dsync();
+  __isync();
+}
+
+/****************************************************************************
+ * Name: up_coherent_dcache
+ *
+ * Description:
+ *   Ensure that the I and D caches are coherent within specified region
+ *   by cleaning the D cache (i.e., flushing the D cache contents to memory
+ *   and invalidating the I cache. This is typically used when code has been
+ *   written to a memory region, and will be executed.
+ *
+ * Input Parameters:
+ *   addr - virtual start address of region
+ *   len  - Size of the address region in bytes
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void up_coherent_dcache(uintptr_t addr, size_t len)
+{
+  if (len > 0)
+    {
+      up_flush_dcache(addr, addr + len);
+      up_invalidate_icache_all();
+    }
+}
+#endif
diff --git a/arch/tricore/src/common/tricore_initialize.c 
b/arch/tricore/src/common/tricore_initialize.c
index 21173d355fd..5757ea93435 100644
--- a/arch/tricore/src/common/tricore_initialize.c
+++ b/arch/tricore/src/common/tricore_initialize.c
@@ -26,6 +26,7 @@
 
 #include <nuttx/arch.h>
 #include <nuttx/board.h>
+#include <nuttx/cache.h>
 #include <arch/board/board.h>
 
 #include "tricore_internal.h"
@@ -63,6 +64,14 @@ void up_initialize(void)
 {
   tricore_trapinit();
 
+#ifdef CONFIG_ARCH_ICACHE
+  up_enable_icache();
+#endif
+
+#ifdef CONFIG_ARCH_DCACHE
+  up_enable_dcache();
+#endif
+
   /* Initialize the serial device driver */
 
 #ifdef USE_SERIALDRIVER

Reply via email to