lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <553eabe7ebfb94ac2e76323ef339634b@codeaurora.org>
Date:   Fri, 25 Sep 2020 19:14:01 +0530
From:   b_lkasam@...eaurora.org
To:     broonie@...nel.org, gregkh@...uxfoundation.org, rafael@...nel.org
Cc:     linux-kernel@...r.kernel.org, srinivas.kandagatla@...aro.org
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@...eaurora.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.
View attachment "0001-regmap-irq-Add-support-to-clear-ack-registers.patch" of type "text/x-diff" (4242 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ