linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lars-Peter Clausen <lars@metafoo.de>
To: Linus Walleij <linus.walleij@linaro.org>,
	Alexandre Courbot <gnurou@gmail.com>
Cc: Michal Simek <michal.simek@xilinx.com>,
	Harini Katakam <harini.katakam@xilinx.com>,
	linux-gpio@vger.kernel.org, Lars-Peter Clausen <lars@metafoo.de>
Subject: [PATCH 2/3] gpio: zynq: Clear pending interrupt when enabling a IRQ
Date: Fri, 18 Jul 2014 11:52:12 +0200	[thread overview]
Message-ID: <1405677133-8706-2-git-send-email-lars@metafoo.de> (raw)
In-Reply-To: <1405677133-8706-1-git-send-email-lars@metafoo.de>

The Zynq GPIO controller does not disable the interrupt detection when the
interrupt is masked and only disables the propagation of the interrupt. This
means when the controller detects an interrupt condition while the interrupt is
logically disabled (and masked) it will propagate the recorded interrupt event
once the interrupt is enabled. This will cause the interrupt consumer to see
spurious interrupts to prevent this first make sure that the interrupt is not
asserted and then enable it.

E.g. when a interrupt is requested with request_irq() it will be configured
according to the requested type (edge/level triggered, etc.) after that it will
be enabled. But the detection circuit might have already registered a false
interrupt before the interrupt type was correctly configured and once the
interrupt is unmasked this false interrupt will be propagated and the interrupt
handler for the just request interrupt will called.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/gpio/gpio-zynq.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 8e6a32f..fa3ad23 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -324,6 +324,48 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
 }
 
 /**
+ * zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
+ * @irq_data:	irq data containing irq number of gpio pin for the interrupt
+ *		to ack
+ *
+ * This function calculates gpio pin number from irq number and sets the bit
+ * in the Interrupt Status Register of the corresponding bank, to ACK the irq.
+ */
+static void zynq_gpio_irq_ack(struct irq_data *irq_data)
+{
+	unsigned int device_pin_num, bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+	device_pin_num = irq_data->hwirq;
+	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+	writel_relaxed(BIT(bank_pin_num),
+		       gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
+ * @irq_data:	irq data containing irq number of gpio pin for the interrupt
+ *		to enable
+ *
+ * Clears the INTSTS bit and unmasks the given interrrupt.
+ */
+static void zynq_gpio_irq_enable(struct irq_data *irq_data)
+{
+	/*
+	 * The Zynq GPIO controller does not disable interrupt detection when
+	 * the interrupt is masked and only disables the propagation of the
+	 * interrupt. This means when the controller detects an interrupt
+	 * condition while the interrupt is logically disabled it will propagate
+	 * that interrupt event once the interrupt is enabled. This will cause
+	 * the interrupt consumer to see spurious interrupts to prevent this
+	 * first make sure that the interrupt is not asserted and then enable
+	 * it.
+	 */
+	zynq_gpio_irq_ack(irq_data);
+	zynq_gpio_irq_unmask(irq_data);
+}
+
+/**
  * zynq_gpio_set_irq_type - Set the irq type for a gpio pin
  * @irq_data:	irq data containing irq number of gpio pin
  * @type:	interrupt type that is to be set for the gpio pin
@@ -407,6 +449,7 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
 /* irq chip descriptor */
 static struct irq_chip zynq_gpio_irqchip = {
 	.name		= DRIVER_NAME,
+	.irq_enable	= zynq_gpio_irq_enable,
 	.irq_mask	= zynq_gpio_irq_mask,
 	.irq_unmask	= zynq_gpio_irq_unmask,
 	.irq_set_type	= zynq_gpio_set_irq_type,
-- 
1.8.0


  reply	other threads:[~2014-07-18  9:52 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-18  9:52 [PATCH 1/3] gpio: zynq: Take bank offset into account when reporting a IRQ Lars-Peter Clausen
2014-07-18  9:52 ` Lars-Peter Clausen [this message]
2014-07-23 14:31   ` [PATCH 2/3] gpio: zynq: Clear pending interrupt when enabling " Linus Walleij
2014-07-23 17:42     ` Sören Brinkmann
2014-07-24  0:08       ` Alexandre Courbot
2014-07-24  7:36       ` Harini Katakam
2014-07-18  9:52 ` [PATCH 3/3] gpio: zynq: Fix IRQ handlers Lars-Peter Clausen
2014-07-18  9:58   ` Varka Bhadram
2014-07-23 14:36   ` Linus Walleij
2014-07-31 16:19     ` Sören Brinkmann
2014-08-11  7:03   ` Linus Walleij
2014-07-19  4:14 ` [PATCH 1/3] gpio: zynq: Take bank offset into account when reporting a IRQ Alexandre Courbot
2014-07-23 14:22   ` Linus Walleij

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=1405677133-8706-2-git-send-email-lars@metafoo.de \
    --to=lars@metafoo.de \
    --cc=gnurou@gmail.com \
    --cc=harini.katakam@xilinx.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=michal.simek@xilinx.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 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).