File indexing completed on 2025-05-11 08:23:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <sys/param.h>
0037 #include <sys/bitset.h>
0038
0039 #include <rtems.h>
0040
0041 #include <libcpu/powerpc-utility.h>
0042
0043 #include <asm/epapr_hcalls.h>
0044
0045 #include <bsp.h>
0046 #include <bsp/irq-generic.h>
0047 #include <bsp/vectors.h>
0048 #include <bsp/utility.h>
0049 #include <bsp/qoriq.h>
0050 #include <rtems/score/processormaskimpl.h>
0051
0052 #ifdef RTEMS_SMP
0053 #include <rtems/score/smpimpl.h>
0054 #endif
0055
0056 RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ")
0057
0058 #define SPURIOUS 0xffff
0059
0060 #ifdef QORIQ_IS_HYPERVISOR_GUEST
0061
0062 rtems_status_code bsp_interrupt_set_affinity(
0063 rtems_vector_number vector,
0064 const Processor_mask *affinity
0065 )
0066 {
0067 uint32_t config;
0068 unsigned int priority;
0069 uint32_t destination;
0070 uint32_t new_destination;
0071 rtems_interrupt_lock_context lock_context;
0072
0073 new_destination = _Processor_mask_Find_last_set(affinity) - 1;
0074
0075 rtems_interrupt_lock_acquire(&lock, &lock_context);
0076 ev_int_get_config(vector, &config, &priority, &destination);
0077 ev_int_set_config(vector, config, priority, new_destination);
0078 rtems_interrupt_lock_release(&lock, &lock_context);
0079 return RTEMS_SUCCESSFUL;
0080 }
0081
0082 rtems_status_code bsp_interrupt_get_affinity(
0083 rtems_vector_number vector,
0084 Processor_mask *affinity
0085 )
0086 {
0087 uint32_t config;
0088 unsigned int priority;
0089 uint32_t destination;
0090
0091 ev_int_get_config(vector, &config, &priority, &destination);
0092 _Processor_mask_From_uint32_t(affinity, destination, 0);
0093 return RTEMS_SUCCESSFUL;
0094 }
0095
0096 rtems_status_code bsp_interrupt_get_attributes(
0097 rtems_vector_number vector,
0098 rtems_interrupt_attributes *attributes
0099 )
0100 {
0101 return RTEMS_SUCCESSFUL;
0102 }
0103
0104 rtems_status_code bsp_interrupt_is_pending(
0105 rtems_vector_number vector,
0106 bool *pending
0107 )
0108 {
0109 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0110 bsp_interrupt_assert(pending != NULL);
0111 *pending = false;
0112 return RTEMS_UNSATISFIED;
0113 }
0114
0115 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0116 {
0117 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0118 return RTEMS_UNSATISFIED;
0119 }
0120
0121 #if defined(RTEMS_SMP)
0122 rtems_status_code bsp_interrupt_raise_on(
0123 rtems_vector_number vector,
0124 uint32_t cpu_index
0125 )
0126 {
0127 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0128 return RTEMS_UNSATISFIED;
0129 }
0130 #endif
0131
0132 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0133 {
0134 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0135 return RTEMS_UNSATISFIED;
0136 }
0137
0138 rtems_status_code bsp_interrupt_vector_is_enabled(
0139 rtems_vector_number vector,
0140 bool *enabled
0141 )
0142 {
0143 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0144 bsp_interrupt_assert(enabled != NULL);
0145 *enabled = false;
0146 return RTEMS_UNSATISFIED;
0147 }
0148
0149 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0150 {
0151 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0152 ev_int_set_mask(vector, 0);
0153 return RTEMS_SUCCESSFUL;
0154 }
0155
0156 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0157 {
0158 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0159 ev_int_set_mask(vector, 1);
0160 return RTEMS_SUCCESSFUL;
0161 }
0162
0163 void bsp_interrupt_dispatch(uintptr_t exception_number)
0164 {
0165 unsigned int vector;
0166
0167 if (exception_number == 10) {
0168 qoriq_decrementer_dispatch();
0169 return;
0170 }
0171
0172 #ifdef RTEMS_SMP
0173 if (exception_number == 36) {
0174 _SMP_Inter_processor_interrupt_handler(_Per_CPU_Get());
0175 return;
0176 }
0177 #endif
0178
0179
0180
0181
0182
0183 PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR, vector);
0184
0185 if (vector != SPURIOUS) {
0186 uint32_t msr;
0187
0188 msr = ppc_external_exceptions_enable();
0189 bsp_interrupt_handler_dispatch(vector);
0190 ppc_external_exceptions_disable(msr);
0191
0192 ev_int_eoi(vector);
0193 } else {
0194 bsp_interrupt_handler_default(vector);
0195 }
0196 }
0197
0198 void bsp_interrupt_facility_initialize(void)
0199 {
0200 unsigned int i;
0201
0202 for (i = 0; i < BSP_INTERRUPT_VECTOR_COUNT; ++i) {
0203 uint32_t config;
0204 unsigned int priority;
0205 uint32_t destination;
0206 unsigned int err;
0207
0208 err = ev_int_get_config(i, &config, &priority, &destination);
0209 if (err != EV_SUCCESS)
0210 continue;
0211
0212 priority = QORIQ_PIC_PRIORITY_DEFAULT;
0213
0214 ev_int_set_config(i, config, priority, destination);
0215 }
0216
0217 return RTEMS_SUCCESSFUL;
0218 }
0219
0220 #else
0221
0222 #define VPR_MSK BSP_BBIT32(0)
0223 #define VPR_A BSP_BBIT32(1)
0224 #define VPR_P BSP_BBIT32(8)
0225 #define VPR_S BSP_BBIT32(9)
0226 #define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15)
0227 #define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15)
0228 #define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15)
0229 #define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31)
0230 #define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31)
0231 #define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31)
0232
0233 #define GCR_RST BSP_BBIT32(0)
0234 #define GCR_M BSP_BBIT32(2)
0235
0236 #define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE)
0237
0238 static const uint16_t src_cfg_offsets [] = {
0239 [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4,
0240 [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4,
0241 [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4,
0242 [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4,
0243 [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4,
0244 [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4,
0245 [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4,
0246 [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4,
0247 [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4,
0248 [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4,
0249 [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4,
0250 [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4,
0251 [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4,
0252 [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4,
0253 [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4,
0254 [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4,
0255 [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4,
0256 [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4,
0257 [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4,
0258 [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4,
0259 [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4,
0260 [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4,
0261 [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4,
0262 [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4,
0263 [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4,
0264 [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4,
0265 [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4,
0266 [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4,
0267 [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4,
0268 [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4,
0269 [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4,
0270 [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4,
0271 [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4,
0272 [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4,
0273 [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4,
0274 [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4,
0275 [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4,
0276 [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4,
0277 [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4,
0278 [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4
0279 };
0280
0281 static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector)
0282 {
0283 uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE);
0284
0285 if (vector < n) {
0286 return &qoriq.pic.ii_0 [vector];
0287 } else if (vector < QORIQ_IRQ_EXT_BASE) {
0288 return &qoriq.pic.ii_1 [vector - n];
0289 } else {
0290 uintptr_t offs = ((uintptr_t)
0291 src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4;
0292
0293 return (volatile qoriq_pic_src_cfg *) ((uintptr_t) &qoriq.pic + offs);
0294 }
0295 }
0296
0297 static bool pic_is_ipi(rtems_vector_number vector)
0298 {
0299 return (vector - QORIQ_IRQ_IPI_BASE) < 4;
0300 }
0301
0302 rtems_status_code bsp_interrupt_get_priority(
0303 rtems_vector_number vector,
0304 uint32_t *priority
0305 )
0306 {
0307 volatile qoriq_pic_src_cfg *src_cfg;
0308
0309 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0310 bsp_interrupt_assert(priority != NULL);
0311
0312 if (QORIQ_IRQ_IS_MSI(vector)) {
0313 return RTEMS_UNSATISFIED;
0314 }
0315
0316 src_cfg = get_src_cfg(vector);
0317 *priority =
0318 QORIQ_PIC_PRIORITY_DISABLED - VPR_PRIORITY_GET(src_cfg->vpr);
0319 return RTEMS_SUCCESSFUL;
0320 }
0321
0322 rtems_status_code bsp_interrupt_set_priority(
0323 rtems_vector_number vector,
0324 uint32_t priority
0325 )
0326 {
0327 volatile qoriq_pic_src_cfg *src_cfg;
0328 rtems_interrupt_lock_context lock_context;
0329 uint32_t vpr;
0330
0331 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0332
0333 if (QORIQ_IRQ_IS_MSI(vector)) {
0334 return RTEMS_UNSATISFIED;
0335 }
0336
0337 if (!QORIQ_PIC_PRIORITY_IS_VALID(priority)) {
0338 return RTEMS_INVALID_PRIORITY;
0339 }
0340
0341 src_cfg = get_src_cfg(vector);
0342 rtems_interrupt_lock_acquire(&lock, &lock_context);
0343 vpr = src_cfg->vpr;
0344 src_cfg->vpr =
0345 VPR_PRIORITY_SET(vpr, QORIQ_PIC_PRIORITY_DISABLED - priority);
0346 rtems_interrupt_lock_release(&lock, &lock_context);
0347 return RTEMS_SUCCESSFUL;
0348 }
0349
0350 rtems_status_code qoriq_pic_set_sense_and_polarity(
0351 rtems_vector_number vector,
0352 qoriq_eirq_sense_and_polarity new_sense_and_polarity,
0353 qoriq_eirq_sense_and_polarity *old_sense_and_polarity
0354 )
0355 {
0356 rtems_status_code sc = RTEMS_SUCCESSFUL;
0357 uint32_t old_vpr = 0;
0358 volatile qoriq_pic_src_cfg *src_cfg;
0359 rtems_interrupt_lock_context lock_context;
0360 uint32_t new_p_s = 0;
0361
0362 if (!QORIQ_IRQ_IS_EXT(vector)) {
0363 return RTEMS_UNSATISFIED;
0364 }
0365
0366 if (new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_EDGE_RISING ||
0367 new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_LEVEL_HIGH) {
0368 new_p_s |= VPR_P;
0369 }
0370
0371 if (new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_LEVEL_HIGH ||
0372 new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_LEVEL_LOW) {
0373 new_p_s |= VPR_S;
0374 }
0375
0376 src_cfg = get_src_cfg(vector);
0377
0378 rtems_interrupt_lock_acquire(&lock, &lock_context);
0379 old_vpr = src_cfg->vpr;
0380 src_cfg->vpr = (old_vpr & ~(VPR_P | VPR_S)) | new_p_s;
0381 rtems_interrupt_lock_release(&lock, &lock_context);
0382
0383 if (old_sense_and_polarity != NULL) {
0384 if ((old_vpr & VPR_P) == 0) {
0385 if ((old_vpr & VPR_S) == 0) {
0386 *old_sense_and_polarity =
0387 QORIQ_EIRQ_TRIGGER_EDGE_FALLING;
0388 } else {
0389 *old_sense_and_polarity =
0390 QORIQ_EIRQ_TRIGGER_LEVEL_LOW;
0391 }
0392 } else {
0393 if ((old_vpr & VPR_S) == 0) {
0394 *old_sense_and_polarity =
0395 QORIQ_EIRQ_TRIGGER_EDGE_RISING;
0396 } else {
0397 *old_sense_and_polarity =
0398 QORIQ_EIRQ_TRIGGER_LEVEL_HIGH;
0399 }
0400 }
0401 }
0402
0403 return sc;
0404 }
0405
0406 rtems_status_code bsp_interrupt_set_affinity(
0407 rtems_vector_number vector,
0408 const Processor_mask *affinity
0409 )
0410 {
0411 volatile qoriq_pic_src_cfg *src_cfg;
0412
0413 if (pic_is_ipi(vector)) {
0414 return RTEMS_UNSATISFIED;
0415 }
0416
0417 if (QORIQ_IRQ_IS_MSI(vector)) {
0418 return RTEMS_UNSATISFIED;
0419 }
0420
0421 src_cfg = get_src_cfg(vector);
0422 src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
0423 return RTEMS_SUCCESSFUL;
0424 }
0425
0426 rtems_status_code bsp_interrupt_get_affinity(
0427 rtems_vector_number vector,
0428 Processor_mask *affinity
0429 )
0430 {
0431 volatile qoriq_pic_src_cfg *src_cfg;
0432
0433 if (pic_is_ipi(vector)) {
0434 return RTEMS_UNSATISFIED;
0435 }
0436
0437 if (QORIQ_IRQ_IS_MSI(vector)) {
0438 return RTEMS_UNSATISFIED;
0439 }
0440
0441 src_cfg = get_src_cfg(vector);
0442 _Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
0443 return RTEMS_SUCCESSFUL;
0444 }
0445
0446 static rtems_status_code pic_vector_set_mask(
0447 rtems_vector_number vector,
0448 uint32_t msk
0449 )
0450 {
0451 volatile qoriq_pic_src_cfg *src_cfg;
0452 rtems_interrupt_lock_context lock_context;
0453
0454 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0455
0456 if (QORIQ_IRQ_IS_MSI(vector)) {
0457 return RTEMS_UNSATISFIED;
0458 }
0459
0460 src_cfg = get_src_cfg(vector);
0461 rtems_interrupt_lock_acquire(&lock, &lock_context);
0462 src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
0463 rtems_interrupt_lock_release(&lock, &lock_context);
0464 return RTEMS_SUCCESSFUL;
0465 }
0466
0467 rtems_status_code bsp_interrupt_get_attributes(
0468 rtems_vector_number vector,
0469 rtems_interrupt_attributes *attributes
0470 )
0471 {
0472 bool is_ipi = pic_is_ipi(vector);
0473 bool is_msi = QORIQ_IRQ_IS_MSI(vector);
0474
0475 attributes->is_maskable = true;
0476 attributes->can_enable = !is_msi;
0477 attributes->maybe_enable = !is_msi;
0478 attributes->can_disable = !is_msi;
0479 attributes->maybe_disable = !is_msi;
0480 attributes->cleared_by_acknowledge = true;
0481 attributes->can_get_affinity = !(is_ipi || is_msi);
0482 attributes->can_set_affinity = !(is_ipi || is_msi);
0483 attributes->can_raise = is_ipi;
0484 attributes->can_raise_on = is_ipi;
0485 attributes->maximum_priority = QORIQ_PIC_PRIORITY_DISABLED;
0486 attributes->can_get_priority = !is_msi;
0487 attributes->can_set_priority = !is_msi;
0488
0489 if (is_msi) {
0490 attributes->can_be_triggered_by_message = true;
0491 attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
0492 }
0493
0494 return RTEMS_SUCCESSFUL;
0495 }
0496
0497 rtems_status_code bsp_interrupt_is_pending(
0498 rtems_vector_number vector,
0499 bool *pending
0500 )
0501 {
0502 volatile qoriq_pic_src_cfg *src_cfg;
0503
0504 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0505 bsp_interrupt_assert(pending != NULL);
0506
0507 if (QORIQ_IRQ_IS_MSI(vector)) {
0508 *pending = false;
0509 return RTEMS_SUCCESSFUL;
0510 }
0511
0512 src_cfg = get_src_cfg(vector);
0513 *pending = (src_cfg->vpr & VPR_A) != 0;
0514 return RTEMS_SUCCESSFUL;
0515 }
0516
0517 static void raise_on(rtems_vector_number vector, uint32_t cpu_index)
0518 {
0519 rtems_vector_number ipi_index = vector - QORIQ_IRQ_IPI_BASE;
0520 qoriq.pic.ipidr[ipi_index].reg = 1U << cpu_index;
0521 }
0522
0523 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0524 {
0525 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0526
0527 if (pic_is_ipi(vector)) {
0528 raise_on(vector, rtems_scheduler_get_processor());
0529 return RTEMS_SUCCESSFUL;
0530 }
0531
0532 return RTEMS_UNSATISFIED;
0533 }
0534
0535 #if defined(RTEMS_SMP)
0536 rtems_status_code bsp_interrupt_raise_on(
0537 rtems_vector_number vector,
0538 uint32_t cpu_index
0539 )
0540 {
0541 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0542
0543 if (pic_is_ipi(vector)) {
0544 raise_on(vector, cpu_index);
0545 return RTEMS_SUCCESSFUL;
0546 }
0547
0548 return RTEMS_UNSATISFIED;
0549 }
0550 #endif
0551
0552 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0553 {
0554 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0555 return RTEMS_UNSATISFIED;
0556 }
0557
0558 rtems_status_code bsp_interrupt_vector_is_enabled(
0559 rtems_vector_number vector,
0560 bool *enabled
0561 )
0562 {
0563 volatile qoriq_pic_src_cfg *src_cfg;
0564
0565 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0566 bsp_interrupt_assert(enabled != NULL);
0567
0568 if (QORIQ_IRQ_IS_MSI(vector)) {
0569 vector = QORIQ_IRQ_MSI_0 + QORIQ_IRQ_MSI_INDEX(vector) / 32;
0570 }
0571
0572 src_cfg = get_src_cfg(vector);
0573 *enabled = (src_cfg->vpr & VPR_MSK) == 0;
0574 return RTEMS_SUCCESSFUL;
0575 }
0576
0577 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0578 {
0579 return pic_vector_set_mask(vector, 0);
0580 }
0581
0582 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0583 {
0584 return pic_vector_set_mask(vector, VPR_MSK);
0585 }
0586
0587 void bsp_interrupt_dispatch(uintptr_t exception_number)
0588 {
0589 rtems_vector_number vector = qoriq.pic.iack;
0590
0591 if (vector != SPURIOUS) {
0592 uint32_t msr = ppc_external_exceptions_enable();
0593
0594 bsp_interrupt_handler_dispatch(vector);
0595
0596 ppc_external_exceptions_disable(msr);
0597
0598 qoriq.pic.eoi = 0;
0599 qoriq.pic.whoami;
0600 } else {
0601 bsp_interrupt_handler_default(vector);
0602 }
0603 }
0604
0605 static void pic_reset(void)
0606 {
0607 qoriq.pic.gcr = GCR_RST;
0608 while ((qoriq.pic.gcr & GCR_RST) != 0) {
0609
0610 }
0611 }
0612
0613 static void pic_global_timer_init(void)
0614 {
0615 int i = 0;
0616
0617 qoriq.pic.tcra = 0;
0618 qoriq.pic.tcrb = 0;
0619
0620 for (i = 0; i < 4; ++i) {
0621 qoriq.pic.gta [0].bcr = GTBCR_CI;
0622 qoriq.pic.gtb [0].bcr = GTBCR_CI;
0623 }
0624 }
0625
0626 void bsp_interrupt_facility_initialize(void)
0627 {
0628 rtems_vector_number i = 0;
0629 uint32_t processor_id = ppc_processor_id();
0630
0631 if (processor_id == 0) {
0632
0633
0634 pic_reset();
0635
0636 for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
0637 volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
0638
0639 src_cfg->vpr = VPR_MSK | VPR_P
0640 | VPR_PRIORITY(QORIQ_PIC_PRIORITY_DEFAULT) | VPR_VECTOR(i);
0641
0642 if (!pic_is_ipi(i)) {
0643 src_cfg->dr = 0x1;
0644 }
0645 }
0646
0647 qoriq.pic.mer03 = 0xf;
0648 qoriq.pic.mer47 = 0xf;
0649 qoriq.pic.svr = SPURIOUS;
0650 qoriq.pic.gcr = GCR_M;
0651
0652
0653 for (i = 0; i < RTEMS_ARRAY_SIZE(qoriq.pic.msir); ++i) {
0654 (void) qoriq.pic.msir[i].reg;
0655 }
0656
0657 pic_global_timer_init();
0658 }
0659
0660 qoriq.pic.ctpr = 0;
0661
0662 for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
0663 qoriq.pic.iack;
0664 qoriq.pic.eoi = 0;
0665 qoriq.pic.whoami;
0666 }
0667 }
0668
0669 typedef __BITSET_DEFINE(pic_msi_bitset, QORIQ_IRQ_MSI_COUNT) pic_msi_bitset;
0670
0671 static pic_msi_bitset pic_msi_available =
0672 __BITSET_T_INITIALIZER(__BITSET_FSET(__bitset_words(QORIQ_IRQ_MSI_COUNT)));
0673
0674
0675 static uint32_t pic_msi_bitset_to_uint32_t(
0676 const pic_msi_bitset *bitset,
0677 uint32_t index
0678 )
0679 {
0680 long bits = bitset->__bits[index / _BITSET_BITS];
0681
0682 return (uint32_t) (bits >> (32 * ((index % _BITSET_BITS) / 32)));
0683 }
0684
0685 static void pic_msi_dispatch(void *arg)
0686 {
0687 uintptr_t reg = (uintptr_t) arg;
0688 uint32_t msir = qoriq.pic.msir[reg].reg;
0689
0690 while (msir != 0) {
0691 uint32_t index = 31 - __builtin_clz(msir);
0692 const rtems_interrupt_entry *entry;
0693
0694 msir &= ~(UINT32_C(1) << index);
0695 entry = bsp_interrupt_entry_load_first(
0696 QORIQ_IRQ_MSI_VECTOR(32 * reg + index)
0697 );
0698
0699 if (entry != NULL) {
0700 bsp_interrupt_dispatch_entries(entry);
0701 }
0702 }
0703 }
0704
0705 static rtems_status_code pic_msi_allocate(rtems_vector_number *vector)
0706 {
0707 pic_msi_bitset *available = &pic_msi_available;
0708 long found = __BIT_FFS(QORIQ_IRQ_MSI_COUNT, available);
0709 rtems_vector_number index;
0710 uint32_t subset;
0711
0712 if (found == 0) {
0713 return RTEMS_UNSATISFIED;
0714 }
0715
0716 index = (rtems_vector_number) found - 1;
0717 subset = pic_msi_bitset_to_uint32_t(available, index);
0718
0719 if (subset == 0xffffffff) {
0720 uintptr_t reg = index / 32;
0721 rtems_status_code sc;
0722
0723 sc = rtems_interrupt_handler_install(
0724 QORIQ_IRQ_MSI_0 + reg,
0725 "MSI",
0726 RTEMS_INTERRUPT_UNIQUE,
0727 pic_msi_dispatch,
0728 (void *) reg
0729 );
0730
0731 if (sc != RTEMS_SUCCESSFUL) {
0732 return sc;
0733 }
0734 }
0735
0736 __BIT_CLR(QORIQ_IRQ_MSI_COUNT, index, available);
0737 *vector = QORIQ_IRQ_MSI_VECTOR(index);
0738 return RTEMS_SUCCESSFUL;
0739 }
0740
0741 static rtems_status_code pic_msi_free(rtems_vector_number vector)
0742 {
0743 pic_msi_bitset *available = &pic_msi_available;
0744 rtems_vector_number index = QORIQ_IRQ_MSI_INDEX(vector);
0745 uint32_t subset;
0746
0747 if (__BIT_ISSET(QORIQ_IRQ_MSI_COUNT, index, available)) {
0748 return RTEMS_NOT_DEFINED;
0749 }
0750
0751 __BIT_SET(QORIQ_IRQ_MSI_COUNT, index, available);
0752 subset = pic_msi_bitset_to_uint32_t(available, index);
0753
0754 if (subset == 0xffffffff) {
0755 uintptr_t reg = index / 32;
0756
0757 return rtems_interrupt_handler_remove(
0758 QORIQ_IRQ_MSI_0 + reg,
0759 pic_msi_dispatch,
0760 (void *) reg
0761 );
0762 }
0763
0764 return RTEMS_SUCCESSFUL;
0765 }
0766
0767 rtems_status_code qoriq_pic_msi_allocate(rtems_vector_number *vector)
0768 {
0769 rtems_status_code sc;
0770
0771 if (!bsp_interrupt_is_initialized()) {
0772 return RTEMS_INCORRECT_STATE;
0773 }
0774
0775 if (vector == NULL) {
0776 return RTEMS_INVALID_ADDRESS;
0777 }
0778
0779 if (rtems_interrupt_is_in_progress()) {
0780 return RTEMS_CALLED_FROM_ISR;
0781 }
0782
0783 bsp_interrupt_lock();
0784 sc = pic_msi_allocate(vector);
0785 bsp_interrupt_unlock();
0786 return sc;
0787 }
0788
0789 rtems_status_code qoriq_pic_msi_free(rtems_vector_number vector)
0790 {
0791 rtems_status_code sc;
0792
0793 if (!bsp_interrupt_is_initialized()) {
0794 return RTEMS_INCORRECT_STATE;
0795 }
0796
0797 if (!QORIQ_IRQ_IS_MSI(vector) ) {
0798 return RTEMS_INVALID_ID;
0799 }
0800
0801 if (rtems_interrupt_is_in_progress()) {
0802 return RTEMS_CALLED_FROM_ISR;
0803 }
0804
0805 bsp_interrupt_lock();
0806 sc = pic_msi_free(vector);
0807 bsp_interrupt_unlock();
0808 return sc;
0809 }
0810
0811 rtems_status_code qoriq_pic_msi_map(
0812 rtems_vector_number vector,
0813 uint64_t *addr,
0814 uint32_t *data
0815 )
0816 {
0817 if (addr == NULL) {
0818 return RTEMS_INVALID_ADDRESS;
0819 }
0820
0821 if (data == NULL) {
0822 return RTEMS_INVALID_ADDRESS;
0823 }
0824
0825 if (!QORIQ_IRQ_IS_MSI(vector) ) {
0826 return RTEMS_INVALID_ID;
0827 }
0828
0829 *addr = (uint64_t)(uintptr_t) &qoriq.pic.msiir;
0830 *data = QORIQ_IRQ_MSI_INDEX(vector) << 24;
0831 return RTEMS_SUCCESSFUL;
0832 }
0833
0834 #endif