Changeset 8c5c53f4 in rtems


Ignore:
Timestamp:
Feb 27, 2016, 11:19:33 PM (4 years ago)
Author:
Martin Galvan <martin.galvan@…>
Branches:
master
Children:
75518fb
Parents:
67de508
git-author:
Martin Galvan <martin.galvan@…> (02/27/16 23:19:33)
git-committer:
Ben Gras <ben@…> (02/27/16 23:23:02)
Message:

am335x irq handling improvement

This patch makes the following changes to the Beaglebone IRQ handling code:

  • Disable support for nested interrupts.
  • Detect spurious IRQs using the SPURIOUSIRQ field of the INTC_SIR_IRQ register.
  • Acknowledge spurious IRQs by setting the NewIRQAgr bit of the INTC_CONTROL register. This cleans the SPURIOUSIRQ field and allows new interrupts to be generated.
  • Improve the get_mir_reg function a bit.

Closes #2580.

Location:
c/src/lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/arm/beagle/irq.c

    r67de508 r8c5c53f4  
    1919#include <bsp/irq-generic.h>
    2020#include <bsp/linker-symbols.h>
     21#include <bsp/fatal.h>
    2122
    2223#include <rtems/score/armv4.h>
     
    4445#endif
    4546
    46 static int irqs_enabled[BSP_INTERRUPT_VECTOR_MAX+1];
     47/* Enables interrupts at the Interrupt Controller side. */
     48static inline void omap_irq_ack(void)
     49{
     50  mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR);
    4751
    48 volatile static int level = 0;
     52  /* Flush data cache to make sure all the previous writes are done
     53     before re-enabling interrupts. */
     54  flush_data_cache();
     55}
    4956
    5057void bsp_interrupt_dispatch(void)
    5158{
    52   /* get irq */
    53   uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
    54   int irq;
    55   irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK;
     59  const uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
    5660
    57   if(!irqs_enabled[irq]) {
    58         /* Ignore spurious interrupt */
     61  if ((reg & OMAP3_INTR_SPURIOUSIRQ_MASK) != OMAP3_INTR_SPURIOUSIRQ_MASK) {
     62    const rtems_vector_number irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK;
     63
     64    bsp_interrupt_handler_dispatch(irq);
    5965  } else {
    60     bsp_interrupt_vector_disable(irq);
     66    /* Ignore spurious interrupts. We'll still ACK it so new interrupts
     67       can be generated. */
     68  }
    6169
    62     /* enable new interrupts, and flush data cache to make sure
    63      * it hits the intc
    64      */
    65     mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR);
    66     flush_data_cache();
    67     mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
    68     flush_data_cache();
    69 
    70     /* keep current irq masked but enable unmasked ones */
    71     uint32_t psr = _ARMV4_Status_irq_enable();
    72     bsp_interrupt_handler_dispatch(irq);
    73 
    74     _ARMV4_Status_restore(psr);
    75 
    76     bsp_interrupt_vector_enable(irq);
    77   }
     70  omap_irq_ack();
    7871}
    7972
    80 static uint32_t get_mir_reg(int vector, uint32_t *mask)
     73/* There are 4 32-bit interrupt mask registers for a total of 128 interrupts.
     74   The IRQ number tells us which register to use. */
     75static uint32_t omap_get_mir_reg(rtems_vector_number vector, uint32_t *const mask)
    8176{
    82   *mask = 1UL << (vector % 32);
     77  uint32_t mir_reg;
    8378
    84   if(vector <   0) while(1) ;
    85   if(vector <  32) return OMAP3_INTCPS_MIR0;
    86   if(vector <  64) return OMAP3_INTCPS_MIR1;
    87   if(vector <  96) return OMAP3_INTCPS_MIR2;
    88   if(vector < 128) return OMAP3_INTCPS_MIR3;
    89   while(1) ;
     79  /* Select which bit to set/clear in the MIR register. */
     80  *mask = 1ul << (vector % 32u);
     81
     82  if (vector < 32u) {
     83    mir_reg = OMAP3_INTCPS_MIR0;
     84  } else if (vector < 64u) {
     85    mir_reg = OMAP3_INTCPS_MIR1;
     86  } else if (vector < 96u) {
     87    mir_reg = OMAP3_INTCPS_MIR2;
     88  } else if (vector < 128u) {
     89    mir_reg = OMAP3_INTCPS_MIR3;
     90  } else {
     91    /* Invalid IRQ number. This should never happen. */
     92    bsp_fatal(0);
     93  }
     94
     95  return mir_reg;
    9096}
    9197
     
    9399{
    94100  uint32_t mask, cur;
    95   uint32_t mir_reg = get_mir_reg(vector, &mask);
     101  uint32_t mir_reg = omap_get_mir_reg(vector, &mask);
    96102
    97103  cur = mmio_read(omap_intr.base + mir_reg);
    98104  mmio_write(omap_intr.base + mir_reg, cur & ~mask);
    99105  flush_data_cache();
    100 
    101   irqs_enabled[vector] = 1;
    102106
    103107  return RTEMS_SUCCESSFUL;
     
    107111{
    108112  uint32_t mask, cur;
    109   uint32_t mir_reg = get_mir_reg(vector, &mask);
     113  uint32_t mir_reg = omap_get_mir_reg(vector, &mask);
    110114
    111115  cur = mmio_read(omap_intr.base + mir_reg);
    112116  mmio_write(omap_intr.base + mir_reg, cur | mask);
    113117  flush_data_cache();
    114 
    115   irqs_enabled[vector] = 0;
    116118
    117119  return RTEMS_SUCCESSFUL;
  • c/src/lib/libcpu/arm/shared/include/omap3.h

    r67de508 r8c5c53f4  
    7373    (base + OMAP3_INTCPS_ILR0 + 0x4 * (m))
    7474
    75 #define OMAP3_INTR_ACTIVEIRQ_MASK 0x7f /* Active IRQ mask for SIR_IRQ */
     75#define OMAP3_INTR_SPURIOUSIRQ_MASK (0x1FFFFFF << 7) /* Spurious IRQ mask for SIR_IRQ */
     76#define OMAP3_INTR_ACTIVEIRQ_MASK 0x7F /* Active IRQ mask for SIR_IRQ */
    7677#define OMAP3_INTR_NEWIRQAGR      0x1  /* New IRQ Generation */
    7778
Note: See TracChangeset for help on using the changeset viewer.