File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <rtems.h>
0021 #include <bsp.h>
0022 #include <rtems/bspIo.h>
0023 #include <bsp/openpic.h>
0024 #include <rtems/pci.h>
0025 #include <libcpu/io.h>
0026 #include <libcpu/byteorder.h>
0027 #include <rtems/bspIo.h>
0028 #include <inttypes.h>
0029
0030 #ifndef NULL
0031 #define NULL 0
0032 #endif
0033 #define REGISTER_DEBUG
0034 #undef REGISTER_DEBUG
0035
0036 volatile struct OpenPIC *OpenPIC = NULL;
0037
0038 static unsigned int NumProcessors;
0039 static unsigned int NumSources;
0040
0041 static unsigned int openpic_eoi_delay = 0;
0042 static int openpic_src_offst = 0;
0043 #define SOURCE(irq) Source[ (irq) + openpic_src_offst ]
0044
0045
0046
0047
0048
0049 #define THIS_CPU Processor[cpu]
0050 #define CHECK_THIS_CPU check_arg_cpu(cpu)
0051
0052
0053
0054
0055
0056 #if 1
0057
0058
0059
0060 #pragma GCC diagnostic push
0061 #pragma GCC diagnostic ignored "-Wframe-address"
0062 #define check_arg_ipi(ipi) \
0063 if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
0064 printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
0065 #define check_arg_timer(timer) \
0066 if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
0067 printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
0068 #define check_arg_vec(vec) \
0069 if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
0070 printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
0071 #define check_arg_pri(pri) \
0072 if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
0073 printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
0074 #define check_arg_irq(irq) \
0075 if (irq < 0 || irq >= NumSources) \
0076 printk("openpic.c:%d: illegal irq %d from 0x%08" PRIxPTR ",[0x%08" PRIxPTR "],[[0x%08" PRIxPTR "]]\n", \
0077 __LINE__, irq, (uintptr_t) __builtin_return_address(0), \
0078 (uintptr_t) __builtin_return_address(1), (uintptr_t) __builtin_return_address(2) \
0079 );
0080 #define check_arg_cpu(cpu) \
0081 if (cpu < 0 || cpu >= NumProcessors) \
0082 printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
0083 #else
0084 #define check_arg_ipi(ipi) do {} while (0)
0085 #define check_arg_timer(timer) do {} while (0)
0086 #define check_arg_vec(vec) do {} while (0)
0087 #define check_arg_pri(pri) do {} while (0)
0088 #define check_arg_irq(irq) do {} while (0)
0089 #define check_arg_cpu(cpu) do {} while (0)
0090 #endif
0091
0092
0093
0094
0095
0096 static inline unsigned int openpic_read(volatile unsigned int *addr)
0097 {
0098 unsigned int val;
0099
0100 #ifdef BSP_OPEN_PIC_BIG_ENDIAN
0101 val = in_be32((volatile uint32_t *)addr);
0102 #else
0103 val = in_le32((volatile uint32_t *)addr);
0104 #endif
0105 #ifdef REGISTER_DEBUG
0106 printk("openpic_read(0x%08x) = 0x%08x\n", (unsigned int)addr, val);
0107 #endif
0108 return val;
0109 }
0110
0111 static inline void openpic_write(volatile unsigned int *addr, unsigned int val)
0112 {
0113 #ifdef REGISTER_DEBUG
0114 printk("openpic_write(0x%08x, 0x%08x)\n", (unsigned int)addr, val);
0115 #endif
0116 #ifdef BSP_OPEN_PIC_BIG_ENDIAN
0117 out_be32((volatile uint32_t *)addr, val);
0118 #else
0119 out_le32((volatile uint32_t *)addr, val);
0120 #endif
0121 }
0122
0123 static inline unsigned int openpic_readfield(volatile unsigned int *addr, unsigned int mask)
0124 {
0125 unsigned int val = openpic_read(addr);
0126 return val & mask;
0127 }
0128
0129 static inline void openpic_writefield(volatile unsigned int *addr, unsigned int mask,
0130 unsigned int field)
0131 {
0132 unsigned int val = openpic_read(addr);
0133 openpic_write(addr, (val & ~mask) | (field & mask));
0134 }
0135
0136 static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask)
0137 {
0138 openpic_writefield(addr, mask, 0);
0139 }
0140
0141 static inline void openpic_setfield(volatile unsigned int *addr, unsigned int mask)
0142 {
0143 openpic_writefield(addr, mask, mask);
0144 }
0145
0146
0147
0148
0149
0150
0151 static void openpic_safe_writefield(volatile unsigned int *addr, unsigned int mask,
0152 unsigned int field)
0153 {
0154 openpic_setfield(addr, OPENPIC_MASK);
0155
0156 while (openpic_read(addr) & OPENPIC_ACTIVITY);
0157 openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 void openpic_init(int main_pic, unsigned char *polarities, unsigned char *senses, int num_sources, int source_offset, unsigned long epic_freq)
0175 {
0176 unsigned int t, i;
0177 unsigned int vendorid, devid, stepping, timerfreq;
0178 const char *version, *vendor, *device;
0179
0180 if (!OpenPIC)
0181 rtems_panic("No OpenPIC found");
0182
0183 t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
0184 switch (t & OPENPIC_FEATURE_VERSION_MASK) {
0185 case 1:
0186 version = "1.0";
0187 break;
0188 case 2:
0189 version = "1.2";
0190 break;
0191 default:
0192 version = "?";
0193 break;
0194 }
0195 NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
0196 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
0197 NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
0198 OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
0199 t = openpic_read(&OpenPIC->Global.Vendor_Identification);
0200
0201 vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK;
0202 devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >>
0203 OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT;
0204 stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >>
0205 OPENPIC_VENDOR_ID_STEPPING_SHIFT;
0206
0207
0208
0209
0210
0211 if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
0212 vendor = "Motorola";
0213 device = "Raven";
0214 NumSources += 1;
0215 }
0216 else if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_HAWK<<16)) {
0217 vendor = "Motorola";
0218 device = "Hawk";
0219 NumSources += 1;
0220 } else {
0221 switch (vendorid) {
0222 case OPENPIC_VENDOR_ID_APPLE:
0223 vendor = "Apple";
0224 break;
0225 default:
0226 vendor = "Unknown";
0227 break;
0228 }
0229 switch (devid) {
0230 case OPENPIC_DEVICE_ID_APPLE_HYDRA:
0231 device = "Hydra";
0232 break;
0233 default:
0234 device = "Unknown";
0235 break;
0236 }
0237 }
0238 printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at 0x%08" PRIuPTR "\n", version,
0239 NumProcessors, NumSources, (uintptr_t) OpenPIC);
0240
0241 printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid,
0242 vendor, devid, device, stepping);
0243
0244
0245 if ( num_sources ) {
0246 if ( NumSources != num_sources )
0247 printk("Overriding NumSources (%i) from configuration with %i\n",
0248 NumSources, num_sources);
0249 NumSources = num_sources;
0250 }
0251
0252 openpic_src_offst = source_offset;
0253
0254 timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
0255 printk("OpenPIC timer frequency is ");
0256 if (timerfreq)
0257 printk("%d Hz\n", timerfreq);
0258 else
0259 printk("not set\n");
0260
0261 if ( main_pic )
0262 {
0263
0264 for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
0265
0266 openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
0267
0268 openpic_maptimer(i, 0);
0269 }
0270
0271
0272 for (i = 0; i < OPENPIC_NUM_IPI; i++) {
0273
0274 openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
0275 }
0276
0277
0278 for (i = 0; i < NumSources; i++) {
0279
0280 openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i,
0281 polarities ? polarities[i] : 0,
0282 senses ? senses[i] : 1);
0283
0284 openpic_mapirq(i, 1<<0);
0285 }
0286
0287
0288 openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
0289 #if 0
0290 if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
0291 "82c59 cascade", NULL))
0292 printk("Unable to get OpenPIC IRQ 0 for cascade\n");
0293 #endif
0294 openpic_set_priority(0, 0);
0295 openpic_disable_8259_pass_through();
0296 }
0297 if ( epic_freq ) {
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 uint32_t eicr_val, ratio;
0315
0316 eicr_val = in_le32( (volatile uint32_t *)&OpenPIC->Global.Global_Configuration1 ) & ~(7<<28);
0317 if ( (1<<27) & eicr_val ) {
0318
0319
0320
0321
0322
0323 ratio = epic_freq / 16500000 + 1;
0324 ratio >>= 2;
0325 if ( 0==ratio )
0326 ratio = 1;
0327 out_le32((volatile uint32_t *)&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28));
0328
0329 openpic_set_eoi_delay( 16 * (2*ratio) / 4 );
0330 }
0331 }
0332 }
0333
0334
0335
0336
0337
0338 void openpic_reset(void)
0339 {
0340 openpic_setfield(&OpenPIC->Global.Global_Configuration0,
0341 OPENPIC_CONFIG_RESET);
0342 }
0343
0344
0345
0346
0347
0348 void openpic_enable_8259_pass_through(void)
0349 {
0350 openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
0351 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
0352 }
0353
0354 void openpic_disable_8259_pass_through(void)
0355 {
0356 openpic_setfield(&OpenPIC->Global.Global_Configuration0,
0357 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
0358 }
0359
0360
0361
0362
0363
0364 unsigned int openpic_irq(unsigned int cpu)
0365 {
0366 unsigned int vec;
0367
0368 check_arg_cpu(cpu);
0369 vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
0370 OPENPIC_VECTOR_MASK);
0371 return vec;
0372 }
0373
0374
0375
0376
0377
0378 void openpic_eoi(unsigned int cpu)
0379 {
0380 check_arg_cpu(cpu);
0381 if ( openpic_eoi_delay )
0382 rtems_bsp_delay_in_bus_cycles(openpic_eoi_delay);
0383 openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
0384 }
0385
0386 unsigned openpic_set_eoi_delay(unsigned tb_cycles)
0387 {
0388 unsigned rval = openpic_eoi_delay;
0389 openpic_eoi_delay = tb_cycles;
0390 return rval;
0391 }
0392
0393
0394
0395
0396
0397 unsigned int openpic_get_priority(unsigned int cpu)
0398 {
0399 CHECK_THIS_CPU;
0400 return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
0401 OPENPIC_CURRENT_TASK_PRIORITY_MASK);
0402 }
0403
0404 void openpic_set_priority(unsigned int cpu, unsigned int pri)
0405 {
0406 CHECK_THIS_CPU;
0407 check_arg_pri(pri);
0408 openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
0409 OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
0410 }
0411
0412
0413
0414
0415
0416 unsigned int openpic_get_spurious(void)
0417 {
0418 return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
0419 OPENPIC_VECTOR_MASK);
0420 }
0421
0422 void openpic_set_spurious(unsigned int vec)
0423 {
0424 check_arg_vec(vec);
0425 openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
0426 vec);
0427 }
0428
0429
0430
0431
0432
0433 void openpic_init_processor(unsigned int cpumask)
0434 {
0435 openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
0436 }
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 void openpic_initipi(unsigned int ipi, unsigned int pri, unsigned int vec)
0449 {
0450 check_arg_timer(ipi);
0451 check_arg_pri(pri);
0452 check_arg_vec(vec);
0453 openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
0454 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
0455 (pri << OPENPIC_PRIORITY_SHIFT) | vec);
0456 }
0457
0458
0459
0460
0461
0462 void openpic_cause_IPI(unsigned int cpu, unsigned int ipi, unsigned int cpumask)
0463 {
0464 CHECK_THIS_CPU;
0465 check_arg_ipi(ipi);
0466 openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
0467 }
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 void openpic_inittimer(unsigned int timer, unsigned int pri, unsigned int vec)
0480 {
0481 check_arg_timer(timer);
0482 check_arg_pri(pri);
0483 check_arg_vec(vec);
0484 openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
0485 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
0486 (pri << OPENPIC_PRIORITY_SHIFT) | vec);
0487 }
0488
0489
0490
0491
0492
0493 void openpic_maptimer(unsigned int timer, unsigned int cpumask)
0494 {
0495 check_arg_timer(timer);
0496 openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
0497 }
0498
0499
0500
0501
0502
0503
0504 void openpic_settimer(unsigned int timer, unsigned int base_count, int irq_enable)
0505 {
0506 check_arg_timer(timer);
0507 if ( base_count )
0508 openpic_write(&OpenPIC->Global.Timer[timer].Base_Count, base_count);
0509 if ( irq_enable )
0510 openpic_clearfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK);
0511 else
0512 openpic_setfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK);
0513 }
0514
0515 unsigned int openpic_gettimer(unsigned int timer)
0516 {
0517 check_arg_timer(timer);
0518 return (openpic_read(&OpenPIC->Global.Timer[timer].Current_Count) & ~OPENPIC_MASK);
0519 }
0520
0521
0522
0523
0524
0525
0526
0527 void openpic_enable_irq(unsigned int irq)
0528 {
0529 unsigned long flags;
0530 check_arg_irq(irq);
0531 rtems_interrupt_disable(flags);
0532 openpic_clearfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK);
0533 rtems_interrupt_enable(flags);
0534 }
0535
0536 int openpic_disable_irq(unsigned int irq)
0537 {
0538 int rval;
0539 unsigned long flags;
0540 check_arg_irq(irq);
0541 if ( irq < 0 || irq >=NumSources )
0542 return -1;
0543 rtems_interrupt_disable(flags);
0544 rval = openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK) ? 0 : 1;
0545 openpic_setfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK);
0546 rtems_interrupt_enable(flags);
0547 return rval;
0548 }
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560 void openpic_initirq(unsigned int irq, unsigned int pri, unsigned int vec, int pol, int sense)
0561 {
0562 #if 0
0563 printk("openpic_initirq: irq=%d pri=%d vec=%d pol=%d sense=%d\n",
0564 irq, pri, vec, pol, sense);
0565 #endif
0566
0567 check_arg_irq(irq);
0568 check_arg_pri(pri);
0569 check_arg_vec(vec);
0570 openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority,
0571 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
0572 OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
0573 (pri << OPENPIC_PRIORITY_SHIFT) | vec |
0574 (pol ? OPENPIC_SENSE_POLARITY : 0) |
0575 (sense ? OPENPIC_SENSE_LEVEL : 0));
0576 }
0577
0578
0579
0580
0581
0582 void openpic_mapirq(unsigned int irq, unsigned int cpumask)
0583 {
0584 check_arg_irq(irq);
0585 openpic_write(&OpenPIC->SOURCE(irq).Destination, cpumask);
0586 }
0587
0588
0589
0590
0591 unsigned int openpic_get_source_priority(unsigned int irq)
0592 {
0593 check_arg_irq(irq);
0594 return openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority,
0595 OPENPIC_PRIORITY_MASK) >> OPENPIC_PRIORITY_SHIFT;
0596 }
0597
0598 void openpic_set_source_priority(unsigned int irq, unsigned int pri)
0599 {
0600 unsigned long flags;
0601 check_arg_irq(irq);
0602 check_arg_pri(pri);
0603 rtems_interrupt_disable(flags);
0604 openpic_writefield(
0605 &OpenPIC->SOURCE(irq).Vector_Priority,
0606 OPENPIC_PRIORITY_MASK,
0607 pri << OPENPIC_PRIORITY_SHIFT);
0608 rtems_interrupt_enable(flags);
0609 }
0610
0611
0612
0613
0614
0615
0616 void openpic_set_sense(unsigned int irq, int sense)
0617 {
0618 check_arg_irq(irq);
0619 openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority,
0620 OPENPIC_SENSE_LEVEL,
0621 (sense ? OPENPIC_SENSE_LEVEL : 0));
0622 }