summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bsps/or1k/generic_or1k/clock/clockdrv.c8
-rw-r--r--bsps/shared/dev/cpucounter/cpucounterdiff.c23
-rw-r--r--bsps/sparc/erc32/clock/ckinit.c138
-rw-r--r--bsps/sparc/leon2/clock/ckinit.c93
-rw-r--r--bsps/sparc/leon3/clock/ckinit.c126
-rw-r--r--bsps/sparc/leon3/include/leon.h6
-rw-r--r--bsps/sparc/leon3/start/cpucounter.c32
-rw-r--r--c/src/lib/libbsp/sparc/leon2/Makefile.am1
-rw-r--r--cpukit/Makefile.am1
-rw-r--r--cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h7
-rw-r--r--cpukit/score/cpu/or1k/include/rtems/score/cpu.h7
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/cpu.h23
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h61
-rw-r--r--cpukit/score/cpu/sparc/sparc-counter-asm.S105
-rw-r--r--cpukit/score/cpu/sparc/sparc-counter.c48
15 files changed, 332 insertions, 347 deletions
diff --git a/bsps/or1k/generic_or1k/clock/clockdrv.c b/bsps/or1k/generic_or1k/clock/clockdrv.c
index 44365aa02c..7b8a07fd3d 100644
--- a/bsps/or1k/generic_or1k/clock/clockdrv.c
+++ b/bsps/or1k/generic_or1k/clock/clockdrv.c
@@ -109,14 +109,6 @@ static void generic_or1k_clock_initialize(void)
rtems_timecounter_install(&or1ksim_tc);
}
-CPU_Counter_ticks _CPU_Counter_difference(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-)
-{
- return second - first;
-}
-
#define Clock_driver_support_at_tick() generic_or1k_clock_at_tick()
#define Clock_driver_support_initialize_hardware() generic_or1k_clock_initialize()
diff --git a/bsps/shared/dev/cpucounter/cpucounterdiff.c b/bsps/shared/dev/cpucounter/cpucounterdiff.c
deleted file mode 100644
index d77945d5b8..0000000000
--- a/bsps/shared/dev/cpucounter/cpucounterdiff.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
- *
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#include <rtems/score/cpu.h>
-
-CPU_Counter_ticks _CPU_Counter_difference(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-)
-{
- return second - first;
-}
diff --git a/bsps/sparc/erc32/clock/ckinit.c b/bsps/sparc/erc32/clock/ckinit.c
index e7c5b07f33..6d6a335fed 100644
--- a/bsps/sparc/erc32/clock/ckinit.c
+++ b/bsps/sparc/erc32/clock/ckinit.c
@@ -24,103 +24,97 @@
#include <bsp.h>
#include <bspopts.h>
-#include <rtems/counter.h>
+#include <rtems/sysinit.h>
#include <rtems/timecounter.h>
#include <rtems/score/sparcimpl.h>
-#define ERC32_REAL_TIME_CLOCK_FREQUENCY 1000000
-
-/*
- * The Real Time Clock Counter Timer uses this trap type.
- */
-#define CLOCK_VECTOR ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK )
-
-#define Clock_driver_support_install_isr( _new ) \
- set_vector( _new, CLOCK_VECTOR, 1 )
-
-#define Clock_driver_support_set_interrupt_affinity( _online_processors ) \
- do { \
- (void) _online_processors; \
- } while (0)
-
extern int CLOCK_SPEED;
-static rtems_timecounter_simple erc32_tc;
+#define ERC32_REAL_TIME_CLOCK_FREQUENCY 1000000
-static uint32_t erc32_tc_get( rtems_timecounter_simple *tc )
-{
- return ERC32_MEC.Real_Time_Clock_Counter;
-}
+static struct timecounter erc32_tc;
-static bool erc32_tc_is_pending( rtems_timecounter_simple *tc )
+static void erc32_clock_init( void )
{
- return ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK );
+ struct timecounter *tc;
+
+ tc = &erc32_tc;
+ tc->tc_get_timecount = _SPARC_Get_timecount_clock;
+ tc->tc_counter_mask = 0xffffffff;
+ tc->tc_frequency = ERC32_REAL_TIME_CLOCK_FREQUENCY;
+ tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(tc);
}
-static uint32_t erc32_tc_get_timecount( struct timecounter *tc )
+uint32_t _CPU_Counter_frequency(void)
{
- return rtems_timecounter_simple_downcounter_get(
- tc,
- erc32_tc_get,
- erc32_tc_is_pending
- );
+ return ERC32_REAL_TIME_CLOCK_FREQUENCY;
}
-static void erc32_tc_at_tick( rtems_timecounter_simple *tc )
+static void erc32_clock_at_tick( void )
{
- /* Nothing to do */
-}
+ SPARC_Counter *counter;
+ rtems_interrupt_level level;
-static void erc32_tc_tick( void )
-{
- rtems_timecounter_simple_downcounter_tick(
- &erc32_tc,
- erc32_tc_get,
- erc32_tc_at_tick
- );
+ counter = &_SPARC_Counter_mutable;
+ rtems_interrupt_local_disable(level);
+
+ ERC32_Clear_interrupt( ERC32_INTERRUPT_REAL_TIME_CLOCK );
+ counter->accumulated += counter->interval;
+
+ rtems_interrupt_local_enable(level);
}
-static void erc32_counter_initialize( void )
+static void erc32_clock_initialize_early( void )
{
- _SPARC_Counter_initialize(
- _SPARC_Counter_read_address,
- _SPARC_Counter_difference_clock_period,
- &ERC32_MEC.Real_Time_Clock_Counter
+ SPARC_Counter *counter;
+
+ /* approximately 1 us per countdown */
+ ERC32_MEC.Real_Time_Clock_Scalar = CLOCK_SPEED - 1;
+ ERC32_MEC.Real_Time_Clock_Counter =
+ rtems_configuration_get_microseconds_per_tick();
+ ERC32_MEC_Set_Real_Time_Clock_Timer_Control(
+ ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING |
+ ERC32_MEC_TIMER_COUNTER_LOAD_SCALER |
+ ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER
+ );
+ ERC32_MEC_Set_Real_Time_Clock_Timer_Control(
+ ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING |
+ ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO
);
-}
-uint32_t _CPU_Counter_frequency(void)
-{
- return ERC32_REAL_TIME_CLOCK_FREQUENCY;
+ counter = &_SPARC_Counter_mutable;
+ 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,
+ counter->pending_register = &ERC32_MEC.Interrupt_Pending;
+ counter->pending_mask = UINT32_C(1) << ERC32_INTERRUPT_REAL_TIME_CLOCK;
+ counter->accumulated = rtems_configuration_get_microseconds_per_tick();
+ counter->interval = rtems_configuration_get_microseconds_per_tick();
}
-#define Clock_driver_support_initialize_hardware() \
+RTEMS_SYSINIT_ITEM(
+ erc32_clock_initialize_early,
+ RTEMS_SYSINIT_CPU_COUNTER,
+ RTEMS_SYSINIT_ORDER_FIRST
+);
+
+/*
+ * The Real Time Clock Counter Timer uses this trap type.
+ */
+#define CLOCK_VECTOR ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK )
+
+#define Clock_driver_support_install_isr( _new ) \
+ set_vector( _new, CLOCK_VECTOR, 1 )
+
+#define Clock_driver_support_set_interrupt_affinity( _online_processors ) \
do { \
- /* approximately 1 us per countdown */ \
- ERC32_MEC.Real_Time_Clock_Scalar = CLOCK_SPEED - 1; \
- ERC32_MEC.Real_Time_Clock_Counter = \
- rtems_configuration_get_microseconds_per_tick(); \
- \
- ERC32_MEC_Set_Real_Time_Clock_Timer_Control( \
- ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | \
- ERC32_MEC_TIMER_COUNTER_LOAD_SCALER | \
- ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER \
- ); \
- \
- ERC32_MEC_Set_Real_Time_Clock_Timer_Control( \
- ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | \
- ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO \
- ); \
- rtems_timecounter_simple_install( \
- &erc32_tc, \
- ERC32_REAL_TIME_CLOCK_FREQUENCY, \
- rtems_configuration_get_microseconds_per_tick(), \
- erc32_tc_get_timecount \
- ); \
- erc32_counter_initialize(); \
+ (void) _online_processors; \
} while (0)
-#define Clock_driver_timecounter_tick() erc32_tc_tick()
+#define Clock_driver_support_at_tick() erc32_clock_at_tick()
+
+#define Clock_driver_support_initialize_hardware() erc32_clock_init()
#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/sparc/leon2/clock/ckinit.c b/bsps/sparc/leon2/clock/ckinit.c
index f622975832..2707c7daa2 100644
--- a/bsps/sparc/leon2/clock/ckinit.c
+++ b/bsps/sparc/leon2/clock/ckinit.c
@@ -24,42 +24,73 @@
#include <bsp.h>
#include <bspopts.h>
+#include <rtems/sysinit.h>
#include <rtems/timecounter.h>
#include <rtems/score/sparcimpl.h>
-static rtems_timecounter_simple leon2_tc;
+extern int CLOCK_SPEED;
+
+#define LEON2_TIMER_1_FREQUENCY 1000000
+
+static struct timecounter leon2_tc;
-static uint32_t leon2_tc_get( rtems_timecounter_simple *tc )
+static void leon2_clock_init( void )
{
- return LEON_REG.Timer_Counter_1;
+ struct timecounter *tc;
+
+ tc = &leon2_tc;
+ tc->tc_get_timecount = _SPARC_Get_timecount_clock;
+ tc->tc_counter_mask = 0xffffffff;
+ tc->tc_frequency = LEON2_TIMER_1_FREQUENCY;
+ tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(tc);
}
-static bool leon2_tc_is_pending( rtems_timecounter_simple *tc )
+static void leon2_clock_at_tick( void )
{
- return LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 );
+ SPARC_Counter *counter;
+ rtems_interrupt_level level;
+
+ counter = &_SPARC_Counter_mutable;
+ rtems_interrupt_local_disable(level);
+
+ LEON_Clear_interrupt( LEON_INTERRUPT_TIMER1 );
+ counter->accumulated += counter->interval;
+
+ rtems_interrupt_local_enable(level);
}
-static uint32_t leon2_tc_get_timecount( struct timecounter *tc )
+static void leon2_clock_initialize_early( void )
{
- return rtems_timecounter_simple_downcounter_get(
- tc,
- leon2_tc_get,
- leon2_tc_is_pending
+ SPARC_Counter *counter;
+
+ LEON_REG.Timer_Reload_1 =
+ rtems_configuration_get_microseconds_per_tick() - 1;
+ LEON_REG.Timer_Control_1 = (
+ LEON_REG_TIMER_COUNTER_ENABLE_COUNTING |
+ LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO |
+ LEON_REG_TIMER_COUNTER_LOAD_COUNTER
);
-}
-static void leon2_tc_at_tick( rtems_timecounter_simple *tc )
-{
- /* Nothing to do */
+ counter = &_SPARC_Counter_mutable;
+ counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
+ counter->read = _SPARC_Counter_read_clock;
+ counter->counter_register = &LEON_REG.Timer_Counter_1;
+ counter->pending_register = &LEON_REG.Interrupt_Pending;
+ counter->pending_mask = UINT32_C(1) << LEON_INTERRUPT_TIMER1;
+ counter->accumulated = rtems_configuration_get_microseconds_per_tick();
+ counter->interval = rtems_configuration_get_microseconds_per_tick();
}
-static void leon2_tc_tick( void )
+RTEMS_SYSINIT_ITEM(
+ leon2_clock_initialize_early,
+ RTEMS_SYSINIT_CPU_COUNTER,
+ RTEMS_SYSINIT_ORDER_FIRST
+);
+
+uint32_t _CPU_Counter_frequency(void)
{
- rtems_timecounter_simple_downcounter_tick(
- &leon2_tc,
- leon2_tc_get,
- leon2_tc_at_tick
- );
+ return LEON2_TIMER_1_FREQUENCY;
}
/*
@@ -71,27 +102,9 @@ static void leon2_tc_tick( void )
#define Clock_driver_support_install_isr( _new ) \
set_vector( _new, CLOCK_VECTOR, 1 )
-extern int CLOCK_SPEED;
+#define Clock_driver_support_at_tick() leon2_clock_at_tick()
-#define Clock_driver_support_initialize_hardware() \
- do { \
- LEON_REG.Timer_Reload_1 = \
- rtems_configuration_get_microseconds_per_tick() - 1; \
- \
- LEON_REG.Timer_Control_1 = ( \
- LEON_REG_TIMER_COUNTER_ENABLE_COUNTING | \
- LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO | \
- LEON_REG_TIMER_COUNTER_LOAD_COUNTER \
- ); \
- rtems_timecounter_simple_install( \
- &leon2_tc, \
- 1000000, \
- rtems_configuration_get_microseconds_per_tick(), \
- leon2_tc_get_timecount \
- ); \
- } while (0)
-
-#define Clock_driver_timecounter_tick() leon2_tc_tick()
+#define Clock_driver_support_initialize_hardware() leon2_clock_init()
#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/sparc/leon3/clock/ckinit.c b/bsps/sparc/leon3/clock/ckinit.c
index 0cd78ea716..fecbf32c1b 100644
--- a/bsps/sparc/leon3/clock/ckinit.c
+++ b/bsps/sparc/leon3/clock/ckinit.c
@@ -27,6 +27,7 @@
#include <rtems/rtems/intr.h>
#include <ambapp.h>
#include <rtems/score/profiling.h>
+#include <rtems/score/sparcimpl.h>
#include <rtems/timecounter.h>
/* The LEON3 BSP Timer driver can rely on the Driver Manager if the
@@ -42,59 +43,7 @@ static int clkirq;
static void (*leon3_tc_tick)(void);
-static rtems_timecounter_simple leon3_tc;
-
-#ifndef RTEMS_SMP
-static uint32_t leon3_tc_get(rtems_timecounter_simple *tc)
-{
- return LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value;
-}
-
-static bool leon3_tc_is_pending(rtems_timecounter_simple *tc)
-{
- return LEON_Is_interrupt_pending(clkirq);
-}
-
-static void leon3_tc_at_tick( rtems_timecounter_simple *tc )
-{
- /* Nothing to do */
-}
-
-static uint32_t leon3_tc_get_timecount(struct timecounter *tc)
-{
- return rtems_timecounter_simple_downcounter_get(
- tc,
- leon3_tc_get,
- leon3_tc_is_pending
- );
-}
-
-static void leon3_tc_tick_simple(void)
-{
- rtems_timecounter_simple_downcounter_tick(
- &leon3_tc,
- leon3_tc_get,
- leon3_tc_at_tick
- );
-}
-#endif
-
-static uint32_t leon3_tc_get_timecount_up_counter(struct timecounter *tc)
-{
- return leon3_up_counter_low();
-}
-
-static uint32_t leon3_tc_get_timecount_irqmp(struct timecounter *tc)
-{
- return LEON3_IrqCtrl_Regs->timestamp[0].counter;
-}
-
-#ifdef RTEMS_SMP
-static uint32_t leon3_tc_get_timecount_second_timer(struct timecounter *tc)
-{
- return 0xffffffff - LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX + 1].value;
-}
-#endif
+static struct timecounter leon3_tc;
#ifdef RTEMS_PROFILING
#define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26))
@@ -146,12 +95,23 @@ static void leon3_tc_tick_irqmp_timestamp_init(void)
rtems_timecounter_tick();
}
-#ifdef RTEMS_SMP
-static void leon3_tc_tick_second_timer(void)
+static void leon3_tc_tick_default(void)
{
+#ifndef RTEMS_SMP
+ SPARC_Counter *counter;
+ rtems_interrupt_level level;
+
+ counter = &_SPARC_Counter_mutable;
+ rtems_interrupt_local_disable(level);
+
+ LEON3_IrqCtrl_Regs->iclear = counter->pending_mask;
+ counter->accumulated += counter->interval;
+
+ rtems_interrupt_local_enable(level);
+#endif
+
rtems_timecounter_tick();
}
-#endif
static void leon3_tc_do_tick(void)
{
@@ -196,9 +156,11 @@ static void leon3_clock_initialize(void)
{
volatile struct irqmp_timestamp_regs *irqmp_ts;
volatile struct gptimer_regs *gpt;
+ struct timecounter *tc;
irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
gpt = LEON3_Timer_Regs;
+ tc = &leon3_tc;
gpt->timer[LEON3_CLOCK_INDEX].reload =
rtems_configuration_get_microseconds_per_tick() - 1;
@@ -210,10 +172,8 @@ static void leon3_clock_initialize(void)
if (leon3_up_counter_is_available()) {
/* Use the LEON4 up-counter if available */
- leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_up_counter;
- leon3_tc.tc.tc_counter_mask = 0xffffffff;
- leon3_tc.tc.tc_frequency = leon3_up_counter_frequency();
- leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ tc->tc_get_timecount = _SPARC_Get_timecount_asr23;
+ tc->tc_frequency = leon3_up_counter_frequency();
#ifdef RTEMS_PROFILING
if (!leon3_irqmp_has_timestamp(irqmp_ts)) {
@@ -222,13 +182,11 @@ static void leon3_clock_initialize(void)
#endif
leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
- rtems_timecounter_install(&leon3_tc.tc);
} else if (leon3_irqmp_has_timestamp(irqmp_ts)) {
/* Use the interrupt controller timestamp counter if available */
- leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_irqmp;
- leon3_tc.tc.tc_counter_mask = 0xffffffff;
- leon3_tc.tc.tc_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev);
- leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ tc->tc_get_timecount = _SPARC_Get_timecount_up;
+ tc->tc_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev);
+
leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
/*
@@ -236,8 +194,6 @@ static void leon3_clock_initialize(void)
* counter. Use an arbitrary interrupt source.
*/
irqmp_ts->control = 0x1;
-
- rtems_timecounter_install(&leon3_tc.tc);
} else {
#ifdef RTEMS_SMP
/*
@@ -245,24 +201,32 @@ static void leon3_clock_initialize(void)
* controller. At least on SMP configurations we must use a second timer
* in free running mode for the timecounter.
*/
- gpt->timer[LEON3_CLOCK_INDEX + 1].ctrl =
+ gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl =
GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_IE;
- leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_second_timer;
- leon3_tc.tc.tc_counter_mask = 0xffffffff;
- leon3_tc.tc.tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
- leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- leon3_tc_tick = leon3_tc_tick_second_timer;
- rtems_timecounter_install(&leon3_tc.tc);
+
+ tc->tc_get_timecount = _SPARC_Get_timecount_down;
#else
- leon3_tc_tick = leon3_tc_tick_simple;
- rtems_timecounter_simple_install(
- &leon3_tc,
- LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER,
- rtems_configuration_get_microseconds_per_tick(),
- leon3_tc_get_timecount
- );
+ SPARC_Counter *counter;
+
+ counter = &_SPARC_Counter_mutable;
+ counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
+ counter->read = _SPARC_Counter_read_clock;
+ counter->counter_register = &gpt->timer[LEON3_CLOCK_INDEX].value;
+ counter->pending_register = &LEON3_IrqCtrl_Regs->ipend;
+ counter->pending_mask = UINT32_C(1) << clkirq;
+ counter->accumulated = rtems_configuration_get_microseconds_per_tick();
+ counter->interval = rtems_configuration_get_microseconds_per_tick();
+
+ tc->tc_get_timecount = _SPARC_Get_timecount_clock;
#endif
+
+ tc->tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER,
+ leon3_tc_tick = leon3_tc_tick_default;
}
+
+ tc->tc_counter_mask = 0xffffffff;
+ tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(tc);
}
#define Clock_driver_support_initialize_hardware() \
diff --git a/bsps/sparc/leon3/include/leon.h b/bsps/sparc/leon3/include/leon.h
index 758b760b0b..afe0d91ca4 100644
--- a/bsps/sparc/leon3/include/leon.h
+++ b/bsps/sparc/leon3/include/leon.h
@@ -333,6 +333,12 @@ extern rtems_interrupt_lock LEON3_IrqCtrl_Lock;
#define LEON3_CLOCK_INDEX 0
#endif
+#if defined(RTEMS_SMP)
+#define LEON3_COUNTER_GPTIMER_INDEX (LEON3_CLOCK_INDEX + 1)
+#else
+#define LEON3_COUNTER_GPTIMER_INDEX LEON3_CLOCK_INDEX
+#endif
+
/*
* We assume that a boot loader (usually GRMON) initialized the GPTIMER 0 to
* run with 1MHz. This is used to determine all clock frequencies of the PnP
diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index f583d9b0fb..007bb6d8ec 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2014, 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -29,46 +29,38 @@ static void leon3_counter_initialize(void)
{
volatile struct irqmp_timestamp_regs *irqmp_ts;
volatile struct gptimer_regs *gpt;
+ SPARC_Counter *counter;
irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
gpt = LEON3_Timer_Regs;
+ counter = &_SPARC_Counter_mutable;
leon3_up_counter_enable();
if (leon3_up_counter_is_available()) {
/* Use the LEON4 up-counter if available */
-
- _SPARC_Counter_initialize(
- _SPARC_Counter_read_asr23,
- _SPARC_Counter_difference_normal,
- NULL
- );
+ counter->read_isr_disabled = _SPARC_Counter_read_asr23;
+ counter->read = _SPARC_Counter_read_asr23;
leon3_counter_frequency = leon3_up_counter_frequency();
} else if (leon3_irqmp_has_timestamp(irqmp_ts)) {
/* Use the interrupt controller timestamp counter if available */
+ counter->read_isr_disabled = _SPARC_Counter_read_up;
+ counter->read = _SPARC_Counter_read_up;
+ counter->counter_register = &LEON3_IrqCtrl_Regs->timestamp[0].counter;
/* Enable interrupt timestamping for an arbitrary interrupt line */
irqmp_ts->control = 0x1;
- _SPARC_Counter_initialize(
- _SPARC_Counter_read_address,
- _SPARC_Counter_difference_normal,
- (volatile const uint32_t *) &irqmp_ts->counter
- );
-
leon3_counter_frequency = ambapp_freq_get(&ambapp_plb, LEON3_IrqCtrl_Adev);
} else if (gpt != NULL) {
/* Fall back to the first GPTIMER if available */
+ counter->read_isr_disabled = _SPARC_Counter_read_down;
+ counter->read = _SPARC_Counter_read_down;
+ counter->counter_register = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].value;
/* Enable timer just in case no clock driver is configured */
- gpt->timer[LEON3_CLOCK_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN;
-
- _SPARC_Counter_initialize(
- _SPARC_Counter_read_address,
- _SPARC_Counter_difference_clock_period,
- (volatile const uint32_t *) &gpt->timer[LEON3_CLOCK_INDEX].value
- );
+ gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN;
leon3_counter_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev) /
(gpt->scaler_reload + 1);
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index 7471007ef9..72946c03db 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -26,7 +26,6 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/bspstart.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bspgetworkarea.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterfrequency.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy-cpucounter.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/setvec.c
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 5e7d471329..188001aed7 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -1753,7 +1753,6 @@ librtemscpu_a_SOURCES += score/cpu/sparc/sparc-access.S
librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-validate.S
librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-volatile-clobber.S
librtemscpu_a_SOURCES += score/cpu/sparc/sparc-counter-asm.S
-librtemscpu_a_SOURCES += score/cpu/sparc/sparc-counter.c
librtemscpu_a_SOURCES += score/cpu/sparc/syscall.S
librtemscpu_a_SOURCES += score/cpu/sparc/window.S
diff --git a/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h
index 7ab09d990e..6b6094ae10 100644
--- a/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h
@@ -1219,10 +1219,13 @@ CPU_Counter_ticks _CPU_Counter_read( void );
*
* @return Returns second minus first modulo counter period.
*/
-CPU_Counter_ticks _CPU_Counter_difference(
+static inline CPU_Counter_ticks _CPU_Counter_difference(
CPU_Counter_ticks second,
CPU_Counter_ticks first
-);
+)
+{
+ return second - first;
+}
#ifdef RTEMS_SMP
/**
diff --git a/cpukit/score/cpu/or1k/include/rtems/score/cpu.h b/cpukit/score/cpu/or1k/include/rtems/score/cpu.h
index 0d1566a0c9..663a1755ba 100644
--- a/cpukit/score/cpu/or1k/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/or1k/include/rtems/score/cpu.h
@@ -712,10 +712,13 @@ uint32_t _CPU_Counter_frequency( void );
CPU_Counter_ticks _CPU_Counter_read( void );
-CPU_Counter_ticks _CPU_Counter_difference(
+static inline CPU_Counter_ticks _CPU_Counter_difference(
CPU_Counter_ticks second,
CPU_Counter_ticks first
-);
+)
+{
+ return second - first;
+}
/** Type that can store a 32-bit integer or a pointer. */
typedef uintptr_t CPU_Uint32ptr;
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
index 252aa4026e..abc813cfa5 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
@@ -1103,29 +1103,28 @@ uint32_t _CPU_Counter_frequency( void );
typedef CPU_Counter_ticks ( *SPARC_Counter_read )( void );
-typedef CPU_Counter_ticks ( *SPARC_Counter_difference )(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-);
-
/*
* 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 and difference functions. This
- * allows the use of dynamic hardware enumeration.
+ * an implementation of the CPU counter read function. This allows the use of
+ * dynamic hardware enumeration.
*/
typedef struct {
- SPARC_Counter_read counter_read;
- SPARC_Counter_difference counter_difference;
- volatile const CPU_Counter_ticks *counter_address;
+ 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 const SPARC_Counter _SPARC_Counter;
static inline CPU_Counter_ticks _CPU_Counter_read( void )
{
- return ( *_SPARC_Counter.counter_read )();
+ return ( *_SPARC_Counter.read )();
}
static inline CPU_Counter_ticks _CPU_Counter_difference(
@@ -1133,7 +1132,7 @@ static inline CPU_Counter_ticks _CPU_Counter_difference(
CPU_Counter_ticks first
)
{
- return ( *_SPARC_Counter.counter_difference )( second, first );
+ return second - first;
}
/** Type that can store a 32-bit integer or a pointer. */
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h
index 81b4441b25..edc03bd074 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -21,6 +21,8 @@
extern "C" {
#endif /* __cplusplus */
+struct timecounter;
+
/*
* Provides a mutable alias to _SPARC_Counter for use in
* _SPARC_Counter_initialize(). The _SPARC_Counter and _SPARC_Counter_mutable
@@ -28,40 +30,27 @@ extern "C" {
*/
extern SPARC_Counter _SPARC_Counter_mutable;
-CPU_Counter_ticks _SPARC_Counter_read_address( void );
+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 );
-CPU_Counter_ticks _SPARC_Counter_difference_normal(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-);
+uint32_t _SPARC_Get_timecount_up( struct timecounter * );
-CPU_Counter_ticks _SPARC_Counter_difference_clock_period(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-);
+uint32_t _SPARC_Get_timecount_down( struct timecounter * );
-/*
- * Returns always a value of one regardless of the parameters. This prevents
- * an infinite loop in rtems_counter_delay_ticks(). Its only a reasonably safe
- * default.
- */
-CPU_Counter_ticks _SPARC_Counter_difference_one(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-);
-
-static inline void _SPARC_Counter_initialize(
- SPARC_Counter_read counter_read,
- SPARC_Counter_difference counter_difference,
- volatile const CPU_Counter_ticks *counter_address
-)
-{
- _SPARC_Counter_mutable.counter_read = counter_read;
- _SPARC_Counter_mutable.counter_difference = counter_difference;
- _SPARC_Counter_mutable.counter_address = counter_address;
-}
+uint32_t _SPARC_Get_timecount_clock( struct timecounter * );
+
+uint32_t _SPARC_Get_timecount_asr23( struct timecounter * );
/*
* Defines the _SPARC_Counter and _SPARC_Counter_mutable global variables.
@@ -75,12 +64,16 @@ static inline void _SPARC_Counter_initialize(
"\t.section\t.data._SPARC_Counter,\"aw\",@progbits\n" \
"\t.align\t4\n" \
"\t.type\t_SPARC_Counter, #object\n" \
- "\t.size\t_SPARC_Counter, 12\n" \
+ "\t.size\t_SPARC_Counter, 28\n" \
"_SPARC_Counter:\n" \
"_SPARC_Counter_mutable:\n" \
- "\t.long\t_SPARC_Counter_read_address\n" \
- "\t.long\t_SPARC_Counter_difference_one\n" \
- "\t.long\t_SPARC_Counter\n" \
+ "\t.long\t_SPARC_Counter_read_default\n" \
+ "\t.long\t_SPARC_Counter_read_default\n" \
+ "\t.long\t0\n" \
+ "\t.long\t0\n" \
+ "\t.long\t0\n" \
+ "\t.long\t0\n" \
+ "\t.long\t0\n" \
"\t.previous\n" \
)
diff --git a/cpukit/score/cpu/sparc/sparc-counter-asm.S b/cpukit/score/cpu/sparc/sparc-counter-asm.S
index 8ed079f48b..6f3e61c12b 100644
--- a/cpukit/score/cpu/sparc/sparc-counter-asm.S
+++ b/cpukit/score/cpu/sparc/sparc-counter-asm.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -18,17 +18,116 @@
#include <rtems/asm.h>
+ /*
+ * All functions except _SPARC_Counter_read_clock() in this module are
+ * sometimes called with traps disabled.
+ */
+
.section ".text"
.align 4
- PUBLIC(_SPARC_Counter_read_address)
-SYM(_SPARC_Counter_read_address):
+ 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
+ jmp %o7 + 8
+ st %o0, [%o1 + %lo(_SPARC_Counter + 12)]
+
+ 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
+ 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
diff --git a/cpukit/score/cpu/sparc/sparc-counter.c b/cpukit/score/cpu/sparc/sparc-counter.c
deleted file mode 100644
index 9bc4061e9e..0000000000
--- a/cpukit/score/cpu/sparc/sparc-counter.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved.
- *
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-#include <rtems/score/sparcimpl.h>
-#include <rtems/config.h>
-
-CPU_Counter_ticks _SPARC_Counter_difference_normal(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-)
-{
- return second - first;
-}
-
-CPU_Counter_ticks _SPARC_Counter_difference_clock_period(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-)
-{
- CPU_Counter_ticks period;
-
- period = rtems_configuration_get_microseconds_per_tick();
-
- return ( first + period - second ) % period;
-}
-
-CPU_Counter_ticks _SPARC_Counter_difference_one(
- CPU_Counter_ticks second,
- CPU_Counter_ticks first
-)
-{
- return 1;
-}