Commit 7920af5c authored by Samuel Holland's avatar Samuel Holland Committed by Bartosz Golaszewski
Browse files

gpio: rockchip: Reset int_bothedge when changing trigger



With v2 hardware, an IRQ can be configured to trigger on both edges via
a bit in the int_bothedge register. Currently, the driver sets this bit
when changing the trigger type to IRQ_TYPE_EDGE_BOTH, but fails to reset
this bit if the trigger type is later changed to something else. This
causes spurious IRQs, and when using gpio-keys with wakeup-event-action
set to EV_ACT_(DE)ASSERTED, those IRQs translate into spurious wakeups.

Fixes: 3bcbd1a8 ("gpio/rockchip: support next version gpio controller")
Reported-by: default avatarGuillaume Savaton <guillaume@baierouge.fr>
Tested-by: default avatarGuillaume Savaton <guillaume@baierouge.fr>
Signed-off-by: default avatarSamuel Holland <samuel@sholland.org>
Signed-off-by: default avatarBartosz Golaszewski <brgl@bgdev.pl>
parent 754e0b0e
Loading
Loading
Loading
Loading
+29 −27
Original line number Diff line number Diff line
@@ -410,10 +410,8 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
	level = rockchip_gpio_readl(bank, bank->gpio_regs->int_type);
	polarity = rockchip_gpio_readl(bank, bank->gpio_regs->int_polarity);

	switch (type) {
	case IRQ_TYPE_EDGE_BOTH:
	if (type == IRQ_TYPE_EDGE_BOTH) {
		if (bank->gpio_type == GPIO_TYPE_V2) {
			bank->toggle_edge_mode &= ~mask;
			rockchip_gpio_writel_bit(bank, d->hwirq, 1,
						 bank->gpio_regs->int_bothedge);
			goto out;
@@ -431,24 +429,27 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
			else
				polarity |= mask;
		}
		break;
	case IRQ_TYPE_EDGE_RISING:
	} else {
		if (bank->gpio_type == GPIO_TYPE_V2) {
			rockchip_gpio_writel_bit(bank, d->hwirq, 0,
						 bank->gpio_regs->int_bothedge);
		} else {
			bank->toggle_edge_mode &= ~mask;
		}
		switch (type) {
		case IRQ_TYPE_EDGE_RISING:
			level |= mask;
			polarity |= mask;
			break;
		case IRQ_TYPE_EDGE_FALLING:
		bank->toggle_edge_mode &= ~mask;
			level |= mask;
			polarity &= ~mask;
			break;
		case IRQ_TYPE_LEVEL_HIGH:
		bank->toggle_edge_mode &= ~mask;
			level &= ~mask;
			polarity |= mask;
			break;
		case IRQ_TYPE_LEVEL_LOW:
		bank->toggle_edge_mode &= ~mask;
			level &= ~mask;
			polarity &= ~mask;
			break;
@@ -456,6 +457,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
			ret = -EINVAL;
			goto out;
		}
	}

	rockchip_gpio_writel(bank, level, bank->gpio_regs->int_type);
	rockchip_gpio_writel(bank, polarity, bank->gpio_regs->int_polarity);