File indexing completed on 2025-05-11 08:23: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 #include <rtems/score/armv4.h>
0037
0038 #include <bsp.h>
0039 #include <bsp/irq.h>
0040 #include <bsp/irq-generic.h>
0041 #include <bsp/lpc32xx.h>
0042 #include <bsp/linker-symbols.h>
0043 #include <bsp/mmu.h>
0044
0045
0046 #define LPC32XX_MIC_STATUS_MASK 0x3ffffffcU
0047
0048 typedef union {
0049 struct {
0050 uint32_t mic;
0051 uint32_t sic_1;
0052 uint32_t sic_2;
0053 } field;
0054 uint32_t fields_table [LPC32XX_IRQ_MODULE_COUNT];
0055 } lpc32xx_irq_fields;
0056
0057 static uint8_t lpc32xx_irq_priority_table [LPC32XX_IRQ_COUNT];
0058
0059 static lpc32xx_irq_fields lpc32xx_irq_priority_masks [LPC32XX_IRQ_PRIORITY_COUNT];
0060
0061 static lpc32xx_irq_fields lpc32xx_irq_enable;
0062
0063 static const lpc32xx_irq_fields lpc32xx_irq_is_valid = {
0064 .field = {
0065 .mic = 0x3fffeff8U,
0066 .sic_1 = 0xffde71d6U,
0067 .sic_2 = 0x9fdc9fffU
0068 }
0069 };
0070
0071 static inline bool lpc32xx_irq_priority_is_valid(unsigned priority)
0072 {
0073 return priority <= LPC32XX_IRQ_PRIORITY_LOWEST;
0074 }
0075
0076 #define LPC32XX_IRQ_BIT_OPS_DEFINE \
0077 unsigned bit = index & 0x1fU; \
0078 unsigned module = index >> 5
0079
0080 #define LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE \
0081 LPC32XX_IRQ_BIT_OPS_DEFINE; \
0082 unsigned module_offset = module << 14; \
0083 volatile uint32_t *reg = (volatile uint32_t *) \
0084 ((volatile char *) &lpc32xx.mic + module_offset + register_offset)
0085
0086 #define LPC32XX_IRQ_OFFSET_ER 0U
0087 #define LPC32XX_IRQ_OFFSET_RSR 4U
0088 #define LPC32XX_IRQ_OFFSET_SR 8U
0089 #define LPC32XX_IRQ_OFFSET_APR 12U
0090 #define LPC32XX_IRQ_OFFSET_ATR 16U
0091 #define LPC32XX_IRQ_OFFSET_ITR 20U
0092
0093 static inline bool lpc32xx_irq_is_bit_set_in_register(unsigned index, unsigned register_offset)
0094 {
0095 LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE;
0096
0097 return *reg & (1U << bit);
0098 }
0099
0100 static inline void lpc32xx_irq_set_bit_in_register(unsigned index, unsigned register_offset)
0101 {
0102 LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE;
0103
0104 *reg |= 1U << bit;
0105 }
0106
0107 static inline void lpc32xx_irq_clear_bit_in_register(unsigned index, unsigned register_offset)
0108 {
0109 LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE;
0110
0111 *reg &= ~(1U << bit);
0112 }
0113
0114 static inline bool lpc32xx_irq_is_bit_set_in_field(
0115 unsigned index,
0116 const lpc32xx_irq_fields *fields
0117 )
0118 {
0119 LPC32XX_IRQ_BIT_OPS_DEFINE;
0120
0121 return fields->fields_table [module] & (1U << bit);
0122 }
0123
0124 static inline void lpc32xx_irq_set_bit_in_field(unsigned index, lpc32xx_irq_fields *fields)
0125 {
0126 LPC32XX_IRQ_BIT_OPS_DEFINE;
0127
0128 fields->fields_table [module] |= 1U << bit;
0129 }
0130
0131 static inline void lpc32xx_irq_clear_bit_in_field(unsigned index, lpc32xx_irq_fields *fields)
0132 {
0133 LPC32XX_IRQ_BIT_OPS_DEFINE;
0134
0135 fields->fields_table [module] &= ~(1U << bit);
0136 }
0137
0138 bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
0139 {
0140 if (vector >= BSP_INTERRUPT_VECTOR_COUNT) {
0141 return false;
0142 }
0143
0144 return lpc32xx_irq_is_bit_set_in_field(vector, &lpc32xx_irq_is_valid);
0145 }
0146
0147 static inline unsigned lpc32xx_irq_get_index(uint32_t val)
0148 {
0149 ARM_SWITCH_REGISTERS;
0150
0151 __asm__ volatile (
0152 ARM_SWITCH_TO_ARM
0153 "clz %[val], %[val]\n"
0154 "rsb %[val], %[val], #31\n"
0155 ARM_SWITCH_BACK
0156 : [val] "=r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0157 : "[val]" (val)
0158 );
0159
0160 return val;
0161 }
0162
0163 rtems_status_code bsp_interrupt_set_priority(
0164 rtems_vector_number vector,
0165 uint32_t priority
0166 )
0167 {
0168 rtems_interrupt_level level;
0169 uint32_t i;
0170
0171 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0172
0173 if (priority > LPC32XX_IRQ_PRIORITY_VALUE_MAX) {
0174 return RTEMS_INVALID_PRIORITY;
0175 }
0176
0177 rtems_interrupt_disable(level);
0178 lpc32xx_irq_priority_table [vector] = (uint8_t) priority;
0179
0180 for (i = LPC32XX_IRQ_PRIORITY_HIGHEST; i <= priority; ++i) {
0181 lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]);
0182 }
0183
0184 for (i = priority + 1; i <= LPC32XX_IRQ_PRIORITY_LOWEST; ++i) {
0185 lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]);
0186 }
0187
0188 rtems_interrupt_enable(level);
0189 return RTEMS_SUCCESSFUL;
0190 }
0191
0192 rtems_status_code bsp_interrupt_get_priority(
0193 rtems_vector_number vector,
0194 uint32_t *priority
0195 )
0196 {
0197 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0198 bsp_interrupt_assert(priority != NULL);
0199 *priority = lpc32xx_irq_priority_table [vector];
0200 return RTEMS_SUCCESSFUL;
0201 }
0202
0203 void lpc32xx_irq_set_activation_polarity(rtems_vector_number vector, lpc32xx_irq_activation_polarity activation_polarity)
0204 {
0205 if (bsp_interrupt_is_valid_vector(vector)) {
0206 rtems_interrupt_level level;
0207
0208 rtems_interrupt_disable(level);
0209 if (activation_polarity == LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE) {
0210 lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR);
0211 } else {
0212 lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR);
0213 }
0214 rtems_interrupt_enable(level);
0215 }
0216 }
0217
0218 lpc32xx_irq_activation_polarity lpc32xx_irq_get_activation_polarity(rtems_vector_number vector)
0219 {
0220 if (bsp_interrupt_is_valid_vector(vector)) {
0221 if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_APR)) {
0222 return LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE;
0223 } else {
0224 return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE;
0225 }
0226 } else {
0227 return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE;
0228 }
0229 }
0230
0231 void lpc32xx_irq_set_activation_type(rtems_vector_number vector, lpc32xx_irq_activation_type activation_type)
0232 {
0233 if (bsp_interrupt_is_valid_vector(vector)) {
0234 rtems_interrupt_level level;
0235
0236 rtems_interrupt_disable(level);
0237 if (activation_type == LPC32XX_IRQ_EDGE_SENSITIVE) {
0238 lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR);
0239 } else {
0240 lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR);
0241 }
0242 rtems_interrupt_enable(level);
0243 }
0244 }
0245
0246 lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number vector)
0247 {
0248 if (bsp_interrupt_is_valid_vector(vector)) {
0249 if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_ATR)) {
0250 return LPC32XX_IRQ_EDGE_SENSITIVE;
0251 } else {
0252 return LPC32XX_IRQ_LEVEL_SENSITIVE;
0253 }
0254 } else {
0255 return LPC32XX_IRQ_LEVEL_SENSITIVE;
0256 }
0257 }
0258
0259 void bsp_interrupt_dispatch(void)
0260 {
0261
0262
0263
0264
0265
0266
0267 uint32_t status = (lpc32xx.mic.sr & ~lpc32xx.mic.itr) &
0268 LPC32XX_MIC_STATUS_MASK;
0269 uint32_t er_mic = lpc32xx.mic.er;
0270 uint32_t er_sic_1 = lpc32xx.sic_1.er;
0271 uint32_t er_sic_2 = lpc32xx.sic_2.er;
0272 uint32_t psr = 0;
0273 lpc32xx_irq_fields *masks = NULL;
0274 rtems_vector_number vector = 0;
0275 unsigned priority = 0;
0276
0277 if (status != 0) {
0278 vector = lpc32xx_irq_get_index(status);
0279 } else {
0280 status = lpc32xx.sic_1.sr & ~lpc32xx.sic_1.itr;
0281 if (status != 0) {
0282 vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_1;
0283 } else {
0284 status = lpc32xx.sic_2.sr & ~lpc32xx.sic_2.itr;
0285 if (status != 0) {
0286 vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_2;
0287 } else {
0288 return;
0289 }
0290 }
0291 }
0292
0293 priority = lpc32xx_irq_priority_table [vector];
0294
0295 masks = &lpc32xx_irq_priority_masks [priority];
0296
0297 lpc32xx.mic.er = er_mic & masks->field.mic;
0298 lpc32xx.sic_1.er = er_sic_1 & masks->field.sic_1;
0299 lpc32xx.sic_2.er = er_sic_2 & masks->field.sic_2;
0300
0301 psr = _ARMV4_Status_irq_enable();
0302
0303 bsp_interrupt_handler_dispatch(vector);
0304
0305 _ARMV4_Status_restore(psr);
0306
0307 lpc32xx.mic.er = er_mic & lpc32xx_irq_enable.field.mic;
0308 lpc32xx.sic_1.er = er_sic_1 & lpc32xx_irq_enable.field.sic_1;
0309 lpc32xx.sic_2.er = er_sic_2 & lpc32xx_irq_enable.field.sic_2;
0310 }
0311
0312 rtems_status_code bsp_interrupt_get_attributes(
0313 rtems_vector_number vector,
0314 rtems_interrupt_attributes *attributes
0315 )
0316 {
0317 bool is_sw_irq;
0318
0319 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0320 bsp_interrupt_assert(attributes != NULL);
0321
0322 attributes->is_maskable =
0323 !lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_ITR);
0324 attributes->can_enable = true;
0325 attributes->maybe_enable = true;
0326 attributes->can_disable = true;
0327 attributes->maybe_disable = true;
0328 is_sw_irq = vector == LPC32XX_IRQ_SW;
0329 attributes->can_raise = is_sw_irq;
0330 attributes->can_raise_on = is_sw_irq;
0331 attributes->can_clear = is_sw_irq;
0332 attributes->can_get_affinity = true;
0333 attributes->can_set_affinity = true;
0334 attributes->maximum_priority = LPC32XX_IRQ_PRIORITY_VALUE_MAX;
0335 attributes->can_get_priority = true;
0336 attributes->can_set_priority = true;
0337
0338 return RTEMS_SUCCESSFUL;
0339 }
0340
0341 rtems_status_code bsp_interrupt_is_pending(
0342 rtems_vector_number vector,
0343 bool *pending
0344 )
0345 {
0346 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0347 bsp_interrupt_assert(pending != NULL);
0348
0349 *pending = lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_RSR);
0350
0351 return RTEMS_SUCCESSFUL;
0352 }
0353
0354 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0355 {
0356 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0357
0358 if (vector != LPC32XX_IRQ_SW) {
0359 return RTEMS_UNSATISFIED;
0360 }
0361
0362 LPC32XX_SW_INT = 0x1;
0363
0364 return RTEMS_SUCCESSFUL;
0365 }
0366
0367 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0368 {
0369 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0370
0371 if (vector != LPC32XX_IRQ_SW) {
0372 return RTEMS_UNSATISFIED;
0373 }
0374
0375 LPC32XX_SW_INT = 0x0;
0376
0377 return RTEMS_SUCCESSFUL;
0378 }
0379
0380 rtems_status_code bsp_interrupt_vector_is_enabled(
0381 rtems_vector_number vector,
0382 bool *enabled
0383 )
0384 {
0385 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0386 bsp_interrupt_assert(enabled != NULL);
0387
0388 *enabled = lpc32xx_irq_is_bit_set_in_field(vector, &lpc32xx_irq_enable);
0389
0390 return RTEMS_SUCCESSFUL;
0391 }
0392
0393 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0394 {
0395 rtems_interrupt_level level;
0396
0397 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0398
0399 rtems_interrupt_disable(level);
0400
0401 if (!lpc32xx_irq_is_bit_set_in_field(vector, &lpc32xx_irq_enable)) {
0402 lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_enable);
0403 lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER);
0404 }
0405
0406 rtems_interrupt_enable(level);
0407
0408 return RTEMS_SUCCESSFUL;
0409 }
0410
0411 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0412 {
0413 rtems_interrupt_level level;
0414
0415 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0416
0417 rtems_interrupt_disable(level);
0418 lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_enable);
0419 lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER);
0420 rtems_interrupt_enable(level);
0421
0422 return RTEMS_SUCCESSFUL;
0423 }
0424
0425 void lpc32xx_set_exception_handler(
0426 Arm_symbolic_exception_name exception,
0427 void (*handler)(void)
0428 )
0429 {
0430 if ((unsigned) exception < MAX_EXCEPTIONS) {
0431 uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS;
0432
0433 table [exception] = (uint32_t) handler;
0434
0435 #ifndef LPC32XX_DISABLE_MMU
0436 rtems_cache_flush_multiple_data_lines(table, 64);
0437 rtems_cache_invalidate_multiple_instruction_lines(NULL, 64);
0438 #endif
0439 }
0440 }
0441
0442 void bsp_interrupt_facility_initialize(void)
0443 {
0444 size_t i = 0;
0445
0446
0447 for (i = 0; i < LPC32XX_IRQ_COUNT; ++i) {
0448 lpc32xx_irq_priority_table [i] = LPC32XX_IRQ_PRIORITY_LOWEST;
0449 }
0450
0451
0452 for (i = 0; i < LPC32XX_IRQ_PRIORITY_COUNT; ++i) {
0453 lpc32xx_irq_priority_masks [i].field.mic = 0xc0000003;
0454 }
0455
0456
0457 lpc32xx_irq_enable.field.sic_2 = 0x0;
0458 lpc32xx_irq_enable.field.sic_1 = 0x0;
0459 lpc32xx_irq_enable.field.mic = 0xc0000003;
0460 lpc32xx.sic_1.er = 0x0;
0461 lpc32xx.sic_2.er = 0x0;
0462 lpc32xx.mic.er = 0xc0000003;
0463
0464
0465 lpc32xx.mic.itr = 0x0;
0466 lpc32xx.sic_1.itr = 0x0;
0467 lpc32xx.sic_2.itr = 0x0;
0468
0469
0470 lpc32xx.mic.apr = 0x3ff0efe0;
0471 lpc32xx.sic_1.apr = 0xfbd27184;
0472 lpc32xx.sic_2.apr = 0x801810c0;
0473
0474
0475 lpc32xx.mic.atr = 0x0;
0476 lpc32xx.sic_1.atr = 0x26000;
0477 lpc32xx.sic_2.atr = 0x0;
0478
0479 lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt);
0480 }