source: rtems/bsps/sparc/leon3/start/amba.c @ 2c07f24

Last change on this file since 2c07f24 was 2c07f24, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 10, 2021 at 11:04:13 AM

grlib: Add ambapp_plb()

Replace the global variable ambapp_plb with a function to allow an automatic on
demand initialization.

  • Property mode set to 100644
File size: 5.4 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 <grlib/ambapp.h>
18#include <rtems/score/memory.h>
19#include <rtems/sysinit.h>
20
21#include <string.h>
22
23unsigned int leon3_timer_prescaler __attribute__((weak)) = 0;
24int leon3_timer_core_index __attribute__((weak)) = 0;
25
26/* AMBA Plug&Play information description.
27 *
28 * After software has scanned AMBA PnP it builds a tree to make
29 * it easier for drivers to work with the bus architecture.
30 */
31static struct ambapp_bus ambapp_plb_instance;
32
33static void *ambapp_plb_alloc( size_t size )
34{
35  return _Memory_Allocate( _Memory_Get(), size, CPU_HEAP_ALIGNMENT );
36}
37
38struct ambapp_bus *ambapp_plb( void )
39{
40  struct ambapp_bus *plb;
41
42  plb = &ambapp_plb_instance;
43
44  if ( plb->root == NULL ) {
45    struct ambapp_context ctx;
46
47    ctx.copy_from_device = (ambapp_memcpy_t) memcpy;
48    ctx.alloc = ambapp_plb_alloc;
49
50    /* Scan AMBA Plug&Play read-only information. The routine builds a PnP
51     * tree into ambapp_plb in RAM, after this we never access the PnP
52     * information in hardware directly any more.
53     * Since on Processor Local Bus (PLB) memory mapping is 1:1
54     */
55    ambapp_scan( plb, LEON3_IO_AREA, &ctx, NULL );
56  }
57
58  return plb;
59}
60
61/* If RTEMS_DRVMGR_STARTUP is defined extra code is added that
62 * registers the GRLIB AMBA PnP bus driver as root driver.
63 */
64#ifdef RTEMS_DRVMGR_STARTUP
65#include <drvmgr/drvmgr.h>
66#include <grlib/ambapp_bus_grlib.h>
67
68/* Driver resources configuration for AMBA root bus. It is declared weak
69 * so that the user may override it, if the defualt settings are not
70 * enough.
71 */
72struct drvmgr_bus_res grlib_drv_resources __attribute__((weak)) =
73{
74  .next = NULL,
75  .resource =
76  {
77    DRVMGR_RES_EMPTY,
78  }
79};
80
81/* GRLIB AMBA bus configuration (the LEON3 root bus configuration) */
82struct grlib_config grlib_bus_config;
83
84static void ambapp_grlib_root_initialize( void )
85{
86  /* Register Root bus, Use GRLIB AMBA PnP bus as root bus for LEON3 */
87  grlib_bus_config.abus = ambapp_plb();
88  grlib_bus_config.resources = &grlib_drv_resources;
89  ambapp_grlib_root_register(&grlib_bus_config);
90}
91
92RTEMS_SYSINIT_ITEM(
93  ambapp_grlib_root_initialize,
94  RTEMS_SYSINIT_BSP_START,
95  RTEMS_SYSINIT_ORDER_SECOND
96};
97#endif
98
99rtems_interrupt_lock LEON3_IrqCtrl_Lock =
100  RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
101
102/* Pointers to Interrupt Controller configuration registers */
103volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
104struct ambapp_dev *LEON3_IrqCtrl_Adev;
105volatile struct gptimer_regs *LEON3_Timer_Regs;
106struct ambapp_dev *LEON3_Timer_Adev;
107
108/*
109 *  amba_initialize
110 *
111 *  Must be called just before drivers are initialized.
112 *  Used to scan system bus. Probes for AHB masters, AHB slaves and
113 *  APB slaves. Addresses to configuration areas of the AHB masters,
114 *  AHB slaves, APB slaves and APB master are storeds in
115 *  amba_ahb_masters, amba_ahb_slaves and amba.
116 */
117
118static void amba_initialize(void)
119{
120  int icsel;
121  struct ambapp_dev *adev;
122  struct ambapp_bus *plb;
123
124  plb = ambapp_plb();
125
126  /* Find LEON3 Interrupt controller */
127  adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
128                                 VENDOR_GAISLER, GAISLER_IRQMP,
129                                 ambapp_find_by_idx, NULL);
130  if (adev == NULL) {
131    /* PANIC IRQ controller not found!
132     *
133     *  What else can we do but stop ...
134     */
135    bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER);
136  }
137
138  LEON3_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
139  LEON3_IrqCtrl_Adev = adev;
140  if ((LEON3_IrqCtrl_Regs->ampctrl >> 28) > 0) {
141    /* IRQ Controller has support for multiple IRQ Controllers, each
142     * CPU can be routed to different Controllers, we find out which
143     * controller by looking at the IRQCTRL Select Register for this CPU.
144     * Each Controller is located at a 4KByte offset.
145     */
146    icsel = LEON3_IrqCtrl_Regs->icsel[LEON3_Cpu_Index/8];
147    icsel = (icsel >> ((7 - (LEON3_Cpu_Index & 0x7)) * 4)) & 0xf;
148    LEON3_IrqCtrl_Regs += icsel;
149  }
150  LEON3_IrqCtrl_Regs->mask[LEON3_Cpu_Index] = 0;
151  LEON3_IrqCtrl_Regs->force[LEON3_Cpu_Index] = 0;
152  LEON3_IrqCtrl_Regs->iclear = 0xffffffff;
153
154  /* Init Extended IRQ controller if available */
155  leon3_ext_irq_init();
156
157  /* find GP Timer */
158  adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
159                                 VENDOR_GAISLER, GAISLER_GPTIMER,
160                                 ambapp_find_by_idx, &leon3_timer_core_index);
161  if (adev) {
162    LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
163    LEON3_Timer_Adev = adev;
164
165    /* Register AMBA Bus Frequency */
166    ambapp_freq_init(
167      plb,
168      LEON3_Timer_Adev,
169      (LEON3_Timer_Regs->scaler_reload + 1)
170        * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
171    );
172    /* Set user prescaler configuration. Use this to increase accuracy of timer
173     * and accociated services like cpucounter.
174     * Note that minimum value is the number of timer instances present in
175     * GRTIMER/GPTIMER hardware. See HW manual.
176     */
177    if (leon3_timer_prescaler)
178      LEON3_Timer_Regs->scaler_reload = leon3_timer_prescaler;
179  }
180}
181
182RTEMS_SYSINIT_ITEM(
183  amba_initialize,
184  RTEMS_SYSINIT_BSP_EARLY,
185  RTEMS_SYSINIT_ORDER_MIDDLE
186);
Note: See TracBrowser for help on using the repository browser.