summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-15 14:29:15 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-15 14:32:16 +0100
commit5a0b27ed11d01dc734589ac42339da38b8693aa3 (patch)
tree8d064f2b279e81812d49c745c1c43a36dd9cd8c6
parentbsp/beatnik: Delete unused linkcmds file (diff)
downloadrtems-5a0b27ed11d01dc734589ac42339da38b8693aa3.tar.bz2
bsp/leon3: Clock driver workaround for GR712RC
-rw-r--r--c/src/lib/libbsp/sparc/leon3/clock/ckinit.c71
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"