[PATCH 4/6] bsps/leon3: Simplify clock and CPU counter
Sebastian Huber
sebastian.huber at embedded-brains.de
Fri Sep 15 14:40:11 UTC 2023
Share the timecounter instance between the clock and the CPU counter.
This greatly simplifies the clock driver since we have to do the device
selection only in one place, the CPU counter support.
Update #4954.
---
bsps/sparc/leon3/clock/ckinit.c | 130 +++++----------------------
bsps/sparc/leon3/include/bsp/leon3.h | 9 ++
bsps/sparc/leon3/start/cpucounter.c | 46 +++++++---
3 files changed, 62 insertions(+), 123 deletions(-)
diff --git a/bsps/sparc/leon3/clock/ckinit.c b/bsps/sparc/leon3/clock/ckinit.c
index d800f01e4a..c77fd23aff 100644
--- a/bsps/sparc/leon3/clock/ckinit.c
+++ b/bsps/sparc/leon3/clock/ckinit.c
@@ -16,7 +16,7 @@
* COPYRIGHT (c) 2004.
* Gaisler Research.
*
- * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG
+ * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -47,13 +47,8 @@
#include <rtems/rtems/intr.h>
#include <grlib/irqamp.h>
#include <rtems/score/profiling.h>
-#include <bsp/sparc-counter.h>
#include <rtems/timecounter.h>
-#if !defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
-#include <grlib/ambapp.h>
-#endif
-
/* The LEON3 BSP Timer driver can rely on the Driver Manager if the
* DrvMgr is initialized during startup. Otherwise the classic driver
* must be used.
@@ -65,17 +60,26 @@
/* LEON3 Timer system interrupt number */
static int clkirq;
-static struct timecounter leon3_tc;
+#if defined(RTEMS_PROFILING) && \
+ (defined(LEON3_HAS_ASR_22_23_UP_COUNTER) || \
+ defined(LEON3_PROBE_ASR_22_23_UP_COUNTER) || \
+ defined(LEON3_IRQAMP_PROBE_TIMESTAMP))
+
+#define LEON3_CLOCK_PROBE_IRQAMP_TIMESTAMP
+
+#define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26))
static void leon3_tc_tick_default(void)
{
rtems_timecounter_tick();
}
-#if defined(RTEMS_PROFILING)
static void (*leon3_tc_tick)(void) = leon3_tc_tick_default;
-#define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26))
+static void leon3_tc_do_tick(void)
+{
+ (*leon3_tc_tick)();
+}
static void leon3_tc_tick_irqmp_timestamp(void)
{
@@ -124,16 +128,12 @@ static void leon3_tc_tick_irqmp_timestamp_init(void)
rtems_timecounter_tick();
}
-#endif /* RTEMS_PROFILING */
-
+#else
static void leon3_tc_do_tick(void)
{
-#if defined(RTEMS_PROFILING)
- (*leon3_tc_tick)();
-#else
- leon3_tc_tick_default();
-#endif
+ rtems_timecounter_tick();
}
+#endif
#define Adjust_clkirq_for_node() do { clkirq += LEON3_CLOCK_INDEX; } while(0)
@@ -175,74 +175,9 @@ static void bsp_clock_handler_install(rtems_interrupt_handler isr)
#define Clock_driver_support_set_interrupt_affinity(online_processors) \
bsp_interrupt_set_affinity(clkirq, online_processors)
-#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER) || \
- defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
-static void leon3_clock_use_up_counter(struct timecounter *tc)
-{
- tc->tc_get_timecount = _SPARC_Get_timecount_asr23;
- tc->tc_frequency = leon3_up_counter_frequency();
-
-#if defined(RTEMS_PROFILING)
- if (irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs) != NULL) {
- leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
- }
-#endif
-
- rtems_timecounter_install(tc);
-}
-#endif
-
-#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
-static void leon3_clock_use_irqamp_timestamp(
- struct timecounter *tc,
- irqamp_timestamp *irqmp_ts
-)
-{
- tc->tc_get_timecount = _SPARC_Get_timecount_up;
-#if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
- tc->tc_frequency = leon3_processor_local_bus_frequency();
-#else
- tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev);
-#endif
-
-#if defined(RTEMS_PROFILING)
- leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
-#endif
-
- /*
- * At least one TSISEL field must be non-zero to enable the timestamp
- * counter. Use an arbitrary interrupt source.
- */
- grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
-
- rtems_timecounter_install(tc);
-}
-#endif
-
-#if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
-static void leon3_clock_use_gptimer(
- struct timecounter *tc,
- gptimer_timer *timer
-)
-{
- /*
- * As a fall back, use a second timer in free-running mode for the
- * timecounter. The timer is initialized by leon3_counter_initialize().
- */
- tc->tc_get_timecount = _SPARC_Get_timecount_down;
- tc->tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER,
-
- rtems_timecounter_install(tc);
-}
-#endif
-
static void leon3_clock_initialize(void)
{
-#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
- irqamp_timestamp *irqmp_ts;
-#endif
gptimer_timer *timer;
- struct timecounter *tc;
timer = &LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX];
@@ -255,36 +190,13 @@ static void leon3_clock_initialize(void)
GPTIMER_TCTRL_EN | GPTIMER_TCTRL_RS | GPTIMER_TCTRL_LD | GPTIMER_TCTRL_IE
);
- tc = &leon3_tc;
- tc->tc_counter_mask = 0xffffffff;
- tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
-
-#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
- leon3_up_counter_enable();
- leon3_clock_use_up_counter(tc);
-#else /* LEON3_HAS_ASR_22_23_UP_COUNTER */
-#if defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
- leon3_up_counter_enable();
-
- if (leon3_up_counter_is_available()) {
- /* Use the LEON4 up-counter if available */
- leon3_clock_use_up_counter(tc);
- return;
- }
-#endif
-
-#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
- irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
-
- if (irqmp_ts != NULL) {
- /* Use the interrupt controller timestamp counter if available */
- leon3_clock_use_irqamp_timestamp(tc, irqmp_ts);
- return;
+#if defined(LEON3_CLOCK_PROBE_IRQAMP_TIMESTAMP)
+ if (irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs) != NULL) {
+ leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
}
#endif
- leon3_clock_use_gptimer(tc, timer);
-#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER */
+ rtems_timecounter_install(&leon3_timecounter_instance);
}
#define Clock_driver_support_initialize_hardware() \
@@ -296,4 +208,4 @@ static void leon3_clock_initialize(void)
#include "../../../shared/dev/clock/clockimpl.h"
-#endif
+#endif /* RTEMS_DRVMGR_STARTUP */
diff --git a/bsps/sparc/leon3/include/bsp/leon3.h b/bsps/sparc/leon3/include/bsp/leon3.h
index 84790b590f..a5eecdded7 100644
--- a/bsps/sparc/leon3/include/bsp/leon3.h
+++ b/bsps/sparc/leon3/include/bsp/leon3.h
@@ -46,6 +46,8 @@
#include <grlib/ambapp.h>
#endif
+#include <sys/timetc.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -310,6 +312,13 @@ static inline uint32_t leon3_up_counter_frequency( void )
extern apbuart *leon3_debug_uart;
#endif
+/**
+ * @brief Provides the LEON3-specific timecounter.
+ *
+ * It is also used by the CPU counter implementation.
+ */
+extern struct timecounter leon3_timecounter_instance;
+
/** @} */
#ifdef __cplusplus
diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index 374e43c9b1..61b767568d 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -38,28 +38,38 @@
#include <rtems/counter.h>
#include <rtems/sysinit.h>
+#include <rtems/timecounter.h>
#include <bsp/sparc-counter.h>
-static uint32_t leon3_counter_frequency = 1000000000;
+struct timecounter leon3_timecounter_instance = {
+ .tc_counter_mask = 0xffffffff,
+ .tc_frequency = 1000000000,
+ .tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER
+};
uint32_t _CPU_Counter_frequency(void)
{
- return leon3_counter_frequency;
+ return leon3_timecounter_instance.tc_frequency;
}
#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER) || \
defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
-static void leon3_counter_use_up_counter(SPARC_Counter *counter)
+static void leon3_counter_use_up_counter(
+ struct timecounter *tc,
+ SPARC_Counter *counter
+)
{
counter->read_isr_disabled = _SPARC_Counter_read_asr23;
counter->read = _SPARC_Counter_read_asr23;
- leon3_counter_frequency = leon3_up_counter_frequency();
+ tc->tc_get_timecount = _SPARC_Get_timecount_asr23;
+ tc->tc_frequency = leon3_up_counter_frequency();
}
#endif
#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
static void leon3_counter_use_irqamp_timestamp(
+ struct timecounter *tc,
SPARC_Counter *counter,
irqamp_timestamp *irqmp_ts
)
@@ -71,16 +81,21 @@ static void leon3_counter_use_irqamp_timestamp(
/* Enable interrupt timestamping for an arbitrary interrupt line */
grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
+ tc->tc_get_timecount = _SPARC_Get_timecount_up;
#if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
- leon3_counter_frequency = leon3_processor_local_bus_frequency();
+ tc->tc_frequency = leon3_processor_local_bus_frequency();
#else
- leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
+ tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
#endif
}
#endif
#if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
-static void leon3_counter_use_gptimer(SPARC_Counter *counter, gptimer *gpt)
+static void leon3_counter_use_gptimer(
+ struct timecounter *tc,
+ SPARC_Counter *counter,
+ gptimer *gpt
+)
{
gptimer_timer *timer;
@@ -93,10 +108,11 @@ static void leon3_counter_use_gptimer(SPARC_Counter *counter, gptimer *gpt)
grlib_store_32(&timer->trldval, 0xffffffff);
grlib_store_32(&timer->tctrl, GPTIMER_TCTRL_EN | GPTIMER_TCTRL_RS);
+ tc->tc_get_timecount = _SPARC_Get_timecount_down;
#if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
- leon3_counter_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
+ tc->tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
#else
- leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
+ tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
(grlib_load_32(&gpt->sreload) + 1);
#endif
}
@@ -110,20 +126,22 @@ static void leon3_counter_initialize(void)
#if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
gptimer *gpt;
#endif
+ struct timecounter *tc;
SPARC_Counter *counter;
+ tc = &leon3_timecounter_instance;
counter = &_SPARC_Counter;
#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
leon3_up_counter_enable();
- leon3_counter_use_up_counter(counter);
+ leon3_counter_use_up_counter(tc, counter);
#else /* LEON3_HAS_ASR_22_23_UP_COUNTER */
#if defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
leon3_up_counter_enable();
if (leon3_up_counter_is_available()) {
/* Use the LEON4 up-counter if available */
- leon3_counter_use_up_counter(counter);
+ leon3_counter_use_up_counter(tc, counter);
return;
}
#endif
@@ -133,7 +151,7 @@ static void leon3_counter_initialize(void)
if (irqmp_ts != NULL) {
/* Use the interrupt controller timestamp counter if available */
- leon3_counter_use_irqamp_timestamp(counter, irqmp_ts);
+ leon3_counter_use_irqamp_timestamp(tc, counter, irqmp_ts);
return;
}
#endif
@@ -141,11 +159,11 @@ static void leon3_counter_initialize(void)
gpt = LEON3_Timer_Regs;
#if defined(LEON3_GPTIMER_BASE)
- leon3_counter_use_gptimer(counter, gpt);
+ leon3_counter_use_gptimer(tc, counter, gpt);
#else
if (gpt != NULL) {
/* Fall back to the first GPTIMER if available */
- leon3_counter_use_gptimer(counter, gpt);
+ leon3_counter_use_gptimer(tc, counter, gpt);
}
#endif
#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER */
--
2.35.3
More information about the devel
mailing list