aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Breathitt Gray <vilhelm.gray@gmail.com>2015-12-15 18:52:44 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-12-22 04:19:49 -0500
commit9ae482104cb99076e007ae15792a3194fc1eedd8 (patch)
tree3af186305493514f942f0bf66d073310d9ec463d
parentf3154a46b64ca74be258e1e00b36596499ab6159 (diff)
gpio: 104-idi-48: Clear pending interrupt once in IRQ handler
Performing a read operation on the IRQ Status register will clear the IRQ latch. Since a read operation on the IRQ Status register must be performed in the IRQ handler in order to determine if the IRQ was in fact generated by the device, the IRQ latch is consequently cleared by the IRQ handler. A spinlock is used to guarantee that each IRQ is serviced in the order it was received. Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
-rw-r--r--drivers/gpio/gpio-104-idi-48.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index b5c693409a58..296dbd4cadd9 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -36,6 +36,7 @@ MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number");
36 * struct idi_48_gpio - GPIO device private data structure 36 * struct idi_48_gpio - GPIO device private data structure
37 * @chip: instance of the gpio_chip 37 * @chip: instance of the gpio_chip
38 * @lock: synchronization lock to prevent I/O race conditions 38 * @lock: synchronization lock to prevent I/O race conditions
39 * @ack_lock: synchronization lock to prevent IRQ handler race conditions
39 * @irq_mask: input bits affected by interrupts 40 * @irq_mask: input bits affected by interrupts
40 * @base: base port address of the GPIO device 41 * @base: base port address of the GPIO device
41 * @extent: extent of port address region of the GPIO device 42 * @extent: extent of port address region of the GPIO device
@@ -45,6 +46,7 @@ MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number");
45struct idi_48_gpio { 46struct idi_48_gpio {
46 struct gpio_chip chip; 47 struct gpio_chip chip;
47 spinlock_t lock; 48 spinlock_t lock;
49 spinlock_t ack_lock;
48 unsigned char irq_mask[6]; 50 unsigned char irq_mask[6];
49 unsigned base; 51 unsigned base;
50 unsigned extent; 52 unsigned extent;
@@ -89,15 +91,6 @@ static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset)
89 91
90static void idi_48_irq_ack(struct irq_data *data) 92static void idi_48_irq_ack(struct irq_data *data)
91{ 93{
92 struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
93 struct idi_48_gpio *const idi48gpio = to_idi48gpio(chip);
94 unsigned long flags;
95
96 spin_lock_irqsave(&idi48gpio->lock, flags);
97
98 inb(idi48gpio->base + 7);
99
100 spin_unlock_irqrestore(&idi48gpio->lock, flags);
101} 94}
102 95
103static void idi_48_irq_mask(struct irq_data *data) 96static void idi_48_irq_mask(struct irq_data *data)
@@ -192,6 +185,8 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
192 unsigned long gpio; 185 unsigned long gpio;
193 struct gpio_chip *const chip = &idi48gpio->chip; 186 struct gpio_chip *const chip = &idi48gpio->chip;
194 187
188 spin_lock(&idi48gpio->ack_lock);
189
195 spin_lock(&idi48gpio->lock); 190 spin_lock(&idi48gpio->lock);
196 191
197 cos_status = inb(idi48gpio->base + 7); 192 cos_status = inb(idi48gpio->base + 7);
@@ -199,8 +194,10 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
199 spin_unlock(&idi48gpio->lock); 194 spin_unlock(&idi48gpio->lock);
200 195
201 /* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */ 196 /* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
202 if (cos_status & BIT(6)) 197 if (cos_status & BIT(6)) {
198 spin_unlock(&idi48gpio->ack_lock);
203 return IRQ_NONE; 199 return IRQ_NONE;
200 }
204 201
205 /* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */ 202 /* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */
206 cos_status &= 0x3F; 203 cos_status &= 0x3F;
@@ -216,6 +213,8 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
216 } 213 }
217 } 214 }
218 215
216 spin_unlock(&idi48gpio->ack_lock);
217
219 return IRQ_HANDLED; 218 return IRQ_HANDLED;
220} 219}
221 220