]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
gpio: document gpio irqchips a bit more, describe helpers
authorLinus Walleij <linus.walleij@linaro.org>
Wed, 9 Apr 2014 12:36:32 +0000 (14:36 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 14 Apr 2014 08:22:50 +0000 (10:22 +0200)
This adds some documentation about the GPIO irqchips, what types
exist etc.

Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Documentation/gpio/driver.txt

index f73cc7b5dc853df94b05a035b9531bc215648471..fa9a0a8b37348273df54a56c6c0022da94078078 100644 (file)
@@ -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