File indexing completed on 2025-05-11 08:24:08
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
0038
0039
0040
0041 #include <bsp/irq-generic.h>
0042 #include <bsp/irqimpl.h>
0043 #include <rtems/score/processormaskimpl.h>
0044
0045 #if !defined(LEON3_IRQAMP_EXTENDED_INTERRUPT)
0046
0047 uint32_t LEON3_IrqCtrl_EIrq;
0048 #endif
0049
0050 rtems_interrupt_lock LEON3_IrqCtrl_Lock =
0051 RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
0052
0053
0054 void leon3_ext_irq_init(irqamp *regs)
0055 {
0056 grlib_store_32(®s->pimask[LEON3_Cpu_Index], 0);
0057 grlib_store_32(®s->piforce[LEON3_Cpu_Index], 0);
0058 grlib_store_32(®s->iclear, 0xffffffff);
0059 #if !defined(LEON3_IRQAMP_EXTENDED_INTERRUPT)
0060 LEON3_IrqCtrl_EIrq = IRQAMP_MPSTAT_EIRQ_GET(grlib_load_32(®s->mpstat));
0061 #endif
0062 }
0063
0064 bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
0065 {
0066 if (vector == 0) {
0067 return false;
0068 }
0069
0070 #if defined(LEON3_IRQAMP_EXTENDED_INTERRUPT)
0071 return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT;
0072 #else
0073 if (LEON3_IrqCtrl_EIrq > 0) {
0074 return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT;
0075 }
0076
0077 return vector <= BSP_INTERRUPT_VECTOR_MAX_STD;
0078 #endif
0079 }
0080
0081 #if defined(RTEMS_SMP)
0082 Processor_mask leon3_interrupt_affinities[BSP_INTERRUPT_VECTOR_MAX_STD + 1];
0083 #endif
0084
0085 void bsp_interrupt_facility_initialize(void)
0086 {
0087 #if defined(RTEMS_SMP)
0088 Processor_mask affinity;
0089 size_t i;
0090
0091 _Processor_mask_From_index(&affinity, rtems_scheduler_get_processor());
0092
0093 for (i = 0; i < RTEMS_ARRAY_SIZE(leon3_interrupt_affinities); ++i) {
0094 leon3_interrupt_affinities[i] = affinity;
0095 }
0096 #endif
0097
0098 leon3_ext_irq_init(LEON3_IrqCtrl_Regs);
0099 }
0100
0101 rtems_status_code bsp_interrupt_get_attributes(
0102 rtems_vector_number vector,
0103 rtems_interrupt_attributes *attributes
0104 )
0105 {
0106 bool is_standard_interrupt;
0107
0108 is_standard_interrupt = (vector <= BSP_INTERRUPT_VECTOR_MAX_STD);
0109 attributes->is_maskable = (vector != 15);
0110 attributes->can_enable = true;
0111 attributes->maybe_enable = true;
0112 attributes->can_disable = true;
0113 attributes->maybe_disable = true;
0114 attributes->can_raise = true;
0115 attributes->can_raise_on = is_standard_interrupt;
0116 attributes->can_clear = true;
0117 attributes->cleared_by_acknowledge = true;
0118 attributes->can_get_affinity = is_standard_interrupt;
0119 attributes->can_set_affinity = is_standard_interrupt;
0120 return RTEMS_SUCCESSFUL;
0121 }
0122
0123 rtems_status_code bsp_interrupt_is_pending(
0124 rtems_vector_number vector,
0125 bool *pending
0126 )
0127 {
0128 rtems_interrupt_level level;
0129 uint32_t bit;
0130 irqamp *regs;
0131
0132 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0133 bsp_interrupt_assert(pending != NULL);
0134 bit = 1U << vector;
0135 regs = LEON3_IrqCtrl_Regs;
0136
0137 rtems_interrupt_local_disable(level);
0138 *pending = (grlib_load_32(®s->ipend) & bit) != 0 ||
0139 (grlib_load_32(®s->piforce[rtems_scheduler_get_processor()]) & bit) != 0;
0140 rtems_interrupt_local_enable(level);
0141 return RTEMS_SUCCESSFUL;
0142 }
0143
0144 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0145 {
0146 uint32_t bit;
0147 irqamp *regs;
0148
0149 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0150 bit = 1U << vector;
0151 regs = LEON3_IrqCtrl_Regs;
0152
0153 if ( vector <= BSP_INTERRUPT_VECTOR_MAX_STD ) {
0154 uint32_t cpu_count;
0155 uint32_t cpu_index;
0156
0157 cpu_count = rtems_scheduler_get_processor_maximum();
0158
0159 for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
0160 grlib_store_32(®s->piforce[cpu_index], bit);
0161 }
0162 } else {
0163 rtems_interrupt_lock_context lock_context;
0164 uint32_t ipend;
0165
0166
0167
0168
0169
0170
0171 LEON3_IRQCTRL_ACQUIRE(&lock_context);
0172 ipend = grlib_load_32(®s->ipend);
0173 ipend |= bit;
0174 grlib_store_32(®s->ipend, ipend);
0175 LEON3_IRQCTRL_RELEASE(&lock_context);
0176 }
0177
0178 return RTEMS_SUCCESSFUL;
0179 }
0180
0181 #if defined(RTEMS_SMP)
0182 rtems_status_code bsp_interrupt_raise_on(
0183 rtems_vector_number vector,
0184 uint32_t cpu_index
0185 )
0186 {
0187 irqamp *regs;
0188
0189 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0190 bsp_interrupt_assert(cpu_index < rtems_scheduler_get_processor_maximum());
0191
0192 if ( vector > BSP_INTERRUPT_VECTOR_MAX_STD ) {
0193 return RTEMS_UNSATISFIED;
0194 }
0195
0196 regs = LEON3_IrqCtrl_Regs;
0197 grlib_store_32(®s->piforce[cpu_index], 1U << vector);
0198 return RTEMS_SUCCESSFUL;
0199 }
0200 #endif
0201
0202 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0203 {
0204 uint32_t bit;
0205 irqamp *regs;
0206
0207 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0208 bit = 1U << vector;
0209 regs = LEON3_IrqCtrl_Regs;
0210
0211 grlib_store_32(®s->iclear, bit);
0212
0213 if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
0214 grlib_store_32(®s->piforce[rtems_scheduler_get_processor()], bit << 16);
0215 }
0216
0217 return RTEMS_SUCCESSFUL;
0218 }
0219
0220 rtems_status_code bsp_interrupt_vector_is_enabled(
0221 rtems_vector_number vector,
0222 bool *enabled
0223 )
0224 {
0225 uint32_t bit;
0226 irqamp *regs;
0227 uint32_t pimask;
0228
0229 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0230
0231 bit = 1U << vector;
0232 regs = LEON3_IrqCtrl_Regs;
0233 pimask = grlib_load_32(®s->pimask[_LEON3_Get_current_processor()]);
0234 *enabled = (pimask & bit) != 0;
0235 return RTEMS_SUCCESSFUL;
0236 }
0237
0238 #if defined(RTEMS_SMP)
0239 static void leon3_interrupt_vector_enable(rtems_vector_number vector)
0240 {
0241 uint32_t cpu_index;
0242 uint32_t cpu_count;
0243 Processor_mask affinity;
0244 uint32_t bit;
0245 uint32_t unmasked;
0246 uint32_t brdcst;
0247 irqamp *regs;
0248
0249 if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
0250 affinity = leon3_interrupt_affinities[vector];
0251 } else {
0252 affinity = leon3_interrupt_affinities[LEON3_IrqCtrl_EIrq];
0253 }
0254
0255 cpu_count = rtems_scheduler_get_processor_maximum();
0256 bit = 1U << vector;
0257 regs = LEON3_IrqCtrl_Regs;
0258 unmasked = 0;
0259
0260 for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
0261 uint32_t pimask;
0262
0263 pimask = grlib_load_32(®s->pimask[cpu_index]);
0264
0265 if (_Processor_mask_Is_set(&affinity, cpu_index)) {
0266 ++unmasked;
0267 pimask |= bit;
0268 } else {
0269 pimask &= ~bit;
0270 }
0271
0272 grlib_store_32(®s->pimask[cpu_index], pimask);
0273 }
0274
0275 brdcst = grlib_load_32(®s->brdcst);
0276
0277 if (unmasked > 1) {
0278 brdcst |= bit;
0279 } else {
0280 brdcst &= ~bit;
0281 }
0282
0283 grlib_store_32(®s->brdcst, brdcst);
0284 }
0285 #endif
0286
0287 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0288 {
0289 rtems_interrupt_lock_context lock_context;
0290 #if !defined(RTEMS_SMP)
0291 uint32_t bit;
0292 irqamp *regs;
0293 uint32_t pimask;
0294 uint32_t cpu_index;
0295 #endif
0296
0297 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0298 #if !defined(RTEMS_SMP)
0299 bit = 1U << vector;
0300 regs = LEON3_IrqCtrl_Regs;
0301 #endif
0302
0303 LEON3_IRQCTRL_ACQUIRE(&lock_context);
0304 #if defined(RTEMS_SMP)
0305 leon3_interrupt_vector_enable(vector);
0306 #else
0307 cpu_index = _LEON3_Get_current_processor();
0308 pimask = grlib_load_32(®s->pimask[cpu_index]);
0309 pimask |= bit;
0310 grlib_store_32(®s->pimask[cpu_index], pimask);
0311 #endif
0312 LEON3_IRQCTRL_RELEASE(&lock_context);
0313 return RTEMS_SUCCESSFUL;
0314 }
0315
0316 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0317 {
0318 rtems_interrupt_lock_context lock_context;
0319 uint32_t bit;
0320 irqamp *regs;
0321 uint32_t pimask;
0322 uint32_t cpu_index;
0323 #if defined(RTEMS_SMP)
0324 uint32_t cpu_count;
0325 uint32_t brdcst;
0326 #endif
0327
0328 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0329 bit = 1U << vector;
0330 regs = LEON3_IrqCtrl_Regs;
0331
0332 LEON3_IRQCTRL_ACQUIRE(&lock_context);
0333
0334 #if defined(RTEMS_SMP)
0335 cpu_count = rtems_scheduler_get_processor_maximum();
0336
0337 for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
0338 pimask = grlib_load_32(®s->pimask[cpu_index]);
0339 pimask &= ~bit;
0340 grlib_store_32(®s->pimask[cpu_index], pimask);
0341 }
0342
0343 brdcst = grlib_load_32(®s->brdcst);
0344 brdcst &= ~bit;
0345 grlib_store_32(®s->brdcst, brdcst);
0346 #else
0347 cpu_index = _LEON3_Get_current_processor();
0348 pimask = grlib_load_32(®s->pimask[cpu_index]);
0349 pimask &= ~bit;
0350 grlib_store_32(®s->pimask[cpu_index], pimask);
0351 #endif
0352
0353 LEON3_IRQCTRL_RELEASE(&lock_context);
0354 return RTEMS_SUCCESSFUL;
0355 }
0356
0357 rtems_status_code bsp_interrupt_set_priority(
0358 rtems_vector_number vector,
0359 uint32_t priority
0360 )
0361 {
0362 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0363 return RTEMS_UNSATISFIED;
0364 }
0365
0366 rtems_status_code bsp_interrupt_get_priority(
0367 rtems_vector_number vector,
0368 uint32_t *priority
0369 )
0370 {
0371 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0372 bsp_interrupt_assert(priority != NULL);
0373 return RTEMS_UNSATISFIED;
0374 }
0375
0376 #if defined(RTEMS_SMP)
0377 rtems_status_code bsp_interrupt_set_affinity(
0378 rtems_vector_number vector,
0379 const Processor_mask *affinity
0380 )
0381 {
0382 rtems_interrupt_lock_context lock_context;
0383 uint32_t cpu_count;
0384 uint32_t cpu_index;
0385 uint32_t bit;
0386 irqamp *regs;
0387
0388 if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) {
0389 return RTEMS_UNSATISFIED;
0390 }
0391
0392 cpu_count = rtems_scheduler_get_processor_maximum();
0393 bit = 1U << vector;
0394 regs = LEON3_IrqCtrl_Regs;
0395
0396 LEON3_IRQCTRL_ACQUIRE(&lock_context);
0397 leon3_interrupt_affinities[vector] = *affinity;
0398
0399
0400
0401
0402
0403 for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
0404 if ((grlib_load_32(®s->pimask[cpu_index]) & bit) != 0) {
0405 leon3_interrupt_vector_enable(vector);
0406 break;
0407 }
0408 }
0409
0410 LEON3_IRQCTRL_RELEASE(&lock_context);
0411 return RTEMS_SUCCESSFUL;
0412 }
0413
0414 rtems_status_code bsp_interrupt_get_affinity(
0415 rtems_vector_number vector,
0416 Processor_mask *affinity
0417 )
0418 {
0419 if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) {
0420 return RTEMS_UNSATISFIED;
0421 }
0422
0423 *affinity = leon3_interrupt_affinities[vector];
0424 return RTEMS_SUCCESSFUL;
0425 }
0426 #endif