regmap-irq: Add no_status support
authorWilliam Breathitt Gray <william.gray@linaro.org>
Mon, 27 Feb 2023 16:45:22 +0000 (11:45 -0500)
committerMark Brown <broonie@kernel.org>
Sun, 5 Mar 2023 23:38:50 +0000 (23:38 +0000)
Some devices lack status registers, yet expect to handle interrupts.
Introduce a no_status flag to indicate such a configuration, where
rather than read a status register to verify, all interrupts received
are assumed to be active.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
Link: https://lore.kernel.org/r/bd501b4b5ff88da24d467f75e8c71b4e0e6f21e2.1677515341.git.william.gray@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/base/regmap/regmap-irq.c
include/linux/regmap.h

index 8c903b8c97146e3247c5bcf65bf18e24f6362dca..f4d544ee7c3044f72992e9c21979820db5e033ce 100644 (file)
@@ -433,7 +433,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
         * possible in order to reduce the I/O overheads.
         */
 
-       if (chip->num_main_regs) {
+       if (chip->no_status) {
+               /* no status register so default to all active */
+               memset32(data->status_buf, GENMASK(31, 0), chip->num_regs);
+       } else if (chip->num_main_regs) {
                unsigned int max_main_bits;
                unsigned long size;
 
@@ -949,12 +952,17 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
                        continue;
 
                /* Ack masked but set interrupts */
-               reg = d->get_irq_reg(d, d->chip->status_base, i);
-               ret = regmap_read(map, reg, &d->status_buf[i]);
-               if (ret != 0) {
-                       dev_err(map->dev, "Failed to read IRQ status: %d\n",
-                               ret);
-                       goto err_alloc;
+               if (d->chip->no_status) {
+                       /* no status register so default to all active */
+                       d->status_buf[i] = GENMASK(31, 0);
+               } else {
+                       reg = d->get_irq_reg(d, d->chip->status_base, i);
+                       ret = regmap_read(map, reg, &d->status_buf[i]);
+                       if (ret != 0) {
+                               dev_err(map->dev, "Failed to read IRQ status: %d\n",
+                                       ret);
+                               goto err_alloc;
+                       }
                }
 
                if (chip->status_invert)
index 4d10790adeb0a6644aa8270c41a0f57d0c10c12b..3012861496431b401fc0452ecbe160d445a7305d 100644 (file)
@@ -1567,6 +1567,7 @@ struct regmap_irq_chip_data;
  *                   the need for a @sub_reg_offsets table.
  * @status_invert: Inverted status register: cleared bits are active interrupts.
  * @runtime_pm:  Hold a runtime PM lock on the device when accessing it.
+ * @no_status: No status register: all interrupts assumed generated by device.
  *
  * @num_regs:    Number of registers in each control bank.
  * @irqs:        Descriptors for individual IRQs.  Interrupt numbers are
@@ -1631,6 +1632,7 @@ struct regmap_irq_chip {
        unsigned int clear_on_unmask:1;
        unsigned int not_fixed_stride:1;
        unsigned int status_invert:1;
+       unsigned int no_status:1;
 
        int num_regs;