Unverified Commit 3a6f0fb7 authored by Laxminath Kasam's avatar Laxminath Kasam Committed by Mark Brown
Browse files

regmap: irq: Add support to clear ack registers



For particular codec HWs have requirement to toggle interrupt clear
register twice 0->1->0. To accommodate it, need to add one more field
(clear_ack) in the regmap_irq struct and update regmap-irq driver to
support it.

Signed-off-by: default avatarLaxminath Kasam <lkasam@codeaurora.org>
Link: https://lore.kernel.org/r/1601907440-13373-1-git-send-email-lkasam@codeaurora.org


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d05199af
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -168,6 +168,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
				ret = regmap_write(map, reg, ~d->mask_buf[i]);
			else
				ret = regmap_write(map, reg, d->mask_buf[i]);
			if (d->chip->clear_ack) {
				if (d->chip->ack_invert && !ret)
					ret = regmap_write(map, reg,
							   d->mask_buf[i]);
				else if (!ret)
					ret = regmap_write(map, reg,
							   ~d->mask_buf[i]);
			}
			if (ret != 0)
				dev_err(d->map->dev, "Failed to ack 0x%x: %d\n",
					reg, ret);
@@ -493,7 +501,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
		if (data->status_buf[i] && (chip->ack_base || chip->use_ack)) {
			reg = chip->ack_base +
				(i * map->reg_stride * data->irq_reg_stride);
			ret = regmap_write(map, reg, data->status_buf[i]);
			if (chip->ack_invert)
				ret = regmap_write(map, reg,
						~data->status_buf[i]);
			else
				ret = regmap_write(map, reg,
						data->status_buf[i]);
			if (chip->clear_ack) {
				if (chip->ack_invert && !ret)
					ret = regmap_write(map, reg,
							data->status_buf[i]);
				else if (!ret)
					ret = regmap_write(map, reg,
							~data->status_buf[i]);
			}
			if (ret != 0)
				dev_err(map->dev, "Failed to ack 0x%x: %d\n",
					reg, ret);
@@ -722,6 +743,16 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
			else
				ret = regmap_write(map, reg,
					d->status_buf[i] & d->mask_buf[i]);
			if (chip->clear_ack) {
				if (chip->ack_invert && !ret)
					ret = regmap_write(map, reg,
						(d->status_buf[i] &
						 d->mask_buf[i]));
				else if (!ret)
					ret = regmap_write(map, reg,
						~(d->status_buf[i] &
						  d->mask_buf[i]));
			}
			if (ret != 0) {
				dev_err(map->dev, "Failed to ack 0x%x: %d\n",
					reg, ret);
+2 −0
Original line number Diff line number Diff line
@@ -1355,6 +1355,7 @@ struct regmap_irq_sub_irq_map {
 * @mask_invert: Inverted mask register: cleared bits are masked out.
 * @use_ack:     Use @ack register even if it is zero.
 * @ack_invert:  Inverted ack register: cleared bits for ack.
 * @clear_ack:  Use this to set 1 and 0 or vice-versa to clear interrupts.
 * @wake_invert: Inverted wake register: cleared bits are wake enabled.
 * @type_invert: Invert the type flags.
 * @type_in_mask: Use the mask registers for controlling irq type. For
@@ -1403,6 +1404,7 @@ struct regmap_irq_chip {
	bool mask_invert:1;
	bool use_ack:1;
	bool ack_invert:1;
	bool clear_ack:1;
	bool wake_invert:1;
	bool runtime_pm:1;
	bool type_invert:1;