From: Gregory CLEMENT <gregory.clement@free-electrons.com>
To: Linus Walleij <linus.walleij@linaro.org>,
linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: "Jason Cooper" <jason@lakedaemon.net>,
"Andrew Lunn" <andrew@lunn.ch>,
"Sebastian Hesselbarth" <sebastian.hesselbarth@gmail.com>,
"Gregory CLEMENT" <gregory.clement@free-electrons.com>,
"Thomas Petazzoni" <thomas.petazzoni@free-electrons.com>,
linux-arm-kernel@lists.infradead.org,
"Antoine Tenart" <antoine.tenart@free-electrons.com>,
"Miquèl Raynal" <miquel.raynal@free-electrons.com>,
"Nadav Haklai" <nadavh@marvell.com>,
"Victor Gu" <xigu@marvell.com>, "Marcin Wojtas" <mw@semihalf.com>,
"Wilson Ding" <dingwei@marvell.com>,
"Hua Jing" <jinghua@marvell.com>,
"Neta Zur Hershkovits" <neta@marvell.com>,
"Ken Ma" <make@marvell.com>
Subject: [PATCH] pinctrl: armada-37xx: Add edge both type gpio irq support
Date: Thu, 19 Oct 2017 15:10:03 +0200 [thread overview]
Message-ID: <20171019131003.9684-1-gregory.clement@free-electrons.com> (raw)
From: Ken Ma <make@marvell.com>
Current edge both type gpio irqs which need to swap polarity in each
interrupt are not supported, this patch adds edge both type gpio irq
support.
Signed-off-by: Ken Ma <make@marvell.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 64 +++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 71b944748304..4e8d836a8c6f 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -576,6 +576,19 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
case IRQ_TYPE_EDGE_FALLING:
val |= (BIT(d->hwirq % GPIO_PER_REG));
break;
+ case IRQ_TYPE_EDGE_BOTH: {
+ u32 in_val, in_reg = INPUT_VAL;
+
+ armada_37xx_irq_update_reg(&in_reg, d);
+ regmap_read(info->regmap, in_reg, &in_val);
+
+ /* Set initial polarity based on current input level. */
+ if (in_val & d->mask)
+ val |= d->mask; /* falling */
+ else
+ val &= ~d->mask; /* rising */
+ break;
+ }
default:
spin_unlock_irqrestore(&info->irq_lock, flags);
return -EINVAL;
@@ -586,6 +599,40 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
return 0;
}
+static int armada_37xx_edge_both_irq_swap_pol(struct armada_37xx_pinctrl *info,
+ u32 pin_idx)
+{
+ u32 reg_idx = pin_idx / GPIO_PER_REG;
+ u32 bit_num = pin_idx % GPIO_PER_REG;
+ u32 p, l, ret;
+ unsigned long flags;
+
+ regmap_read(info->regmap, INPUT_VAL + 4*reg_idx, &l);
+
+ spin_lock_irqsave(&info->irq_lock, flags);
+ p = readl(info->base + IRQ_POL + 4 * reg_idx);
+ if ((p ^ l) & (1 << bit_num)) {
+ /*
+ * For the gpios which are used for both-edge irqs, when their
+ * interrupts happen, their input levels are changed,
+ * yet their interrupt polarities are kept in old values, we
+ * should synchronize their interrupt polarities; for example,
+ * at first a gpio's input level is low and its interrupt
+ * polarity control is "Detect rising edge", then the gpio has
+ * a interrupt , its level turns to high, we should change its
+ * polarity control to "Detect falling edge" correspondingly.
+ */
+ p ^= 1 << bit_num;
+ writel(p, info->base + IRQ_POL + 4 * reg_idx);
+ ret = 0;
+ } else {
+ /* Spurious irq */
+ ret = -1;
+ }
+
+ spin_unlock_irqrestore(&info->irq_lock, flags);
+ return ret;
+}
static void armada_37xx_irq_handler(struct irq_desc *desc)
{
@@ -609,6 +656,23 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
u32 hwirq = ffs(status) - 1;
u32 virq = irq_find_mapping(d, hwirq +
i * GPIO_PER_REG);
+ u32 t = irq_get_trigger_type(virq);
+
+ if ((t & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ /* Swap polarity (race with GPIO line) */
+ if (armada_37xx_edge_both_irq_swap_pol(info,
+ hwirq + i * GPIO_PER_REG)) {
+ /*
+ * For spurious irq, which gpio level
+ * is not as expected after incoming
+ * edge, just ack the gpio irq.
+ */
+ writel(1 << hwirq,
+ info->base +
+ IRQ_STATUS + 4 * i);
+ continue;
+ }
+ }
generic_handle_irq(virq);
--
2.14.2
next reply other threads:[~2017-10-19 13:10 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-19 13:10 Gregory CLEMENT [this message]
2017-10-19 13:38 ` [PATCH] pinctrl: armada-37xx: Add edge both type gpio irq support Andrew Lunn
2017-10-27 12:57 ` Gregory CLEMENT
2017-10-27 19:39 ` Andrew Lunn
2017-10-31 12:07 ` Linus Walleij
2017-10-31 13:16 ` Andrew Lunn
2017-10-31 13:27 ` Linus Walleij
2018-03-20 21:56 ` Uwe Kleine-König
2018-03-21 8:02 ` 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=20171019131003.9684-1-gregory.clement@free-electrons.com \
--to=gregory.clement@free-electrons.com \
--cc=andrew@lunn.ch \
--cc=antoine.tenart@free-electrons.com \
--cc=dingwei@marvell.com \
--cc=jason@lakedaemon.net \
--cc=jinghua@marvell.com \
--cc=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=make@marvell.com \
--cc=miquel.raynal@free-electrons.com \
--cc=mw@semihalf.com \
--cc=nadavh@marvell.com \
--cc=neta@marvell.com \
--cc=sebastian.hesselbarth@gmail.com \
--cc=thomas.petazzoni@free-electrons.com \
--cc=xigu@marvell.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).