Message ID | 1e14e042c84f0c0a5e7d25ae9986f88a9620965c.1675876659.git.william.gray@linaro.org |
---|---|
State | New |
Headers | show |
Series | Migrate IDIO-16 GPIO drivers to regmap API | expand |
On Wed, Feb 08, 2023 at 12:18:16PM -0500, William Breathitt Gray wrote: > 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. ... > + /* no status register so default to all active */ > + memset(data->status_buf, 0xFF, > + chip->num_regs * sizeof(*data->status_buf)); memset32()? As we know the sizeof()... ... > + /* no status register so default to all active */ > + d->status_buf[i] = -1; -1 for unsigned?! Can we simply use GENMASK() just plain value? ... > * @status_invert: Inverted status register: cleared bits are active interrupts. > + * @no_status: No status register: all interrupts assumed generated by device. > * @runtime_pm: Hold a runtime PM lock on the device when accessing it. > * > * @num_regs: Number of registers in each control bank. > @@ -1630,6 +1631,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; Seems a bit unordered, I have just sent a patch to fix ordering of the couple of fields and their respective kernel doc.
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index a8f185430a07..7abc42c5794d 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -437,7 +437,11 @@ 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 */ + memset(data->status_buf, 0xFF, + chip->num_regs * sizeof(*data->status_buf)); + } else if (chip->num_main_regs) { unsigned int max_main_bits; unsigned long size; @@ -967,12 +971,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] = -1; + } 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) diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a3bc695bcca0..12637c4d231e 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -1563,6 +1563,7 @@ struct regmap_irq_chip_data; * can be accomplished with a @get_irq_reg callback, without * the need for a @sub_reg_offsets table. * @status_invert: Inverted status register: cleared bits are active interrupts. + * @no_status: No status register: all interrupts assumed generated by device. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. @@ -1630,6 +1631,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;
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> --- drivers/base/regmap/regmap-irq.c | 23 ++++++++++++++++------- include/linux/regmap.h | 2 ++ 2 files changed, 18 insertions(+), 7 deletions(-)