summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c453
1 files changed, 0 insertions, 453 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c b/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
deleted file mode 100644
index 3f56d725d9..0000000000
--- a/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Clock Tick Device Driver using Timer Library implemented
- * by the GRLIB GPTIMER / LEON2 Timer drivers.
- *
- * COPYRIGHT (c) 2010 - 2017.
- * Cobham Gaisler AB.
- *
- * 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.
- *
- */
-
-/*
- * This is an implementation of the RTEMS "clockdrv_shell" interface for
- * LEON2/3/4 systems using the Driver Manager. It is clock hardware agnostic
- * and compatible with SMP and UP. Availability of free running counters is
- * probed and selected as needed.
- */
-#include <rtems.h>
-#include <rtems/timecounter.h>
-#include <rtems/clockdrv.h>
-#include <stdlib.h>
-#include <bsp.h>
-#include <bsp/tlib.h>
-
-#ifdef RTEMS_DRVMGR_STARTUP
-
-#if defined(LEON3)
-#include <leon.h>
-#endif
-
-struct ops {
- /*
- * Set up the free running counter using the Timecounter or Simple
- * Timecounter interface.
- */
- rtems_device_driver (*initialize_counter)(void);
-
- /*
- * Hardware-specific support at tick interrupt which runs early in Clock_isr.
- * It can for example be used to check if interrupt was actually caused by
- * the timer hardware. If return value is not RTEMS_SUCCESSFUL then Clock_isr
- * returns immediately. at_tick can be initialized with NULL.
- */
- rtems_device_driver (*at_tick)(void);
-
- /*
- * Typically calls rtems_timecounter_tick(). A specialized clock driver may
- * use for example rtems_timecounter_tick_simple() instead.
- */
- void (*timecounter_tick)(void);
-
- /*
- * Called when the clock driver exits. It can be used to stop functionality
- * started by initialize_counter. The tick timer is stopped by default.
- * shutdown_hardware can be initialized with NULL
- */
- void (*shutdown_hardware)(void);
-};
-
-/*
- * Different implementation depending on available free running counter for the
- * timecounter.
- *
- * NOTE: The clock interface is not compatible with shared interrupts on the
- * clock (tick) timer in SMP configuration.
- */
-
-/* "simple timecounter" interface. Only for non-SMP. */
-static const struct ops ops_simple;
-/* Hardware support up-counter using LEON3 %asr23. */
-static const struct ops ops_timetag;
-/* Timestamp counter available in some IRQ(A)MP instantiations. */
-static const struct ops ops_irqamp;
-/* Separate GPTIMER subtimer as timecounter */
-static const struct ops ops_subtimer;
-
-struct clock_priv {
- const struct ops *ops;
- /*
- * Timer number in Timer Library for tick timer used by this interface.
- * Defaults to the first Timer in the System.
- */
- int tlib_tick_index;
- /* Timer number for timecounter timer if separate GPTIMER subtimer is used */
- int tlib_counter_index;
- void *tlib_tick;
- void *tlib_counter;
- rtems_timecounter_simple tc_simple;
- struct timecounter tc;
-};
-static struct clock_priv priv;
-
-/** Common interface **/
-
-/* Set system clock timer instance */
-void Clock_timer_register(int timer_number)
-{
- priv.tlib_tick_index = timer_number;
- priv.tlib_counter_index = timer_number + 1;
-}
-
-static rtems_device_driver tlib_clock_find_timer(void)
-{
- /* Take Timer that should be used as system timer. */
- priv.tlib_tick = tlib_open(priv.tlib_tick_index);
- if (priv.tlib_tick == NULL) {
- /* System Clock Timer not found */
- return RTEMS_NOT_DEFINED;
- }
-
- /* Select which operation set to use */
-#ifndef RTEMS_SMP
- priv.ops = &ops_simple;
-#else
- /* When on LEON3 try to use dedicated hardware free running counter. */
- leon3_up_counter_enable();
- if (leon3_up_counter_is_available()) {
- priv.ops = &ops_timetag;
- return RTEMS_SUCCESSFUL;
- } else {
- volatile struct irqmp_timestamp_regs *irqmp_ts;
-
- irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
- if (leon3_irqmp_has_timestamp(irqmp_ts)) {
- priv.ops = &ops_irqamp;
- return RTEMS_SUCCESSFUL;
- }
- }
-
- /* Take another subtimer as the final option. */
- priv.ops = &ops_subtimer;
-#endif
-
- return RTEMS_SUCCESSFUL;
-}
-
-static rtems_device_driver tlib_clock_initialize_hardware(void)
-{
- /* Set tick rate in number of "Base-Frequency ticks" */
- tlib_set_freq(priv.tlib_tick, rtems_configuration_get_microseconds_per_tick());
- priv.ops->initialize_counter();
- tlib_start(priv.tlib_tick, 0);
-
- return RTEMS_SUCCESSFUL;
-}
-
-static rtems_device_driver tlib_clock_at_tick(void)
-{
- if (priv.ops->at_tick) {
- return priv.ops->at_tick();
- }
-
- return RTEMS_SUCCESSFUL;
-}
-
-static void tlib_clock_timecounter_tick(void)
-{
- priv.ops->timecounter_tick();
-}
-
-/* Return a value not equal to RTEMS_SUCCESFUL to make Clock_initialize fail. */
-static rtems_device_driver tlib_clock_install_isr(rtems_isr *isr)
-{
- int flags = 0;
-
-#ifdef RTEMS_SMP
- /* We shall broadcast the clock interrupt to all processors. */
- flags = TLIB_FLAGS_BROADCAST;
-#endif
- tlib_irq_register(priv.tlib_tick, isr, NULL, flags);
-
- return RTEMS_SUCCESSFUL;
-}
-
-static void tlib_clock_shutdown_hardware(void)
-{
- if (priv.tlib_tick) {
- tlib_stop(priv.tlib_tick);
- priv.tlib_tick = NULL;
- }
- if (priv.ops->shutdown_hardware) {
- priv.ops->shutdown_hardware();
- }
-}
-
-/** Simple counter **/
-static uint32_t simple_tlib_tc_get(rtems_timecounter_simple *tc)
-{
- unsigned int clicks = 0;
-
- if (priv.tlib_tick != NULL) {
- tlib_get_counter(priv.tlib_tick, &clicks);
- }
-
- return clicks;
-}
-
-static bool simple_tlib_tc_is_pending(rtems_timecounter_simple *tc)
-{
- bool pending = false;
-
- if (priv.tlib_tick != NULL) {
- pending = tlib_interrupt_pending(priv.tlib_tick, 0) != 0;
- }
-
- return pending;
-}
-
-static uint32_t simple_tlib_tc_get_timecount(struct timecounter *tc)
-{
- return rtems_timecounter_simple_downcounter_get(
- tc,
- simple_tlib_tc_get,
- simple_tlib_tc_is_pending
- );
-}
-
-static rtems_device_driver simple_initialize_counter(void)
-{
- uint64_t frequency;
- unsigned int tick_hz;
-
- frequency = 1000000;
- tick_hz = rtems_configuration_get_microseconds_per_tick();
-
- rtems_timecounter_simple_install(
- &priv.tc_simple,
- frequency,
- tick_hz,
- simple_tlib_tc_get_timecount
- );
-
- return RTEMS_NOT_DEFINED;
-}
-
-static void simple_tlib_tc_at_tick(rtems_timecounter_simple *tc)
-{
- /* Nothing to do */
-}
-
-/*
- * Support for shared interrupts. Ack IRQ at source, only handle interrupts
- * generated from the tick-timer. This is called early in Clock_isr.
- */
-static rtems_device_driver simple_at_tick(void)
-{
- if (tlib_interrupt_pending(priv.tlib_tick, 1) == 0) {
- return RTEMS_NOT_DEFINED;
- }
- return RTEMS_SUCCESSFUL;
-}
-
-static void simple_timecounter_tick(void)
-{
- rtems_timecounter_simple_downcounter_tick(
- &priv.tc_simple,
- simple_tlib_tc_get,
- simple_tlib_tc_at_tick
- );
-}
-
-static const struct ops ops_simple = {
- .initialize_counter = simple_initialize_counter,
- .at_tick = simple_at_tick,
- .timecounter_tick = simple_timecounter_tick,
- .shutdown_hardware = NULL,
-};
-
-/** Subtimer as counter **/
-static uint32_t subtimer_get_timecount(struct timecounter *tc)
-{
- unsigned int counter;
-
- tlib_get_counter(priv.tlib_counter, &counter);
-
- return 0xffffffff - counter;
-}
-
-static rtems_device_driver subtimer_initialize_counter(void)
-{
- unsigned int mask;
- unsigned int basefreq;
-
- if (priv.tlib_counter_index == priv.tlib_tick_index) {
- priv.tlib_counter_index = priv.tlib_tick_index + 1;
- }
- /* Take Timer that should be used as timecounter upcounter timer. */
- priv.tlib_counter = tlib_open(priv.tlib_counter_index);
- if (priv.tlib_counter == NULL) {
- /* Timecounter timer not found */
- return RTEMS_NOT_DEFINED;
- }
-
- /* Configure free running counter: GPTIMER */
- tlib_get_freq(priv.tlib_counter, &basefreq, NULL);
- tlib_get_widthmask(priv.tlib_counter, &mask);
-
- priv.tc.tc_get_timecount = subtimer_get_timecount;
- priv.tc.tc_counter_mask = mask;
- priv.tc.tc_frequency = basefreq;
- priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- rtems_timecounter_install(&priv.tc);
- /* Start free running counter */
- tlib_start(priv.tlib_counter, 0);
-
- return RTEMS_SUCCESSFUL;
-}
-
-static void subtimer_timecounter_tick(void)
-{
- rtems_timecounter_tick();
-}
-
-static void subtimer_shutdown_hardware(void)
-{
- if (priv.tlib_counter) {
- tlib_stop(priv.tlib_counter);
- priv.tlib_counter = NULL;
- }
-}
-
-static const struct ops ops_subtimer = {
- .initialize_counter = subtimer_initialize_counter,
- .timecounter_tick = subtimer_timecounter_tick,
- .shutdown_hardware = subtimer_shutdown_hardware,
-};
-
-#if defined(LEON3)
-/** DSU timetag as counter **/
-static uint32_t timetag_get_timecount(struct timecounter *tc)
-{
- return leon3_up_counter_low();
-}
-
-static rtems_device_driver timetag_initialize_counter(void)
-{
- /* Configure free running counter: timetag */
- priv.tc.tc_get_timecount = timetag_get_timecount;
- priv.tc.tc_counter_mask = 0xffffffff;
- priv.tc.tc_frequency = leon3_up_counter_frequency();
- priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- rtems_timecounter_install(&priv.tc);
-
- return RTEMS_SUCCESSFUL;
-}
-
-static void timetag_timecounter_tick(void)
-{
- rtems_timecounter_tick();
-}
-
-static const struct ops ops_timetag = {
- .initialize_counter = timetag_initialize_counter,
- .at_tick = NULL,
- .timecounter_tick = timetag_timecounter_tick,
- .shutdown_hardware = NULL,
-};
-#endif
-
-#if defined(LEON3)
-/** IRQ(A)MP timestamp as counter **/
-static uint32_t irqamp_get_timecount(struct timecounter *tc)
-{
- return LEON3_IrqCtrl_Regs->timestamp[0].counter;
-}
-
-static rtems_device_driver irqamp_initialize_counter(void)
-{
- volatile struct irqmp_timestamp_regs *irqmp_ts;
- static const uint32_t A_TSISEL_FIELD = 0xf;
-
- /* Configure free running counter: timetag */
- priv.tc.tc_get_timecount = irqamp_get_timecount;
- priv.tc.tc_counter_mask = 0xffffffff;
- priv.tc.tc_frequency = leon3_up_counter_frequency();
- priv.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- rtems_timecounter_install(&priv.tc);
-
- /*
- * The counter increments whenever a TSISEL field in a Timestamp Control
- * Register is non-zero.
- */
- irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
- irqmp_ts->control = A_TSISEL_FIELD;
-
- return RTEMS_SUCCESSFUL;
-}
-
-static void irqamp_timecounter_tick(void)
-{
- rtems_timecounter_tick();
-}
-
-static const struct ops ops_irqamp = {
- .initialize_counter = irqamp_initialize_counter,
- .at_tick = NULL,
- .timecounter_tick = irqamp_timecounter_tick,
- .shutdown_hardware = NULL,
-};
-#endif
-
-/** Interface to the Clock Driver Shell (dev/clock/clockimpl.h) **/
-#define Clock_driver_support_find_timer() \
- do { \
- rtems_device_driver ret; \
- ret = tlib_clock_find_timer(); \
- if (RTEMS_SUCCESSFUL != ret) { \
- return ret; \
- } \
- } while (0)
-
-#define Clock_driver_support_install_isr( isr ) \
- do { \
- rtems_device_driver ret; \
- ret = tlib_clock_install_isr( isr ); \
- if (RTEMS_SUCCESSFUL != ret) { \
- return ret; \
- } \
- } while (0)
-
-#define Clock_driver_support_set_interrupt_affinity(online_processors) \
- /* Done by tlib_clock_install_isr() */
-
-#define Clock_driver_support_initialize_hardware() \
- do { \
- rtems_device_driver ret; \
- ret = tlib_clock_initialize_hardware(); \
- if (RTEMS_SUCCESSFUL != ret) { \
- return ret; \
- } \
- } while (0)
-
-#define Clock_driver_support_shutdown_hardware() \
- tlib_clock_shutdown_hardware()
-
-#define Clock_driver_timecounter_tick() \
- tlib_clock_timecounter_tick()
-
-#define Clock_driver_support_at_tick() \
- do { \
- rtems_device_driver ret; \
- ret = tlib_clock_at_tick(); \
- if (RTEMS_SUCCESSFUL != ret) { \
- return; \
- } \
- } while (0)
-
-#include "../../../shared/dev/clock/clockimpl.h"
-
-#endif /* RTEMS_DRVMGR_STARTUP */
-