This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

omapl138 linux interrupt

Other Parts Discussed in Thread: DA8XX, OMAPL138, OMAP-L138

I have write a kernel module, it is as follow, I want it can respond DSP's interrupt.

#define REG_CHIPSIG       0x01C14174
#define REG_CHIPINT_CLEAR 0x01C14178
int i=0;
unsigned int reg_chipsig_clear;
unsigned int reg_chipsig;
static irqreturn_t handler_chipint0(int irq,void *dev_id)
{
 //clear interrupt
 writel(0x1,reg_chipsig_clear);
 //memery interrupt time
 i++;
 return IRQ_HANDLED;
   }
 

int porc_init(void)
{
 
  int result;
  printk("\nporc_init:enter\n");

  reg_chipsig=(unsigned int*)ioremap_nocache(REG_CHIPSIG,4);
  reg_chipsig_clear=(unsigned int*)ioremap_nocache(REG_CHIPINT_CLEAR,4);

  if(request_irq(IRQ_DA8XX_CHIPINT0, handler_chipint0,0,"proc_chipint0",0))
  {
   printk("porc_init:request handler_chipint0 error\n");
  } 
  printk("\nporc_init:exit\n");
  return 0;

}

void porc_exit(void)
{
  
 printk("\nporc_exit:enter\n");
 
 //get time of interrupt
 printk("i=%d\n",i);
 
 free_irq(IRQ_DA8XX_CHIPINT0,0); 
    printk("\nporc_exit:exit\n");
}
MODULE_AUTHOR("test");
MODULE_LICENSE("Dual BSD/GPL");

module_init(porc_init);
module_exit(porc_exit);

But I find that when DSP set bit0 of reg CHIPSIG the ISR will run three times, why?

I use OMAPL138.

  • Lisong Xu said:

    But I find that when DSP set bit0 of reg CHIPSIG the ISR will run three times, why?

    We have observed similar behaviour with the OMAP-L138 DSP->ARM interrupt (CHIPINT0).  We found that this happens because it is a "level" interrupt line, and Linux's IRQ handling ACKs the interrupt before calling the handler.  Since it's a level interrupt line that isn't cleared until your handler runs, just after Linux's IRQ handler ACKs the interrupt, it gets asserted again before your handler is able to clear the line level.

    This caused our handler to run twice for every occurrence of the interrupt, but I can't explain why it's running 3 times for you.

    We solved this by manually ACKing the interrupt from the handler, after clearing the CHIPINT0 line in the handler.  That method is a bit complicated, requiring access to the chip's ack() handler.  A simpler solution for you might be to simply lower the line from the DSP immediately after setting it, creating a pulse on the CHIPINT0 line instead of a level.  This will work as long as Linux doesn't respond too quickly (by ACKing the interrupt before the DSP has lowered the signal level), and I doubt Linux will respond nearly quickly enough for that to happen.  If the DSP lowers the line immediately after raising it then the line will be high for only a few cycles (which is plenty enough for the ARM AINTC mechanism to recognize it).

    Regards,

    - Rob

     

  • I am not understand you very well, how can I do in my program?

  • Lisong Xu said:

    I am not understand you very well, how can I do in my program?

    Your existing code today does something like this:
        DSP code:
            int *chipsig_reg = 0x01c14174;

            /* interrupt ARM */
            *chipsig_reg = 1;

       ARM code:
            static irqreturn_t handler_chipint0(int irq,void *dev_id)
            {
             //clear interrupt
             writel(0x1,reg_chipsig_clear);
             //memery interrupt time
             i++;
             return IRQ_HANDLED;
            }

    I am suggesting that you do something like this:
        DSP code:
             int *chipsig_reg = 0x01c14174;
             int *chipsig_clr_reg = 0x01c14178;

             /* pulse interrupt ARM */
             *chipsig_reg = 1;
             *chipsig_clr_reg = 1;

       ARM code:
            static irqreturn_t handler_chipint0(int irq,void *dev_id)
            {
             //memery interrupt time
             i++;
             return IRQ_HANDLED;
            }

    Regards,

    - Rob