diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-15 14:29:15 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-15 14:32:16 +0100 |
commit | 5a0b27ed11d01dc734589ac42339da38b8693aa3 (patch) | |
tree | 8d064f2b279e81812d49c745c1c43a36dd9cd8c6 | |
parent | bsp/beatnik: Delete unused linkcmds file (diff) | |
download | rtems-5a0b27ed11d01dc734589ac42339da38b8693aa3.tar.bz2 |
bsp/leon3: Clock driver workaround for GR712RC
-rw-r--r-- | c/src/lib/libbsp/sparc/leon3/clock/ckinit.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c index 4ef29d33ef..ef24ee4303 100644 --- a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c +++ b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c @@ -41,10 +41,11 @@ /* LEON3 Timer system interrupt number */ static int clkirq; -static bool leon3_tc_use_irqmp; +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; @@ -55,6 +56,11 @@ 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( @@ -64,12 +70,29 @@ static uint32_t leon3_tc_get_timecount(struct timecounter *tc) ); } +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_irqmp(struct timecounter *tc) { return LEON3_IrqCtrl_Regs->timestamp[0].counter; } -static void leon3_clock_profiling_interrupt_delay(void) +#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 void leon3_tc_tick_irqmp_timestamp(void) { #ifdef RTEMS_PROFILING /* @@ -90,7 +113,7 @@ static void leon3_clock_profiling_interrupt_delay(void) irqmp_ts->control |= s1_s2; _Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first); - } else if (state == 1 && leon3_irqmp_has_timestamp(irqmp_ts)) { + } else if (state == 1) { unsigned int ks = 1U << 5; state = 0; @@ -100,25 +123,20 @@ static void leon3_clock_profiling_interrupt_delay(void) state = 2; } #endif + + rtems_timecounter_tick(); } -static void leon3_tc_at_tick( rtems_timecounter_simple *tc ) +#ifdef RTEMS_SMP +static void leon3_tc_tick_second_timer(void) { - leon3_clock_profiling_interrupt_delay(); + rtems_timecounter_tick(); } +#endif -static void leon3_tc_tick(void) +static void leon3_tc_do_tick(void) { - if (leon3_tc_use_irqmp) { - leon3_clock_profiling_interrupt_delay(); - rtems_timecounter_tick(); - } else { - rtems_timecounter_simple_downcounter_tick( - &leon3_tc, - leon3_tc_get, - leon3_tc_at_tick - ); - } + (*leon3_tc_tick)(); } #define Adjust_clkirq_for_node() do { clkirq += LEON3_CLOCK_INDEX; } while(0) @@ -183,15 +201,32 @@ static void leon3_clock_initialize(void) 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; - leon3_tc_use_irqmp = true; + leon3_tc_tick = leon3_tc_tick_irqmp_timestamp; rtems_timecounter_install(&leon3_tc.tc); } else { +#ifdef RTEMS_SMP + /* + * The GR712RC for example has no timestamp unit in the interrupt + * controller. At least on SMP configurations we must use a second timer + * in free running mode for the timecounter. + */ + LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX + 1].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); +#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 ); +#endif } } @@ -204,7 +239,7 @@ static void leon3_clock_initialize(void) LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl = 0; \ } while (0) -#define Clock_driver_timecounter_tick() leon3_tc_tick() +#define Clock_driver_timecounter_tick() leon3_tc_do_tick() #include "../../../shared/clockdrv_shell.h" |