summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMichael Grzeschik <m.grzeschik@pengutronix.de>2017-06-23 15:35:09 +0300
committerMark Brown <broonie@kernel.org>2017-06-28 22:11:07 +0300
commita71411dbf6c82ba2eb2519717c04ffb19bc4dda5 (patch)
treeb2c38d143a0a48f15f0527abacc89d0ffe2a7b86 /drivers
parent63c73b059cbbd96d5161ebe34c533136b4639d26 (diff)
downloadlinux-a71411dbf6c82ba2eb2519717c04ffb19bc4dda5.tar.xz
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 <m.grzeschik@pengutronix.de> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/regmap/regmap-irq.c40
1 files changed, 25 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,