Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /*
0002  *  This file contains the implementation of the function described in irq.h
0003  */
0004 
0005 /*
0006  *  Copyright (C) 1998, 1999 valette@crf.canon.fr
0007  *
0008  *  The license and distribution terms for this file may be
0009  *  found in the file LICENSE in this distribution or at
0010  *  http://www.OARcorp.com/rtems/license.html.
0011  *
0012  *  Acknowledgement May 2004, to Till Straumann <strauman@slac.stanford.edu>
0013  *  for some inputs.
0014  *
0015  *  Copyright 2003, 2004, 2005, 2007  Shuchen Kate Feng <feng1@bnl.gov>,
0016  *            NSLS, Brookhaven National Laboratory. All rights reserved.
0017  *
0018  *  1) Used GT_GPP_Value register instead of the GT_GPP_Interrupt_Cause
0019  *     register to monitor the cause of the level sensitive interrupts.
0020  *     (Copyright : NDA item)
0021  *  2) The implementation of picPrioTable[] is an original work by the
0022  *     author to optimize the software IRQ priority scheduling because
0023  *     Discovery controller does not provide H/W IRQ priority schedule.
0024  *     It ensures the fastest/faster interrupt service to the
0025  *     highest/higher priority IRQ, if pendig.
0026  *  3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER()
0027  *
0028  */
0029 
0030 #include <inttypes.h>
0031 #include <stdio.h>
0032 #include <bsp.h>
0033 #include <bsp/irq.h>
0034 #include <rtems/score/thread.h>
0035 #include <rtems/rtems/intr.h>
0036 #include <libcpu/io.h>
0037 #include <libcpu/byteorder.h>
0038 #include <bsp/vectors.h>
0039 
0040 #include <rtems/bspIo.h> /* for printk */
0041 #include "bsp/gtreg.h"
0042 
0043 #define HI_INT_CAUSE 0x40000000
0044 
0045 #define MAX_IRQ_LOOP 20
0046 
0047 /* #define DEBUG_IRQ*/
0048 
0049 /*
0050  * pointer to the mask representing the additionnal irq vectors
0051  * that must be disabled when a particular entry is activated.
0052  * They will be dynamically computed from the table given
0053  * in BSP_rtems_irq_mngt_set();
0054  * CAUTION : this table is accessed directly by interrupt routine
0055  *       prologue.
0056  */
0057 static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER];
0058 
0059 /*
0060  * location used to store initial tables used for interrupt
0061  * management.BSP copy of the configuration
0062  */
0063 static rtems_irq_global_settings    BSP_config;
0064 static rtems_irq_connect_data*      rtems_hdl_tbl;
0065 
0066 /*
0067  * default handler connected on each irq after bsp initialization
0068  * (locally cached copy)
0069  */
0070 void (*default_rtems_hdl)(rtems_irq_hdl_param) = (void(*)(rtems_irq_hdl_param)) -1;
0071 
0072 
0073 static volatile unsigned  *BSP_irqMask_reg[3];
0074 static volatile unsigned  *BSP_irqCause_reg[3];
0075 static volatile unsigned  BSP_irqMask_cache[3]={0,0,0};
0076 
0077 static int picPrioTblPtr=0;
0078 static unsigned int GPPIrqInTbl=0;
0079 static unsigned long long MainIrqInTbl=0;
0080 
0081 /*
0082  * The software developers are forbidden to setup picPrioTable[],
0083  * as it is a powerful engine for the BSP to find the pending
0084  * highest priority IRQ at run time.  It ensures the fastest/faster
0085  * interrupt service to the highest/higher priority IRQ, if pendig.
0086  *
0087  * The picPrioTable[96] is updated dynamically at run time
0088  * based on the priority levels set at BSPirqPrioTable[96],
0089  * while the BSP_enable_irq_at_pic(), and BSP_disable_irq_at_pic()
0090  * commands are invoked.
0091  *
0092  * The picPrioTable[96] lists the enabled CPU main and GPP external interrupt
0093  * numbers [0 (lowest)- 95 (highest)] starting from the highest priority
0094  * one to the lowest priority one. The highest priority interrupt is
0095  * located at picPrioTable[0], and the lowest priority interrupt is located
0096  * at picPrioTable[picPrioTblPtr-1].
0097  *
0098  *
0099  */
0100 #define DynamicIsrTable
0101 #ifdef DynamicIsrTable
0102 /* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */
0103 static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={
0104      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0105      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0106      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0107      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0108      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0109      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0110      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0111      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0112      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0113      -1, -1, -1, -1, -1, -1 };
0114 #else
0115 static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={
0116      80, 84, 76, 77, 32, -1, -1, -1, -1, -1,
0117      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0118      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0119      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0120      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0121      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0122      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0123      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0124      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0125      -1, -1, -1, -1, -1, -1 };
0126 #endif
0127 
0128 /*
0129  * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ
0130  */
0131 static inline int is_pic_irq(const rtems_irq_number irqLine)
0132 {
0133   return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) &
0134       ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET)
0135      );
0136 }
0137 
0138 /*
0139  * Check if IRQ is a Porcessor IRQ
0140  */
0141 static inline int is_processor_irq(const rtems_irq_number irqLine)
0142 {
0143   return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
0144       ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
0145      );
0146 }
0147 
0148 /*
0149  * ------------------------ RTEMS Irq helper functions ----------------
0150  */
0151 
0152 /*
0153  * Caution : this function assumes the variable "BSP_config"
0154  * is already set and that the tables it contains are still valid
0155  * and accessible.
0156  */
0157 static void compute_pic_masks_from_prio(void)
0158 {
0159   int i,j, k, isGppMain;
0160   unsigned long long irq_prio_mask=0;
0161 
0162   /*
0163    * Always mask at least current interrupt to prevent re-entrance
0164    */
0165   for (i=0; i <BSP_PIC_IRQ_NUMBER; i++) {
0166     switch(i) {
0167       case BSP_MAIN_GPP7_0_IRQ:
0168       case BSP_MAIN_GPP15_8_IRQ:
0169       case BSP_MAIN_GPP23_16_IRQ:
0170       case BSP_MAIN_GPP31_24_IRQ:
0171     for (k=0; k< 3; k++)
0172         BSP_irq_prio_mask_tbl[k][i]=0;
0173 
0174         irq_prio_mask =0;
0175         isGppMain =1;
0176         break;
0177       default :
0178         isGppMain =0;
0179         irq_prio_mask = (unsigned long long) (1LLU << i);
0180     break;
0181     }
0182     if ( isGppMain) continue;
0183     for (j = 0; j <BSP_MAIN_IRQ_NUMBER; j++) {
0184         /*
0185          * Mask interrupts at PIC level that have a lower priority
0186          * or <Till Straumann> a equal priority.
0187          */
0188         if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j])
0189        irq_prio_mask |= (unsigned long long)(1LLU << j);
0190     }
0191 
0192 
0193     BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff;
0194     BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff;
0195 #if 0
0196     printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i],
0197        BSP_irq_prio_mask_tbl[0][i]);
0198 #endif
0199 
0200     BSP_irq_prio_mask_tbl[2][i] = 1<<i;
0201     /* Compute for the GPP priority interrupt mask */
0202     for (j=BSP_GPP_IRQ_LOWEST_OFFSET; j <BSP_PROCESSOR_IRQ_LOWEST_OFFSET; j++) {
0203       if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j])
0204        BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET);
0205     }
0206 #if 0
0207     printk("GPPirq_mask_prio_tbl[%d]:0x%8x\n",i,BSP_irq_prio_mask_tbl[2][i]);
0208 #endif
0209   }
0210 }
0211 
0212 static void UpdateMainIrqTbl(int irqNum)
0213 {
0214   int i=0, j, shifted=0;
0215 
0216   switch (irqNum) {
0217     case BSP_MAIN_GPP7_0_IRQ:
0218     case BSP_MAIN_GPP15_8_IRQ:
0219     case BSP_MAIN_GPP23_16_IRQ:
0220     case BSP_MAIN_GPP31_24_IRQ:
0221       return;  /* Do nothing, let GPP take care of it */
0222       break;
0223   }
0224 #ifdef SHOW_MORE_INIT_SETTINGS
0225   unsigned long val2, val1;
0226 #endif
0227 
0228   /* If entry not in table*/
0229   if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
0230         (!((unsigned long long)(1LLU << irqNum) & MainIrqInTbl))) ||
0231        ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
0232         (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))))
0233   {
0234       while ( picPrioTable[i]!=-1) {
0235         if (BSP_config.irqPrioTbl[irqNum]>BSP_config.irqPrioTbl[picPrioTable[i]]) {
0236           /* all other lower priority entries shifted right */
0237           for (j=picPrioTblPtr;j>i; j--) {
0238               picPrioTable[j]=picPrioTable[j-1];
0239           }
0240           picPrioTable[i]=irqNum;
0241           shifted=1;
0242           break;
0243        }
0244        i++;
0245      }
0246      if (!shifted) picPrioTable[picPrioTblPtr] =irqNum;
0247 
0248      if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
0249         GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
0250      else
0251         MainIrqInTbl |= (unsigned long long)(1LLU << irqNum);
0252      picPrioTblPtr++;
0253   }
0254 #ifdef SHOW_MORE_INIT_SETTINGS
0255   val2 = (MainIrqInTbl>>32) & 0xffffffff;
0256   val1 = MainIrqInTbl&0xffffffff;
0257   printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1);
0258   BSP_printPicIsrTbl();
0259 #endif
0260 
0261 }
0262 
0263 
0264 static void CleanMainIrqTbl(int irqNum)
0265 {
0266   int i, j;
0267 
0268   switch (irqNum) {
0269     case BSP_MAIN_GPP7_0_IRQ:
0270     case BSP_MAIN_GPP15_8_IRQ:
0271     case BSP_MAIN_GPP23_16_IRQ:
0272     case BSP_MAIN_GPP31_24_IRQ:
0273       return;  /* Do nothing, let GPP take care of it */
0274       break;
0275   }
0276   if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
0277         ((unsigned long long)(1LLU << irqNum) & MainIrqInTbl)) ||
0278        ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
0279         (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))
0280   { /* If entry in table*/
0281      for (i=0; i<64; i++) {
0282        if (picPrioTable[i]==irqNum) {/*remove it from the entry */
0283           /* all other lower priority entries shifted left */
0284       for (j=i;j<picPrioTblPtr; j++) {
0285               picPrioTable[j]=picPrioTable[j+1];
0286           }
0287           if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
0288             GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
0289           else
0290             MainIrqInTbl &= ~(1LLU << irqNum);
0291           picPrioTblPtr--;
0292           break;
0293        }
0294      }
0295   }
0296 }
0297 
0298 void BSP_enable_irq_at_pic(const rtems_irq_number irqNum)
0299 {
0300   unsigned bitNum, regNum;
0301   unsigned int level;
0302 
0303   if ( !is_pic_irq(irqNum) )
0304     return;
0305 
0306   bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32;
0307   regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5;
0308 
0309   rtems_interrupt_disable(level);
0310 
0311 #ifdef DynamicIsrTable
0312   UpdateMainIrqTbl((int) irqNum);
0313 #endif
0314   BSP_irqMask_cache[regNum] |= (1 << bitNum);
0315 
0316   out_le32((volatile uint32_t *)BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
0317   while (in_le32((volatile uint32_t *)BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
0318 
0319   rtems_interrupt_enable(level);
0320 }
0321 
0322 int BSP_disable_irq_at_pic(const rtems_irq_number irqNum)
0323 {
0324   int      rval;
0325   unsigned bitNum, regNum;
0326   unsigned int level;
0327 
0328   if ( ! is_pic_irq(irqNum) )
0329     return -1;
0330 
0331   bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32;
0332   regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5;
0333 
0334   rtems_interrupt_disable(level);
0335 
0336 #ifdef DynamicIsrTable
0337   CleanMainIrqTbl((int) irqNum);
0338 #endif
0339 
0340   rval = BSP_irqMask_cache[regNum] & (1<<bitNum);
0341 
0342   BSP_irqMask_cache[regNum] &=  ~(1 << bitNum);
0343 
0344   out_le32((volatile uint32_t *)BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
0345   while (in_le32((volatile uint32_t *)BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
0346 
0347   rtems_interrupt_enable(level);
0348 
0349   return rval ? 1 : 0;
0350 }
0351 
0352 /* Use shared/irq : 2008 */
0353 int BSP_setup_the_pic(rtems_irq_global_settings* config)
0354 {
0355   int i;
0356 
0357   BSP_config = *config;
0358   default_rtems_hdl = config->defaultEntry.hdl;
0359   rtems_hdl_tbl     = config->irqHdlTbl;
0360 
0361   /* Get ready for discovery BSP */
0362   BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_LO);
0363   BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_HI);
0364   BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_LO);
0365   BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_HI);
0366   BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Interrupt_Mask);
0367   BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Value);
0368 
0369   /* Page 401, Table 598:
0370    * Comm Unit Arbiter Control register :
0371    * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0).
0372    * MOTload default is set as level sensitive(1). Set it agin to make sure.
0373    */
0374   out_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl,
0375            (in_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl)| (1<<10)));
0376 
0377 #if 0
0378   printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n",
0379          in_le32((volatile uint32_t *)BSP_irqMask_reg[0]),
0380          in_le32((volatile uint32_t *)BSP_irqCause_reg[0]));
0381   printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n",
0382          in_le32((volatile uint32_t *)BSP_irqMask_reg[1]),
0383          in_le32((volatile uint32_t *)BSP_irqCause_reg[1]));
0384   printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n",
0385          in_le32((volatile uint32_t *)BSP_irqMask_reg[2]),
0386          in_le32((volatile uint32_t *)BSP_irqCause_reg[2]));
0387 #endif
0388 
0389   /* Initialize the interrupt related  registers */
0390   for (i=0; i<3; i++) {
0391     out_le32((volatile uint32_t *)BSP_irqCause_reg[i], 0);
0392     out_le32((volatile uint32_t *)BSP_irqMask_reg[i], 0);
0393   }
0394   in_le32((volatile uint32_t *)BSP_irqMask_reg[2]);
0395   compute_pic_masks_from_prio();
0396 
0397 #if 0
0398   printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n",
0399          in_le32((volatile uint32_t *)BSP_irqMask_reg[0]),
0400          in_le32((volatile uint32_t *)BSP_irqCause_reg[0]));
0401   printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n",
0402          in_le32((volatile uint32_t *)BSP_irqMask_reg[1]),
0403          in_le32((volatile uint32_t *)BSP_irqCause_reg[1]));
0404   printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n",
0405          in_le32((volatile uint32_t *)BSP_irqMask_reg[2]),
0406          in_le32((volatile uint32_t *)BSP_irqCause_reg[2]));
0407 #endif
0408 
0409   /*
0410    *
0411    */
0412   for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET ; i++) {
0413     if ( BSP_config.irqHdlTbl[i].hdl != BSP_config.defaultEntry.hdl) {
0414       BSP_enable_irq_at_pic(i);
0415       BSP_config.irqHdlTbl[i].on(&BSP_config.irqHdlTbl[i]);
0416     }
0417     else {
0418       BSP_config.irqHdlTbl[i].off(&BSP_config.irqHdlTbl[i]);
0419       BSP_disable_irq_at_pic(i);
0420     }
0421   }
0422   for (i= BSP_MAIN_GPP7_0_IRQ; i < BSP_MAIN_GPP31_24_IRQ; i++)
0423     BSP_enable_irq_at_pic(i);
0424 
0425   return(1);
0426 }
0427 
0428 /*
0429  * High level IRQ handler called from shared_raw_irq_code_entry
0430  */
0431 int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
0432 {
0433   unsigned long irqCause[3]={0, 0,0};
0434   unsigned oldMask[3]={0,0,0};
0435   int loop=0, i=0, j;
0436   int irq=0, group=0;
0437 
0438   if (excNum == ASM_DEC_VECTOR) {
0439       bsp_irq_dispatch_list( rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_hdl);
0440       return 0;
0441   }
0442 
0443   for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j];
0444   for (j=0; j<3; j++) irqCause[j] = in_le32((volatile uint32_t *)BSP_irqCause_reg[j]) & in_le32((volatile uint32_t *)BSP_irqMask_reg[j]);
0445 
0446   while (((irq = picPrioTable[i++])!=-1)&& (loop++ < MAX_IRQ_LOOP))
0447   {
0448     if (irqCause[group= irq/32] & ( 1<<(irq % 32))) {
0449       for (j=0; j<3; j++)
0450         BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]);
0451 
0452       out_le32((volatile uint32_t *)BSP_irqMask_reg[0], BSP_irqMask_cache[0]);
0453       out_le32((volatile uint32_t *)BSP_irqMask_reg[1], BSP_irqMask_cache[1]);
0454       out_le32((volatile uint32_t *)BSP_irqMask_reg[2], BSP_irqMask_cache[2]);
0455       in_le32((volatile uint32_t *)BSP_irqMask_reg[2]);
0456 
0457       bsp_irq_dispatch_list( rtems_hdl_tbl, irq, default_rtems_hdl);
0458 
0459       for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j];
0460 
0461       out_le32((volatile uint32_t *)BSP_irqMask_reg[0], oldMask[0]);
0462       out_le32((volatile uint32_t *)BSP_irqMask_reg[1], oldMask[1]);
0463       out_le32((volatile uint32_t *)BSP_irqMask_reg[2], oldMask[2]);
0464       in_le32((volatile uint32_t *)BSP_irqMask_reg[2]);
0465     }
0466   }
0467 
0468   return 0;
0469 }
0470 
0471 /* Only print part of the entries for now */
0472 void BSP_printPicIsrTbl(void)
0473 {
0474   int i;
0475 
0476   printf("picPrioTable[12]={ {irq# : ");
0477   for (i=0; i<12; i++)
0478     printf("%d,", picPrioTable[i]);
0479   printf("}\n");
0480 
0481   printf("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl);
0482 }