diff options
Diffstat (limited to 'drivers/gpio/timbgpio.c')
-rw-r--r-- | drivers/gpio/timbgpio.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index ddd053108a13..0265872e57d1 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 | ||
52 | static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, | 53 | static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, |
@@ -108,26 +109,34 @@ static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) | |||
108 | /* | 109 | /* |
109 | * GPIO IRQ | 110 | * GPIO IRQ |
110 | */ | 111 | */ |
111 | static void timbgpio_irq_disable(unsigned irq) | 112 | static void timbgpio_irq_disable(struct irq_data *d) |
112 | { | 113 | { |
113 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 114 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); |
114 | int offset = irq - tgpio->irq_base; | 115 | int offset = d->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 | ||
119 | static void timbgpio_irq_enable(unsigned irq) | 124 | static void timbgpio_irq_enable(struct irq_data *d) |
120 | { | 125 | { |
121 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 126 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); |
122 | int offset = irq - tgpio->irq_base; | 127 | int offset = d->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 | ||
127 | static int timbgpio_irq_type(unsigned irq, unsigned trigger) | 136 | static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) |
128 | { | 137 | { |
129 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 138 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); |
130 | int offset = irq - tgpio->irq_base; | 139 | int offset = d->irq - tgpio->irq_base; |
131 | unsigned long flags; | 140 | unsigned long flags; |
132 | u32 lvr, flr, bflr = 0; | 141 | u32 lvr, flr, bflr = 0; |
133 | u32 ver; | 142 | u32 ver; |
@@ -186,23 +195,31 @@ out: | |||
186 | 195 | ||
187 | static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) | 196 | static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) |
188 | { | 197 | { |
189 | struct timbgpio *tgpio = get_irq_data(irq); | 198 | struct timbgpio *tgpio = irq_get_handler_data(irq); |
190 | unsigned long ipr; | 199 | unsigned long ipr; |
191 | int offset; | 200 | int offset; |
192 | 201 | ||
193 | desc->chip->ack(irq); | 202 | desc->irq_data.chip->irq_ack(irq_get_irq_data(irq)); |
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 | ||
201 | static struct irq_chip timbgpio_irqchip = { | 218 | static struct irq_chip timbgpio_irqchip = { |
202 | .name = "GPIO", | 219 | .name = "GPIO", |
203 | .enable = timbgpio_irq_enable, | 220 | .irq_enable = timbgpio_irq_enable, |
204 | .disable = timbgpio_irq_disable, | 221 | .irq_disable = timbgpio_irq_disable, |
205 | .set_type = timbgpio_irq_type, | 222 | .irq_set_type = timbgpio_irq_type, |
206 | }; | 223 | }; |
207 | 224 | ||
208 | static int __devinit timbgpio_probe(struct platform_device *pdev) | 225 | static int __devinit timbgpio_probe(struct platform_device *pdev) |
@@ -274,16 +291,16 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) | |||
274 | return 0; | 291 | return 0; |
275 | 292 | ||
276 | for (i = 0; i < pdata->nr_pins; i++) { | 293 | for (i = 0; i < pdata->nr_pins; i++) { |
277 | set_irq_chip_and_handler_name(tgpio->irq_base + i, | 294 | irq_set_chip_and_handler_name(tgpio->irq_base + i, |
278 | &timbgpio_irqchip, handle_simple_irq, "mux"); | 295 | &timbgpio_irqchip, handle_simple_irq, "mux"); |
279 | set_irq_chip_data(tgpio->irq_base + i, tgpio); | 296 | irq_set_chip_data(tgpio->irq_base + i, tgpio); |
280 | #ifdef CONFIG_ARM | 297 | #ifdef CONFIG_ARM |
281 | set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); | 298 | set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); |
282 | #endif | 299 | #endif |
283 | } | 300 | } |
284 | 301 | ||
285 | set_irq_data(irq, tgpio); | 302 | irq_set_handler_data(irq, tgpio); |
286 | set_irq_chained_handler(irq, timbgpio_irq); | 303 | irq_set_chained_handler(irq, timbgpio_irq); |
287 | 304 | ||
288 | return 0; | 305 | return 0; |
289 | 306 | ||
@@ -310,12 +327,12 @@ static int __devexit timbgpio_remove(struct platform_device *pdev) | |||
310 | if (irq >= 0 && tgpio->irq_base > 0) { | 327 | if (irq >= 0 && tgpio->irq_base > 0) { |
311 | int i; | 328 | int i; |
312 | for (i = 0; i < pdata->nr_pins; i++) { | 329 | for (i = 0; i < pdata->nr_pins; i++) { |
313 | set_irq_chip(tgpio->irq_base + i, NULL); | 330 | irq_set_chip(tgpio->irq_base + i, NULL); |
314 | set_irq_chip_data(tgpio->irq_base + i, NULL); | 331 | irq_set_chip_data(tgpio->irq_base + i, NULL); |
315 | } | 332 | } |
316 | 333 | ||
317 | set_irq_handler(irq, NULL); | 334 | irq_set_handler(irq, NULL); |
318 | set_irq_data(irq, NULL); | 335 | irq_set_handler_data(irq, NULL); |
319 | } | 336 | } |
320 | 337 | ||
321 | err = gpiochip_remove(&tgpio->gpio); | 338 | err = gpiochip_remove(&tgpio->gpio); |