diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-10-16 15:25:33 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-10-17 04:51:53 -0400 |
commit | df231f280f0051e8de05a1f31c13b2ce2a761c3f (patch) | |
tree | 55e3a4549b2a3a99ee7725faabe2d6b0cd581e4e /drivers/gpio | |
parent | bd0bf46844ad79c1360eebc73bf6f1e4c31b39fb (diff) |
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>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 9a62672f1bed..cfd3b9037bc7 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -75,6 +75,7 @@ struct tegra_gpio_bank { | |||
75 | #endif | 75 | #endif |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static struct device *dev; | ||
78 | static struct irq_domain *irq_domain; | 79 | static struct irq_domain *irq_domain; |
79 | static void __iomem *regs; | 80 | static void __iomem *regs; |
80 | static u32 tegra_gpio_bank_count; | 81 | static u32 tegra_gpio_bank_count; |
@@ -205,6 +206,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
205 | int lvl_type; | 206 | int lvl_type; |
206 | int val; | 207 | int val; |
207 | unsigned long flags; | 208 | unsigned long flags; |
209 | int ret; | ||
208 | 210 | ||
209 | switch (type & IRQ_TYPE_SENSE_MASK) { | 211 | switch (type & IRQ_TYPE_SENSE_MASK) { |
210 | case IRQ_TYPE_EDGE_RISING: | 212 | case IRQ_TYPE_EDGE_RISING: |
@@ -231,6 +233,12 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
231 | return -EINVAL; | 233 | return -EINVAL; |
232 | } | 234 | } |
233 | 235 | ||
236 | ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio); | ||
237 | if (ret) { | ||
238 | dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio); | ||
239 | return ret; | ||
240 | } | ||
241 | |||
234 | spin_lock_irqsave(&bank->lvl_lock[port], flags); | 242 | spin_lock_irqsave(&bank->lvl_lock[port], flags); |
235 | 243 | ||
236 | val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); | 244 | 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) | |||
251 | return 0; | 259 | return 0; |
252 | } | 260 | } |
253 | 261 | ||
262 | static void tegra_gpio_irq_shutdown(struct irq_data *d) | ||
263 | { | ||
264 | int gpio = d->hwirq; | ||
265 | |||
266 | gpio_unlock_as_irq(&tegra_gpio_chip, gpio); | ||
267 | } | ||
268 | |||
254 | static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 269 | static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) |
255 | { | 270 | { |
256 | struct tegra_gpio_bank *bank; | 271 | struct tegra_gpio_bank *bank; |
@@ -368,6 +383,7 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
368 | .irq_mask = tegra_gpio_irq_mask, | 383 | .irq_mask = tegra_gpio_irq_mask, |
369 | .irq_unmask = tegra_gpio_irq_unmask, | 384 | .irq_unmask = tegra_gpio_irq_unmask, |
370 | .irq_set_type = tegra_gpio_irq_set_type, | 385 | .irq_set_type = tegra_gpio_irq_set_type, |
386 | .irq_shutdown = tegra_gpio_irq_shutdown, | ||
371 | #ifdef CONFIG_PM_SLEEP | 387 | #ifdef CONFIG_PM_SLEEP |
372 | .irq_set_wake = tegra_gpio_irq_set_wake, | 388 | .irq_set_wake = tegra_gpio_irq_set_wake, |
373 | #endif | 389 | #endif |
@@ -413,6 +429,8 @@ static int tegra_gpio_probe(struct platform_device *pdev) | |||
413 | int i; | 429 | int i; |
414 | int j; | 430 | int j; |
415 | 431 | ||
432 | dev = &pdev->dev; | ||
433 | |||
416 | match = of_match_device(tegra_gpio_of_match, &pdev->dev); | 434 | match = of_match_device(tegra_gpio_of_match, &pdev->dev); |
417 | if (!match) { | 435 | if (!match) { |
418 | dev_err(&pdev->dev, "Error: No device match found\n"); | 436 | dev_err(&pdev->dev, "Error: No device match found\n"); |