gpio: tegra: use new gpio_lock_as_irq() API

Whenever an IRQ is claimed or freed, call gpio_lock_as_irq() or
gpio_unlock_as_irq() on the associated GPIO, to prevent that GPIO from
being configured in a manner incompatible with an interrupt.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Javier Martinez Canillas <javier@dowhile0.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Stephen Warren 2013-10-16 13:25:33 -06:00 committed by Linus Walleij
parent bd0bf46844
commit df231f280f

View File

@ -75,6 +75,7 @@ struct tegra_gpio_bank {
#endif #endif
}; };
static struct device *dev;
static struct irq_domain *irq_domain; static struct irq_domain *irq_domain;
static void __iomem *regs; static void __iomem *regs;
static u32 tegra_gpio_bank_count; static u32 tegra_gpio_bank_count;
@ -205,6 +206,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
int lvl_type; int lvl_type;
int val; int val;
unsigned long flags; unsigned long flags;
int ret;
switch (type & IRQ_TYPE_SENSE_MASK) { switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
@ -231,6 +233,12 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL; return -EINVAL;
} }
ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio);
if (ret) {
dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio);
return ret;
}
spin_lock_irqsave(&bank->lvl_lock[port], flags); spin_lock_irqsave(&bank->lvl_lock[port], flags);
val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
@ -251,6 +259,13 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return 0; return 0;
} }
static void tegra_gpio_irq_shutdown(struct irq_data *d)
{
int gpio = d->hwirq;
gpio_unlock_as_irq(&tegra_gpio_chip, gpio);
}
static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{ {
struct tegra_gpio_bank *bank; struct tegra_gpio_bank *bank;
@ -368,6 +383,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
.irq_mask = tegra_gpio_irq_mask, .irq_mask = tegra_gpio_irq_mask,
.irq_unmask = tegra_gpio_irq_unmask, .irq_unmask = tegra_gpio_irq_unmask,
.irq_set_type = tegra_gpio_irq_set_type, .irq_set_type = tegra_gpio_irq_set_type,
.irq_shutdown = tegra_gpio_irq_shutdown,
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
.irq_set_wake = tegra_gpio_irq_set_wake, .irq_set_wake = tegra_gpio_irq_set_wake,
#endif #endif
@ -413,6 +429,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
int i; int i;
int j; int j;
dev = &pdev->dev;
match = of_match_device(tegra_gpio_of_match, &pdev->dev); match = of_match_device(tegra_gpio_of_match, &pdev->dev);
if (!match) { if (!match) {
dev_err(&pdev->dev, "Error: No device match found\n"); dev_err(&pdev->dev, "Error: No device match found\n");