]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
gpio: regmap: Allow to allocate regmap-irq device
authorMathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Sun, 24 Aug 2025 11:57:24 +0000 (13:57 +0200)
committerLee Jones <lee@kernel.org>
Tue, 16 Sep 2025 14:24:48 +0000 (15:24 +0100)
GPIO controller often have support for IRQ: allow to easily allocate
both gpio-regmap and regmap-irq in one operation.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Link: https://lore.kernel.org/r/20250824-mdb-max7360-support-v14-5-435cfda2b1ea@bootlin.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/gpio/gpio-regmap.c
include/linux/gpio/regmap.h

index e8a32dfebdcb31890e691f6739e8a76a02662202..e1944931ee7ccf5c3b47755dd72c06bb34892afd 100644 (file)
@@ -32,6 +32,11 @@ struct gpio_regmap {
        unsigned int reg_dir_in_base;
        unsigned int reg_dir_out_base;
 
+#ifdef CONFIG_REGMAP_IRQ
+       int regmap_irq_line;
+       struct regmap_irq_chip_data *irq_chip_data;
+#endif
+
        int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base,
                              unsigned int offset, unsigned int *reg,
                              unsigned int *mask);
@@ -215,6 +220,7 @@ EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata);
  */
 struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config)
 {
+       struct irq_domain *irq_domain;
        struct gpio_regmap *gpio;
        struct gpio_chip *chip;
        int ret;
@@ -295,8 +301,22 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
        if (ret < 0)
                goto err_free_gpio;
 
-       if (config->irq_domain) {
-               ret = gpiochip_irqchip_add_domain(chip, config->irq_domain);
+#ifdef CONFIG_REGMAP_IRQ
+       if (config->regmap_irq_chip) {
+               gpio->regmap_irq_line = config->regmap_irq_line;
+               ret = regmap_add_irq_chip_fwnode(dev_fwnode(config->parent), config->regmap,
+                                                config->regmap_irq_line, config->regmap_irq_flags,
+                                                0, config->regmap_irq_chip, &gpio->irq_chip_data);
+               if (ret)
+                       goto err_free_gpio;
+
+               irq_domain = regmap_irq_get_domain(gpio->irq_chip_data);
+       } else
+#endif
+       irq_domain = config->irq_domain;
+
+       if (irq_domain) {
+               ret = gpiochip_irqchip_add_domain(chip, irq_domain);
                if (ret)
                        goto err_remove_gpiochip;
        }
@@ -317,6 +337,11 @@ EXPORT_SYMBOL_GPL(gpio_regmap_register);
  */
 void gpio_regmap_unregister(struct gpio_regmap *gpio)
 {
+#ifdef CONFIG_REGMAP_IRQ
+       if (gpio->irq_chip_data)
+               regmap_del_irq_chip(gpio->regmap_irq_line, gpio->irq_chip_data);
+#endif
+
        gpiochip_remove(&gpio->gpio_chip);
        kfree(gpio);
 }
index c722c67668c6e557114bc8df9d7cfae0ca8e64bb..19b52ac03a5dec797490c02af26ef8e8d52598b1 100644 (file)
@@ -40,6 +40,11 @@ struct regmap;
  * @drvdata:           (Optional) Pointer to driver specific data which is
  *                     not used by gpio-remap but is provided "as is" to the
  *                     driver callback(s).
+ * @regmap_irq_chip:   (Optional) Pointer on an regmap_irq_chip structure. If
+ *                     set, a regmap-irq device will be created and the IRQ
+ *                     domain will be set accordingly.
+ * @regmap_irq_line    (Optional) The IRQ the device uses to signal interrupts.
+ * @regmap_irq_flags   (Optional) The IRQF_ flags to use for the interrupt.
  *
  * The ->reg_mask_xlate translates a given base address and GPIO offset to
  * register and mask pair. The base address is one of the given register
@@ -78,6 +83,12 @@ struct gpio_regmap_config {
        int ngpio_per_reg;
        struct irq_domain *irq_domain;
 
+#ifdef CONFIG_REGMAP_IRQ
+       struct regmap_irq_chip *regmap_irq_chip;
+       int regmap_irq_line;
+       unsigned long regmap_irq_flags;
+#endif
+
        int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base,
                              unsigned int offset, unsigned int *reg,
                              unsigned int *mask);