regmap: irq: add an option to clear status registers on unmask
[linux-2.6-microblaze.git] / drivers / base / regmap / regmap-irq.c
index 31d23c9..1bd1145 100644 (file)
@@ -44,6 +44,8 @@ struct regmap_irq_chip_data {
 
        unsigned int irq_reg_stride;
        unsigned int type_reg_stride;
+
+       bool clear_status:1;
 };
 
 static inline const
@@ -77,6 +79,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
        int i, ret;
        u32 reg;
        u32 unmask_offset;
+       u32 val;
 
        if (d->chip->runtime_pm) {
                ret = pm_runtime_get_sync(map->dev);
@@ -85,6 +88,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
                                ret);
        }
 
+       if (d->clear_status) {
+               for (i = 0; i < d->chip->num_regs; i++) {
+                       reg = d->chip->status_base +
+                               (i * map->reg_stride * d->irq_reg_stride);
+
+                       ret = regmap_read(map, reg, &val);
+                       if (ret)
+                               dev_err(d->map->dev,
+                                       "Failed to clear the interrupt status bits\n");
+               }
+
+               d->clear_status = false;
+       }
+
        /*
         * If there's been a change in the mask write it back to the
         * hardware.  We rely on the use of the regmap core cache to
@@ -217,6 +234,9 @@ static void regmap_irq_enable(struct irq_data *data)
        else
                mask = irq_data->mask;
 
+       if (d->chip->clear_on_unmask)
+               d->clear_status = true;
+
        d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask;
 }
 
@@ -474,6 +494,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        if (chip->num_regs <= 0)
                return -EINVAL;
 
+       if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack))
+               return -EINVAL;
+
        for (i = 0; i < chip->num_irqs; i++) {
                if (chip->irqs[i].reg_offset % map->reg_stride)
                        return -EINVAL;