Setting up more than one input port for interrrupt in kernel

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been reading the AVR32408 application note from Atmel. This particular application note deals with the GPIO driver. In the code that discusses how to check for GPIO in a kernel module, an interrupt is generated when a switch attached to a port is pressed. However, how do I check the state of numerous port pins at the same time?

What I'm doing is developing a bit-banging driver for my camera, which outputs parallel data. Can this be done with an interrupt-based driver such as the following example pasted below?

/*   This file is prepared for Doxygen automatic documentation generation   */
/*! \file ********************************************************************
 *
 * \brief
 *      This kernel module shows the usage of GPIOs in a driver. This 
 *      example includes no driver or device registering to keep is short 
 *      and simple.
 *      Connect header J1 with header SWITCH on the STK1000.
 *      Press button SW0 and run dmesg to view the kernel log. 
 *
 *
 * \par Application note:
 *      AVR32408: Using GPIO with Linux on the AVR32
 *
 * \par Documentation
 *      For comprehensive code documentation, supported compilers, compiler
 *      settings and supported devices see readme.html
 *
 * \author
 *      Atmel Corporation: http://www.atmel.com \n
 *      Support email: avr32@atmel.com
 *
 * $Name$
 * $Revision$
 * $RCSfile$
 * $Date$  \n
 ****************************************************************************/

/*! \page License
 * Copyright (c) 2006, Atmel Corporation All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. The name of ATMEL may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

/*! \brief I/O line number for switch 0 on the STK1000. */
static int gpio_switch0 = GPIO_PIN_PB(0);
/*! \brief Interrupt line number */
static int irq;

/*! \brief Interrupt service routine for the switch 0. */
static irqreturn_t switch0_interrupt(int irq, void *dev_id){
	
	printk("Switch0 interrupt\n");
	return IRQ_HANDLED;
}

/*! \brief Module init function.
 *  This function is called when the module is loaded into the kernel.
 */
static int __init gpio_example_init(void)
{
	
	printk(KERN_DEBUG"Gpio example init\n");
	
	/* Set GPIO for switch 0 a s input */
	if(gpio_direction_input(gpio_switch0))
		goto err_gpio_input;

	/* Get IRQ number corresponding to the GPIO number*/
	irq = gpio_to_irq(gpio_switch0);
	
	/* Request IRQ line for switch 0 GPIO and install a handler */
	if(request_irq(irq, switch0_interrupt, 0, "gpio-example",NULL)){
		printk(KERN_ERR"IRQ request failed\n"); 
		goto err_req_int;
	}

	printk(KERN_DEBUG"GPIO %d IRQ %d \n",gpio_switch0, irq);

	return 0;

err_req_int:
err_gpio_input:
	return -EIO;
}
/*! \brief Module exit function.
 *  This function is called when the module is unloaded from the kernel
 */
static void __exit gpio_example_exit(void)
{
	free_irq(irq, NULL);
}
module_init(gpio_example_init);
module_exit(gpio_example_exit);

MODULE_DESCRIPTION("Atmel gpio example driver");
MODULE_AUTHOR("Lars Häring ");
MODULE_LICENSE("GPL");
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The generic gpio framework doesn't support the set and get of multiple pins at once. If you're sure that this is going to be an AVR32-specific driver then you can use the avr32 specific gpio extensions, namely gpio_{get,set}_value_multiple(). These are in arch/avr32/mach-at32ap/pio.c and AFAICS not exported through any standard headers. You can modify the headers to give you access to these or move your drivers in to the arch/avr32 folder and use relative paths.

-S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, I see. Thanks for pointing me in the right direction, Squidgit. I 'll look at moving my code into that particular folder. :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got a similar situation. I have an 8 bit bus wired up to PB08-15 that I need to monitor. I don't think setting up 8 different IRQs would be really efficient.

What I was thinking I could do was setup a single irq handler. Any of the 8 bits would trigger it. Once triggered, the routine would somehow figure out which pin changed and read it's value.

As I understand the gpio docs, I can see my servicer could use

pin = irq_to_gpio(irq)

to figure out which pin triggered and

value = gpio_get_value(pin)

to find out what state the pin is in. It this correct?

But how would I assoicate all 8 pins to a single irq number? If I called gpio_to_irq(pin) 8 times, wouldn't I get 8 different IRQs?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yzf600 wrote:
As I understand the gpio docs, I can see my servicer could use
pin = irq_to_gpio(irq)

to figure out which pin triggered and

value = gpio_get_value(pin)

to find out what state the pin is in. It this correct?

But how would I assoicate all 8 pins to a single irq number? If I called gpio_to_irq(pin) 8 times, wouldn't I get 8 different IRQs?

I don't know what you mean regarding gpio_to_irq(). That function just converts a GPIO cookie to the interrupt number associated with it. You can call it as many times as you want but if the argument is the same, so will the result be.

In the kernel just go through and request_irq() each one of the 8 interrupts, just point them all to the same ISR.

-S.