mirror of https://gitee.com/openkylin/linux.git
gpio: document gpio irqchips a bit more, describe helpers
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>
This commit is contained in:
parent
cf42f1cfe4
commit
90887db883
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue