Back to home page

LXR

 
 

    


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

0001 /**
0002  * @file
0003  *
0004  * @ingroup raspberrypi_interrupt
0005  *
0006  * @brief Interrupt support.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2014 Andre Marques <andre.lousa.marques at gmail.com>
0011  *
0012  * Copyright (c) 2009 embedded brains GmbH & Co. KG
0013  *
0014  * The license and distribution terms for this file may be
0015  * found in the file LICENSE in this distribution or at
0016  * http://www.rtems.org/license/LICENSE.
0017  */
0018 
0019 #include <rtems/score/armv4.h>
0020 
0021 #include <bsp.h>
0022 #include <bsp/irq-generic.h>
0023 #include <bsp/raspberrypi.h>
0024 #include <bsp/linker-symbols.h>
0025 #include <bsp/mmu.h>
0026 #include <rtems/bspIo.h>
0027 #include <strings.h>
0028 
0029 #include <rtems/inttypes.h>
0030 
0031 #ifdef RTEMS_SMP
0032 #include <rtems/score/smp.h>
0033 #include <rtems/score/smpimpl.h>
0034 #endif
0035 
0036 typedef struct {
0037   unsigned long enable_reg_addr;
0038   unsigned long disable_reg_addr;
0039 } bcm2835_irq_ctrl_reg_t;
0040 
0041 static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = {
0042   { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 },
0043   { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 },
0044   { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC }
0045 };
0046 
0047 static inline const bcm2835_irq_ctrl_reg_t *
0048 bsp_vector_to_reg(rtems_vector_number vector)
0049 {
0050   return bcm2835_irq_ctrl_reg_table + (vector >> 5);
0051 }
0052 
0053 static inline uint32_t
0054 bsp_vector_to_mask(rtems_vector_number vector)
0055 {
0056   return 1 << (vector & 0x1f);
0057 }
0058 
0059 static const int bcm2835_irq_speedup_table[] =
0060 {
0061   /*  0 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  0,
0062   /*  1 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  1,
0063   /*  2 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  2,
0064   /*  3 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  3,
0065   /*  4 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  4,
0066   /*  5 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  5,
0067   /*  6 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  6,
0068   /*  7 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  7,
0069   /*  8 */ -1, /* One or more bits set in pending register 1 */
0070   /*  9 */ -2, /* One or more bits set in pending register 2 */
0071   /* 10 */  7, /* GPU IRQ 7 */
0072   /* 11 */  9, /* GPU IRQ 9 */
0073   /* 12 */ 10, /* GPU IRQ 10 */
0074   /* 13 */ 18, /* GPU IRQ 18 */
0075   /* 14 */ 19, /* GPU IRQ 19 */
0076   /* 15 */ 53, /* GPU IRQ 53 */
0077   /* 16 */ 54, /* GPU IRQ 54 */
0078   /* 17 */ 55, /* GPU IRQ 55 */
0079   /* 18 */ 56, /* GPU IRQ 56 */
0080   /* 19 */ 57, /* GPU IRQ 57 */
0081   /* 20 */ 62, /* GPU IRQ 62 */
0082 };
0083 
0084 /*
0085  * Define which basic peding register (BCM2835_IRQ_BASIC) bits
0086  * should be processed through bcm2835_irq_speedup_table
0087  */
0088 
0089 #define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff
0090 
0091 /*
0092  * Determine the source of the interrupt and dispatch the correct handler.
0093  */
0094 void bsp_interrupt_dispatch(void)
0095 {
0096   unsigned int pend;
0097   unsigned int pend_bit;
0098 
0099   rtems_vector_number vector = 255;
0100 
0101 #ifdef RTEMS_SMP
0102   uint32_t cpu_index_self = _SMP_Get_current_processor();
0103   uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self));
0104 
0105   if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) {
0106     /* reset mailbox 3 contents to zero */
0107     BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff;
0108     _SMP_Inter_processor_interrupt_handler(
0109       _Per_CPU_Get_by_index(cpu_index_self)
0110     );
0111   }
0112   if ( cpu_index_self != 0 )
0113     return;
0114 #endif /* RTEMS_SMP */
0115 
0116   pend = BCM2835_REG(BCM2835_IRQ_BASIC);
0117   if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) {
0118     pend_bit = ffs(pend) - 1;
0119     vector = bcm2835_irq_speedup_table[pend_bit];
0120   } else {
0121     pend = BCM2835_REG(BCM2835_IRQ_PENDING1);
0122     if ( pend != 0 ) {
0123       pend_bit = ffs(pend) - 1;
0124       vector = pend_bit;
0125     } else {
0126       pend = BCM2835_REG(BCM2835_IRQ_PENDING2);
0127       if ( pend != 0 ) {
0128         pend_bit = ffs(pend) - 1;
0129         vector = pend_bit + 32;
0130       }
0131     }
0132   }
0133 
0134   if ( vector < 255 )
0135   {
0136       bsp_interrupt_handler_dispatch(vector);
0137   }
0138 }
0139 
0140 rtems_status_code bsp_interrupt_get_attributes(
0141   rtems_vector_number         vector,
0142   rtems_interrupt_attributes *attributes
0143 )
0144 {
0145   return RTEMS_SUCCESSFUL;
0146 }
0147 
0148 rtems_status_code bsp_interrupt_is_pending(
0149   rtems_vector_number vector,
0150   bool               *pending
0151 )
0152 {
0153   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0154   bsp_interrupt_assert(pending != NULL);
0155   *pending = false;
0156   return RTEMS_UNSATISFIED;
0157 }
0158 
0159 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0160 {
0161   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0162   return RTEMS_UNSATISFIED;
0163 }
0164 
0165 #if defined(RTEMS_SMP)
0166 rtems_status_code bsp_interrupt_raise_on(
0167   rtems_vector_number vector,
0168   uint32_t            cpu_index
0169 )
0170 {
0171   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0172   return RTEMS_UNSATISFIED;
0173 }
0174 #endif
0175 
0176 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0177 {
0178   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0179   return RTEMS_UNSATISFIED;
0180 }
0181 
0182 rtems_status_code bsp_interrupt_vector_is_enabled(
0183   rtems_vector_number vector,
0184   bool               *enabled
0185 )
0186 {
0187   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0188   bsp_interrupt_assert(enabled != NULL);
0189   *enabled = false;
0190   return RTEMS_UNSATISFIED;
0191 }
0192 
0193 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0194 {
0195   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0196   BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) =
0197               bsp_vector_to_mask(vector);
0198   return RTEMS_SUCCESSFUL;
0199 }
0200 
0201 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0202 {
0203   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0204   BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) =
0205               bsp_vector_to_mask(vector);
0206   return RTEMS_SUCCESSFUL;
0207 }
0208 
0209 rtems_status_code bsp_interrupt_set_priority(
0210   rtems_vector_number vector,
0211   uint32_t priority
0212 )
0213 {
0214   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0215   return RTEMS_UNSATISFIED;
0216 }
0217 
0218 rtems_status_code bsp_interrupt_get_priority(
0219   rtems_vector_number vector,
0220   uint32_t *priority
0221 )
0222 {
0223   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0224   bsp_interrupt_assert(priority != NULL);
0225   return RTEMS_UNSATISFIED;
0226 }
0227 
0228 #if defined(RTEMS_SMP)
0229 rtems_status_code bsp_interrupt_get_affinity(
0230   rtems_vector_number  vector,
0231   Processor_mask      *affinity
0232 )
0233 {
0234   (void) vector;
0235   _Processor_mask_From_index( affinity, 0 );
0236   return RTEMS_UNSATISFIED;
0237 }
0238 
0239 rtems_status_code bsp_interrupt_set_affinity(
0240   rtems_vector_number   vector,
0241   const Processor_mask *affinity
0242 )
0243 {
0244   (void) vector;
0245   (void) affinity;
0246   return RTEMS_UNSATISFIED;
0247 }
0248 #endif
0249 
0250 void bsp_interrupt_handler_default(rtems_vector_number vector)
0251 {
0252     printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector);
0253 }
0254 
0255 void bsp_interrupt_facility_initialize(void)
0256 {
0257    BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff;
0258    BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff;
0259    BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff;
0260    BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0;
0261 }