Back to home page

LXR

 
 

    


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

0001 /*
0002  *
0003  *  This file contains the implementation of the function described in irq.h
0004  *
0005  *  Copyright (C) 1998, 1999 valette@crf.canon.fr
0006  *
0007  *  Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk>
0008  *  Surrey Satellite Technology Limited, 2000
0009  *    21/4/2002 Added support for nested interrupts and improved
0010  *    masking operations.  Now we compute priority mask based
0011  *     on table in irq_init.c
0012  *
0013  *  The license and distribution terms for this file may be
0014  *  found in the file LICENSE in this distribution or at
0015  *  http://www.rtems.org/license/LICENSE.
0016  */
0017 
0018 #include <bsp.h>
0019 #include <bsp/irq.h>
0020 #include <bsp/irq-generic.h>
0021 #include <rtems.h>
0022 #include <rtems/bspIo.h>
0023 #include <bsp/vectors.h>
0024 #include <mpc8260.h>
0025 
0026 /*
0027  * Check if symbolic IRQ name is an CPM IRQ
0028  */
0029 static inline int is_cpm_irq(const rtems_irq_number irqLine)
0030 {
0031   return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
0032       ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
0033   );
0034 }
0035 
0036 typedef struct {
0037   uint32_t         mask_h;  /* mask for sipnr_h and simr_h */
0038   uint32_t         mask_l;  /* mask for sipnr_l and simr_l */
0039   uint32_t         priority_h;  /* mask this and lower priority ints */
0040   uint32_t         priority_l;
0041 } m82xxIrqMasks_t;
0042 
0043 static unsigned char irqPrioTable[BSP_CPM_IRQ_NUMBER]={
0044   /*
0045    * actual priorities for interrupt :
0046    */
0047   /*
0048    * CPM Interrupts
0049    */
0050   0,  45, 63, 44, 66, 68, 35, 39, 50, 62, 34,  0,  30, 40, 52, 58,
0051   2,  3,  0,  5,  15, 16, 17, 18, 49, 51,  0,  0,  0,  0,  0,  0,
0052   6,  7,  8,  0,  11, 12, 0,  0,  20, 21, 22,  23, 0,  0,  0,  0,
0053   29, 31, 33, 37, 38, 41, 47, 48, 55, 56, 57,  60, 64, 65, 69, 70,
0054 
0055 };
0056 
0057 /*
0058  *  Mask fields should have a '1' in the bit position for that
0059  *  interrupt.
0060  *  Priority masks calculated later based on priority table
0061  */
0062 
0063 static m82xxIrqMasks_t SIU_MaskBit[BSP_CPM_IRQ_NUMBER] =
0064 {
0065   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* err */
0066   { 0x00000000, 0x00008000, 0x00000000, 0x00000000 }, /* i2c */
0067   { 0x00000000, 0x00004000, 0x00000000, 0x00000000 }, /* spi */
0068   { 0x00000000, 0x00002000, 0x00000000, 0x00000000 }, /* rtt */
0069   { 0x00000000, 0x00001000, 0x00000000, 0x00000000 }, /* smc1 */
0070   { 0x00000000, 0x00000800, 0x00000000, 0x00000000 }, /* smc2 */
0071   { 0x00000000, 0x00000400, 0x00000000, 0x00000000 }, /* idma1 */
0072   { 0x00000000, 0x00000200, 0x00000000, 0x00000000 }, /* idma2 */
0073   { 0x00000000, 0x00000100, 0x00000000, 0x00000000 }, /* idma3 */
0074   { 0x00000000, 0x00000080, 0x00000000, 0x00000000 }, /* idma4 */
0075   { 0x00000000, 0x00000040, 0x00000000, 0x00000000 }, /* sdma */
0076   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0077   { 0x00000000, 0x00000010, 0x00000000, 0x00000000 }, /* tmr1 */
0078   { 0x00000000, 0x00000008, 0x00000000, 0x00000000 }, /* tmr2 */
0079   { 0x00000000, 0x00000004, 0x00000000, 0x00000000 }, /* tmr3 */
0080   { 0x00000000, 0x00000002, 0x00000000, 0x00000000 }, /* tmr4 */
0081   { 0x00000004, 0x00000000, 0x00000000, 0x00000000 }, /* tmcnt */
0082   { 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* pit */
0083   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0084   { 0x00004000, 0x00000000, 0x00000000, 0x00000000 }, /* irq1 */
0085   { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* irq2 */
0086   { 0x00001000, 0x00000000, 0x00000000, 0x00000000 }, /* irq3 */
0087   { 0x00000800, 0x00000000, 0x00000000, 0x00000000 }, /* irq4 */
0088   { 0x00000400, 0x00000000, 0x00000000, 0x00000000 }, /* irq5 */
0089   { 0x00000200, 0x00000000, 0x00000000, 0x00000000 }, /* irq6 */
0090   { 0x00000100, 0x00000000, 0x00000000, 0x00000000 }, /* irq7 */
0091   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0092   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0093   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0094   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0095   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0096   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0097   { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }, /* fcc1 */
0098   { 0x00000000, 0x40000000, 0x00000000, 0x00000000 }, /* fcc2 */
0099   { 0x00000000, 0x20000000, 0x00000000, 0x00000000 }, /* fcc3 */
0100   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0101   { 0x00000000, 0x08000000, 0x00000000, 0x00000000 }, /* mcc1 */
0102   { 0x00000000, 0x04000000, 0x00000000, 0x00000000 }, /* mcc2 */
0103   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0104   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0105   { 0x00000000, 0x00800000, 0x00000000, 0x00000000 }, /* scc1 */
0106   { 0x00000000, 0x00400000, 0x00000000, 0x00000000 }, /* scc2 */
0107   { 0x00000000, 0x00200000, 0x00000000, 0x00000000 }, /* scc3 */
0108   { 0x00000000, 0x00100000, 0x00000000, 0x00000000 }, /* scc4 */
0109   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0110   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0111   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0112   { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
0113   { 0x00010000, 0x00000000, 0x00000000, 0x00000000 }, /* pc15 */
0114   { 0x00020000, 0x00000000, 0x00000000, 0x00000000 }, /* pc14 */
0115   { 0x00040000, 0x00000000, 0x00000000, 0x00000000 }, /* pc13 */
0116   { 0x00080000, 0x00000000, 0x00000000, 0x00000000 }, /* pc12 */
0117   { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* pc11 */
0118   { 0x00200000, 0x00000000, 0x00000000, 0x00000000 }, /* pc10 */
0119   { 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* pc9 */
0120   { 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* pc8 */
0121   { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc7 */
0122   { 0x02000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc6 */
0123   { 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc5 */
0124   { 0x08000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc4 */
0125   { 0x10000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc3 */
0126   { 0x20000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc2 */
0127   { 0x40000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc1 */
0128   { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc0 */
0129 
0130 };
0131 
0132 /*
0133  * ------------------------ RTEMS Irq helper functions ----------------
0134  */
0135 
0136 /*
0137  * Caution : this function assumes the variable "internal_config"
0138  * is already set and that the tables it contains are still valid
0139  * and accessible.
0140  */
0141 static void compute_SIU_IvectMask_from_prio (void)
0142 {
0143   /*
0144    * The actual masks defined
0145    * correspond to the priorities defined
0146    * for the SIU in irq_init.c.
0147    */
0148 
0149    int i,j;
0150 
0151    for( i=0; i<BSP_CPM_IRQ_NUMBER; i++ )
0152    {
0153      for( j=0;j<BSP_CPM_IRQ_NUMBER; j++ )
0154        if( irqPrioTable[j] < irqPrioTable[i] )
0155        {
0156         SIU_MaskBit[i].priority_h |= SIU_MaskBit[j].mask_h;
0157         SIU_MaskBit[i].priority_l |= SIU_MaskBit[j].mask_l;
0158       }
0159    }
0160 
0161 }
0162 
0163 
0164 int BSP_irq_enable_at_cpm(const rtems_irq_number irqLine)
0165 {
0166   int cpm_irq_index;
0167 
0168   if (!is_cpm_irq(irqLine))
0169     return 1;
0170 
0171   cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
0172 
0173   m8260.simr_h |= SIU_MaskBit[cpm_irq_index].mask_h;
0174   m8260.simr_l |= SIU_MaskBit[cpm_irq_index].mask_l;
0175 
0176   return 0;
0177 }
0178 
0179 int BSP_irq_disable_at_cpm(const rtems_irq_number irqLine)
0180 {
0181   int cpm_irq_index;
0182 
0183   if (!is_cpm_irq(irqLine))
0184     return 1;
0185 
0186   cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
0187 
0188   m8260.simr_h &= ~(SIU_MaskBit[cpm_irq_index].mask_h);
0189   m8260.simr_l &= ~(SIU_MaskBit[cpm_irq_index].mask_l);
0190 
0191   return 0;
0192 }
0193 
0194 int BSP_irq_enabled_at_cpm(const rtems_irq_number irqLine)
0195 {
0196        int cpm_irq_index;
0197 
0198        if (!is_cpm_irq(irqLine))
0199                return 0;
0200 
0201        cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
0202 
0203        return ((m8260.simr_h & SIU_MaskBit[cpm_irq_index].mask_h) ||
0204                    (m8260.simr_l & SIU_MaskBit[cpm_irq_index].mask_l));
0205 }
0206 
0207 #ifdef DISPATCH_HANDLER_STAT
0208 volatile unsigned int maxLoop = 0;
0209 #endif
0210 
0211 /*
0212  * High level IRQ handler called from shared_raw_irq_code_entry
0213  */
0214 static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned excNum)
0215 {
0216   register unsigned int irq;
0217 #if 0
0218   register unsigned oldMask;          /* old siu pic masks */
0219 #endif
0220   register unsigned msr;
0221   register unsigned new_msr;
0222   register unsigned old_simr_h;
0223   register unsigned old_simr_l;
0224 #ifdef DISPATCH_HANDLER_STAT
0225   unsigned loopCounter;
0226 #endif
0227 
0228   /*
0229    * Handle decrementer interrupt
0230    */
0231   if (excNum == ASM_DEC_VECTOR) {
0232     _CPU_MSR_GET(msr);
0233     new_msr = msr | MSR_EE;
0234     _CPU_MSR_SET(new_msr);
0235 
0236     bsp_interrupt_handler_dispatch(BSP_DECREMENTER);
0237 
0238     _CPU_MSR_SET(msr);
0239 
0240     return 0;
0241   }
0242 
0243   /*
0244    * Handle external interrupt generated by SIU on PPC core
0245    */
0246 #ifdef DISPATCH_HANDLER_STAT
0247   loopCounter = 0;
0248 #endif
0249 
0250   while (1) {
0251 
0252     if( ((m8260.sipnr_h & m8260.simr_h) | (m8260.sipnr_l & m8260.simr_l)) == 0 ) {
0253 #ifdef DISPATCH_HANDLER_STAT
0254       if (loopCounter >  maxLoop) maxLoop = loopCounter;
0255 #endif
0256       break;
0257     }
0258 
0259     irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET;
0260 
0261     /* Clear mask and pending register */
0262     if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) {
0263       /* save interrupt masks */
0264       old_simr_h = m8260.simr_h;
0265       old_simr_l = m8260.simr_l;
0266 
0267       /* mask off current interrupt and lower priority ones */
0268       m8260.simr_h &= SIU_MaskBit[irq].priority_h;
0269       m8260.simr_l &= SIU_MaskBit[irq].priority_l;
0270 
0271       /* clear pending bit */
0272       m8260.sipnr_h |= SIU_MaskBit[irq].mask_h;
0273       m8260.sipnr_l |= SIU_MaskBit[irq].mask_l;
0274 
0275       /*
0276        * make sure, that the masking operations in
0277        * ICTL and MSR are executed in order
0278        */
0279       __asm__ volatile("sync":::"memory");
0280 
0281       /* re-enable external exceptions */
0282       _CPU_MSR_GET(msr);
0283       new_msr = msr | MSR_EE;
0284       _CPU_MSR_SET(new_msr);
0285 
0286       /* call handler */
0287       bsp_interrupt_handler_dispatch(irq);
0288 
0289       /* disable exceptions again */
0290       _CPU_MSR_SET(msr);
0291 
0292       /*
0293        * make sure, that the masking operations in
0294        * ICTL and MSR are executed in order
0295        */
0296       __asm__ volatile("sync":::"memory");
0297 
0298       /* restore interrupt masks */
0299       m8260.simr_h = old_simr_h;
0300       m8260.simr_l = old_simr_l;
0301 
0302     }
0303 #ifdef DISPATCH_HANDLER_STAT
0304     ++ loopCounter;
0305 #endif
0306   }
0307   return 0;
0308 }
0309 
0310 /*
0311  * Initialize CPM interrupt management
0312  */
0313 static void
0314 BSP_CPM_irq_init(void)
0315 {
0316    m8260.simr_l = 0;
0317    m8260.simr_h = 0;
0318    m8260.sipnr_l = 0xffffffff;
0319    m8260.sipnr_h = 0xffffffff;
0320    m8260.sicr = 0;
0321 
0322   /*
0323    * Initialize the interrupt priorities.
0324    */
0325    m8260.siprr   = 0x05309770;  /* reset value */
0326    m8260.scprr_h = 0x05309770;  /* reset value */
0327    m8260.scprr_l = 0x05309770;  /* reset value */
0328 
0329 }
0330 
0331 rtems_status_code bsp_interrupt_get_attributes(
0332   rtems_vector_number         vector,
0333   rtems_interrupt_attributes *attributes
0334 )
0335 {
0336   return RTEMS_SUCCESSFUL;
0337 }
0338 
0339 rtems_status_code bsp_interrupt_is_pending(
0340   rtems_vector_number vector,
0341   bool               *pending
0342 )
0343 {
0344   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0345   bsp_interrupt_assert(pending != NULL);
0346   *pending = false;
0347   return RTEMS_UNSATISFIED;
0348 }
0349 
0350 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0351 {
0352   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0353   return RTEMS_UNSATISFIED;
0354 }
0355 
0356 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0357 {
0358   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0359   return RTEMS_UNSATISFIED;
0360 }
0361 
0362 rtems_status_code bsp_interrupt_vector_is_enabled(
0363   rtems_vector_number vector,
0364   bool               *enabled
0365 )
0366 {
0367   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0368   bsp_interrupt_assert(enabled != NULL);
0369   *enabled = false;
0370   return RTEMS_UNSATISFIED;
0371 }
0372 
0373 rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number irqnum)
0374 {
0375   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
0376 
0377   if (is_cpm_irq(irqnum)) {
0378     /*
0379      * Enable interrupt at PIC level
0380      */
0381     BSP_irq_enable_at_cpm (irqnum);
0382   }
0383 
0384   return RTEMS_SUCCESSFUL;
0385 }
0386 
0387 rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number irqnum)
0388 {
0389   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
0390 
0391   if (is_cpm_irq(irqnum)) {
0392     /*
0393      * disable interrupt at PIC level
0394      */
0395     BSP_irq_disable_at_cpm (irqnum);
0396   }
0397 
0398   return RTEMS_SUCCESSFUL;
0399 }
0400 
0401 rtems_status_code bsp_interrupt_set_priority(
0402   rtems_vector_number vector,
0403   uint32_t priority
0404 )
0405 {
0406   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0407   return RTEMS_UNSATISFIED;
0408 }
0409 
0410 rtems_status_code bsp_interrupt_get_priority(
0411   rtems_vector_number vector,
0412   uint32_t *priority
0413 )
0414 {
0415   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0416   bsp_interrupt_assert(priority != NULL);
0417   return RTEMS_UNSATISFIED;
0418 }
0419 
0420 void bsp_interrupt_facility_initialize()
0421 {
0422   rtems_status_code sc;
0423 
0424   /* Install exception handler */
0425   sc = ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler);
0426   _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL);
0427   sc = ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler);
0428   _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL);
0429 
0430   /* Fill in priority masks */
0431   compute_SIU_IvectMask_from_prio();
0432 
0433   /* Initialize the interrupt controller */
0434   BSP_CPM_irq_init();
0435 }