All of lore.kernel.org
 help / color / mirror / Atom feed
From: Claudiu <claudiu.beznea@tuxon.dev>
To: nobuhiro1.iwamatsu@toshiba.co.jp, pavel@denx.de
Cc: cip-dev@lists.cip-project.org, biju.das.jz@bp.renesas.com,
	prabhakar.mahadev-lad.rj@bp.renesas.com,
	claudiu.beznea@tuxon.dev
Subject: [PATCH 6.1.y-cip 12/13] irqchip/renesas-rzg2l: Prevent spurious interrupts when setting trigger type
Date: Wed, 27 Mar 2024 10:35:07 +0200	[thread overview]
Message-ID: <20240327083508.2229567-13-claudiu.beznea.uj@bp.renesas.com> (raw)
In-Reply-To: <20240327083508.2229567-1-claudiu.beznea.uj@bp.renesas.com>

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 853a6030303f8a8fa54929b68e5665d9b21aa405 upstream.

RZ/G2L interrupt chips require that the interrupt is masked before changing
the NMI, IRQ, TINT interrupt settings. Aside of that, after setting an edge
trigger type it is required to clear the interrupt status register in order
to avoid spurious interrupts.

The current implementation fails to do either of that and therefore is
prone to generate spurious interrupts when setting the trigger type.

Address this by:

  - Ensuring that the interrupt is masked at the chip level across the
    update for the TINT chip

  - Clearing the interrupt status register after updating the trigger mode
    for edge type interrupts

[ tglx: Massaged changelog and reverted the spin_lock_irqsave() change as
  	the set_type() callback is always called with interrupts disabled. ]

Fixes: 3fed09559cd8 ("irqchip: Add RZ/G2L IA55 Interrupt Controller driver")
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/irqchip/irq-renesas-rzg2l.c | 36 +++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index fb04e5450497..3acdecf39404 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -168,8 +168,10 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
 
 static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
 	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
+	unsigned int hwirq = irqd_to_hwirq(d);
+	u32 iitseln = hwirq - IRQC_IRQ_START;
+	bool clear_irq_int = false;
 	u16 sense, tmp;
 
 	switch (type & IRQ_TYPE_SENSE_MASK) {
@@ -179,14 +181,17 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
 
 	case IRQ_TYPE_EDGE_FALLING:
 		sense = IITSR_IITSEL_EDGE_FALLING;
+		clear_irq_int = true;
 		break;
 
 	case IRQ_TYPE_EDGE_RISING:
 		sense = IITSR_IITSEL_EDGE_RISING;
+		clear_irq_int = true;
 		break;
 
 	case IRQ_TYPE_EDGE_BOTH:
 		sense = IITSR_IITSEL_EDGE_BOTH;
+		clear_irq_int = true;
 		break;
 
 	default:
@@ -195,21 +200,40 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
 
 	raw_spin_lock(&priv->lock);
 	tmp = readl_relaxed(priv->base + IITSR);
-	tmp &= ~IITSR_IITSEL_MASK(hw_irq);
-	tmp |= IITSR_IITSEL(hw_irq, sense);
+	tmp &= ~IITSR_IITSEL_MASK(iitseln);
+	tmp |= IITSR_IITSEL(iitseln, sense);
+	if (clear_irq_int)
+		rzg2l_clear_irq_int(priv, hwirq);
 	writel_relaxed(tmp, priv->base + IITSR);
 	raw_spin_unlock(&priv->lock);
 
 	return 0;
 }
 
+static u32 rzg2l_disable_tint_and_set_tint_source(struct irq_data *d, struct rzg2l_irqc_priv *priv,
+						  u32 reg, u32 tssr_offset, u8 tssr_index)
+{
+	u32 tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d);
+	u32 tien = reg & (TIEN << TSSEL_SHIFT(tssr_offset));
+
+	/* Clear the relevant byte in reg */
+	reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset));
+	/* Set TINT and leave TIEN clear */
+	reg |= tint << TSSEL_SHIFT(tssr_offset);
+	writel_relaxed(reg, priv->base + TSSR(tssr_index));
+
+	return reg | tien;
+}
+
 static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
 {
 	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
 	unsigned int hwirq = irqd_to_hwirq(d);
 	u32 titseln = hwirq - IRQC_TINT_START;
+	u32 tssr_offset = TSSR_OFFSET(titseln);
+	u8 tssr_index = TSSR_INDEX(titseln);
 	u8 index, sense;
-	u32 reg;
+	u32 reg, tssr;
 
 	switch (type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -231,10 +255,14 @@ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
 	}
 
 	raw_spin_lock(&priv->lock);
+	tssr = readl_relaxed(priv->base + TSSR(tssr_index));
+	tssr = rzg2l_disable_tint_and_set_tint_source(d, priv, tssr, tssr_offset, tssr_index);
 	reg = readl_relaxed(priv->base + TITSR(index));
 	reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH));
 	reg |= sense << (titseln * TITSEL_WIDTH);
 	writel_relaxed(reg, priv->base + TITSR(index));
+	rzg2l_clear_tint_int(priv, hwirq);
+	writel_relaxed(tssr, priv->base + TSSR(tssr_index));
 	raw_spin_unlock(&priv->lock);
 
 	return 0;
-- 
2.39.2



  parent reply	other threads:[~2024-03-27 10:37 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-27  8:34 [PATCH 6.1.y-cip 00/13] Update IA55 driver Claudiu
2024-03-27  8:34 ` [PATCH 6.1.y-cip 01/13] pinctrl: renesas: rzg2l: Use devm_clk_get_enabled() helper Claudiu
2024-03-27  8:34 ` [PATCH 6.1.y-cip 02/13] irqchip: remove MODULE_LICENSE in non-modules Claudiu
2024-03-27  8:34 ` [PATCH 6.1.y-cip 03/13] irqchip/renesas-rzg2l: Convert to irq_data_get_irq_chip_data() Claudiu
2024-03-27  8:34 ` [PATCH 6.1.y-cip 04/13] irqchip/renesas-rzg2l: Use tabs instead of spaces Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 05/13] irqchip/renesas-rzg2l: Align struct member names to tabs Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 06/13] irqchip/renesas-rzg2l: Document structure members Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 07/13] irqchip/renesas-rzg2l: Implement restriction when writing ISCR register Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 08/13] irqchip/renesas-rzg2l: Add macro to retrieve TITSR register offset based on register's index Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 09/13] irqchip/renesas-rzg2l: Flush posted write in irq_eoi() Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 10/13] irqchip/renesas-rzg2l: Rename rzg2l_tint_eoi() Claudiu
2024-03-27  8:35 ` [PATCH 6.1.y-cip 11/13] irqchip/renesas-rzg2l: Rename rzg2l_irq_eoi() Claudiu
2024-03-27  8:35 ` Claudiu [this message]
2024-03-27  8:35 ` [PATCH 6.1.y-cip 13/13] irqchip/renesas-rzg2l: Do not set TIEN and TINT source at the same time Claudiu
2024-03-27 11:53 ` [PATCH 6.1.y-cip 00/13] Update IA55 driver Pavel Machek
2024-03-28 10:44 ` Pavel Machek

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=20240327083508.2229567-13-claudiu.beznea.uj@bp.renesas.com \
    --to=claudiu.beznea@tuxon.dev \
    --cc=biju.das.jz@bp.renesas.com \
    --cc=cip-dev@lists.cip-project.org \
    --cc=nobuhiro1.iwamatsu@toshiba.co.jp \
    --cc=pavel@denx.de \
    --cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.