diff --git a/c/src/lib/libbsp/sparc/leon3/amba/amba.c b/c/src/lib/libbsp/sparc/leon3/amba/amba.c index 9706b25791..8655ee3bb5 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 #include +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 c7270cf7d9..6057c42f4b 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 */