All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pinctrl: armada-37xx: Add edge both type gpio irq support
@ 2017-10-19 13:10 ` Gregory CLEMENT
  0 siblings, 0 replies; 20+ messages in thread
From: Gregory CLEMENT @ 2017-10-19 13:10 UTC (permalink / raw)
  To: Linus Walleij, linux-gpio, linux-kernel
  Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
	Gregory CLEMENT, Thomas Petazzoni, linux-arm-kernel,
	Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
	Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits,
	Ken Ma

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

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

end of thread, other threads:[~2018-03-21  8:02 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-19 13:10 [PATCH] pinctrl: armada-37xx: Add edge both type gpio irq support Gregory CLEMENT
2017-10-19 13:10 ` Gregory CLEMENT
2017-10-19 13:38 ` Andrew Lunn
2017-10-19 13:38   ` Andrew Lunn
2017-10-27 12:57   ` Gregory CLEMENT
2017-10-27 12:57     ` Gregory CLEMENT
2017-10-27 19:39     ` Andrew Lunn
2017-10-27 19:39       ` Andrew Lunn
2017-10-31 12:07 ` Linus Walleij
2017-10-31 12:07   ` Linus Walleij
2017-10-31 13:16   ` Andrew Lunn
2017-10-31 13:16     ` Andrew Lunn
2017-10-31 13:27     ` Linus Walleij
2017-10-31 13:27       ` Linus Walleij
2018-03-20 21:56     ` Uwe Kleine-König
2018-03-20 21:56       ` Uwe Kleine-König
2018-03-20 21:56       ` Uwe Kleine-König
2018-03-21  8:02       ` Linus Walleij
2018-03-21  8:02         ` Linus Walleij
2018-03-21  8:02         ` Linus Walleij

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.