[PATCH v2 9/9] bsps/leon3: Use DSU time tag for GR712RC

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Sep 21 15:19:34 UTC 2023


Update #4954.
---
 bsps/sparc/leon3/start/cpucounter.c        | 62 ++++++++++++++++++++--
 spec/build/bsps/sparc/leon3/grp.yml        |  2 +
 spec/build/bsps/sparc/leon3/optdsubase.yml | 24 +++++++++
 3 files changed, 84 insertions(+), 4 deletions(-)
 create mode 100644 spec/build/bsps/sparc/leon3/optdsubase.yml

diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index db4f566021..35db839cd4 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -77,7 +77,57 @@ RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
 
 #define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_processor_up_counter
 
-#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER */
+#elif defined(LEON3_DSU_BASE)
+
+/*
+ * In general, using the Debug Support Unit (DSU) is not recommended.  Before
+ * you use it, check that it is available in flight models and that the time
+ * tag register is implemented in radiation hardened flip-flops.  For the
+ * GR712RC, this is the case.
+ */
+
+/* This value is specific to the GR712RC */
+#define LEON3_DSU_TIME_TAG_ZERO_BITS 2
+
+static uint32_t leon3_read_dsu_time_tag(void)
+{
+  uint32_t value;
+  volatile uint32_t *reg;
+
+  /* Use a load with a forced cache miss */
+  reg = (uint32_t *) (LEON3_DSU_BASE + 8);
+  __asm__ volatile (
+    "\tlda\t[%1]1, %0"
+    : "=&r"(value)
+    : "r"(reg)
+  );
+  return value << LEON3_DSU_TIME_TAG_ZERO_BITS;
+}
+
+static uint32_t leon3_timecounter_get_dsu_time_tag(
+  struct timecounter *tc
+)
+{
+  (void) tc;
+  return leon3_read_dsu_time_tag();
+}
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+  return leon3_read_dsu_time_tag();
+}
+
+RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
+
+static void leon3_counter_use_dsu_time_tag(leon3_timecounter *tc)
+{
+  tc->base.tc_frequency =
+    leon3_processor_local_bus_frequency() << LEON3_DSU_TIME_TAG_ZERO_BITS;
+}
+
+#define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_dsu_time_tag
+
+#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER && !LEON3_DSU_BASE */
 
 /*
  * This is a workaround for:
@@ -169,7 +219,7 @@ static void leon3_counter_use_irqamp_timestamp(
 }
 
 #endif /* LEON3_IRQAMP_PROBE_TIMESTAMP */
-#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER */
+#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER || LEON3_DSU_BASE */
 
 leon3_timecounter leon3_timecounter_instance = {
   .base = {
@@ -192,7 +242,11 @@ static void leon3_counter_initialize(void)
   leon3_up_counter_enable();
   leon3_counter_use_asr_22_23_up_counter(&leon3_timecounter_instance);
 
-#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER */
+#elif defined(LEON3_DSU_BASE)
+
+  leon3_counter_use_dsu_time_tag(&leon3_timecounter_instance);
+
+#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER && !LEON3_DSU_BASE */
 
   /* Try to find the best CPU counter available */
 
@@ -235,7 +289,7 @@ static void leon3_counter_initialize(void)
   }
 #endif
 
-#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER */
+#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER || LEON3_DSU_BASE */
 }
 
 RTEMS_SYSINIT_ITEM(
diff --git a/spec/build/bsps/sparc/leon3/grp.yml b/spec/build/bsps/sparc/leon3/grp.yml
index d708a65735..a995ccc60a 100644
--- a/spec/build/bsps/sparc/leon3/grp.yml
+++ b/spec/build/bsps/sparc/leon3/grp.yml
@@ -38,6 +38,8 @@ links:
   uid: optasrupcnt
 - role: build-dependency
   uid: optasrupcntprobe
+- role: build-dependency
+  uid: optdsubase
 - role: build-dependency
   uid: optgptimerbase
 - role: build-dependency
diff --git a/spec/build/bsps/sparc/leon3/optdsubase.yml b/spec/build/bsps/sparc/leon3/optdsubase.yml
new file mode 100644
index 0000000000..5fd0b9bfb7
--- /dev/null
+++ b/spec/build/bsps/sparc/leon3/optdsubase.yml
@@ -0,0 +1,24 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2023 embedded brains GmbH & Co. KG
+actions:
+- get-integer: null
+- format-and-define: null
+build-type: option
+default:
+- enabled-by: sparc/gr712rc
+  value: 0x90000000
+enabled-by: true
+format: '{:#010x}'
+links: []
+name: LEON3_DSU_BASE
+description: |
+  This option defines the base address of the DSU register block used by
+  the clock driver and CPU counter implementation.
+
+  In general, using the Debug Support Unit (DSU) is not recommended for the
+  clock driver and CPU counter implementation.  Before you use it, check that
+  it is available in flight models and that the time tag register is
+  implemented in radiation hardened flip-flops.  For the GR712RC, this is the
+  case.
+type: build
-- 
2.35.3



More information about the devel mailing list