gpio: max77620: Initialize hardware state of interrupts

I noticed on Nexus 7 that after rebooting from downstream kernel to
upstream, the GPIO interrupt is triggering non-stop despite interrupts
being disabled for all of GPIOs. This happens because Nexus 7 uses a
soft-reboot, meaning that bootloader should take care of resetting
hardware, but the bootloader doesn't do it well. As a result, GPIO
interrupt may be left ON at a boot time. Let's mask all GPIO interrupts
at the driver's initialization time in order to resolve the issue.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Laxman Dewangan <ldewangan@nvidia.com>
Link: https://lore.kernel.org/r/20200709171203.12950-7-digetx@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Dmitry Osipenko 2020-07-09 20:12:03 +03:00 committed by Linus Walleij
parent 15d9e7e847
commit e6827bc3fa

View File

@ -260,6 +260,30 @@ static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
return -ENOTSUPP; return -ENOTSUPP;
} }
static int max77620_gpio_irq_init_hw(struct gpio_chip *gc)
{
struct max77620_gpio *gpio = gpiochip_get_data(gc);
unsigned int i;
int err;
/*
* GPIO interrupts may be left ON after bootloader, hence let's
* pre-initialize hardware to the expected state by disabling all
* the interrupts.
*/
for (i = 0; i < MAX77620_GPIO_NR; i++) {
err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(i),
MAX77620_CNFG_GPIO_INT_MASK, 0);
if (err < 0) {
dev_err(gpio->dev,
"failed to disable interrupt: %d\n", err);
return err;
}
}
return 0;
}
static int max77620_gpio_probe(struct platform_device *pdev) static int max77620_gpio_probe(struct platform_device *pdev)
{ {
struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent); struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent);
@ -295,6 +319,7 @@ static int max77620_gpio_probe(struct platform_device *pdev)
mgpio->gpio_chip.irq.chip = &max77620_gpio_irqchip; mgpio->gpio_chip.irq.chip = &max77620_gpio_irqchip;
mgpio->gpio_chip.irq.default_type = IRQ_TYPE_NONE; mgpio->gpio_chip.irq.default_type = IRQ_TYPE_NONE;
mgpio->gpio_chip.irq.handler = handle_edge_irq; mgpio->gpio_chip.irq.handler = handle_edge_irq;
mgpio->gpio_chip.irq.init_hw = max77620_gpio_irq_init_hw,
mgpio->gpio_chip.irq.threaded = true; mgpio->gpio_chip.irq.threaded = true;
platform_set_drvdata(pdev, mgpio); platform_set_drvdata(pdev, mgpio);