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.

Interrupt on GPIO line is not being detected

There is an interrupt being generated at every 10ms on GPIO_39 in the pandaboard OMAP4. I have registered a handler for this in Linux driver code, but the handler is not being called since the interrupt is not being detected.

GPIO 39 is multiplexed to pin 22 of J3 expansion connector. I made sure, by probing pin 22, that the interrupt is being generated every 10ms.

I've the following in my driver code.

iowrite16(0x3, gpio_39_address + 2); /* Configured the pin 22 to be used as gpio. */

#define GPIO_NO     39

  ret = gpio_request(GPIO_NO, "Claiming GPIO");
  if(ret < 0)
  {
    printk(KERN_ALERT "%s: Claiming GPIO_%d failed\n", __func__, GPIO_NO);
    return -1;
  }
  else
  {
    printk(KERN_INFO "%s: Claiming GPIO_%d successful\n", __func__, GPIO_NO);
  }

  ret = gpio_direction_input(GPIO_NO);  
  if(ret < 0)
  {
    printk(KERN_INFO "%s: Setting GPIO direction to input failed\n", __func__);
    return -1;
  }
  else
  {
    printk(KERN_INFO "%s: Direction of GPIO_%d set to input\n", __func__, GPIO_NO);
  }

  GPIO_IRQ = gpio_to_irq(GPIO_NO);

  if(GPIO_IRQ < 0)
  {
    printk(KERN_INFO "%s: Mapping GPIO_%d to IRQ failed\n", __func__, GPIO_NO);
    return -1;
  }
  else
  {
    printk(KERN_INFO "%s: Mapping GPIO_%d to IRQ_%d successful\n", __func__, GPIO_NO, GPIO_IRQ);
  }

  if((request_irq(GPIO_IRQ, ten_ms_int, IRQF_TRIGGER_FALLING, DEVICE_NAME, NULL)))
  {
    printk(KERN_ALERT "%s: requeseting GPIO_IRQ %d failed\n", __func__, GPIO_IRQ);
    return -1;
  }
  else
  {
    printk(KERN_INFO "%s: requesting GPIO_IRQ %d successful\n", __func__, GPIO_IRQ);
  }

irqreturn_t ten_ms_int(int irq, void *dev_id)
{
  T_UINT32 l;
  /* Enable spi channel */
  l = ioread32(spi_base + SPI_CHCONF0);
  l |= SPI_CHCONF0_FORCE;
  iowrite32(l, (spi_base +  SPI_CHCONF0));

  l = ioread32(spi_base + SPI_CHCTRL0);
  l |= SPI_CHCTRL_EN;
  iowrite32(l, (spi_base + SPI_CHCTRL0));

  /* Enable dma channel 0 */
  l = ioread32(sdma_base + SDMA_CCR(CHANNEL0));
  l |= SDMA_CCR_ENABLE;
  iowrite32(l, sdma_base + SDMA_CCR(CHANNEL0));

  /* Enable dma channel 1 */
  l = ioread32(sdma_base + SDMA_CCR(CHANNEL1));
  l |= SDMA_CCR_ENABLE;
  iowrite32(l, sdma_base + SDMA_CCR(CHANNEL1));
  printk(KERN_INFO "%s: 10ms interrupt detected %d\n", __func__, irq); /* I know that I've to remove this printk statement */
  return IRQ_HANDLED;
}

GPIO_39 belongs to the bank GPIO2 and the corresponding interrupt number is 32. But, the return value of gpio_to_irq() is 199. This is another cause of concern.

Is this the correct way of doing it? Please let me know if something is wrong in the code or if I have missed something. If you need further information, please ask.

  • Hi,

    For start I didn't see any pinmux settings (may use the  omap_mux_init_gpio API )

    also  res = request_irq(..) can be handy when used  for proper debug.

    switch(res) {
    case -EBUSY:   printk("irq %d busy\n", irq);                  gpio_free(GPIO_NR); return -EBUSY;
    case -EINVAL:  printk("bad irq number or handler\n");  gpio_free(GPIO_NR); return -EINVAL;
    default:             printk("irq %d, gpio %d obtained\n", irq, GPIO_NR);
    break;
    }

     

    Regards,

    Boyko

  • Hi,

    Multiplexing is done as per the TRM. ie

    iowrite16(0x3, gpio_39_address + 2); /* Configured the pin 22 to be used as gpio. */ 

    ie. writing mode 3 to gpio_39_address(which is the virtual address obtained after ioremap(0x4A10005C,4)

    Also,

    Since the return value of request_irq is positive, the default statement (printk("irq %d, gpio %d obtained\n", irq, GPIO_NR); is getting displayed

    Kind Regards
    DDPD
  • Hi,

    Have you tried observing the level on that particular gpio through the device node?

    If it works then I am missing something from the interrupt assignment flow.

    Regards,

    Boyko

  • Hello,

    As mentioned earlier, the 10ms task is being detected in the respective GPIO line. I think we are missing some API with respect to Level Triggering.Please have a look over it.

    Thanks & Regards

    DDPD

  • Oh I thought you observed actual signal only with a scope.

    Have you tried using fast  irq handler ( dependant on the kernel version you are using)

    request_irq(GPIO_IRQ,ten_ms_intr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "test_irq", NULL);

    and also is you handler function  static or the code you have presented is separated in different parts?

    Regards,

    Boyko

  • Hello,

    Sorry for the misconception, the 10ms task detection was verified in oscilloscope.

    I modified the above code without using API's except gpio_to_irq and request_irq.

    The code below is configured as per the TRM and the result was positive in this case(Interrupt detected).

    /* Clock Gating Power Saving */
      iowrite32(0x000000FF,gpio2_base + GPIO_LEVELDETECT_0);//Low level	
    
      /* IRQ Clear */	
      iowrite32(0x80,gpio2_base + GPIO_CLEARDATAOUT);//Clear_Data_Out
      iowrite32(0x80,gpio2_base + GPIO_IRQSTATUS_CLR_0);//Set 0	
      /* IRQ Enable */	
      iowrite32(0x80,gpio2_base + GPIO_SETDATAOUT);//Set_Data_Out
      iowrite32(0x80,gpio2_base + GPIO_IRQSTATUS_SET_0);//Set 0	
    
      /* Enable Wakeup GPIO Channels */
      iowrite32(0x80,gpio2_base + GPIO_IRQWAKEN_0);//Set 0	
    
      iowrite32(0x0C, gpio2_base + GPIO_SYSCONFIG);//SYSCONFIG

    But the code using the API's does not detect the Interrupt.Guess some API is missed

    Regards

    DDPD

  • Hi,

    What  kernel version did you use to check if there is specific patch fix?

    Regards,

    Boyko

  • Hi,


    I am using kernel version 3.4

    Regards

    DDPD

  • @DDPD - any chance you could have a look at - 

    http://e2e.ti.com/support/embedded/linux/f/354/t/364623.aspx