aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-altera.c
diff options
context:
space:
mode:
authorPhil Reid <preid@electromag.com.au>2017-02-19 20:41:45 -0500
committerLinus Walleij <linus.walleij@linaro.org>2017-03-06 08:35:22 -0500
commitf759921cfbf4847319d197a6ed7c9534d593f8bc (patch)
tree8ddcfd6b5da2781a2d320c4edbe82635bb6203fd /drivers/gpio/gpio-altera.c
parentb115bebc07f282067eccc06fd5aa3060ab1426da (diff)
gpio: altera: Use handle_level_irq when configured as a level_high
When a threaded irq handler is chained attached to one of the gpio pins when configure for level irq the altera_gpio_irq_leveL_high_handler does not mask the interrupt while being handled by the chained irq. This resulting in the threaded irq not getting enough cycles to complete quickly enough before the irq was disabled as faulty. handle_level_irq should be used in this situation instead of handle_simple_irq. In gpiochip_irqchip_add set default handler to handle_bad_irq as per Documentation/gpio/driver.txt. Then set the correct handler in the set_type callback. Signed-off-by: Phil Reid <preid@electromag.com.au> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-altera.c')
-rw-r--r--drivers/gpio/gpio-altera.c26
1 files changed, 11 insertions, 15 deletions
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 5bddbd507ca9..3fe6a21e05a5 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -90,21 +90,18 @@ static int altera_gpio_irq_set_type(struct irq_data *d,
90 90
91 altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); 91 altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
92 92
93 if (type == IRQ_TYPE_NONE) 93 if (type == IRQ_TYPE_NONE) {
94 irq_set_handler_locked(d, handle_bad_irq);
94 return 0; 95 return 0;
95 if (type == IRQ_TYPE_LEVEL_HIGH && 96 }
96 altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH) 97 if (type == altera_gc->interrupt_trigger) {
97 return 0; 98 if (type == IRQ_TYPE_LEVEL_HIGH)
98 if (type == IRQ_TYPE_EDGE_RISING && 99 irq_set_handler_locked(d, handle_level_irq);
99 altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_RISING) 100 else
100 return 0; 101 irq_set_handler_locked(d, handle_simple_irq);
101 if (type == IRQ_TYPE_EDGE_FALLING &&
102 altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_FALLING)
103 return 0;
104 if (type == IRQ_TYPE_EDGE_BOTH &&
105 altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_BOTH)
106 return 0; 102 return 0;
107 103 }
104 irq_set_handler_locked(d, handle_bad_irq);
108 return -EINVAL; 105 return -EINVAL;
109} 106}
110 107
@@ -230,7 +227,6 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
230 chained_irq_exit(chip, desc); 227 chained_irq_exit(chip, desc);
231} 228}
232 229
233
234static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc) 230static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
235{ 231{
236 struct altera_gpio_chip *altera_gc; 232 struct altera_gpio_chip *altera_gc;
@@ -310,7 +306,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
310 altera_gc->interrupt_trigger = reg; 306 altera_gc->interrupt_trigger = reg;
311 307
312 ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0, 308 ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0,
313 handle_simple_irq, IRQ_TYPE_NONE); 309 handle_bad_irq, IRQ_TYPE_NONE);
314 310
315 if (ret) { 311 if (ret) {
316 dev_err(&pdev->dev, "could not add irqchip\n"); 312 dev_err(&pdev->dev, "could not add irqchip\n");