Back to home page

LXR

 
 

    


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

0001 /*
0002  * RTEMS generic MPC5200 BSP
0003  *
0004  * This file contains the irq controller handler.
0005  */
0006 
0007 /*
0008  * Copyright (c) 1998, 1999 valette@crf.canon.fr
0009  *
0010  * Copyright (c) 2000 Andy Dachs <a.dachs@sstl.co.uk>
0011  * Surrey Satellite Technology Limited
0012  *
0013  * Copyright (c) 2003 IPR Engineering. All rights reserved.
0014  *
0015  * Copyright (c) 2005 embedded brains GmbH & Co. KG
0016  *
0017  * The license and distribution terms for this file may be
0018  * found in the file LICENSE in this distribution or at
0019  * http://www.rtems.org/license/LICENSE.
0020  */
0021 
0022 #include <inttypes.h>
0023 
0024 #include <rtems.h>
0025 
0026 #include <libcpu/powerpc-utility.h>
0027 #include <bsp/vectors.h>
0028 
0029 #include <bsp.h>
0030 #include <bsp/irq.h>
0031 #include <bsp/irq-generic.h>
0032 #include <bsp/mpc5200.h>
0033 
0034 /*
0035  * bit in the SIU mask registers (PPC bit numbering) that should
0036  * be set to enable the relevant interrupt, mask of 32 is for unused entries
0037  *
0038  */
0039 const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = {
0040   0, 1, 2, 3,                   /* smart_comm, psc1, psc2, psc3            */
0041   4, 5, 6, 7,                   /* irda/psc6, eth, usb, ata                */
0042   8, 9, 10, 11,                 /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4    */
0043   12, 13, 14, 15,               /* psc5,spi_modf, spi_spif, i2c1           */
0044   16, 17, 18, 19,               /* i2c, can1, can2, ir_rx                  */
0045   20, 21, 15, 16,               /* ir_rx, xlb_arb, slice_tim2, irq1,       */
0046   17, 18, 19, 20,               /* irq2, irq3, lo_int, rtc_pint            */
0047   21, 22, 23, 24,               /* rtc_sint, gpio_std, gpio_wkup, tmr0     */
0048   25, 26, 27, 28,               /* tmr1, tmr2, tmr3, tmr4                  */
0049   29, 30, 31, 32,               /* tmr5, tmr6, tmr7, res                   */
0050   32, 32, 32                    /* res, res, res                           */
0051 };
0052 
0053 static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = {
0054 /* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection               */
0055 /* msb = 0 -> non-critical per. int. is routed to main int. (LO_int)               */
0056 /* msb = 1 -> critical per. int. is routed to critical int. (HI_int)               */
0057   0xF, 0, 0, 0,                 /* smart_comm (do not change!), psc1, psc2, psc3             */
0058   0, 0, 0, 0,                   /* irda, eth, usb, ata                                       */
0059   0, 0, 0, 0,                   /* pci_ctrl, pci_sc_rx, pci_sc_tx, res                       */
0060   0, 0, 0, 0,                   /* res, spi_modf, spi_spif, i2c1                             */
0061   0, 0, 0, 0,                   /* i2c, can1, can2, ir_rx                                    */
0062   0, 0,                         /* ir_rx, xlb_arb                                            */
0063 /* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection        */
0064 /* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 )        */
0065 /* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 )       */
0066   0, 0,                         /* slice_tim2, irq1                                          */
0067   0, 0, 0, 0,                   /* irq2, irq3, lo_int, rtc_pint                              */
0068   0, 0, 0, 0,                   /* rtc_sint, gpio_std, gpio_wkup, tmr0                       */
0069   0, 0, 0, 0,                   /* tmr1, tmr2, tmr3, tmr4                                    */
0070   0, 0, 0,                      /* tmr5, tmr6, tmr7                                          */
0071   /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */
0072   0,                            /* irq0                                                      */
0073   0, 0, 0                       /* slice_tim1, hi_int, ccs_wkup                              */
0074 };
0075 
0076 static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER];
0077 
0078 /*
0079  * Check if symbolic IRQ name is a Processor IRQ
0080  */
0081 static inline bool is_processor_irq( rtems_vector_number irqLine)
0082 {
0083 
0084   return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET)
0085     && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
0086 }
0087 
0088 /*
0089  * Check for SIU IRQ and return base index
0090  */
0091 static inline bool is_siu_irq( rtems_vector_number irqLine)
0092 {
0093 
0094   return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET)
0095     && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
0096 }
0097 
0098 /*
0099  * Check for SIU IRQ and return base index
0100  */
0101 static inline int get_siu_irq_base_index( rtems_vector_number irqLine)
0102 {
0103   if (irqLine <= BSP_PER_IRQ_MAX_OFFSET)
0104     return BSP_PER_IRQ_LOWEST_OFFSET;
0105 
0106   if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
0107     return BSP_MAIN_IRQ_LOWEST_OFFSET;
0108 
0109   if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
0110     return BSP_CRIT_IRQ_LOWEST_OFFSET;
0111 
0112   return -1;
0113 }
0114 
0115 static inline void BSP_enable_per_irq_at_siu(
0116   rtems_vector_number irqLine
0117 )
0118 {
0119   uint8_t lo_hi_ind = 0,
0120     prio_index_offset;
0121   uint32_t *reg;
0122 
0123   /* calculate the index offset of priority value bit field */
0124   prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
0125 
0126   /* set interrupt priorities */
0127   if (irqPrioTable [irqLine] <= 15) {
0128 
0129     /* set peripheral int priority */
0130     reg = (uint32_t *) (&(mpc5200.per_pri_1));
0131 
0132     /* choose proper register */
0133     reg += (irqLine >> 3);
0134 
0135     /* set priority as given in priority table */
0136     *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
0137 
0138     /* test msb (hash-bit) and set LO_/HI_int indicator */
0139     if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) {
0140 
0141       /* set critical HI_int priority */
0142       reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
0143       *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26);
0144 
0145       /*
0146        * critical interrupt handling for the 603le core is not
0147        * yet supported, routing of critical interrupts is forced
0148        * to core_int (bit 31 / CEb)
0149        */
0150       mpc5200.ext_en_type |= 1;
0151 
0152     } else {
0153       if (irqPrioTable [irqLine] <= 15) {
0154         /* set main LO_int priority */
0155         reg = (uint32_t *) (&(mpc5200.main_pri_1));
0156         *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16);
0157       }
0158     }
0159   }
0160 
0161   /* if LO_int ind., enable (unmask) main interrupt */
0162   if (!lo_hi_ind) {
0163     mpc5200.crit_pri_main_mask &=
0164       ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]);
0165   }
0166 
0167   /* enable (unmask) peripheral interrupt */
0168   mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
0169 
0170   /* FIXME: Why? */
0171   mpc5200.main_pri_1;
0172   mpc5200.crit_pri_main_mask;
0173   mpc5200.per_pri_1;
0174   mpc5200.per_mask;
0175 }
0176 
0177 static inline void BSP_enable_main_irq_at_siu(
0178   rtems_vector_number irqLine
0179 )
0180 {
0181 
0182   uint8_t prio_index_offset;
0183   uint32_t *reg;
0184 
0185   /* calculate the index offset of priority value bit field */
0186   prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
0187 
0188   /* set main interrupt priority */
0189   if (irqPrioTable [irqLine] <= 15) {
0190 
0191     /* set main int priority */
0192     reg = (uint32_t *) (&(mpc5200.main_pri_1));
0193 
0194     /* choose proper register */
0195     reg += (irqLine >> 3);
0196 
0197     /* set priority as given in priority table */
0198     *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
0199 
0200     if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
0201       /* enable external irq-pin */
0202       mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
0203     }
0204   }
0205 
0206   /* enable (unmask) main interrupt */
0207   mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
0208 
0209 }
0210 
0211 static inline void BSP_enable_crit_irq_at_siu(
0212   rtems_vector_number irqLine
0213 )
0214 {
0215   uint8_t prio_index_offset;
0216   uint32_t *reg;
0217 
0218   prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
0219 
0220   /*
0221    * critical interrupt handling for the 603Le core is not
0222    * yet supported, routing of critical interrupts is forced
0223    * to core_int (bit 31 / CEb)
0224    */
0225   mpc5200.ext_en_type |= 1;
0226 
0227   /* set critical interrupt priorities */
0228   if (irqPrioTable [irqLine] <= 3) {
0229 
0230     /* choose proper register */
0231     reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
0232 
0233     /* set priority as given in priority table */
0234     *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1)));
0235 
0236     /* external irq0-pin */
0237     if (irqLine == BSP_SIU_IRQ_IRQ1) {
0238       /* enable external irq-pin */
0239       mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
0240     }
0241   }
0242 }
0243 
0244 static inline void BSP_disable_per_irq_at_siu(
0245   rtems_vector_number irqLine
0246 )
0247 {
0248   uint8_t prio_index_offset;
0249   uint32_t *reg;
0250 
0251   /* calculate the index offset of priority value bit field */
0252   prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
0253 
0254   /* disable (mask) peripheral interrupt */
0255   mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
0256 
0257   /* reset priority to lowest level (reset value) */
0258   reg = (uint32_t *) (&(mpc5200.per_pri_1));
0259   reg += (irqLine >> 3);
0260   *reg &= ~(15 << (28 - (prio_index_offset << 2)));
0261 }
0262 
0263 static inline void BSP_disable_main_irq_at_siu(
0264   rtems_vector_number irqLine
0265 )
0266 {
0267   uint8_t prio_index_offset;
0268   uint32_t *reg;
0269 
0270   /* calculate the index offset of priority value bit field */
0271   prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
0272 
0273   /* disable (mask) main interrupt */
0274   mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
0275 
0276   if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
0277     /* disable external irq-pin */
0278     mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
0279   }
0280 
0281   /* reset priority to lowest level (reset value) */
0282   reg = (uint32_t *) (&(mpc5200.main_pri_1));
0283   reg += (irqLine >> 3);
0284   *reg &= ~(15 << (28 - (prio_index_offset << 2)));
0285 }
0286 
0287 static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number
0288                                                irqLine)
0289 {
0290   uint8_t prio_index_offset;
0291   uint32_t *reg;
0292 
0293   prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
0294 
0295   /* reset critical int priority to lowest level (reset value) */
0296   reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
0297   *reg &= ~(3 << (30 - (prio_index_offset << 1)));
0298 
0299   if (irqLine == BSP_SIU_IRQ_IRQ1) {
0300     /* disable external irq0-pin */
0301     mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
0302   }
0303 }
0304 
0305 /*
0306  * This function enables a given siu interrupt
0307  */
0308 rtems_status_code bsp_interrupt_get_attributes(
0309   rtems_vector_number         vector,
0310   rtems_interrupt_attributes *attributes
0311 )
0312 {
0313   return RTEMS_SUCCESSFUL;
0314 }
0315 
0316 rtems_status_code bsp_interrupt_is_pending(
0317   rtems_vector_number vector,
0318   bool               *pending
0319 )
0320 {
0321   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0322   bsp_interrupt_assert(pending != NULL);
0323   *pending = false;
0324   return RTEMS_UNSATISFIED;
0325 }
0326 
0327 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0328 {
0329   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0330   return RTEMS_UNSATISFIED;
0331 }
0332 
0333 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0334 {
0335   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0336   return RTEMS_UNSATISFIED;
0337 }
0338 
0339 rtems_status_code bsp_interrupt_vector_is_enabled(
0340   rtems_vector_number vector,
0341   bool               *enabled
0342 )
0343 {
0344   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0345   bsp_interrupt_assert(enabled != NULL);
0346   *enabled = false;
0347   return RTEMS_UNSATISFIED;
0348 }
0349 
0350 rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector)
0351 {
0352   int base_index = get_siu_irq_base_index( vector);
0353 
0354   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0355 
0356   if (is_siu_irq( vector)) {
0357     rtems_interrupt_level level;
0358 
0359     rtems_interrupt_disable( level);
0360 
0361     switch (base_index) {
0362       case BSP_PER_IRQ_LOWEST_OFFSET:
0363         BSP_enable_per_irq_at_siu( vector);
0364         break;
0365       case BSP_MAIN_IRQ_LOWEST_OFFSET:
0366         BSP_enable_main_irq_at_siu( vector);
0367         break;
0368       case BSP_CRIT_IRQ_LOWEST_OFFSET:
0369         BSP_enable_crit_irq_at_siu( vector);
0370         break;
0371       default:
0372         bsp_interrupt_assert(0);
0373         break;
0374     }
0375 
0376     rtems_interrupt_enable( level);
0377   }
0378 
0379   return RTEMS_SUCCESSFUL;
0380 }
0381 
0382 /*
0383  * This function disables a given siu interrupt
0384  */
0385 rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector)
0386 {
0387   int base_index = get_siu_irq_base_index( vector);
0388 
0389   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0390 
0391   if (is_siu_irq( vector)) {
0392     rtems_interrupt_level level;
0393 
0394     rtems_interrupt_disable( level);
0395 
0396     switch (base_index) {
0397       case BSP_PER_IRQ_LOWEST_OFFSET:
0398         BSP_disable_per_irq_at_siu( vector);
0399         break;
0400       case BSP_MAIN_IRQ_LOWEST_OFFSET:
0401         BSP_disable_main_irq_at_siu( vector);
0402         break;
0403       case BSP_CRIT_IRQ_LOWEST_OFFSET:
0404         BSP_disable_crit_irq_at_siu( vector);
0405         break;
0406       default:
0407         bsp_interrupt_assert(0);
0408         break;
0409     }
0410 
0411     rtems_interrupt_enable( level);
0412   }
0413 
0414   return RTEMS_SUCCESSFUL;
0415 }
0416 
0417 rtems_status_code bsp_interrupt_set_priority(
0418   rtems_vector_number vector,
0419   uint32_t priority
0420 )
0421 {
0422   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0423   return RTEMS_UNSATISFIED;
0424 }
0425 
0426 rtems_status_code bsp_interrupt_get_priority(
0427   rtems_vector_number vector,
0428   uint32_t *priority
0429 )
0430 {
0431   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0432   bsp_interrupt_assert(priority != NULL);
0433   return RTEMS_UNSATISFIED;
0434 }
0435 
0436 #if (BENCHMARK_IRQ_PROCESSING == 0)
0437 void BSP_IRQ_Benchmarking_Reset( void)
0438 {
0439 }
0440 void BSP_IRQ_Benchmarking_Report( void)
0441 {
0442 }
0443 #else
0444 #include <stdio.h>
0445 uint64_t BSP_Starting_TBR;
0446 uint64_t BSP_Total_in_ISR;
0447 uint32_t BSP_ISR_Count;
0448 uint32_t BSP_Worst_ISR;
0449 
0450 #define BSP_COUNTED_IRQ 16
0451 uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1];
0452 
0453 void BSP_IRQ_Benchmarking_Reset( void)
0454 {
0455   int i;
0456 
0457   BSP_Starting_TBR = PPC_Get_timebase_register();
0458   BSP_Total_in_ISR = 0;
0459   BSP_ISR_Count = 0;
0460   BSP_Worst_ISR = 0;
0461   for (i = 0; i < BSP_COUNTED_IRQ; i++)
0462     BSP_ISR_Count_Per [i] = 0;
0463 }
0464 
0465 static const char *u64tostring( char *buffer, uint64_t v)
0466 {
0467   sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33));
0468   return buffer;
0469 }
0470 
0471 void BSP_IRQ_Benchmarking_Report( void)
0472 {
0473   uint64_t now;
0474   char buffer [96];
0475   int i;
0476 
0477   now = PPC_Get_timebase_register();
0478   printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR));
0479   printk( "Current   : %s\n", u64tostring( buffer, now));
0480   printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR));
0481   printk( "ISRs      : %d\n", BSP_ISR_Count);
0482   printk( "ISRs ran  : %s\n", u64tostring( buffer, BSP_Total_in_ISR));
0483   printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR));
0484   for (i = 0; i < BSP_COUNTED_IRQ; i++)
0485     printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]);
0486   printk( "Ticks     : %d\n", Clock_driver_ticks);
0487 }
0488 #endif
0489 
0490 static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg)
0491 {
0492   #if (ALLOW_IRQ_NESTING == 1)
0493     uint32_t msr;
0494     uint32_t mask = *maskreg;
0495   #endif
0496 
0497   irq += offset;
0498 
0499   #if (ALLOW_IRQ_NESTING == 1)
0500     *maskreg = mask | irqMaskTable [irq];
0501     /* Make sure that the write operation completed (cache inhibited area) */
0502     *maskreg;
0503     msr = ppc_external_exceptions_enable();
0504   #endif
0505 
0506   bsp_interrupt_handler_dispatch(irq);
0507 
0508   #if (ALLOW_IRQ_NESTING == 1)
0509     ppc_external_exceptions_disable(msr);
0510     *maskreg = mask;
0511   #endif
0512 }
0513 
0514 /*
0515  * High level IRQ handler called from shared_raw_irq_code_entry
0516  */
0517 static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum)
0518 {
0519   uint32_t irq;
0520   uint32_t pmce;
0521 
0522 #if (BENCHMARK_IRQ_PROCESSING == 1)
0523   uint64_t start,
0524     stop,
0525     thisTime;
0526 
0527   start = PPC_Get_timebase_register();
0528   BSP_ISR_Count++;
0529   if (excNum < BSP_COUNTED_IRQ)
0530     BSP_ISR_Count_Per [excNum]++;
0531   else
0532     printk( "not counting %d\n", excNum);
0533 #endif
0534 
0535   /* get the content of main interrupt status register */
0536   pmce = mpc5200.pmce;
0537 
0538   /* critical interrupts are routed to the core_int, see premature
0539    * initialization
0540    */
0541   while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) {
0542     /* first: check for critical interrupt sources (hierarchical order)
0543      * -> HI_int indicates peripheral sources
0544      */
0545     if ((pmce & PMCE_CSE_STICKY) != 0) {
0546       /* get source of critical interrupt */
0547       irq = PMCE_CSE_SOURCE(pmce);
0548 
0549       switch (irq) {
0550           /* peripheral HI_int interrupt source detected */
0551         case 2:
0552           /* check for valid peripheral interrupt source */
0553           if ((pmce & PMCE_PSE_STICKY) != 0) {
0554             /* get source of peripheral interrupt */
0555             irq = PMCE_PSE_SOURCE(pmce);
0556 
0557             dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
0558           } else {
0559             /* this case may not occur: no valid peripheral
0560              * interrupt source */
0561             printk( "No valid peripheral HI_int interrupt source\n");
0562           }
0563           break;
0564 
0565           /* irq0, slice timer 1 or ccs wakeup detected */
0566         case 0:
0567         case 1:
0568         case 3:
0569 
0570           /* add proper offset for critical interrupts in the siu
0571            * handler array */
0572           irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
0573 
0574           /* Dispatch interrupt handlers */
0575           bsp_interrupt_handler_dispatch( irq);
0576 
0577           break;
0578 
0579         default:
0580           /* error: unknown interrupt source */
0581           printk( "Unknown HI_int interrupt source\n");
0582           break;
0583       }
0584     }
0585 
0586     /* second: check for main interrupt sources (hierarchical order)
0587      * -> LO_int indicates peripheral sources */
0588     if ((pmce & PMCE_MSE_STICKY) != 0) {
0589       /* get source of main interrupt */
0590       irq = PMCE_MSE_SOURCE(pmce);
0591 
0592       if (irq == 4) {
0593           /* peripheral LO_int interrupt source detected */
0594           /* check for valid peripheral interrupt source */
0595           if ((pmce & PMCE_PSE_STICKY) != 0) {
0596             /* get source of peripheral interrupt */
0597             irq = PMCE_PSE_SOURCE(pmce);
0598 
0599             dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
0600           } else {
0601             /* this case may not occur: no valid peripheral
0602              * interrupt source */
0603             printk( "No valid peripheral LO_int interrupt source\n");
0604           }
0605       } else if (irq <= 16) {
0606           /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
0607            * 2 is always routed to SMI) */
0608           dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
0609       } else {
0610           /* error: unknown interrupt source */
0611           printk( "Unknown peripheral LO_int interrupt source\n");
0612       }
0613     }
0614 
0615     /* force re-evaluation of interrupts */
0616     mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY;
0617 
0618     /* get the content of main interrupt status register */
0619     pmce = mpc5200.pmce;
0620   }
0621 
0622 #if (BENCHMARK_IRQ_PROCESSING == 1)
0623   stop = PPC_Get_timebase_register();
0624   thisTime = stop - start;
0625   BSP_Total_in_ISR += thisTime;
0626   if (thisTime > BSP_Worst_ISR)
0627     BSP_Worst_ISR = thisTime;
0628 #endif
0629 
0630   return 0;
0631 }
0632 
0633 /*
0634  * setup irqMaskTable to support a priorized/nested interrupt environment
0635  */
0636 static void setup_irqMaskTable( void)
0637 {
0638   rtems_irq_prio prio = 0;
0639   uint32_t i = 0,
0640     j = 0,
0641     mask = 0;
0642 
0643   /* set up the priority dependent masks for peripheral interrupts */
0644   for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) {
0645     prio = irqPrioTable [i];
0646     mask = 0;
0647 
0648     for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) {
0649       if (prio > irqPrioTable [j]) {
0650         mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
0651       }
0652 
0653       if ((prio == irqPrioTable [j]) && (j >= i)) {
0654         mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
0655       }
0656     }
0657 
0658     irqMaskTable [i] = mask;
0659   }
0660 
0661   /* set up the priority dependent masks for main interrupts */
0662   for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) {
0663     prio = irqPrioTable [i];
0664     mask = 0;
0665 
0666     for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) {
0667       if (prio > irqPrioTable [j]) {
0668         mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
0669       }
0670 
0671       if ((prio == irqPrioTable [j]) && (j >= i)) {
0672         mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
0673       }
0674     }
0675 
0676     irqMaskTable [i] = mask;
0677   }
0678 }
0679 
0680 /*
0681  * Initialize MPC5x00 SIU interrupt management
0682  */
0683 static void BSP_SIU_irq_init( void)
0684 {
0685 
0686   /* disable all peripheral interrupts */
0687   mpc5200.per_mask = 0xFFFFFC00;
0688 
0689   /* peripheral interrupt priorities according to reset value */
0690   mpc5200.per_pri_1 = 0xF0000000;
0691   mpc5200.per_pri_2 = 0x00000000;
0692   mpc5200.per_pri_3 = 0x00000000;
0693 
0694   /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */
0695   mpc5200.ext_en_type = 0x0F000001;
0696 
0697   /* disable main interrupts / crit. int. priorities according to reset values */
0698   mpc5200.crit_pri_main_mask = 0x0001FFFF;
0699 
0700   /* main priorities according to reset value */
0701   mpc5200.main_pri_1 = 0;
0702   mpc5200.main_pri_2 = 0;
0703 
0704   /* reset all status indicators */
0705   mpc5200.csa = 0x0001FFFF;
0706   mpc5200.msa = 0x0001FFFF;
0707   mpc5200.psa = 0x003FFFFF;
0708   mpc5200.psa_be = 0x03000000;
0709 
0710   setup_irqMaskTable();
0711 }
0712 
0713 void bsp_interrupt_facility_initialize( void)
0714 {
0715   rtems_status_code sc;
0716 
0717   BSP_SIU_irq_init();
0718 
0719   /* Install exception handler */
0720   sc = ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler);
0721   _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL);
0722   sc = ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler);
0723   _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL);
0724 }
0725 
0726 void bsp_interrupt_handler_default( rtems_vector_number vector)
0727 {
0728   if (vector != BSP_DECREMENTER) {
0729     printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector);
0730   }
0731 }