···417417If you do this, the additional irq_chip will be set up by gpiolib at the418418same time as setting up the rest of the GPIO functionality. The following419419is a typical example of a chained cascaded interrupt handler using420420-the gpio_irq_chip:420420+the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions421421+call into the core gpiolib code:421422422423.. code-block:: c423424424424- /* Typical state container with dynamic irqchip */425425+ /* Typical state container */425426 struct my_gpio {426427 struct gpio_chip gc;427427- struct irq_chip irq;428428+ };429429+430430+ static void my_gpio_mask_irq(struct irq_data *d)431431+ {432432+ struct gpio_chip *gc = irq_desc_get_handler_data(d);433433+434434+ /*435435+ * Perform any necessary action to mask the interrupt,436436+ * and then call into the core code to synchronise the437437+ * state.438438+ */439439+440440+ gpiochip_disable_irq(gc, d->hwirq);441441+ }442442+443443+ static void my_gpio_unmask_irq(struct irq_data *d)444444+ {445445+ struct gpio_chip *gc = irq_desc_get_handler_data(d);446446+447447+ gpiochip_enable_irq(gc, d->hwirq);448448+449449+ /*450450+ * Perform any necessary action to unmask the interrupt,451451+ * after having called into the core code to synchronise452452+ * the state.453453+ */454454+ }455455+456456+ /*457457+ * Statically populate the irqchip. Note that it is made const458458+ * (further indicated by the IRQCHIP_IMMUTABLE flag), and that459459+ * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra460460+ * callbacks to the structure.461461+ */462462+ static const struct irq_chip my_gpio_irq_chip = {463463+ .name = "my_gpio_irq",464464+ .irq_ack = my_gpio_ack_irq,465465+ .irq_mask = my_gpio_mask_irq,466466+ .irq_unmask = my_gpio_unmask_irq,467467+ .irq_set_type = my_gpio_set_irq_type,468468+ .flags = IRQCHIP_IMMUTABLE,469469+ /* Provide the gpio resource callbacks */470470+ GPIOCHIP_IRQ_RESOURCE_HELPERS,428471 };429472430473 int irq; /* from platform etc */431474 struct my_gpio *g;432475 struct gpio_irq_chip *girq;433476434434- /* Set up the irqchip dynamically */435435- g->irq.name = "my_gpio_irq";436436- g->irq.irq_ack = my_gpio_ack_irq;437437- g->irq.irq_mask = my_gpio_mask_irq;438438- g->irq.irq_unmask = my_gpio_unmask_irq;439439- g->irq.irq_set_type = my_gpio_set_irq_type;440440-441477 /* Get a pointer to the gpio_irq_chip */442478 girq = &g->gc.irq;443443- girq->chip = &g->irq;479479+ gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);444480 girq->parent_handler = ftgpio_gpio_irq_handler;445481 girq->num_parents = 1;446482 girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),···494458495459.. code-block:: c496460497497- /* Typical state container with dynamic irqchip */461461+ /* Typical state container */498462 struct my_gpio {499463 struct gpio_chip gc;500500- struct irq_chip irq;464464+ };465465+466466+ static void my_gpio_mask_irq(struct irq_data *d)467467+ {468468+ struct gpio_chip *gc = irq_desc_get_handler_data(d);469469+470470+ /*471471+ * Perform any necessary action to mask the interrupt,472472+ * and then call into the core code to synchronise the473473+ * state.474474+ */475475+476476+ gpiochip_disable_irq(gc, d->hwirq);477477+ }478478+479479+ static void my_gpio_unmask_irq(struct irq_data *d)480480+ {481481+ struct gpio_chip *gc = irq_desc_get_handler_data(d);482482+483483+ gpiochip_enable_irq(gc, d->hwirq);484484+485485+ /*486486+ * Perform any necessary action to unmask the interrupt,487487+ * after having called into the core code to synchronise488488+ * the state.489489+ */490490+ }491491+492492+ /*493493+ * Statically populate the irqchip. Note that it is made const494494+ * (further indicated by the IRQCHIP_IMMUTABLE flag), and that495495+ * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra496496+ * callbacks to the structure.497497+ */498498+ static const struct irq_chip my_gpio_irq_chip = {499499+ .name = "my_gpio_irq",500500+ .irq_ack = my_gpio_ack_irq,501501+ .irq_mask = my_gpio_mask_irq,502502+ .irq_unmask = my_gpio_unmask_irq,503503+ .irq_set_type = my_gpio_set_irq_type,504504+ .flags = IRQCHIP_IMMUTABLE,505505+ /* Provide the gpio resource callbacks */506506+ GPIOCHIP_IRQ_RESOURCE_HELPERS,501507 };502508503509 int irq; /* from platform etc */504510 struct my_gpio *g;505511 struct gpio_irq_chip *girq;506506-507507- /* Set up the irqchip dynamically */508508- g->irq.name = "my_gpio_irq";509509- g->irq.irq_ack = my_gpio_ack_irq;510510- g->irq.irq_mask = my_gpio_mask_irq;511511- g->irq.irq_unmask = my_gpio_unmask_irq;512512- g->irq.irq_set_type = my_gpio_set_irq_type;513512514513 ret = devm_request_threaded_irq(dev, irq, NULL,515514 irq_thread_fn, IRQF_ONESHOT, "my-chip", g);···553482554483 /* Get a pointer to the gpio_irq_chip */555484 girq = &g->gc.irq;556556- girq->chip = &g->irq;485485+ gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);557486 /* This will let us handle the parent IRQ in the driver */558487 girq->parent_handler = NULL;559488 girq->num_parents = 0;···571500 /* Typical state container with dynamic irqchip */572501 struct my_gpio {573502 struct gpio_chip gc;574574- struct irq_chip irq;575503 struct fwnode_handle *fwnode;576504 };577505578578- int irq; /* from platform etc */506506+ static void my_gpio_mask_irq(struct irq_data *d)507507+ {508508+ struct gpio_chip *gc = irq_desc_get_handler_data(d);509509+510510+ /*511511+ * Perform any necessary action to mask the interrupt,512512+ * and then call into the core code to synchronise the513513+ * state.514514+ */515515+516516+ gpiochip_disable_irq(gc, d->hwirq);517517+ irq_mask_mask_parent(d);518518+ }519519+520520+ static void my_gpio_unmask_irq(struct irq_data *d)521521+ {522522+ struct gpio_chip *gc = irq_desc_get_handler_data(d);523523+524524+ gpiochip_enable_irq(gc, d->hwirq);525525+526526+ /*527527+ * Perform any necessary action to unmask the interrupt,528528+ * after having called into the core code to synchronise529529+ * the state.530530+ */531531+532532+ irq_mask_unmask_parent(d);533533+ }534534+535535+ /*536536+ * Statically populate the irqchip. Note that it is made const537537+ * (further indicated by the IRQCHIP_IMMUTABLE flag), and that538538+ * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra539539+ * callbacks to the structure.540540+ */541541+ static const struct irq_chip my_gpio_irq_chip = {542542+ .name = "my_gpio_irq",543543+ .irq_ack = my_gpio_ack_irq,544544+ .irq_mask = my_gpio_mask_irq,545545+ .irq_unmask = my_gpio_unmask_irq,546546+ .irq_set_type = my_gpio_set_irq_type,547547+ .flags = IRQCHIP_IMMUTABLE,548548+ /* Provide the gpio resource callbacks */549549+ GPIOCHIP_IRQ_RESOURCE_HELPERS,550550+ };551551+579552 struct my_gpio *g;580553 struct gpio_irq_chip *girq;581554582582- /* Set up the irqchip dynamically */583583- g->irq.name = "my_gpio_irq";584584- g->irq.irq_ack = my_gpio_ack_irq;585585- g->irq.irq_mask = my_gpio_mask_irq;586586- g->irq.irq_unmask = my_gpio_unmask_irq;587587- g->irq.irq_set_type = my_gpio_set_irq_type;588588-589555 /* Get a pointer to the gpio_irq_chip */590556 girq = &g->gc.irq;591591- girq->chip = &g->irq;557557+ gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip);592558 girq->default_type = IRQ_TYPE_NONE;593559 girq->handler = handle_bad_irq;594560 girq->fwnode = g->fwnode;···713605typically be called in the .irq_disable() and .irq_enable() callbacks from the714606irqchip.715607716716-When using the gpiolib irqchip helpers, these callbacks are automatically717717-assigned.608608+When IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks609609+are automatically assigned. This behaviour is deprecated and on its way610610+to be removed from the kernel.718611719612720613Real-Time compliance for GPIO IRQ chips
+19
drivers/gpio/TODO
···178178for debugging and hacking and to expose all lines without the179179need of any exporting. Also provide ample ammunition to shoot180180oneself in the foot, because this is debugfs after all.181181+182182+183183+Moving over to immutable irq_chip structures184184+185185+Most of the gpio chips implementing interrupt support rely on gpiolib186186+intercepting some of the irq_chip callbacks, preventing the structures187187+from being made read-only and forcing duplication of structures that188188+should otherwise be unique.189189+190190+The solution is to call into the gpiolib code when needed (resource191191+management, enable/disable or unmask/mask callbacks), and to let the192192+core code know about that by exposing a flag (IRQCHIP_IMMUTABLE) in193193+the irq_chip structure. The irq_chip structure can then be made unique194194+and const.195195+196196+A small number of drivers have been converted (pl061, tegra186, msm,197197+amd, apple), and can be used as examples of how to proceed with this198198+conversion. Note that drivers using the generic irqchip framework199199+cannot be converted yet, but watch this space!
···579579void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset);580580void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset);581581582582+/* irq_data versions of the above */583583+int gpiochip_irq_reqres(struct irq_data *data);584584+void gpiochip_irq_relres(struct irq_data *data);585585+586586+/* Paste this in your irq_chip structure */587587+#define GPIOCHIP_IRQ_RESOURCE_HELPERS \588588+ .irq_request_resources = gpiochip_irq_reqres, \589589+ .irq_release_resources = gpiochip_irq_relres590590+591591+static inline void gpio_irq_chip_set_chip(struct gpio_irq_chip *girq,592592+ const struct irq_chip *chip)593593+{594594+ /* Yes, dropping const is ugly, but it isn't like we have a choice */595595+ girq->chip = (struct irq_chip *)chip;596596+}597597+582598/* Line status inquiry for drivers */583599bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset);584600bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset);
+2
include/linux/irq.h
···569569 * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND: Invokes __enable_irq()/__disable_irq() for wake irqs570570 * in the suspend path if they are in disabled state571571 * IRQCHIP_AFFINITY_PRE_STARTUP: Default affinity update before startup572572+ * IRQCHIP_IMMUTABLE: Don't ever change anything in this chip572573 */573574enum {574575 IRQCHIP_SET_TYPE_MASKED = (1 << 0),···583582 IRQCHIP_SUPPORTS_NMI = (1 << 8),584583 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = (1 << 9),585584 IRQCHIP_AFFINITY_PRE_STARTUP = (1 << 10),585585+ IRQCHIP_IMMUTABLE = (1 << 11),586586};587587588588#include <linux/irqdesc.h>