aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-07-18 05:52:12 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-07-23 10:29:14 -0400
commit190dc2e6844ad8a47838207cbe739c94d88d94cd (patch)
tree8d1533c42bec5070e0be972ac0674bb7d48a8efa
parent14c8a620ba436511b1347c592633befa49535176 (diff)
gpio: zynq: Clear pending interrupt when enabling a IRQ
The Zynq GPIO controller does not disable the interrupt detection when the interrupt is masked and only disables the propagation of the interrupt. This means when the controller detects an interrupt condition while the interrupt is logically disabled (and masked) it will propagate the recorded interrupt event once the interrupt is enabled. This will cause the interrupt consumer to see spurious interrupts to prevent this first make sure that the interrupt is not asserted and then enable it. E.g. when a interrupt is requested with request_irq() it will be configured according to the requested type (edge/level triggered, etc.) after that it will be enabled. But the detection circuit might have already registered a false interrupt before the interrupt type was correctly configured and once the interrupt is unmasked this false interrupt will be propagated and the interrupt handler for the just request interrupt will called. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpio-zynq.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index c0c53fdbf07d..c3145f91fda3 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -301,6 +301,48 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
301} 301}
302 302
303/** 303/**
304 * zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
305 * @irq_data: irq data containing irq number of gpio pin for the interrupt
306 * to ack
307 *
308 * This function calculates gpio pin number from irq number and sets the bit
309 * in the Interrupt Status Register of the corresponding bank, to ACK the irq.
310 */
311static void zynq_gpio_irq_ack(struct irq_data *irq_data)
312{
313 unsigned int device_pin_num, bank_num, bank_pin_num;
314 struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
315
316 device_pin_num = irq_data->hwirq;
317 zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
318 writel_relaxed(BIT(bank_pin_num),
319 gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
320}
321
322/**
323 * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
324 * @irq_data: irq data containing irq number of gpio pin for the interrupt
325 * to enable
326 *
327 * Clears the INTSTS bit and unmasks the given interrrupt.
328 */
329static void zynq_gpio_irq_enable(struct irq_data *irq_data)
330{
331 /*
332 * The Zynq GPIO controller does not disable interrupt detection when
333 * the interrupt is masked and only disables the propagation of the
334 * interrupt. This means when the controller detects an interrupt
335 * condition while the interrupt is logically disabled it will propagate
336 * that interrupt event once the interrupt is enabled. This will cause
337 * the interrupt consumer to see spurious interrupts to prevent this
338 * first make sure that the interrupt is not asserted and then enable
339 * it.
340 */
341 zynq_gpio_irq_ack(irq_data);
342 zynq_gpio_irq_unmask(irq_data);
343}
344
345/**
304 * zynq_gpio_set_irq_type - Set the irq type for a gpio pin 346 * zynq_gpio_set_irq_type - Set the irq type for a gpio pin
305 * @irq_data: irq data containing irq number of gpio pin 347 * @irq_data: irq data containing irq number of gpio pin
306 * @type: interrupt type that is to be set for the gpio pin 348 * @type: interrupt type that is to be set for the gpio pin
@@ -384,6 +426,7 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
384/* irq chip descriptor */ 426/* irq chip descriptor */
385static struct irq_chip zynq_gpio_irqchip = { 427static struct irq_chip zynq_gpio_irqchip = {
386 .name = DRIVER_NAME, 428 .name = DRIVER_NAME,
429 .irq_enable = zynq_gpio_irq_enable,
387 .irq_mask = zynq_gpio_irq_mask, 430 .irq_mask = zynq_gpio_irq_mask,
388 .irq_unmask = zynq_gpio_irq_unmask, 431 .irq_unmask = zynq_gpio_irq_unmask,
389 .irq_set_type = zynq_gpio_set_irq_type, 432 .irq_set_type = zynq_gpio_set_irq_type,