diff options
Diffstat (limited to 'Documentation/gpio/driver.txt')
| -rw-r--r-- | Documentation/gpio/driver.txt | 59 | 
1 files changed, 59 insertions, 0 deletions
| diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index f73cc7b5dc85..fa9a0a8b3734 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -73,6 +73,65 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using  the header <linux/irq.h>. So basically such a driver is utilizing two sub-  systems simultaneously: gpio and irq. +GPIO irqchips usually fall in one of two categories: + +* CHAINED GPIO irqchips: these are usually the type that is embedded on +  an SoC. This means that there is a fast IRQ handler for the GPIOs that +  gets called in a chain from the parent IRQ handler, most typically the +  system interrupt controller. This means the GPIO irqchip is registered +  using irq_set_chained_handler() or the corresponding +  gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip +  handler will be called immediately from the parent irqchip, while +  holding the IRQs disabled. The GPIO irqchip will then end up calling +  something like this sequence in its interrupt handler: + +  static irqreturn_t tc3589x_gpio_irq(int irq, void *data) +      chained_irq_enter(...); +      generic_handle_irq(...); +      chained_irq_exit(...); + +  Chained GPIO irqchips typically can NOT set the .can_sleep flag on +  struct gpio_chip, as everything happens directly in the callbacks. + +* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any +  other GPIO irqchip residing on the other side of a sleeping bus. Of course +  such drivers that need slow bus traffic to read out IRQ status and similar, +  traffic which may in turn incur other IRQs to happen, cannot be handled +  in a quick IRQ handler with IRQs disabled. Instead they need to spawn a +  thread and then mask the parent IRQ line until the interrupt is handled +  by the driver. The hallmark of this driver is to call something like +  this in its interrupt handler: + +  static irqreturn_t tc3589x_gpio_irq(int irq, void *data) +      ... +      handle_nested_irq(irq); + +  The hallmark of threaded GPIO irqchips is that they set the .can_sleep +  flag on struct gpio_chip to true, indicating that this chip may sleep +  when accessing the GPIOs. + +To help out in handling the set-up and management of GPIO irqchips and the +associated irqdomain and resource allocation callbacks, the gpiolib has +some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig +symbol: + +* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass +  the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks +  need to embed the gpio_chip in its state container and obtain a pointer +  to the container using container_of(). +  (See Documentation/driver-model/design-patterns.txt) + +* gpiochip_set_chained_irqchip(): sets up a chained irq handler for a +  gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler +  data. (Notice handler data, since the irqchip data is likely used by the +  parent irqchip!) This is for the chained type of chip. + +To use the helpers please keep the following in mind: + +- Make sure to assign all relevant members of the struct gpio_chip so that +  the irqchip can initialize. E.g. .dev and .can_sleep shall be set up +  properly. +  It is legal for any IRQ consumer to request an IRQ from any irqchip no matter  if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and  irq_chip are orthogonal, and offering their services independent of each | 
