Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:04

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup DevIRQGIC
0007  *
0008  * @brief This source file contains the implementation of the generic GICv3
0009  *   support.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2019 On-Line Applications Research Corporation (OAR)
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <dev/irq/arm-gicv3.h>
0038 
0039 #include <bsp/irq-generic.h>
0040 #include <bsp/start.h>
0041 #include <rtems/score/processormaskimpl.h>
0042 
0043 /*
0044  * The GIC architecture reserves interrupt ID numbers 1020 to 1023 for special
0045  * purposes. BSP_INTERRUPT_VECTOR_COUNT up to 1020 is valid since interrupt IDs
0046  * start at 0.
0047  */
0048 #if BSP_INTERRUPT_VECTOR_COUNT > 1020
0049 #error "BSP_INTERRUPT_VECTOR_COUNT is too large"
0050 #endif
0051 
0052 void bsp_interrupt_dispatch(void)
0053 {
0054   while (true) {
0055     uint32_t icciar = READ_SR(ICC_IAR1);
0056     rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
0057     uint32_t status;
0058 
0059     if (!bsp_interrupt_is_valid_vector(vector)) {
0060       break;
0061     }
0062 
0063     status = arm_interrupt_enable_interrupts();
0064     bsp_interrupt_handler_dispatch_unchecked(vector);
0065     arm_interrupt_restore_interrupts(status);
0066 
0067     WRITE_SR(ICC_EOIR1, icciar);
0068   }
0069 }
0070 
0071 rtems_status_code bsp_interrupt_get_attributes(
0072   rtems_vector_number         vector,
0073   rtems_interrupt_attributes *attributes
0074 )
0075 {
0076   gicv3_get_attributes(vector, attributes);
0077   return RTEMS_SUCCESSFUL;
0078 }
0079 
0080 rtems_status_code bsp_interrupt_is_pending(
0081   rtems_vector_number vector,
0082   bool               *pending
0083 )
0084 {
0085   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0086   bsp_interrupt_assert(pending != NULL);
0087 
0088   if (vector <= ARM_GIC_IRQ_PPI_LAST) {
0089     *pending = gicv3_sgi_ppi_is_pending(vector, _SMP_Get_current_processor());
0090   } else {
0091     volatile gic_dist *dist = ARM_GIC_DIST;
0092 
0093     *pending = gic_id_is_pending(dist, vector);
0094   }
0095 
0096   return RTEMS_SUCCESSFUL;
0097 }
0098 
0099 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0100 {
0101   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0102 
0103   if (vector <= ARM_GIC_IRQ_SGI_LAST) {
0104     arm_gic_trigger_sgi(vector, 1U << _SMP_Get_current_processor());
0105   } else if (vector <= ARM_GIC_IRQ_PPI_LAST) {
0106     gicv3_ppi_set_pending(vector, _SMP_Get_current_processor());
0107   } else {
0108     volatile gic_dist *dist = ARM_GIC_DIST;
0109 
0110     gic_id_set_pending(dist, vector);
0111   }
0112 
0113   return RTEMS_SUCCESSFUL;
0114 }
0115 
0116 #if defined(RTEMS_SMP)
0117 rtems_status_code bsp_interrupt_raise_on(
0118   rtems_vector_number vector,
0119   uint32_t            cpu_index
0120 )
0121 {
0122   if (vector >= 16) {
0123     return RTEMS_UNSATISFIED;
0124   }
0125 
0126   arm_gic_trigger_sgi(vector, 1U << cpu_index);
0127   return RTEMS_SUCCESSFUL;
0128 }
0129 #endif
0130 
0131 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0132 {
0133   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0134 
0135   if (vector <= ARM_GIC_IRQ_SGI_LAST) {
0136     return RTEMS_UNSATISFIED;
0137   }
0138 
0139   if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
0140     gicv3_ppi_clear_pending(vector, _SMP_Get_current_processor());
0141   } else {
0142     volatile gic_dist *dist = ARM_GIC_DIST;
0143 
0144     gic_id_clear_pending(dist, vector);
0145   }
0146 
0147   return RTEMS_SUCCESSFUL;
0148 }
0149 
0150 rtems_status_code bsp_interrupt_vector_is_enabled(
0151   rtems_vector_number vector,
0152   bool               *enabled
0153 )
0154 {
0155   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0156   bsp_interrupt_assert(enabled != NULL);
0157 
0158   if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
0159     *enabled = gicv3_sgi_ppi_is_enabled(vector, _SMP_Get_current_processor());
0160   } else {
0161     volatile gic_dist *dist = ARM_GIC_DIST;
0162 
0163     *enabled = gic_id_is_enabled(dist, vector);
0164   }
0165 
0166   return RTEMS_SUCCESSFUL;
0167 }
0168 
0169 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0170 {
0171 
0172   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0173 
0174   if (vector > ARM_GIC_IRQ_PPI_LAST) {
0175     volatile gic_dist *dist = ARM_GIC_DIST;
0176 
0177     gic_id_enable(dist, vector);
0178   } else {
0179     gicv3_sgi_ppi_enable(vector, _SMP_Get_current_processor());
0180   }
0181 
0182   return RTEMS_SUCCESSFUL;
0183 }
0184 
0185 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0186 {
0187   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0188 
0189   if (vector > ARM_GIC_IRQ_PPI_LAST) {
0190     volatile gic_dist *dist = ARM_GIC_DIST;
0191 
0192     gic_id_disable(dist, vector);
0193   } else {
0194     gicv3_sgi_ppi_disable(vector, _SMP_Get_current_processor());
0195   }
0196 
0197   return RTEMS_SUCCESSFUL;
0198 }
0199 
0200 void bsp_interrupt_facility_initialize(void)
0201 {
0202   arm_interrupt_facility_set_exception_handler();
0203   gicv3_init_dist(ARM_GIC_DIST);
0204   gicv3_init_cpu_interface(_SMP_Get_current_processor());
0205 }
0206 
0207 #ifdef RTEMS_SMP
0208 BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void)
0209 {
0210   gicv3_init_cpu_interface(_SMP_Get_current_processor());
0211 }
0212 #endif
0213 
0214 rtems_status_code bsp_interrupt_set_priority(
0215   rtems_vector_number vector,
0216   uint32_t priority
0217 )
0218 {
0219   uint8_t gic_priority = (uint8_t) priority;
0220 
0221   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0222 
0223   if (gic_priority != priority) {
0224     return RTEMS_INVALID_PRIORITY;
0225   }
0226 
0227   if (vector >= 32) {
0228     volatile gic_dist *dist = ARM_GIC_DIST;
0229     gic_id_set_priority(dist, vector, priority);
0230   } else {
0231     gicv3_sgi_ppi_set_priority(
0232       vector,
0233       priority,
0234       _SMP_Get_current_processor()
0235     );
0236   }
0237 
0238   return RTEMS_SUCCESSFUL;
0239 }
0240 
0241 rtems_status_code bsp_interrupt_get_priority(
0242   rtems_vector_number vector,
0243   uint32_t *priority
0244 )
0245 {
0246   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0247   bsp_interrupt_assert(priority != NULL);
0248 
0249   if (vector >= 32) {
0250     volatile gic_dist *dist = ARM_GIC_DIST;
0251     *priority = gic_id_get_priority(dist, vector);
0252   } else {
0253     *priority = gicv3_sgi_ppi_get_priority(
0254       vector,
0255       _SMP_Get_current_processor()
0256     );
0257   }
0258 
0259   return RTEMS_SUCCESSFUL;
0260 }
0261 
0262 #if defined(BSP_IRQ_HAVE_GET_SET_AFFINITY)
0263 rtems_status_code bsp_interrupt_set_affinity(
0264   rtems_vector_number vector,
0265   const Processor_mask *affinity
0266 )
0267 {
0268   volatile gic_dist *dist = ARM_GIC_DIST;
0269   uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
0270 
0271   if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
0272     return RTEMS_UNSATISFIED;
0273   }
0274 
0275   gic_id_set_targets(dist, vector, targets);
0276   return RTEMS_SUCCESSFUL;
0277 }
0278 
0279 rtems_status_code bsp_interrupt_get_affinity(
0280   rtems_vector_number vector,
0281   Processor_mask *affinity
0282 )
0283 {
0284   volatile gic_dist *dist = ARM_GIC_DIST;
0285   uint8_t targets;
0286 
0287   if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
0288     return RTEMS_UNSATISFIED;
0289   }
0290 
0291   targets = gic_id_get_targets(dist, vector);
0292   _Processor_mask_From_uint32_t(affinity, targets, 0);
0293   return RTEMS_SUCCESSFUL;
0294 }
0295 #endif
0296 
0297 void arm_gic_trigger_sgi(rtems_vector_number vector, uint32_t targets)
0298 {
0299   gicv3_trigger_sgi(vector, targets);
0300 }
0301 
0302 #ifdef RTEMS_SMP
0303 uint32_t arm_gic_irq_processor_count(void)
0304 {
0305   volatile gic_dist *dist = ARM_GIC_DIST;
0306   uint32_t cpu_count;
0307 
0308   if ((dist->icddcr & GIC_DIST_ICDDCR_ARE_S) == 0) {
0309     cpu_count = GIC_DIST_ICDICTR_CPU_NUMBER_GET(dist->icdictr) + 1;
0310   } else {
0311     int i;
0312 
0313     /* Assume that an interrupt export port exists */
0314     cpu_count = 0;
0315 
0316     for (i = 0; i < CPU_MAXIMUM_PROCESSORS; ++i) {
0317       volatile gic_redist *redist = gicv3_get_redist(i);
0318 
0319       ++cpu_count;
0320       if ((redist->icrtyper & GIC_REDIST_ICRTYPER_LAST) != 0) {
0321         break;
0322       }
0323     }
0324   }
0325 
0326   return cpu_count;
0327 }
0328 #endif