summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-09-15 15:46:31 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-10-20 11:16:54 +0200
commitabb2f8bd6635457fcac4ddbd0cb284b623b5c602 (patch)
treea195c62faecafb702e708bd41bd447152f56f39e
parentff533cec9dc4f5c10972f0f6d8a2f90064765462 (diff)
bsps/leon3: Use custom CPU counter implementation
Merge the timecounter and CPU counter support for the leon3 BSP family. Remove now unused functions from the CPU counter support of the erc32 and leon3 BSPs. Update #4954.
-rw-r--r--bsps/sparc/include/bsp/sparc-counter.h12
-rw-r--r--bsps/sparc/leon3/clock/ckinit.c2
-rw-r--r--bsps/sparc/leon3/include/bsp/leon3.h26
-rw-r--r--bsps/sparc/leon3/start/cpucounter.c157
-rw-r--r--bsps/sparc/shared/start/sparc-counter-asm.S26
-rw-r--r--spec/build/bsps/sparc/leon3/obj.yml2
6 files changed, 134 insertions, 91 deletions
diff --git a/bsps/sparc/include/bsp/sparc-counter.h b/bsps/sparc/include/bsp/sparc-counter.h
index c71cddf304..bc4f2220e7 100644
--- a/bsps/sparc/include/bsp/sparc-counter.h
+++ b/bsps/sparc/include/bsp/sparc-counter.h
@@ -49,24 +49,12 @@ void _SPARC_Counter_at_tick_clock( void );
CPU_Counter_ticks _SPARC_Counter_read_default( void );
-CPU_Counter_ticks _SPARC_Counter_read_up( void );
-
-CPU_Counter_ticks _SPARC_Counter_read_down( void );
-
CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void );
CPU_Counter_ticks _SPARC_Counter_read_clock( void );
-CPU_Counter_ticks _SPARC_Counter_read_asr23( void );
-
-uint32_t _SPARC_Get_timecount_up( struct timecounter * );
-
-uint32_t _SPARC_Get_timecount_down( struct timecounter * );
-
uint32_t _SPARC_Get_timecount_clock( struct timecounter * );
-uint32_t _SPARC_Get_timecount_asr23( struct timecounter * );
-
typedef CPU_Counter_ticks ( *SPARC_Counter_read )( void );
/*
diff --git a/bsps/sparc/leon3/clock/ckinit.c b/bsps/sparc/leon3/clock/ckinit.c
index c77fd23aff..d530f260a8 100644
--- a/bsps/sparc/leon3/clock/ckinit.c
+++ b/bsps/sparc/leon3/clock/ckinit.c
@@ -196,7 +196,7 @@ static void leon3_clock_initialize(void)
}
#endif
- rtems_timecounter_install(&leon3_timecounter_instance);
+ rtems_timecounter_install(&leon3_timecounter_instance.base);
}
#define Clock_driver_support_initialize_hardware() \
diff --git a/bsps/sparc/leon3/include/bsp/leon3.h b/bsps/sparc/leon3/include/bsp/leon3.h
index 99e16b90dd..06d73cffe3 100644
--- a/bsps/sparc/leon3/include/bsp/leon3.h
+++ b/bsps/sparc/leon3/include/bsp/leon3.h
@@ -9,7 +9,7 @@
*/
/*
- * Copyright (C) 2014, 2021 embedded brains GmbH & Co. KG
+ * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG
*
* Copyright (C) 2015 Cobham Gaisler AB
*
@@ -350,11 +350,33 @@ extern apbuart *leon3_debug_uart;
#endif
/**
+ * @brief Represents the LEON3-specific timecounter.
+ */
+typedef struct {
+ /**
+ * @brief This member contains the base timecounter.
+ */
+ struct timecounter base;
+
+ /**
+ * @brief This member provides a software fall-back counter.
+ */
+ uint32_t software_counter;
+
+#if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
+ /**
+ * @brief This member may reference a hardware counter register.
+ */
+ volatile uint32_t *counter_register;
+#endif
+} leon3_timecounter;
+
+/**
* @brief Provides the LEON3-specific timecounter.
*
* It is also used by the CPU counter implementation.
*/
-extern struct timecounter leon3_timecounter_instance;
+extern leon3_timecounter leon3_timecounter_instance;
/** @} */
diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index 61b767568d..71262ff210 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -9,7 +9,7 @@
*/
/*
- * 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
@@ -39,80 +39,143 @@
#include <rtems/counter.h>
#include <rtems/sysinit.h>
#include <rtems/timecounter.h>
-#include <bsp/sparc-counter.h>
-struct timecounter leon3_timecounter_instance = {
- .tc_counter_mask = 0xffffffff,
- .tc_frequency = 1000000000,
- .tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER
+#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER) || \
+ defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
+static uint32_t leon3_timecounter_get_asr_22_23_up_counter(
+ struct timecounter *tc
+)
+{
+ return leon3_up_counter_low();
+}
+#endif
+
+#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+ return leon3_up_counter_low();
+}
+
+RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
+
+#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER */
+
+/*
+ * This is a workaround for:
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69027
+ */
+__asm__ (
+ "\t.section\t\".text\"\n"
+ "\t.align\t4\n"
+ "\t.globl\t_CPU_Counter_read\n"
+ "\t.globl\t_SPARC_Counter_read_ISR_disabled\n"
+ "\t.type\t_CPU_Counter_read, #function\n"
+ "\t.type\t_SPARC_Counter_read_ISR_disabled, #function\n"
+ "_CPU_Counter_read:\n"
+ "_SPARC_Counter_read_ISR_disabled:\n"
+ "\tsethi\t%hi(leon3_timecounter_instance), %o0\n"
+ "\tld [%o0 + %lo(leon3_timecounter_instance)], %o1\n"
+ "\tor\t%o0, %lo(leon3_timecounter_instance), %o0\n"
+ "\tor\t%o7, %g0, %g1\n"
+ "\tcall\t%o1, 0\n"
+ "\t or\t%g1, %g0, %o7\n"
+ "\t.previous\n"
+);
+
+static uint32_t leon3_timecounter_get_counter_down(struct timecounter *base)
+{
+ leon3_timecounter *tc;
+
+ tc = (leon3_timecounter *) base;
+ return -(*tc->counter_register);
+}
+
+#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
+static uint32_t leon3_timecounter_get_counter_up(struct timecounter *base)
+{
+ leon3_timecounter *tc;
+
+ tc = (leon3_timecounter *) base;
+ return *tc->counter_register;
+}
+#endif
+
+#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER */
+
+static uint32_t leon3_timecounter_get_dummy(struct timecounter *base)
+{
+ leon3_timecounter *tc;
+ uint32_t counter;
+
+ tc = (leon3_timecounter *) base;
+ counter = tc->software_counter + 1;
+ tc->software_counter = counter;
+ return counter;
+}
+
+leon3_timecounter leon3_timecounter_instance = {
+ .base = {
+ .tc_get_timecount = leon3_timecounter_get_dummy,
+ .tc_counter_mask = 0xffffffff,
+ .tc_frequency = 1000000000,
+ .tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER
+ }
};
uint32_t _CPU_Counter_frequency(void)
{
- return leon3_timecounter_instance.tc_frequency;
+ return leon3_timecounter_instance.base.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(
- struct timecounter *tc,
- SPARC_Counter *counter
-)
+static void leon3_counter_use_asr_22_23_up_counter(leon3_timecounter *tc)
{
- counter->read_isr_disabled = _SPARC_Counter_read_asr23;
- counter->read = _SPARC_Counter_read_asr23;
-
- tc->tc_get_timecount = _SPARC_Get_timecount_asr23;
- tc->tc_frequency = leon3_up_counter_frequency();
+ tc->base.tc_get_timecount = leon3_timecounter_get_asr_22_23_up_counter;
+ tc->base.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,
+ leon3_timecounter *tc,
irqamp_timestamp *irqmp_ts
)
{
- counter->read_isr_disabled = _SPARC_Counter_read_up;
- counter->read = _SPARC_Counter_read_up;
- counter->counter_register = &irqmp_ts->itcnt;
-
/* 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;
+ tc->counter_register = &irqmp_ts->itcnt;
+ tc->base.tc_get_timecount = leon3_timecounter_get_counter_up;
#if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
- tc->tc_frequency = leon3_processor_local_bus_frequency();
+ tc->base.tc_frequency = leon3_processor_local_bus_frequency();
#else
- tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
+ tc->base.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(
- struct timecounter *tc,
- SPARC_Counter *counter,
+ leon3_timecounter *tc,
gptimer *gpt
)
{
gptimer_timer *timer;
timer = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX];
- counter->read_isr_disabled = _SPARC_Counter_read_down;
- counter->read = _SPARC_Counter_read_down;
- counter->counter_register = &timer->tcntval;
/* Make timer free-running */
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;
+ tc->counter_register = &timer->tcntval;
+ tc->base.tc_get_timecount = leon3_timecounter_get_counter_down;
#if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
- tc->tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
+ tc->base.tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
#else
- tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
+ tc->base.tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
(grlib_load_32(&gpt->sreload) + 1);
#endif
}
@@ -120,28 +183,27 @@ static void leon3_counter_use_gptimer(
static void leon3_counter_initialize(void)
{
+#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
+
+ leon3_up_counter_enable();
+ leon3_counter_use_asr_22_23_up_counter(&leon3_timecounter_instance);
+
+#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER */
+
#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
irqamp_timestamp *irqmp_ts;
#endif
-#if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
gptimer *gpt;
-#endif
- struct timecounter *tc;
- SPARC_Counter *counter;
+ leon3_timecounter *tc;
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(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(tc, counter);
+ leon3_counter_use_asr_22_23_up_counter(tc);
return;
}
#endif
@@ -151,7 +213,7 @@ static void leon3_counter_initialize(void)
if (irqmp_ts != NULL) {
/* Use the interrupt controller timestamp counter if available */
- leon3_counter_use_irqamp_timestamp(tc, counter, irqmp_ts);
+ leon3_counter_use_irqamp_timestamp(tc, irqmp_ts);
return;
}
#endif
@@ -159,13 +221,14 @@ static void leon3_counter_initialize(void)
gpt = LEON3_Timer_Regs;
#if defined(LEON3_GPTIMER_BASE)
- leon3_counter_use_gptimer(tc, counter, gpt);
+ leon3_counter_use_gptimer(tc, gpt);
#else
if (gpt != NULL) {
/* Fall back to the first GPTIMER if available */
- leon3_counter_use_gptimer(tc, counter, gpt);
+ leon3_counter_use_gptimer(tc, gpt);
}
#endif
+
#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER */
}
@@ -174,5 +237,3 @@ RTEMS_SYSINIT_ITEM(
RTEMS_SYSINIT_CPU_COUNTER,
RTEMS_SYSINIT_ORDER_FIRST
);
-
-SPARC_COUNTER_DEFINITION;
diff --git a/bsps/sparc/shared/start/sparc-counter-asm.S b/bsps/sparc/shared/start/sparc-counter-asm.S
index 8b988bf3ed..590d77050d 100644
--- a/bsps/sparc/shared/start/sparc-counter-asm.S
+++ b/bsps/sparc/shared/start/sparc-counter-asm.S
@@ -74,25 +74,6 @@ SYM(_SPARC_Counter_read_default):
jmp %o7 + 8
nop
- PUBLIC(_SPARC_Counter_read_up)
- PUBLIC(_SPARC_Get_timecount_up)
-SYM(_SPARC_Counter_read_up):
-SYM(_SPARC_Get_timecount_up):
- sethi %hi(_SPARC_Counter + 8), %o0
- ld [%o0 + %lo(_SPARC_Counter + 8)], %o0
- jmp %o7 + 8
- ld [%o0], %o0
-
- PUBLIC(_SPARC_Counter_read_down)
- PUBLIC(_SPARC_Get_timecount_down)
-SYM(_SPARC_Counter_read_down):
-SYM(_SPARC_Get_timecount_down):
- sethi %hi(_SPARC_Counter + 8), %o0
- ld [%o0 + %lo(_SPARC_Counter + 8)], %o0
- ld [%o0], %o0
- jmp %o7 + 8
- xnor %g0, %o0, %o0
-
/*
* For the corresponding C code is something like this:
*
@@ -168,10 +149,3 @@ SYM(_SPARC_Get_timecount_clock):
add %o4, %o5, %o4
jmp %o7 + 8
sub %o4, %o0, %o0
-
- PUBLIC(_SPARC_Counter_read_asr23)
- PUBLIC(_SPARC_Get_timecount_asr23)
-SYM(_SPARC_Counter_read_asr23):
-SYM(_SPARC_Get_timecount_asr23):
- jmp %o7 + 8
- mov %asr23, %o0
diff --git a/spec/build/bsps/sparc/leon3/obj.yml b/spec/build/bsps/sparc/leon3/obj.yml
index 6585b30310..7a4ccaa0cb 100644
--- a/spec/build/bsps/sparc/leon3/obj.yml
+++ b/spec/build/bsps/sparc/leon3/obj.yml
@@ -15,7 +15,6 @@ install:
- bsps/sparc/leon3/include/leon.h
- destination: ${BSP_INCLUDEDIR}/bsp
source:
- - bsps/sparc/include/bsp/sparc-counter.h
- bsps/sparc/leon3/include/bsp/irq.h
- bsps/sparc/leon3/include/bsp/irqimpl.h
- bsps/sparc/leon3/include/bsp/watchdog.h
@@ -58,5 +57,4 @@ source:
- bsps/sparc/shared/pci/pci_memreg_sparc_be.c
- bsps/sparc/shared/pci/pci_memreg_sparc_le.c
- bsps/sparc/shared/start/bsp_fatal_exit.c
-- bsps/sparc/shared/start/sparc-counter-asm.S
type: build