linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] regmap: irq: Add support to clear ack registers
       [not found] ` <65dd6c86415a3d8f565160ca0cd66f2c@codeaurora.org>
@ 2020-09-25 13:44   ` b_lkasam
  2020-09-27 12:23     ` Greg KH
  0 siblings, 1 reply; 3+ messages in thread
From: b_lkasam @ 2020-09-25 13:44 UTC (permalink / raw)
  To: broonie, gregkh, rafael; +Cc: linux-kernel, srinivas.kandagatla

[-- 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.


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] regmap: irq: Add support to clear ack registers
  2020-09-25 13:44   ` [PATCH] regmap: irq: Add support to clear ack registers b_lkasam
@ 2020-09-27 12:23     ` Greg KH
  2020-10-05 12:17       ` b_lkasam
  0 siblings, 1 reply; 3+ messages in thread
From: Greg KH @ 2020-09-27 12:23 UTC (permalink / raw)
  To: b_lkasam; +Cc: broonie, rafael, linux-kernel, srinivas.kandagatla

On Fri, Sep 25, 2020 at 07:14:01PM +0530, b_lkasam@codeaurora.org wrote:
> 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(-)

Patch is line-wrapped :(


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] regmap: irq: Add support to clear ack registers
  2020-09-27 12:23     ` Greg KH
@ 2020-10-05 12:17       ` b_lkasam
  0 siblings, 0 replies; 3+ messages in thread
From: b_lkasam @ 2020-10-05 12:17 UTC (permalink / raw)
  To: Greg KH; +Cc: broonie, rafael, linux-kernel, srinivas.kandagatla

On 2020-09-27 17:53, Greg KH wrote:
> On Fri, Sep 25, 2020 at 07:14:01PM +0530, b_lkasam@codeaurora.org 
> wrote:
>> 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(-)
> 
> Patch is line-wrapped :(
Will fix and send new v2 patch.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-10-05 12:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1601036740-23044-1-git-send-email-lkasam@codeaurora.org>
     [not found] ` <65dd6c86415a3d8f565160ca0cd66f2c@codeaurora.org>
2020-09-25 13:44   ` [PATCH] regmap: irq: Add support to clear ack registers b_lkasam
2020-09-27 12:23     ` Greg KH
2020-10-05 12:17       ` b_lkasam

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).