source: rtems/c/src/lib/libbsp/sparc/leon3/amba/amba.c @ e51eb80

4.115
Last change on this file since e51eb80 was 5da315ff, checked in by Daniel Hellstrom <daniel@…>, on 02/19/15 at 09:06:54

leon3: make timer initialization configurable

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.

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/*
2 *  AMBA Plug & Play Bus Driver
3 *
4 *  This driver hook performs bus scanning.
5 *
6 *  COPYRIGHT (c) 2011.
7 *  Aeroflex Gaisler
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 */
13
14#include <bsp.h>
15#include <bsp/fatal.h>
16#include <leon.h>
17#include <ambapp.h>
18
19unsigned int leon3_timer_prescaler __attribute__((weak)) = 0;
20int leon3_timer_core_index __attribute__((weak)) = 0;
21
22/* AMBA Plug&Play information description.
23 *
24 * After software has scanned AMBA PnP it builds a tree to make
25 * it easier for drivers to work with the bus architecture.
26 */
27struct ambapp_bus ambapp_plb;
28
29rtems_interrupt_lock LEON3_IrqCtrl_Lock =
30  RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
31
32/* Pointers to Interrupt Controller configuration registers */
33volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
34struct ambapp_dev *irqmp_dev;
35struct ambapp_dev *timer_dev;
36
37/*
38 *  amba_initialize
39 *
40 *  Must be called just before drivers are initialized.
41 *  Used to scan system bus. Probes for AHB masters, AHB slaves and
42 *  APB slaves. Addresses to configuration areas of the AHB masters,
43 *  AHB slaves, APB slaves and APB master are storeds in
44 *  amba_ahb_masters, amba_ahb_slaves and amba.
45 */
46
47void amba_initialize(void)
48{
49  int icsel;
50  struct ambapp_dev *adev;
51
52  /* Scan AMBA Plug&Play read-only information. The routine builds a PnP
53   * tree into ambapp_plb in RAM, after this we never access the PnP
54   * information in hardware directly any more.
55   * Since on Processor Local Bus (PLB) memory mapping is 1:1
56   */
57  ambapp_scan(&ambapp_plb, LEON3_IO_AREA, NULL, NULL);
58
59  /* Find LEON3 Interrupt controller */
60  adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
61                                 VENDOR_GAISLER, GAISLER_IRQMP,
62                                 ambapp_find_by_idx, NULL);
63  if (adev == NULL) {
64    /* PANIC IRQ controller not found!
65     *
66     *  What else can we do but stop ...
67     */
68    bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER);
69  }
70
71  LEON3_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
72  irqmp_dev = adev;
73  if ((LEON3_IrqCtrl_Regs->ampctrl >> 28) > 0) {
74    /* IRQ Controller has support for multiple IRQ Controllers, each
75     * CPU can be routed to different Controllers, we find out which
76     * controller by looking at the IRQCTRL Select Register for this CPU.
77     * Each Controller is located at a 4KByte offset.
78     */
79    icsel = LEON3_IrqCtrl_Regs->icsel[LEON3_Cpu_Index/8];
80    icsel = (icsel >> ((7 - (LEON3_Cpu_Index & 0x7)) * 4)) & 0xf;
81    LEON3_IrqCtrl_Regs += icsel;
82  }
83  LEON3_IrqCtrl_Regs->mask[LEON3_Cpu_Index] = 0;
84  LEON3_IrqCtrl_Regs->force[LEON3_Cpu_Index] = 0;
85  LEON3_IrqCtrl_Regs->iclear = 0xffffffff;
86
87  /* Init Extended IRQ controller if available */
88  leon3_ext_irq_init();
89
90  /* find GP Timer */
91  adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
92                                 VENDOR_GAISLER, GAISLER_GPTIMER,
93                                 ambapp_find_by_idx, &leon3_timer_core_index);
94  if (adev) {
95    LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
96    timer_dev = adev;
97
98    /* Register AMBA Bus Frequency */
99    ambapp_freq_init(
100      &ambapp_plb,
101      timer_dev,
102      (LEON3_Timer_Regs->scaler_reload + 1)
103        * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
104    );
105    /* Set user prescaler configuration. Use this to increase accuracy of timer
106     * and accociated services like cpucounter.
107     * Note that minimum value is the number of timer instances present in
108     * GRTIMER/GPTIMER hardware. See HW manual.
109     */
110    if (leon3_timer_prescaler)
111      LEON3_Timer_Regs->scaler_reload = leon3_timer_prescaler;
112  }
113}
Note: See TracBrowser for help on using the repository browser.