diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-06-20 10:08:39 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-06-21 15:54:18 +0200 |
commit | 9460333e9910471eda010423dcb493f758d997d4 (patch) | |
tree | d479396b21572626f835e0d78794a9811129661a /c/src/lib/libbsp/sparc/leon3 | |
parent | bsp/leon3: Fix LEON3_Cpu_Index initialization (diff) | |
download | rtems-9460333e9910471eda010423dcb493f758d997d4.tar.bz2 |
sparc: Rework CPU counter support
Rework CPU counter support to enable use of the GR740 up-counter via
%asr22 and %asr23.
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/sparc/leon3/include/leon.h | 47 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/leon3/startup/bspstart.c | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c | 95 |
3 files changed, 91 insertions, 53 deletions
diff --git a/c/src/lib/libbsp/sparc/leon3/include/leon.h b/c/src/lib/libbsp/sparc/leon3/include/leon.h index ba0673fa75..b7511638eb 100644 --- a/c/src/lib/libbsp/sparc/leon3/include/leon.h +++ b/c/src/lib/libbsp/sparc/leon3/include/leon.h @@ -387,8 +387,6 @@ extern int leon3_timer_core_index; */ extern unsigned int leon3_timer_prescaler; -void leon3_cpu_counter_initialize(void); - /* GRLIB extended IRQ controller register */ void leon3_ext_irq_init(void); @@ -457,6 +455,51 @@ static inline bool leon3_irqmp_has_timestamp( return (irqmp_ts->control >> 27) > 0; } +static inline uint32_t leon3_up_counter_low(void) +{ + uint32_t asr23; + + __asm__ volatile ( + "mov %%asr23, %0" + : "=&r" (asr23) + ); + + return asr23; +} + +static inline uint32_t leon3_up_counter_high(void) +{ + uint32_t asr22; + + __asm__ volatile ( + "mov %%asr22, %0" + : "=&r" (asr22) + ); + + return asr22; +} + +static inline void leon3_up_counter_enable(void) +{ + __asm__ volatile ( + "mov %g0, %asr23" + ); +} + +static inline bool leon3_up_counter_is_available(void) +{ + return leon3_up_counter_low() != leon3_up_counter_low(); +} + +static inline uint32_t leon3_up_counter_frequency(void) +{ + /* + * For simplicity, assume that the interrupt controller uses the processor + * clock. This is at least true on the GR740. + */ + return ambapp_freq_get(&ambapp_plb, LEON3_IrqCtrl_Adev); +} + #endif /* !ASM */ #ifdef __cplusplus diff --git a/c/src/lib/libbsp/sparc/leon3/startup/bspstart.c b/c/src/lib/libbsp/sparc/leon3/startup/bspstart.c index 35fe233561..80c2bc004e 100644 --- a/c/src/lib/libbsp/sparc/leon3/startup/bspstart.c +++ b/c/src/lib/libbsp/sparc/leon3/startup/bspstart.c @@ -58,8 +58,6 @@ static inline int set_snooping(void) void bsp_start( void ) { CPU_SPARC_HAS_SNOOPING = set_snooping(); - - leon3_cpu_counter_initialize(); } static void leon3_cpu_index_init(void) diff --git a/c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c b/c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c index ea0e67118d..53d921a66a 100644 --- a/c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c +++ b/c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -15,69 +15,66 @@ #include <leon.h> #include <rtems/counter.h> +#include <rtems/sysinit.h> -static CPU_Counter_ticks timestamp_counter_difference( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) +static void leon3_counter_initialize(void) { - return second - first; -} - -static CPU_Counter_ticks clock_counter_difference( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - CPU_Counter_ticks period = rtems_configuration_get_microseconds_per_tick(); + volatile struct irqmp_timestamp_regs *irqmp_ts; + volatile struct gptimer_regs *gpt; + unsigned int freq; - return (first + period - second) % period; -} + irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0]; + gpt = LEON3_Timer_Regs; -static void gpt_counter_initialize( - volatile struct gptimer_regs *gpt, - size_t timer_index, - uint32_t frequency, - SPARC_Counter_difference counter_difference -) -{ - _SPARC_Counter_initialize( - (volatile const uint32_t *) &gpt->timer[timer_index].value, - counter_difference - ); + leon3_up_counter_enable(); - rtems_counter_initialize_converter(frequency); -} + if (leon3_up_counter_is_available()) { + /* Use the LEON4 up-counter if available */ -void leon3_cpu_counter_initialize(void) -{ - volatile struct irqmp_timestamp_regs *irqmp_ts = - &LEON3_IrqCtrl_Regs->timestamp[0]; - unsigned int freq; + _SPARC_Counter_initialize( + _SPARC_Counter_read_asr23, + _SPARC_Counter_difference_normal, + NULL + ); - if (leon3_irqmp_has_timestamp(irqmp_ts)) { + freq = leon3_up_counter_frequency(); + rtems_counter_initialize_converter(freq); + } else if (leon3_irqmp_has_timestamp(irqmp_ts)) { /* Use the interrupt controller timestamp counter if available */ /* Enable interrupt timestamping for an arbitrary interrupt line */ irqmp_ts->control = 0x1; _SPARC_Counter_initialize( - (volatile const uint32_t *) &irqmp_ts->counter, - timestamp_counter_difference + _SPARC_Counter_read_address, + _SPARC_Counter_difference_normal, + (volatile const uint32_t *) &irqmp_ts->counter ); - /* Get and set the frequency */ - rtems_counter_initialize_converter( - ambapp_freq_get(&ambapp_plb, LEON3_IrqCtrl_Adev)); - } else if (LEON3_Timer_Regs != NULL) { - /* Fall back to the first GPTIMER if available */ - freq = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev); + freq = ambapp_freq_get(&ambapp_plb, LEON3_IrqCtrl_Adev); + rtems_counter_initialize_converter(freq); + } else if (gpt != NULL) { + /* Fall back to the first GPTIMER if available */ + + _SPARC_Counter_initialize( + _SPARC_Counter_read_address, + _SPARC_Counter_difference_clock_period, + (volatile const uint32_t *) &gpt->timer[LEON3_CLOCK_INDEX].value + ); - gpt_counter_initialize( - LEON3_Timer_Regs, - LEON3_CLOCK_INDEX, - freq / (LEON3_Timer_Regs->scaler_reload - 1), - clock_counter_difference - ); + freq = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev); + rtems_counter_initialize_converter(freq / (gpt->scaler_reload - 1)); } } + +RTEMS_SYSINIT_ITEM( + leon3_counter_initialize, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_THIRD +); + +SPARC_Counter _SPARC_Counter = { + .counter_read = _SPARC_Counter_read_address, + .counter_difference = _SPARC_Counter_difference_one, + .counter_address = (uint32_t *) &_SPARC_Counter +}; |