File indexing completed on 2025-05-11 08:23:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
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
0036
0037
0038
0039 const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = {
0040 0, 1, 2, 3,
0041 4, 5, 6, 7,
0042 8, 9, 10, 11,
0043 12, 13, 14, 15,
0044 16, 17, 18, 19,
0045 20, 21, 15, 16,
0046 17, 18, 19, 20,
0047 21, 22, 23, 24,
0048 25, 26, 27, 28,
0049 29, 30, 31, 32,
0050 32, 32, 32
0051 };
0052
0053 static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = {
0054
0055
0056
0057 0xF, 0, 0, 0,
0058 0, 0, 0, 0,
0059 0, 0, 0, 0,
0060 0, 0, 0, 0,
0061 0, 0, 0, 0,
0062 0, 0,
0063
0064
0065
0066 0, 0,
0067 0, 0, 0, 0,
0068 0, 0, 0, 0,
0069 0, 0, 0, 0,
0070 0, 0, 0,
0071
0072 0,
0073 0, 0, 0
0074 };
0075
0076 static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER];
0077
0078
0079
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
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
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
0124 prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
0125
0126
0127 if (irqPrioTable [irqLine] <= 15) {
0128
0129
0130 reg = (uint32_t *) (&(mpc5200.per_pri_1));
0131
0132
0133 reg += (irqLine >> 3);
0134
0135
0136 *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
0137
0138
0139 if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) {
0140
0141
0142 reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
0143 *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26);
0144
0145
0146
0147
0148
0149
0150 mpc5200.ext_en_type |= 1;
0151
0152 } else {
0153 if (irqPrioTable [irqLine] <= 15) {
0154
0155 reg = (uint32_t *) (&(mpc5200.main_pri_1));
0156 *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16);
0157 }
0158 }
0159 }
0160
0161
0162 if (!lo_hi_ind) {
0163 mpc5200.crit_pri_main_mask &=
0164 ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]);
0165 }
0166
0167
0168 mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
0169
0170
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
0186 prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
0187
0188
0189 if (irqPrioTable [irqLine] <= 15) {
0190
0191
0192 reg = (uint32_t *) (&(mpc5200.main_pri_1));
0193
0194
0195 reg += (irqLine >> 3);
0196
0197
0198 *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
0199
0200 if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
0201
0202 mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
0203 }
0204 }
0205
0206
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
0222
0223
0224
0225 mpc5200.ext_en_type |= 1;
0226
0227
0228 if (irqPrioTable [irqLine] <= 3) {
0229
0230
0231 reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
0232
0233
0234 *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1)));
0235
0236
0237 if (irqLine == BSP_SIU_IRQ_IRQ1) {
0238
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
0252 prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
0253
0254
0255 mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
0256
0257
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
0271 prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
0272
0273
0274 mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
0275
0276 if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
0277
0278 mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
0279 }
0280
0281
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
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
0301 mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
0302 }
0303 }
0304
0305
0306
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
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
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
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
0536 pmce = mpc5200.pmce;
0537
0538
0539
0540
0541 while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) {
0542
0543
0544
0545 if ((pmce & PMCE_CSE_STICKY) != 0) {
0546
0547 irq = PMCE_CSE_SOURCE(pmce);
0548
0549 switch (irq) {
0550
0551 case 2:
0552
0553 if ((pmce & PMCE_PSE_STICKY) != 0) {
0554
0555 irq = PMCE_PSE_SOURCE(pmce);
0556
0557 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
0558 } else {
0559
0560
0561 printk( "No valid peripheral HI_int interrupt source\n");
0562 }
0563 break;
0564
0565
0566 case 0:
0567 case 1:
0568 case 3:
0569
0570
0571
0572 irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
0573
0574
0575 bsp_interrupt_handler_dispatch( irq);
0576
0577 break;
0578
0579 default:
0580
0581 printk( "Unknown HI_int interrupt source\n");
0582 break;
0583 }
0584 }
0585
0586
0587
0588 if ((pmce & PMCE_MSE_STICKY) != 0) {
0589
0590 irq = PMCE_MSE_SOURCE(pmce);
0591
0592 if (irq == 4) {
0593
0594
0595 if ((pmce & PMCE_PSE_STICKY) != 0) {
0596
0597 irq = PMCE_PSE_SOURCE(pmce);
0598
0599 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
0600 } else {
0601
0602
0603 printk( "No valid peripheral LO_int interrupt source\n");
0604 }
0605 } else if (irq <= 16) {
0606
0607
0608 dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
0609 } else {
0610
0611 printk( "Unknown peripheral LO_int interrupt source\n");
0612 }
0613 }
0614
0615
0616 mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY;
0617
0618
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
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
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
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
0682
0683 static void BSP_SIU_irq_init( void)
0684 {
0685
0686
0687 mpc5200.per_mask = 0xFFFFFC00;
0688
0689
0690 mpc5200.per_pri_1 = 0xF0000000;
0691 mpc5200.per_pri_2 = 0x00000000;
0692 mpc5200.per_pri_3 = 0x00000000;
0693
0694
0695 mpc5200.ext_en_type = 0x0F000001;
0696
0697
0698 mpc5200.crit_pri_main_mask = 0x0001FFFF;
0699
0700
0701 mpc5200.main_pri_1 = 0;
0702 mpc5200.main_pri_2 = 0;
0703
0704
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
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 }