Back to home page

LXR

 
 

    


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

0001 
0002 /*
0003  *  Find and initialize irqmp and gptimer.
0004  *  The license and distribution terms for this file may be
0005  *  found in the file LICENSE in this distribution or at
0006  *  http://www.rtems.org/license/LICENSE.
0007  */
0008 
0009 #include <bsp.h>
0010 #include <bsp/fatal.h>
0011 #include <amba.h>
0012 
0013 rtems_interrupt_lock GRLIB_IrqCtrl_Lock =
0014   RTEMS_INTERRUPT_LOCK_INITIALIZER("GRLIB IrqCtrl");
0015 
0016 /* Pointers to Interrupt Controller configuration registers */
0017 volatile struct irqmp_regs *GRLIB_IrqCtrl_Regs;
0018 struct ambapp_dev *GRLIB_IrqCtrl_Adev;
0019 
0020 /* GRLIB extended IRQ controller IRQ number */
0021 int GRLIB_IrqCtrl_EIrq = -1;
0022 
0023 /* Initialize Extended Interrupt controller */
0024 static void grlib_ext_irq_init(void)
0025 {
0026   if ( (GRLIB_IrqCtrl_Regs->mpstat >> 16) & 0xf ) {
0027     /* Extended IRQ controller available */
0028     GRLIB_IrqCtrl_EIrq = (GRLIB_IrqCtrl_Regs->mpstat >> 16) & 0xf;
0029   }
0030 }
0031 
0032 /*
0033  *  irqmp_initialize
0034  *
0035  *  Probes for IRQMP and initialises necessary registers.
0036  *
0037  */
0038 
0039 void irqmp_initialize(void)
0040 {
0041   int icsel;
0042   struct ambapp_dev *adev;
0043 
0044   /* Find GRLIB Interrupt controller */
0045   adev = (void *)ambapp_for_each(ambapp_plb(), (OPTIONS_ALL|OPTIONS_APB_SLVS),
0046                                  VENDOR_GAISLER, GAISLER_IRQMP,
0047                                  ambapp_find_by_idx, NULL);
0048   if (adev != NULL) {
0049 
0050     GRLIB_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
0051     GRLIB_IrqCtrl_Adev = adev;
0052     if ((GRLIB_IrqCtrl_Regs->ampctrl >> 28) > 0) {
0053     /* IRQ Controller has support for multiple IRQ Controllers, each
0054      * CPU can be routed to different Controllers, we find out which
0055      * controller by looking at the IRQCTRL Select Register for this CPU.
0056      * Each Controller is located at a 4KByte offset.
0057      */
0058       icsel = GRLIB_IrqCtrl_Regs->icsel[GRLIB_Cpu_Index/8];
0059       icsel = (icsel >> ((7 - (GRLIB_Cpu_Index & 0x7)) * 4)) & 0xf;
0060       GRLIB_IrqCtrl_Regs += icsel;
0061     }
0062     GRLIB_IrqCtrl_Regs->mask[GRLIB_Cpu_Index] = 0;
0063     GRLIB_IrqCtrl_Regs->force[GRLIB_Cpu_Index] = 0;
0064     GRLIB_IrqCtrl_Regs->iclear = 0xffffffff;
0065 
0066   /* Init Extended IRQ controller if available */
0067     grlib_ext_irq_init();
0068 
0069   }
0070 
0071 }
0072 
0073 
0074 /* GPTIMER */
0075 
0076 unsigned int grlib_timer_prescaler __attribute__((weak)) = 0;
0077 int grlib_timer_core_index __attribute__((weak)) = 0;
0078 
0079 volatile struct gptimer_regs *GRLIB_Timer_Regs;
0080 struct ambapp_dev *GRLIB_Timer_Adev;
0081 
0082 /*
0083  *  gptimer_initialize
0084  *
0085  */
0086 
0087 void gptimer_initialize(void)
0088 {
0089   struct ambapp_dev *adev;
0090 
0091   /* find GP Timer */
0092   adev = (void *)ambapp_for_each(ambapp_plb(), (OPTIONS_ALL|OPTIONS_APB_SLVS),
0093                                  VENDOR_GAISLER, GAISLER_GPTIMER,
0094                                  ambapp_find_by_idx, &grlib_timer_core_index);
0095   if (adev) {
0096     GRLIB_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
0097     GRLIB_Timer_Adev = adev;
0098 
0099     /* Register AMBA Bus Frequency */
0100     ambapp_freq_init(
0101       ambapp_plb(),
0102       GRLIB_Timer_Adev,
0103       (GRLIB_Timer_Regs->scaler_reload + 1)
0104         * GRLIB_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
0105     );
0106     /* Set user prescaler configuration. Use this to increase accuracy of timer
0107      * and accociated services like cpucounter.
0108      * Note that minimum value is the number of timer instances present in
0109      * GRTIMER/GPTIMER hardware. See HW manual.
0110      */
0111     if (grlib_timer_prescaler)
0112       GRLIB_Timer_Regs->scaler_reload = grlib_timer_prescaler;
0113   }
0114 
0115 }