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 06/10/21 at 11:04:13

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
RevLine 
[41c9282]1/*
[9ea65119]2 *  AMBA Plug & Play Bus Driver
[41c9282]3 *
4 *  This driver hook performs bus scanning.
5 *
[9ea65119]6 *  COPYRIGHT (c) 2011.
7 *  Aeroflex Gaisler
[41c9282]8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
[c499856]11 *  http://www.rtems.org/license/LICENSE.
[41c9282]12 */
13
[0b83afe9]14#include <bsp.h>
[46d7fa5]15#include <bsp/fatal.h>
[f71f3d31]16#include <leon.h>
[31720925]17#include <grlib/ambapp.h>
[2c07f24]18#include <rtems/score/memory.h>
[a4fa007b]19#include <rtems/sysinit.h>
[41c9282]20
[2c07f24]21#include <string.h>
22
[5da315ff]23unsigned int leon3_timer_prescaler __attribute__((weak)) = 0;
24int leon3_timer_core_index __attribute__((weak)) = 0;
25
[9ea65119]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 */
[2c07f24]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}
[41c9282]60
[e428dc4a]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>
[31720925]66#include <grlib/ambapp_bus_grlib.h>
[e428dc4a]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  {
[bef5e23e]77    DRVMGR_RES_EMPTY,
[e428dc4a]78  }
79};
80
81/* GRLIB AMBA bus configuration (the LEON3 root bus configuration) */
[2c07f24]82struct grlib_config grlib_bus_config;
83
84static void ambapp_grlib_root_initialize( void )
[e428dc4a]85{
[2c07f24]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
[e428dc4a]96};
97#endif
98
[53ad908]99rtems_interrupt_lock LEON3_IrqCtrl_Lock =
100  RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
[2cb0877]101
[41c9282]102/* Pointers to Interrupt Controller configuration registers */
[226d48d8]103volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
[5564b5a]104struct ambapp_dev *LEON3_IrqCtrl_Adev;
[9fe249d]105volatile struct gptimer_regs *LEON3_Timer_Regs;
[5564b5a]106struct ambapp_dev *LEON3_Timer_Adev;
[41c9282]107
108/*
[d17733c]109 *  amba_initialize
[41c9282]110 *
[d17733c]111 *  Must be called just before drivers are initialized.
[44b06ca]112 *  Used to scan system bus. Probes for AHB masters, AHB slaves and
[41c9282]113 *  APB slaves. Addresses to configuration areas of the AHB masters,
[44b06ca]114 *  AHB slaves, APB slaves and APB master are storeds in
[41c9282]115 *  amba_ahb_masters, amba_ahb_slaves and amba.
116 */
117
[a4fa007b]118static void amba_initialize(void)
[41c9282]119{
[3722ff5a]120  int icsel;
[9ea65119]121  struct ambapp_dev *adev;
[2c07f24]122  struct ambapp_bus *plb;
[03bfdbb]123
[2c07f24]124  plb = ambapp_plb();
[41c9282]125
[684b54a]126  /* Find LEON3 Interrupt controller */
[2c07f24]127  adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
[9ea65119]128                                 VENDOR_GAISLER, GAISLER_IRQMP,
129                                 ambapp_find_by_idx, NULL);
130  if (adev == NULL) {
[684b54a]131    /* PANIC IRQ controller not found!
132     *
133     *  What else can we do but stop ...
134     */
[46d7fa5]135    bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER);
[41c9282]136  }
[44b06ca]137
[226d48d8]138  LEON3_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
[5564b5a]139  LEON3_IrqCtrl_Adev = adev;
[3722ff5a]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  }
[ead16ae1]150  LEON3_IrqCtrl_Regs->mask[LEON3_Cpu_Index] = 0;
151  LEON3_IrqCtrl_Regs->force[LEON3_Cpu_Index] = 0;
152  LEON3_IrqCtrl_Regs->iclear = 0xffffffff;
[684b54a]153
[95518e59]154  /* Init Extended IRQ controller if available */
155  leon3_ext_irq_init();
156
[ad6a58d]157  /* find GP Timer */
[2c07f24]158  adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
[9ea65119]159                                 VENDOR_GAISLER, GAISLER_GPTIMER,
[5da315ff]160                                 ambapp_find_by_idx, &leon3_timer_core_index);
[9ea65119]161  if (adev) {
[226d48d8]162    LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
[5564b5a]163    LEON3_Timer_Adev = adev;
[9ea65119]164
165    /* Register AMBA Bus Frequency */
[0a2096b]166    ambapp_freq_init(
[2c07f24]167      plb,
[5564b5a]168      LEON3_Timer_Adev,
[0a2096b]169      (LEON3_Timer_Regs->scaler_reload + 1)
170        * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
171    );
[5da315ff]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;
[ad6a58d]179  }
[41c9282]180}
[a4fa007b]181
182RTEMS_SYSINIT_ITEM(
183  amba_initialize,
[2c07f24]184  RTEMS_SYSINIT_BSP_EARLY,
185  RTEMS_SYSINIT_ORDER_MIDDLE
[a4fa007b]186);
Note: See TracBrowser for help on using the repository browser.