The patch regmap: irq: add chip option mask_writeonly
has been applied to the regmap tree at git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From a71411dbf6c82ba2eb2519717c04ffb19bc4dda5 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik <[email protected]> Date: Fri, 23 Jun 2017 14:35:09 +0200 Subject: [PATCH] regmap: irq: add chip option mask_writeonly Some irq controllers have writeonly/multipurpose register layouts. In those cases we read invalid data back. Here we add the option mask_writeonly as masking option. Signed-off-by: Michael Grzeschik <[email protected]> Signed-off-by: Mark Brown <[email protected]> --- drivers/base/regmap/regmap-irq.c | 40 +++++++++++++++++++++++++--------------- include/linux/regmap.h | 2 ++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index c4a1eadb093f..429ca8ed7e51 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -60,6 +60,16 @@ static void regmap_irq_lock(struct irq_data *data) mutex_lock(&d->lock); } +static int regmap_irq_update_bits(struct regmap_irq_chip_data *d, + unsigned int reg, unsigned int mask, + unsigned int val) +{ + if (d->chip->mask_writeonly) + return regmap_write_bits(d->map, reg, mask, val); + else + return regmap_update_bits(d->map, reg, mask, val); +} + static void regmap_irq_sync_unlock(struct irq_data *data) { struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); @@ -84,11 +94,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data) reg = d->chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); if (d->chip->mask_invert) { - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], ~d->mask_buf[i]); } else if (d->chip->unmask_base) { /* set mask with mask_base register */ - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], ~d->mask_buf[i]); if (ret < 0) dev_err(d->map->dev, @@ -97,12 +107,12 @@ static void regmap_irq_sync_unlock(struct irq_data *data) unmask_offset = d->chip->unmask_base - d->chip->mask_base; /* clear mask with unmask_base register */ - ret = regmap_update_bits(d->map, + ret = regmap_irq_update_bits(d, reg + unmask_offset, d->mask_buf_def[i], d->mask_buf[i]); } else { - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], d->mask_buf[i]); } if (ret != 0) @@ -113,11 +123,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data) (i * map->reg_stride * d->irq_reg_stride); if (d->wake_buf) { if (d->chip->wake_invert) - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], ~d->wake_buf[i]); else - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], d->wake_buf[i]); if (ret != 0) @@ -153,10 +163,10 @@ static void regmap_irq_sync_unlock(struct irq_data *data) reg = d->chip->type_base + (i * map->reg_stride * d->type_reg_stride); if (d->chip->type_invert) - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], ~d->type_buf[i]); else - ret = regmap_update_bits(d->map, reg, + ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], d->type_buf[i]); if (ret != 0) dev_err(d->map->dev, "Failed to sync type in %x\n", @@ -519,17 +529,17 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, reg = chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); if (chip->mask_invert) - ret = regmap_update_bits(map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf[i], ~d->mask_buf[i]); else if (d->chip->unmask_base) { unmask_offset = d->chip->unmask_base - d->chip->mask_base; - ret = regmap_update_bits(d->map, + ret = regmap_irq_update_bits(d, reg + unmask_offset, d->mask_buf[i], d->mask_buf[i]); } else - ret = regmap_update_bits(map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf[i], d->mask_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", @@ -575,11 +585,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, (i * map->reg_stride * d->irq_reg_stride); if (chip->wake_invert) - ret = regmap_update_bits(map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], 0); else - ret = regmap_update_bits(map, reg, + ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], d->wake_buf[i]); if (ret != 0) { @@ -603,10 +613,10 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, reg = chip->type_base + (i * map->reg_stride * d->type_reg_stride); if (chip->type_invert) - ret = regmap_update_bits(map, reg, + ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], 0xFF); else - ret = regmap_update_bits(map, reg, + ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], 0x0); if (ret != 0) { dev_err(map->dev, diff --git a/include/linux/regmap.h b/include/linux/regmap.h index e88649225a60..400172b59f24 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -884,6 +884,7 @@ struct regmap_irq { * * @status_base: Base status register address. * @mask_base: Base mask register address. + * @mask_writeonly: Base mask register is write only. * @unmask_base: Base unmask register address. for chips who have * separate mask and unmask registers * @ack_base: Base ack address. If zero then the chip is clear on read. @@ -927,6 +928,7 @@ struct regmap_irq_chip { unsigned int wake_base; unsigned int type_base; unsigned int irq_reg_stride; + bool mask_writeonly:1; bool init_ack_masked:1; bool mask_invert:1; bool use_ack:1; -- 2.13.2

