aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/timbgpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/timbgpio.c')
-rw-r--r--drivers/gpio/timbgpio.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
index ddd053108a13..45293662e950 100644
--- a/drivers/gpio/timbgpio.c
+++ b/drivers/gpio/timbgpio.c
@@ -47,6 +47,7 @@ struct timbgpio {
47 spinlock_t lock; /* mutual exclusion */ 47 spinlock_t lock; /* mutual exclusion */
48 struct gpio_chip gpio; 48 struct gpio_chip gpio;
49 int irq_base; 49 int irq_base;
50 unsigned long last_ier;
50}; 51};
51 52
52static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, 53static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
@@ -112,16 +113,24 @@ static void timbgpio_irq_disable(unsigned irq)
112{ 113{
113 struct timbgpio *tgpio = get_irq_chip_data(irq); 114 struct timbgpio *tgpio = get_irq_chip_data(irq);
114 int offset = irq - tgpio->irq_base; 115 int offset = irq - tgpio->irq_base;
116 unsigned long flags;
115 117
116 timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 0); 118 spin_lock_irqsave(&tgpio->lock, flags);
119 tgpio->last_ier &= ~(1 << offset);
120 iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
121 spin_unlock_irqrestore(&tgpio->lock, flags);
117} 122}
118 123
119static void timbgpio_irq_enable(unsigned irq) 124static void timbgpio_irq_enable(unsigned irq)
120{ 125{
121 struct timbgpio *tgpio = get_irq_chip_data(irq); 126 struct timbgpio *tgpio = get_irq_chip_data(irq);
122 int offset = irq - tgpio->irq_base; 127 int offset = irq - tgpio->irq_base;
128 unsigned long flags;
123 129
124 timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 1); 130 spin_lock_irqsave(&tgpio->lock, flags);
131 tgpio->last_ier |= 1 << offset;
132 iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
133 spin_unlock_irqrestore(&tgpio->lock, flags);
125} 134}
126 135
127static int timbgpio_irq_type(unsigned irq, unsigned trigger) 136static int timbgpio_irq_type(unsigned irq, unsigned trigger)
@@ -194,8 +203,16 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
194 ipr = ioread32(tgpio->membase + TGPIO_IPR); 203 ipr = ioread32(tgpio->membase + TGPIO_IPR);
195 iowrite32(ipr, tgpio->membase + TGPIO_ICR); 204 iowrite32(ipr, tgpio->membase + TGPIO_ICR);
196 205
206 /*
207 * Some versions of the hardware trash the IER register if more than
208 * one interrupt is received simultaneously.
209 */
210 iowrite32(0, tgpio->membase + TGPIO_IER);
211
197 for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) 212 for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
198 generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); 213 generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
214
215 iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
199} 216}
200 217
201static struct irq_chip timbgpio_irqchip = { 218static struct irq_chip timbgpio_irqchip = {