Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:08

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  AMBA Plug & Play Bus Driver
0005  *
0006  *  This driver hook performs bus scanning.
0007  *
0008  *  COPYRIGHT (c) 2011.
0009  *  Aeroflex Gaisler
0010  *
0011  * Redistribution and use in source and binary forms, with or without
0012  * modification, are permitted provided that the following conditions
0013  * are met:
0014  * 1. Redistributions of source code must retain the above copyright
0015  *    notice, this list of conditions and the following disclaimer.
0016  * 2. Redistributions in binary form must reproduce the above copyright
0017  *    notice, this list of conditions and the following disclaimer in the
0018  *    documentation and/or other materials provided with the distribution.
0019  *
0020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0021  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0023  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0024  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0025  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0026  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0027  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0028  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0029  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0030  * POSSIBILITY OF SUCH DAMAGE.
0031  */
0032 
0033 #include <bsp.h>
0034 #include <bsp/fatal.h>
0035 #include <leon.h>
0036 #include <grlib/ambapp.h>
0037 #include <rtems/score/memory.h>
0038 #include <rtems/sysinit.h>
0039 
0040 #include <string.h>
0041 
0042 #if !defined(LEON3_GPTIMER_BASE)
0043 unsigned int leon3_timer_prescaler __attribute__((weak)) = 0;
0044 int leon3_timer_core_index __attribute__((weak)) = 0;
0045 #endif
0046 
0047 /* AMBA Plug&Play information description.
0048  *
0049  * After software has scanned AMBA PnP it builds a tree to make
0050  * it easier for drivers to work with the bus architecture.
0051  */
0052 static struct ambapp_bus ambapp_plb_instance;
0053 
0054 static void *ambapp_plb_alloc( size_t size )
0055 {
0056   return _Memory_Allocate( _Memory_Get(), size, CPU_HEAP_ALIGNMENT );
0057 }
0058 
0059 struct ambapp_bus *ambapp_plb( void )
0060 {
0061   struct ambapp_bus *plb;
0062 
0063   plb = &ambapp_plb_instance;
0064 
0065   if ( plb->root == NULL ) {
0066     struct ambapp_context ctx;
0067 
0068     ctx.copy_from_device = (ambapp_memcpy_t) memcpy;
0069     ctx.alloc = ambapp_plb_alloc;
0070 
0071     /* Scan AMBA Plug&Play read-only information. The routine builds a PnP
0072      * tree into ambapp_plb in RAM, after this we never access the PnP
0073      * information in hardware directly any more.
0074      * Since on Processor Local Bus (PLB) memory mapping is 1:1
0075      */
0076     ambapp_scan( plb, LEON3_IO_AREA, &ctx, NULL );
0077   }
0078 
0079   return plb;
0080 }
0081 
0082 /* If RTEMS_DRVMGR_STARTUP is defined extra code is added that
0083  * registers the GRLIB AMBA PnP bus driver as root driver.
0084  */
0085 #ifdef RTEMS_DRVMGR_STARTUP
0086 #include <drvmgr/drvmgr.h>
0087 #include <grlib/ambapp_bus_grlib.h>
0088 
0089 /* Driver resources configuration for AMBA root bus. It is declared weak
0090  * so that the user may override it, if the defualt settings are not
0091  * enough.
0092  */
0093 struct drvmgr_bus_res grlib_drv_resources __attribute__((weak)) =
0094 {
0095   .next = NULL,
0096   .resource =
0097   {
0098     DRVMGR_RES_EMPTY,
0099   }
0100 };
0101 
0102 /* GRLIB AMBA bus configuration (the LEON3 root bus configuration) */
0103 struct grlib_config grlib_bus_config;
0104 
0105 static void ambapp_grlib_root_initialize( void )
0106 {
0107   /* Register Root bus, Use GRLIB AMBA PnP bus as root bus for LEON3 */
0108   grlib_bus_config.abus = ambapp_plb();
0109   grlib_bus_config.resources = &grlib_drv_resources;
0110   ambapp_grlib_root_register(&grlib_bus_config);
0111 }
0112 
0113 RTEMS_SYSINIT_ITEM(
0114   ambapp_grlib_root_initialize,
0115   RTEMS_SYSINIT_BSP_START,
0116   RTEMS_SYSINIT_ORDER_SECOND
0117 );
0118 #endif
0119 
0120 #if !defined(LEON3_IRQAMP_BASE)
0121 irqamp *LEON3_IrqCtrl_Regs;
0122 struct ambapp_dev *LEON3_IrqCtrl_Adev;
0123 #endif
0124 
0125 #if !defined(LEON3_GPTIMER_BASE)
0126 gptimer *LEON3_Timer_Regs;
0127 struct ambapp_dev *LEON3_Timer_Adev;
0128 #endif
0129 
0130 /*
0131  *  amba_initialize
0132  *
0133  *  Must be called just before drivers are initialized.
0134  *  Used to scan system bus. Probes for AHB masters, AHB slaves and
0135  *  APB slaves. Addresses to configuration areas of the AHB masters,
0136  *  AHB slaves, APB slaves and APB master are storeds in
0137  *  amba_ahb_masters, amba_ahb_slaves and amba.
0138  */
0139 
0140 static void amba_initialize(void)
0141 {
0142   struct ambapp_dev *adev;
0143   struct ambapp_bus *plb;
0144 
0145   plb = ambapp_plb();
0146 #if defined(LEON3_IRQAMP_BASE) && defined(LEON3_GPTIMER_BASE)
0147   (void) plb;
0148   (void) adev;
0149 #endif
0150 
0151 #if !defined(LEON3_IRQAMP_BASE)
0152   /* Find LEON3 Interrupt controller */
0153   adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
0154                                  VENDOR_GAISLER, GAISLER_IRQMP,
0155                                  ambapp_find_by_idx, NULL);
0156   if (adev == NULL) {
0157     /* PANIC IRQ controller not found!
0158      *
0159      *  What else can we do but stop ...
0160      */
0161     bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER);
0162   }
0163 
0164   LEON3_IrqCtrl_Regs = (irqamp *)DEV_TO_APB(adev)->start;
0165   LEON3_IrqCtrl_Adev = adev;
0166   if ((grlib_load_32(&LEON3_IrqCtrl_Regs->asmpctrl) >> 28) > 0) {
0167     uint32_t icsel;
0168 
0169     /* IRQ Controller has support for multiple IRQ Controllers, each
0170      * CPU can be routed to different Controllers, we find out which
0171      * controller by looking at the IRQCTRL Select Register for this CPU.
0172      * Each Controller is located at a 4KByte offset.
0173      */
0174     icsel = grlib_load_32(&LEON3_IrqCtrl_Regs->icselr[LEON3_Cpu_Index/8]);
0175     icsel = (icsel >> ((7 - (LEON3_Cpu_Index & 0x7)) * 4)) & 0xf;
0176     LEON3_IrqCtrl_Regs += icsel;
0177   }
0178 #endif
0179 
0180 #if !defined(LEON3_GPTIMER_BASE)
0181   /* find GP Timer */
0182   adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
0183                                  VENDOR_GAISLER, GAISLER_GPTIMER,
0184                                  ambapp_find_by_idx, &leon3_timer_core_index);
0185   if (adev) {
0186     LEON3_Timer_Regs = (gptimer *)DEV_TO_APB(adev)->start;
0187     LEON3_Timer_Adev = adev;
0188 
0189     /* Register AMBA Bus Frequency */
0190     ambapp_freq_init(
0191       plb,
0192       LEON3_Timer_Adev,
0193       (grlib_load_32(&LEON3_Timer_Regs->sreload) + 1)
0194         * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
0195     );
0196     /* Set user prescaler configuration. Use this to increase accuracy of timer
0197      * and accociated services like cpucounter.
0198      * Note that minimum value is the number of timer instances present in
0199      * GRTIMER/GPTIMER hardware. See HW manual.
0200      */
0201     if (leon3_timer_prescaler)
0202       grlib_store_32(&LEON3_Timer_Regs->sreload, leon3_timer_prescaler);
0203   }
0204 #endif
0205 }
0206 
0207 RTEMS_SYSINIT_ITEM(
0208   amba_initialize,
0209   RTEMS_SYSINIT_BSP_EARLY,
0210   RTEMS_SYSINIT_ORDER_MIDDLE
0211 );