diff options
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.c | 453 |
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 */ - |