Skip to content

Commit 30ac0d3

Browse files
makemarvelllinusw
authored andcommitted
pinctrl: armada-37xx: Add edge both type gpio irq support
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 <[email protected]> Signed-off-by: Gregory CLEMENT <[email protected]> Signed-off-by: Linus Walleij <[email protected]>
1 parent 0cc449f commit 30ac0d3

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

drivers/pinctrl/mvebu/pinctrl-armada-37xx.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,19 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
576576
case IRQ_TYPE_EDGE_FALLING:
577577
val |= (BIT(d->hwirq % GPIO_PER_REG));
578578
break;
579+
case IRQ_TYPE_EDGE_BOTH: {
580+
u32 in_val, in_reg = INPUT_VAL;
581+
582+
armada_37xx_irq_update_reg(&in_reg, d);
583+
regmap_read(info->regmap, in_reg, &in_val);
584+
585+
/* Set initial polarity based on current input level. */
586+
if (in_val & d->mask)
587+
val |= d->mask; /* falling */
588+
else
589+
val &= ~d->mask; /* rising */
590+
break;
591+
}
579592
default:
580593
spin_unlock_irqrestore(&info->irq_lock, flags);
581594
return -EINVAL;
@@ -586,6 +599,40 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
586599
return 0;
587600
}
588601

602+
static int armada_37xx_edge_both_irq_swap_pol(struct armada_37xx_pinctrl *info,
603+
u32 pin_idx)
604+
{
605+
u32 reg_idx = pin_idx / GPIO_PER_REG;
606+
u32 bit_num = pin_idx % GPIO_PER_REG;
607+
u32 p, l, ret;
608+
unsigned long flags;
609+
610+
regmap_read(info->regmap, INPUT_VAL + 4*reg_idx, &l);
611+
612+
spin_lock_irqsave(&info->irq_lock, flags);
613+
p = readl(info->base + IRQ_POL + 4 * reg_idx);
614+
if ((p ^ l) & (1 << bit_num)) {
615+
/*
616+
* For the gpios which are used for both-edge irqs, when their
617+
* interrupts happen, their input levels are changed,
618+
* yet their interrupt polarities are kept in old values, we
619+
* should synchronize their interrupt polarities; for example,
620+
* at first a gpio's input level is low and its interrupt
621+
* polarity control is "Detect rising edge", then the gpio has
622+
* a interrupt , its level turns to high, we should change its
623+
* polarity control to "Detect falling edge" correspondingly.
624+
*/
625+
p ^= 1 << bit_num;
626+
writel(p, info->base + IRQ_POL + 4 * reg_idx);
627+
ret = 0;
628+
} else {
629+
/* Spurious irq */
630+
ret = -1;
631+
}
632+
633+
spin_unlock_irqrestore(&info->irq_lock, flags);
634+
return ret;
635+
}
589636

590637
static void armada_37xx_irq_handler(struct irq_desc *desc)
591638
{
@@ -609,6 +656,23 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
609656
u32 hwirq = ffs(status) - 1;
610657
u32 virq = irq_find_mapping(d, hwirq +
611658
i * GPIO_PER_REG);
659+
u32 t = irq_get_trigger_type(virq);
660+
661+
if ((t & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
662+
/* Swap polarity (race with GPIO line) */
663+
if (armada_37xx_edge_both_irq_swap_pol(info,
664+
hwirq + i * GPIO_PER_REG)) {
665+
/*
666+
* For spurious irq, which gpio level
667+
* is not as expected after incoming
668+
* edge, just ack the gpio irq.
669+
*/
670+
writel(1 << hwirq,
671+
info->base +
672+
IRQ_STATUS + 4 * i);
673+
continue;
674+
}
675+
}
612676

613677
generic_handle_irq(virq);
614678

0 commit comments

Comments
 (0)