[PATCH 005/111] leon3: make timer initialization configurable

Daniel Hellstrom daniel at gaisler.com
Thu Feb 26 16:38:07 UTC 2015


Its now possible to select which timer core will be used for
system clock timer and to control the timer prescaler that
affects all timer instances on that timer core.

The timer and interrupt controller AMBA devices are exported
to make it possible for other code to get detailed information.
For example the frequency of the timer and interrupt controller
is required by the cpucounter support.
---
 c/src/lib/libbsp/sparc/leon3/amba/amba.c    |   18 ++++++++++++++++--
 c/src/lib/libbsp/sparc/leon3/include/leon.h |   24 ++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/leon3/amba/amba.c b/c/src/lib/libbsp/sparc/leon3/amba/amba.c
index 9706b25..8655ee3 100644
--- a/c/src/lib/libbsp/sparc/leon3/amba/amba.c
+++ b/c/src/lib/libbsp/sparc/leon3/amba/amba.c
@@ -16,6 +16,9 @@
 #include <leon.h>
 #include <ambapp.h>
 
+unsigned int leon3_timer_prescaler __attribute__((weak)) = 0;
+int leon3_timer_core_index __attribute__((weak)) = 0;
+
 /* AMBA Plug&Play information description.
  *
  * After software has scanned AMBA PnP it builds a tree to make
@@ -28,6 +31,8 @@ rtems_interrupt_lock LEON3_IrqCtrl_Lock =
 
 /* Pointers to Interrupt Controller configuration registers */
 volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
+struct ambapp_dev *irqmp_dev;
+struct ambapp_dev *timer_dev;
 
 /*
  *  amba_initialize
@@ -64,6 +69,7 @@ void amba_initialize(void)
   }
 
   LEON3_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
+  irqmp_dev = adev;
   if ((LEON3_IrqCtrl_Regs->ampctrl >> 28) > 0) {
     /* IRQ Controller has support for multiple IRQ Controllers, each
      * CPU can be routed to different Controllers, we find out which
@@ -84,16 +90,24 @@ void amba_initialize(void)
   /* find GP Timer */
   adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
                                  VENDOR_GAISLER, GAISLER_GPTIMER,
-                                 ambapp_find_by_idx, NULL);
+                                 ambapp_find_by_idx, &leon3_timer_core_index);
   if (adev) {
     LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
+    timer_dev = adev;
 
     /* Register AMBA Bus Frequency */
     ambapp_freq_init(
       &ambapp_plb,
-      adev,
+      timer_dev,
       (LEON3_Timer_Regs->scaler_reload + 1)
         * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
     );
+    /* Set user prescaler configuration. Use this to increase accuracy of timer
+     * and accociated services like cpucounter.
+     * Note that minimum value is the number of timer instances present in
+     * GRTIMER/GPTIMER hardware. See HW manual.
+     */
+    if (leon3_timer_prescaler)
+      LEON3_Timer_Regs->scaler_reload = leon3_timer_prescaler;
   }
 }
diff --git a/c/src/lib/libbsp/sparc/leon3/include/leon.h b/c/src/lib/libbsp/sparc/leon3/include/leon.h
index c7270cf..6057c42 100644
--- a/c/src/lib/libbsp/sparc/leon3/include/leon.h
+++ b/c/src/lib/libbsp/sparc/leon3/include/leon.h
@@ -94,8 +94,11 @@ extern "C" {
 
 /* LEON3 Interrupt Controller */
 extern volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
+extern struct ambapp_dev *irqmp_dev;
+
 /* LEON3 GP Timer */
 extern volatile struct gptimer_regs *LEON3_Timer_Regs;
+extern struct ambapp_dev *timer_dev;
 
 /* LEON3 CPU Index of boot CPU */
 extern uint32_t LEON3_Cpu_Index;
@@ -308,6 +311,27 @@ extern int syscon_uart_index;
  */
 extern int debug_uart_index;
 
+/* Let user override which on-chip TIMER core will be used for system clock
+ * timer. This controls which timer core will be accociated with
+ * LEON3_Timer_Regs registers base address. This value will by destroyed during
+ * initialization.
+ *  0 = Default configuration. GPTIMER[0]
+ *  1 = GPTIMER[1]
+ *  2 = GPTIMER[2]
+ *  ...
+ */
+extern int leon3_timer_core_index;
+
+/* Let user override system clock timer prescaler. This affects all timer
+ * instances on the system clock timer core determined by
+ * leon3_timer_core_index.
+ *  0 = Default configuration. Use bootloader configured value.
+ *  N = Prescaler is set to N. N must not be less that number of timers.
+ *  8 = Prescaler is set to 8 (the fastest prescaler possible on all HW)
+ *  ...
+ */
+extern unsigned int leon3_timer_prescaler;
+
 void leon3_cpu_counter_initialize(void);
 
 /* GRLIB extended IRQ controller register */
-- 
1.7.0.4




More information about the devel mailing list