Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsPowerPCQorIQ
0007  *
0008  * @brief Interrupt implementation.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2010, 2017 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
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      * This works only if the "has-external-proxy" property is present in the
0181      * "epapr,hv-pic" device tree node.
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 /* !QORIQ_IS_HYPERVISOR_GUEST */
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         /* Wait */
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         /* Core 0 must do the basic initialization */
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         /* Clear shared message signaled interrupts */
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 /* QORIQ_IS_HYPERVISOR_GUEST */