File indexing completed on 2025-05-11 08:24:04
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
0037 #include <dev/irq/arm-gic.h>
0038 #include <dev/irq/arm-gic-arch.h>
0039
0040 #include <bsp/irq-generic.h>
0041 #include <bsp/start.h>
0042 #include <rtems/score/assert.h>
0043 #include <rtems/score/processormaskimpl.h>
0044
0045
0046
0047
0048
0049 #if BSP_INTERRUPT_VECTOR_COUNT >= 1020
0050 #error "BSP_INTERRUPT_VECTOR_COUNT is too large"
0051 #endif
0052
0053 #define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE)
0054
0055 #define PRIORITY_DEFAULT 127
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 #ifdef BSP_ARM_GIC_ENABLE_FIQ_FOR_GROUP_0
0074 #define DIST_ICDDCR (GIC_DIST_ICDDCR_ENABLE_GRP_1 | GIC_DIST_ICDDCR_ENABLE)
0075 #define CPUIF_ICCICR \
0076 (GIC_CPUIF_ICCICR_CBPR | GIC_CPUIF_ICCICR_FIQ_EN \
0077 | GIC_CPUIF_ICCICR_ACK_CTL | GIC_CPUIF_ICCICR_ENABLE_GRP_1 \
0078 | GIC_CPUIF_ICCICR_ENABLE)
0079 #else
0080 #define DIST_ICDDCR GIC_DIST_ICDDCR_ENABLE
0081 #define CPUIF_ICCICR GIC_CPUIF_ICCICR_ENABLE
0082 #endif
0083
0084 void bsp_interrupt_dispatch(void)
0085 {
0086 volatile gic_cpuif *cpuif = GIC_CPUIF;
0087
0088 while (true) {
0089 uint32_t icciar = cpuif->icciar;
0090 rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
0091 uint32_t status;
0092
0093 if (!bsp_interrupt_is_valid_vector(vector)) {
0094 break;
0095 }
0096
0097 status = arm_interrupt_enable_interrupts();
0098 bsp_interrupt_handler_dispatch_unchecked(vector);
0099 arm_interrupt_restore_interrupts(status);
0100
0101 cpuif->icceoir = icciar;
0102 }
0103 }
0104
0105 rtems_status_code bsp_interrupt_is_pending(
0106 rtems_vector_number vector,
0107 bool *pending
0108 )
0109 {
0110 volatile gic_dist *dist = ARM_GIC_DIST;
0111
0112 *pending = gic_id_is_pending(dist, vector);
0113 return RTEMS_SUCCESSFUL;
0114 }
0115
0116 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0117 {
0118 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0119
0120 if (vector <= ARM_GIC_IRQ_SGI_LAST) {
0121 arm_gic_trigger_sgi(vector, 1U << _SMP_Get_current_processor());
0122 } else {
0123 volatile gic_dist *dist = ARM_GIC_DIST;
0124
0125 gic_id_set_pending(dist, vector);
0126 }
0127
0128 return RTEMS_SUCCESSFUL;
0129 }
0130
0131 #if defined(RTEMS_SMP)
0132 rtems_status_code bsp_interrupt_raise_on(
0133 rtems_vector_number vector,
0134 uint32_t cpu_index
0135 )
0136 {
0137 if (vector > ARM_GIC_IRQ_SGI_LAST) {
0138 return RTEMS_UNSATISFIED;
0139 }
0140
0141 arm_gic_trigger_sgi(vector, 1U << cpu_index);
0142 return RTEMS_SUCCESSFUL;
0143 }
0144 #endif
0145
0146 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0147 {
0148 volatile gic_dist *dist = ARM_GIC_DIST;
0149
0150 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0151
0152 if (vector <= ARM_GIC_IRQ_SGI_LAST) {
0153 return RTEMS_UNSATISFIED;
0154 }
0155
0156 gic_id_clear_pending(dist, vector);
0157 return RTEMS_SUCCESSFUL;
0158 }
0159
0160 rtems_status_code bsp_interrupt_vector_is_enabled(
0161 rtems_vector_number vector,
0162 bool *enabled
0163 )
0164 {
0165 volatile gic_dist *dist = ARM_GIC_DIST;
0166
0167 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0168 bsp_interrupt_assert(enabled != NULL);
0169
0170 *enabled = gic_id_is_enabled(dist, vector);
0171 return RTEMS_SUCCESSFUL;
0172 }
0173
0174 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0175 {
0176 volatile gic_dist *dist = ARM_GIC_DIST;
0177
0178 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0179
0180 gic_id_enable(dist, vector);
0181 return RTEMS_SUCCESSFUL;
0182 }
0183
0184 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0185 {
0186 volatile gic_dist *dist = ARM_GIC_DIST;
0187
0188 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0189
0190 gic_id_disable(dist, vector);
0191 return RTEMS_SUCCESSFUL;
0192 }
0193
0194 static inline uint32_t get_id_count(volatile gic_dist *dist)
0195 {
0196 uint32_t id_count = GIC_DIST_ICDICTR_IT_LINES_NUMBER_GET(dist->icdictr);
0197
0198 id_count = 32 * (id_count + 1);
0199 id_count = id_count <= 1020 ? id_count : 1020;
0200
0201 return id_count;
0202 }
0203
0204 static inline void init_distributor(volatile gic_dist *dist)
0205 {
0206 uint32_t id_count = get_id_count(dist);
0207 uint32_t id;
0208
0209 for (id = 0; id < id_count; id += 32) {
0210 #ifdef BSP_ARM_GIC_ENABLE_FIQ_FOR_GROUP_0
0211 dist->icdigr[id / 32] = 0xffffffff;
0212 #endif
0213 dist->icdicer[id / 32] = 0xffffffff;
0214 }
0215
0216 for (id = 0; id < id_count; ++id) {
0217 gic_id_set_priority(dist, id, PRIORITY_DEFAULT);
0218 }
0219
0220 for (id = 32; id < id_count; ++id) {
0221 gic_id_set_targets(dist, id, 0x01);
0222 }
0223 }
0224
0225 static inline void init_sgi_ppi(volatile gic_dist *dist)
0226 {
0227 uint32_t id;
0228
0229 #ifdef BSP_ARM_GIC_ENABLE_FIQ_FOR_GROUP_0
0230 dist->icdigr[0] = 0xffffffff;
0231 #endif
0232
0233
0234 for (id = 0; id <= ARM_GIC_IRQ_PPI_LAST; ++id) {
0235 gic_id_set_priority(dist, id, PRIORITY_DEFAULT);
0236 }
0237 }
0238
0239 void bsp_interrupt_facility_initialize(void)
0240 {
0241 volatile gic_cpuif *cpuif = GIC_CPUIF;
0242 volatile gic_dist *dist = ARM_GIC_DIST;
0243
0244 arm_interrupt_facility_set_exception_handler();
0245
0246 #ifdef BSP_ARM_GIC_MULTI_PROCESSOR_SECONDARY
0247 while ((dist->icddcr & GIC_DIST_ICDDCR_ENABLE) == 0) {
0248
0249 }
0250
0251 init_sgi_ppi(dist);
0252 #else
0253 init_distributor(dist);
0254 #endif
0255
0256 cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff);
0257 cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0);
0258 cpuif->iccicr = CPUIF_ICCICR;
0259
0260 dist->icddcr = GIC_DIST_ICDDCR_ENABLE_GRP_1 | GIC_DIST_ICDDCR_ENABLE;
0261 }
0262
0263 #ifdef RTEMS_SMP
0264 BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void)
0265 {
0266 volatile gic_cpuif *cpuif = GIC_CPUIF;
0267 volatile gic_dist *dist = ARM_GIC_DIST;
0268
0269 init_sgi_ppi(dist);
0270
0271 cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff);
0272 cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0);
0273 cpuif->iccicr = CPUIF_ICCICR;
0274 }
0275 #endif
0276
0277 rtems_status_code bsp_interrupt_set_priority(
0278 rtems_vector_number vector,
0279 uint32_t priority
0280 )
0281 {
0282 volatile gic_dist *dist = ARM_GIC_DIST;
0283 uint8_t gic_priority = (uint8_t) priority;
0284
0285 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0286
0287 if (gic_priority != priority) {
0288 return RTEMS_INVALID_PRIORITY;
0289 }
0290
0291 gic_id_set_priority(dist, vector, gic_priority);
0292 return RTEMS_SUCCESSFUL;
0293 }
0294
0295 rtems_status_code bsp_interrupt_get_priority(
0296 rtems_vector_number vector,
0297 uint32_t *priority
0298 )
0299 {
0300 volatile gic_dist *dist = ARM_GIC_DIST;
0301
0302 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0303 bsp_interrupt_assert(priority != NULL);
0304
0305 *priority = gic_id_get_priority(dist, vector);
0306 return RTEMS_SUCCESSFUL;
0307 }
0308
0309 #ifdef BSP_ARM_GIC_ENABLE_FIQ_FOR_GROUP_0
0310 rtems_status_code arm_gic_irq_set_group(
0311 rtems_vector_number vector,
0312 gic_group group
0313 )
0314 {
0315 rtems_status_code sc = RTEMS_SUCCESSFUL;
0316
0317 if (bsp_interrupt_is_valid_vector(vector)) {
0318 volatile gic_dist *dist = ARM_GIC_DIST;
0319
0320 gic_id_set_group(dist, vector, group);
0321 } else {
0322 sc = RTEMS_INVALID_ID;
0323 }
0324
0325 return sc;
0326 }
0327
0328 rtems_status_code arm_gic_irq_get_group(
0329 rtems_vector_number vector,
0330 gic_group *group
0331 )
0332 {
0333 rtems_status_code sc = RTEMS_SUCCESSFUL;
0334
0335 if (bsp_interrupt_is_valid_vector(vector)) {
0336 volatile gic_dist *dist = ARM_GIC_DIST;
0337
0338 *group = gic_id_get_group(dist, vector);
0339 } else {
0340 sc = RTEMS_INVALID_ID;
0341 }
0342
0343 return sc;
0344 }
0345 #endif
0346
0347 #if defined(BSP_IRQ_HAVE_GET_SET_AFFINITY)
0348 rtems_status_code bsp_interrupt_set_affinity(
0349 rtems_vector_number vector,
0350 const Processor_mask *affinity
0351 )
0352 {
0353 volatile gic_dist *dist = ARM_GIC_DIST;
0354 uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
0355 rtems_interrupt_attributes attr;
0356 rtems_status_code sc;
0357
0358 attr.can_set_affinity = false;
0359 sc = bsp_interrupt_get_attributes( vector, &attr );
0360 _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL );
0361
0362 if ( !attr.can_set_affinity ) {
0363 return RTEMS_UNSATISFIED;
0364 }
0365
0366 gic_id_set_targets(dist, vector, targets);
0367 return RTEMS_SUCCESSFUL;
0368 }
0369
0370 rtems_status_code bsp_interrupt_get_affinity(
0371 rtems_vector_number vector,
0372 Processor_mask *affinity
0373 )
0374 {
0375 volatile gic_dist *dist = ARM_GIC_DIST;
0376 uint8_t targets;
0377 rtems_interrupt_attributes attr;
0378 rtems_status_code sc;
0379
0380 attr.can_get_affinity = false;
0381 sc = bsp_interrupt_get_attributes( vector, &attr );
0382 _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL );
0383
0384 targets = gic_id_get_targets(dist, vector);
0385
0386 if ( !attr.can_get_affinity ) {
0387 return RTEMS_UNSATISFIED;
0388 }
0389
0390 _Processor_mask_From_uint32_t(affinity, targets, 0);
0391 return RTEMS_SUCCESSFUL;
0392 }
0393 #endif
0394
0395 void arm_gic_trigger_sgi(rtems_vector_number vector, uint32_t targets)
0396 {
0397 volatile gic_dist *dist = ARM_GIC_DIST;
0398
0399 dist->icdsgir = GIC_DIST_ICDSGIR_TARGET_LIST_FILTER(0)
0400 | GIC_DIST_ICDSGIR_CPU_TARGET_LIST(targets)
0401 #ifdef BSP_ARM_GIC_ENABLE_FIQ_FOR_GROUP_0
0402 | GIC_DIST_ICDSGIR_NSATT
0403 #endif
0404 | GIC_DIST_ICDSGIR_SGIINTID(vector);
0405 }
0406
0407 #ifdef RTEMS_SMP
0408 uint32_t arm_gic_irq_processor_count(void)
0409 {
0410 volatile gic_dist *dist = ARM_GIC_DIST;
0411
0412 return GIC_DIST_ICDICTR_CPU_NUMBER_GET(dist->icdictr) + 1;
0413 }
0414 #endif