aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/timbgpio.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/gpio/timbgpio.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/gpio/timbgpio.c')
-rw-r--r--drivers/gpio/timbgpio.c65
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
52static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, 53static 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 */
111static void timbgpio_irq_disable(unsigned irq) 112static 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
119static void timbgpio_irq_enable(unsigned irq) 124static 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
127static int timbgpio_irq_type(unsigned irq, unsigned trigger) 136static 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
187static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) 196static 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
201static struct irq_chip timbgpio_irqchip = { 218static 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
208static int __devinit timbgpio_probe(struct platform_device *pdev) 225static 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);