From ac53ca3de6c5c352b9089355439b6d878c50e155 Mon Sep 17 00:00:00 2001 From: Tomas Hallenberg Date: Wed, 27 Oct 2010 15:33:17 -0700 Subject: [PATCH] --- yaml --- r: 218506 b: refs/heads/master c: 76d800a5b6e198c4fda07b88bb42a545709f193b h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/gpio/timbgpio.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index e6fe0153ea74..7cf1db43b968 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 09cd9527d621640d4dd231dff77b681e711d8e4b +refs/heads/master: 76d800a5b6e198c4fda07b88bb42a545709f193b diff --git a/trunk/drivers/gpio/timbgpio.c b/trunk/drivers/gpio/timbgpio.c index ddd053108a13..45293662e950 100644 --- a/trunk/drivers/gpio/timbgpio.c +++ b/trunk/drivers/gpio/timbgpio.c @@ -47,6 +47,7 @@ struct timbgpio { spinlock_t lock; /* mutual exclusion */ struct gpio_chip gpio; int irq_base; + unsigned long last_ier; }; static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, @@ -112,16 +113,24 @@ static void timbgpio_irq_disable(unsigned irq) { struct timbgpio *tgpio = get_irq_chip_data(irq); int offset = irq - tgpio->irq_base; + unsigned long flags; - timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 0); + spin_lock_irqsave(&tgpio->lock, flags); + tgpio->last_ier &= ~(1 << offset); + iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); + spin_unlock_irqrestore(&tgpio->lock, flags); } static void timbgpio_irq_enable(unsigned irq) { struct timbgpio *tgpio = get_irq_chip_data(irq); int offset = irq - tgpio->irq_base; + unsigned long flags; - timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 1); + spin_lock_irqsave(&tgpio->lock, flags); + tgpio->last_ier |= 1 << offset; + iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); + spin_unlock_irqrestore(&tgpio->lock, flags); } static int timbgpio_irq_type(unsigned irq, unsigned trigger) @@ -194,8 +203,16 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) ipr = ioread32(tgpio->membase + TGPIO_IPR); iowrite32(ipr, tgpio->membase + TGPIO_ICR); + /* + * Some versions of the hardware trash the IER register if more than + * one interrupt is received simultaneously. + */ + iowrite32(0, tgpio->membase + TGPIO_IER); + for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); + + iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); } static struct irq_chip timbgpio_irqchip = {