summaryrefslogtreecommitdiffstats
path: root/bsps/sparc
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-09-14 16:08:53 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-10-20 11:16:54 +0200
commitb6dc4b47077803cde93648016d15ce3992573d03 (patch)
tree425c75b086ca6c211490c7a73b0c96746dba91d5 /bsps/sparc
parentbsps/leon3: Optional IRQ(A)MP timestamp support (diff)
downloadrtems-b6dc4b47077803cde93648016d15ce3992573d03.tar.bz2
sparc: Move CPU counter implementation
Enable a BSP-specific CPU counter implementation. Update #4954.
Diffstat (limited to 'bsps/sparc')
-rw-r--r--bsps/sparc/erc32/clock/ckinit.c8
-rw-r--r--bsps/sparc/include/bsp/sparc-counter.h101
-rw-r--r--bsps/sparc/leon2/clock/ckinit.c8
-rw-r--r--bsps/sparc/leon3/clock/ckinit.c6
-rw-r--r--bsps/sparc/leon3/start/cpucounter.c4
-rw-r--r--bsps/sparc/shared/start/sparc-counter-asm.S177
6 files changed, 291 insertions, 13 deletions
diff --git a/bsps/sparc/erc32/clock/ckinit.c b/bsps/sparc/erc32/clock/ckinit.c
index 83cafb73c3..e8cf7188eb 100644
--- a/bsps/sparc/erc32/clock/ckinit.c
+++ b/bsps/sparc/erc32/clock/ckinit.c
@@ -26,7 +26,7 @@
#include <rtems/irq-extension.h>
#include <rtems/sysinit.h>
#include <rtems/timecounter.h>
-#include <rtems/score/sparcimpl.h>
+#include <bsp/sparc-counter.h>
extern int CLOCK_SPEED;
@@ -46,7 +46,7 @@ static void erc32_clock_init( void )
rtems_timecounter_install(tc);
}
-uint32_t _CPU_Counter_frequency(void)
+uint32_t _CPU_Counter_frequency( void )
{
return ERC32_REAL_TIME_CLOCK_FREQUENCY;
}
@@ -56,7 +56,7 @@ static void erc32_clock_at_tick( void )
SPARC_Counter *counter;
rtems_interrupt_level level;
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
rtems_interrupt_local_disable(level);
ERC32_Clear_interrupt( ERC32_INTERRUPT_REAL_TIME_CLOCK );
@@ -83,7 +83,7 @@ static void erc32_clock_initialize_early( void )
ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO
);
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
counter->read = _SPARC_Counter_read_clock;
counter->counter_register = &ERC32_MEC.Real_Time_Clock_Counter,
diff --git a/bsps/sparc/include/bsp/sparc-counter.h b/bsps/sparc/include/bsp/sparc-counter.h
new file mode 100644
index 0000000000..c71cddf304
--- /dev/null
+++ b/bsps/sparc/include/bsp/sparc-counter.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSBSPsSPARCShared
+ *
+ * @brief This header file provides interfaces of a CPU counter implementation
+ * for SPARC BSPs.
+ */
+
+/*
+ * Copyright (C) 2016, 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _BSP_SPARC_COUNTER_H
+#define _BSP_SPARC_COUNTER_H
+
+#include <rtems/score/cpu.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct timecounter;
+
+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 );
+
+/*
+ * The SPARC processors supported by RTEMS have no built-in CPU counter
+ * support. We have to use some hardware counter module for this purpose, for
+ * example the GPTIMER instance used by the clock driver. The BSP must provide
+ * an implementation of the CPU counter read function. This allows the use of
+ * dynamic hardware enumeration.
+ */
+typedef struct {
+ SPARC_Counter_read read_isr_disabled;
+ SPARC_Counter_read read;
+ volatile const CPU_Counter_ticks *counter_register;
+ volatile const uint32_t *pending_register;
+ uint32_t pending_mask;
+ CPU_Counter_ticks accumulated;
+ CPU_Counter_ticks interval;
+} SPARC_Counter;
+
+extern SPARC_Counter _SPARC_Counter;
+
+#define SPARC_COUNTER_DEFINITION \
+ SPARC_Counter _SPARC_Counter = { \
+ .read_isr_disabled = _SPARC_Counter_read_default, \
+ .read = _SPARC_Counter_read_default \
+ }
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _BSP_SPARC_COUNTER_H */
diff --git a/bsps/sparc/leon2/clock/ckinit.c b/bsps/sparc/leon2/clock/ckinit.c
index 604d995573..31f8bca7ba 100644
--- a/bsps/sparc/leon2/clock/ckinit.c
+++ b/bsps/sparc/leon2/clock/ckinit.c
@@ -45,7 +45,7 @@
#include <bspopts.h>
#include <rtems/sysinit.h>
#include <rtems/timecounter.h>
-#include <rtems/score/sparcimpl.h>
+#include <bsp/sparc-counter.h>
extern int CLOCK_SPEED;
@@ -70,7 +70,7 @@ static void leon2_clock_at_tick( void )
SPARC_Counter *counter;
rtems_interrupt_level level;
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
rtems_interrupt_local_disable(level);
LEON_Clear_interrupt( LEON_INTERRUPT_TIMER1 );
@@ -91,7 +91,7 @@ static void leon2_clock_initialize_early( void )
LEON_REG_TIMER_COUNTER_LOAD_COUNTER
);
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
counter->read = _SPARC_Counter_read_clock;
counter->counter_register = &LEON_REG.Timer_Counter_1;
@@ -107,7 +107,7 @@ RTEMS_SYSINIT_ITEM(
RTEMS_SYSINIT_ORDER_FIRST
);
-uint32_t _CPU_Counter_frequency(void)
+uint32_t _CPU_Counter_frequency( void )
{
return LEON2_TIMER_1_FREQUENCY;
}
diff --git a/bsps/sparc/leon3/clock/ckinit.c b/bsps/sparc/leon3/clock/ckinit.c
index cff2991e60..eea4649fa3 100644
--- a/bsps/sparc/leon3/clock/ckinit.c
+++ b/bsps/sparc/leon3/clock/ckinit.c
@@ -47,7 +47,7 @@
#include <rtems/rtems/intr.h>
#include <grlib/irqamp.h>
#include <rtems/score/profiling.h>
-#include <rtems/score/sparcimpl.h>
+#include <bsp/sparc-counter.h>
#include <rtems/timecounter.h>
#if !defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
@@ -73,7 +73,7 @@ static void leon3_tc_tick_default(void)
SPARC_Counter *counter;
rtems_interrupt_level level;
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
rtems_interrupt_local_disable(level);
grlib_store_32(&LEON3_IrqCtrl_Regs->iclear, counter->pending_mask);
@@ -249,7 +249,7 @@ static void leon3_clock_use_gptimer(
#else
SPARC_Counter *counter;
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
counter->read = _SPARC_Counter_read_clock;
counter->counter_register = &timer->tcntval;
diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index c36e7ea23b..a6db7677a3 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -38,7 +38,7 @@
#include <rtems/counter.h>
#include <rtems/sysinit.h>
-#include <rtems/score/sparcimpl.h>
+#include <bsp/sparc-counter.h>
static uint32_t leon3_counter_frequency = 1000000000;
@@ -112,7 +112,7 @@ static void leon3_counter_initialize(void)
#endif
SPARC_Counter *counter;
- counter = &_SPARC_Counter_mutable;
+ counter = &_SPARC_Counter;
#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
leon3_up_counter_enable();
diff --git a/bsps/sparc/shared/start/sparc-counter-asm.S b/bsps/sparc/shared/start/sparc-counter-asm.S
new file mode 100644
index 0000000000..8b988bf3ed
--- /dev/null
+++ b/bsps/sparc/shared/start/sparc-counter-asm.S
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2016, 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/asm.h>
+
+ /*
+ * All functions except _SPARC_Counter_read_clock() in this module are
+ * sometimes called with traps disabled.
+ */
+
+ .section ".text"
+ .align 4
+
+ /*
+ * This is a workaround for:
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69027
+ */
+ PUBLIC(_CPU_Counter_read)
+SYM(_CPU_Counter_read):
+ sethi %hi(_SPARC_Counter + 4), %o1
+ ld [%o1 + %lo(_SPARC_Counter + 4)], %o1
+ or %o7, %g0, %g1
+ call %o1, 0
+ or %g1, %g0, %o7
+
+#if defined(RTEMS_PROFILING)
+ /*
+ * This is a workaround for:
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69027
+ */
+ PUBLIC(_SPARC_Counter_read_ISR_disabled)
+SYM(_SPARC_Counter_read_ISR_disabled):
+ sethi %hi(_SPARC_Counter), %o1
+ ld [%o1 + %lo(_SPARC_Counter)], %o1
+ or %o7, %g0, %g1
+ call %o1, 0
+ or %g1, %g0, %o7
+#endif
+
+ PUBLIC(_SPARC_Counter_read_default)
+SYM(_SPARC_Counter_read_default):
+ sethi %hi(_SPARC_Counter + 12), %o1
+ ld [%o1 + %lo(_SPARC_Counter + 12)], %o0
+ add %o0, 1, %o0
+ st %o0, [%o1 + %lo(_SPARC_Counter + 12)]
+ 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:
+ *
+ * CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void )
+ * {
+ * const SPARC_Counter *ctr;
+ * CPU_Counter_ticks ticks;
+ * CPU_Counter_ticks accumulated;
+ *
+ * ctr = &_SPARC_Counter;
+ * ticks = *ctr->counter_register;
+ * accumulated = ctr->accumulated;
+ *
+ * if ( ( *ctr->pending_register & ctr->pending_mask ) != 0 ) {
+ * ticks = *ctr->counter_register;
+ * accumulated += ctr->interval;
+ * }
+ *
+ * return accumulated - ticks;
+ * }
+ */
+ PUBLIC(_SPARC_Counter_read_clock_isr_disabled)
+SYM(_SPARC_Counter_read_clock_isr_disabled):
+ sethi %hi(_SPARC_Counter), %o5
+ or %o5, %lo(_SPARC_Counter), %o5
+ ld [%o5 + 8], %o3
+ ld [%o5 + 12], %o4
+ ld [%o5 + 16], %o2
+ ld [%o3], %o0
+ ld [%o4], %o1
+ btst %o1, %o2
+ bne .Lpending_isr_disabled
+ ld [%o5 + 20], %o4
+ jmp %o7 + 8
+ sub %o4, %o0, %o0
+.Lpending_isr_disabled:
+ ld [%o5 + 24], %o5
+ ld [%o3], %o0
+ add %o4, %o5, %o4
+ jmp %o7 + 8
+ sub %o4, %o0, %o0
+
+ /*
+ * For the corresponding C code see
+ * _SPARC_Counter_read_clock_isr_disabled() above.
+ */
+ PUBLIC(_SPARC_Counter_read_clock)
+ PUBLIC(_SPARC_Get_timecount_clock)
+SYM(_SPARC_Counter_read_clock):
+SYM(_SPARC_Get_timecount_clock):
+ sethi %hi(_SPARC_Counter), %o5
+ or %o5, %lo(_SPARC_Counter), %o5
+ ta SPARC_SWTRAP_IRQDIS
+ ld [%o5 + 8], %o3
+ ld [%o5 + 12], %o4
+ ld [%o5 + 16], %o2
+ ld [%o3], %o0
+ ld [%o4], %o1
+ btst %o1, %o2
+ bne .Lpending
+ ld [%o5 + 20], %o4
+ ta SPARC_SWTRAP_IRQEN
+#ifdef __FIX_LEON3FT_TN0018
+ /* A nop is added to work around the GRLIB-TN-0018 errata */
+ nop
+#endif
+ jmp %o7 + 8
+ sub %o4, %o0, %o0
+.Lpending:
+ ld [%o5 + 24], %o5
+ ld [%o3], %o0
+ ta SPARC_SWTRAP_IRQEN
+ 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