|
|
@@ -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
|