linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: b_lkasam@codeaurora.org
To: broonie@kernel.org, gregkh@linuxfoundation.org, rafael@kernel.org
Cc: linux-kernel@vger.kernel.org, srinivas.kandagatla@linaro.org
Subject: [PATCH] regmap: irq: Add support to clear ack registers
Date: Fri, 25 Sep 2020 19:14:01 +0530	[thread overview]
Message-ID: <553eabe7ebfb94ac2e76323ef339634b@codeaurora.org> (raw)
In-Reply-To: <65dd6c86415a3d8f565160ca0cd66f2c@codeaurora.org>

[-- Attachment #1: Type: text/plain, Size: 4065 bytes --]

For particular codec HWs have requirement to
writing interrupt clear and mask interrupt clear
register to toggle interrupt status. 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: Laxminath Kasam <lkasam@codeaurora.org>
---
  drivers/base/regmap/regmap-irq.c | 52 
++++++++++++++++++++++++++++++++++++----
  include/linux/regmap.h           |  2 ++
  2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/drivers/base/regmap/regmap-irq.c 
b/drivers/base/regmap/regmap-irq.c
index 369a57e..53a1557 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -164,10 +164,21 @@ static void regmap_irq_sync_unlock(struct irq_data 
*data)
  			reg = d->chip->ack_base +
  				(i * map->reg_stride * d->irq_reg_stride);
  			/* some chips ack by write 0 */
-			if (d->chip->ack_invert)
+			if (d->chip->ack_invert) {
  				ret = regmap_write(map, reg, ~d->mask_buf[i]);
-			else
+				if (d->chip->clear_ack) {
+					if (!ret)
+						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 (!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 +504,23 @@ 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]);
+				if (chip->clear_ack) {
+					if (!ret)
+						ret = regmap_write(map, reg,
+							data->status_buf[i]);
+				}
+			} else {
+				ret = regmap_write(map, reg,
+						data->status_buf[i]);
+				if (chip->clear_ack) {
+					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);
@@ -716,12 +743,27 @@ int regmap_add_irq_chip_fwnode(struct 
fwnode_handle *fwnode,
  		if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
  			reg = chip->ack_base +
  				(i * map->reg_stride * d->irq_reg_stride);
-			if (chip->ack_invert)
+			if (chip->ack_invert) {
  				ret = regmap_write(map, reg,
  					~(d->status_buf[i] & d->mask_buf[i]));
-			else
+				if (d->chip->clear_ack) {
+					if (!ret)
+						ret = regmap_write(
+							map, reg,
+							(d->status_buf[i] &
+							 d->mask_buf[i]);
+				}
+			} else {
  				ret = regmap_write(map, reg,
  					d->status_buf[i] & d->mask_buf[i]);
+				if (d->chip->clear_ack) {
+					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);
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 1970ed5..0701671 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1305,6 +1305,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
@@ -1353,6 +1354,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;
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, 
Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative 
Project.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-regmap-irq-Add-support-to-clear-ack-registers.patch --]
[-- Type: text/x-diff; name=0001-regmap-irq-Add-support-to-clear-ack-registers.patch, Size: 4242 bytes --]

From 708ddb8ff2e673ef332bcd594490744b9e472227 Mon Sep 17 00:00:00 2001
From: Laxminath Kasam <lkasam@codeaurora.org>
Date: Wed, 23 Sep 2020 18:42:36 +0530
Subject: [PATCH] regmap: irq: Add support to clear ack registers

For particular codec HWs have requirement to
writing interrupt clear and mask interrupt clear
register to toggle interrupt status. 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: Laxminath Kasam <lkasam@codeaurora.org>
---
 drivers/base/regmap/regmap-irq.c | 52 ++++++++++++++++++++++++++++++++++++----
 include/linux/regmap.h           |  2 ++
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 369a57e..53a1557 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -164,10 +164,21 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
 			reg = d->chip->ack_base +
 				(i * map->reg_stride * d->irq_reg_stride);
 			/* some chips ack by write 0 */
-			if (d->chip->ack_invert)
+			if (d->chip->ack_invert) {
 				ret = regmap_write(map, reg, ~d->mask_buf[i]);
-			else
+				if (d->chip->clear_ack) {
+					if (!ret)
+						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 (!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 +504,23 @@ 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]);
+				if (chip->clear_ack) {
+					if (!ret)
+						ret = regmap_write(map, reg,
+							data->status_buf[i]);
+				}
+			} else {
+				ret = regmap_write(map, reg,
+						data->status_buf[i]);
+				if (chip->clear_ack) {
+					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);
@@ -716,12 +743,27 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
 		if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
 			reg = chip->ack_base +
 				(i * map->reg_stride * d->irq_reg_stride);
-			if (chip->ack_invert)
+			if (chip->ack_invert) {
 				ret = regmap_write(map, reg,
 					~(d->status_buf[i] & d->mask_buf[i]));
-			else
+				if (d->chip->clear_ack) {
+					if (!ret)
+						ret = regmap_write(
+							map, reg,
+							(d->status_buf[i] &
+							 d->mask_buf[i]);
+				}
+			} else {
 				ret = regmap_write(map, reg,
 					d->status_buf[i] & d->mask_buf[i]);
+				if (d->chip->clear_ack) {
+					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);
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 1970ed5..0701671 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1305,6 +1305,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
@@ -1353,6 +1354,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;
-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.


       reply	other threads:[~2020-09-25 13:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1601036740-23044-1-git-send-email-lkasam@codeaurora.org>
     [not found] ` <65dd6c86415a3d8f565160ca0cd66f2c@codeaurora.org>
2020-09-25 13:44   ` b_lkasam [this message]
2020-09-27 12:23     ` [PATCH] regmap: irq: Add support to clear ack registers Greg KH
2020-10-05 12:17       ` b_lkasam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=553eabe7ebfb94ac2e76323ef339634b@codeaurora.org \
    --to=b_lkasam@codeaurora.org \
    --cc=broonie@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=srinivas.kandagatla@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).