diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2023-09-14 16:08:53 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2023-10-20 11:16:54 +0200 |
commit | b6dc4b47077803cde93648016d15ce3992573d03 (patch) | |
tree | 425c75b086ca6c211490c7a73b0c96746dba91d5 /bsps/sparc | |
parent | bsps/leon3: Optional IRQ(A)MP timestamp support (diff) | |
download | rtems-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.c | 8 | ||||
-rw-r--r-- | bsps/sparc/include/bsp/sparc-counter.h | 101 | ||||
-rw-r--r-- | bsps/sparc/leon2/clock/ckinit.c | 8 | ||||
-rw-r--r-- | bsps/sparc/leon3/clock/ckinit.c | 6 | ||||
-rw-r--r-- | bsps/sparc/leon3/start/cpucounter.c | 4 | ||||
-rw-r--r-- | bsps/sparc/shared/start/sparc-counter-asm.S | 177 |
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 |