aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <maz@misterjones.org>2010-03-05 16:44:36 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-06 14:26:48 -0500
commit89ea8bbe9c3eb2ea0cb57a4ecf283cab7326f0b0 (patch)
treef06f9594be6e64699ae3d8672d4868b81e25cfa7
parent8c35c89aa3d7e0f253c3a10456a8b075288b4565 (diff)
gpio: pca953x.c: add interrupt handling capability
Most of the GPIO expanders controlled by the pca953x driver are able to report changes on the input pins through an *INT pin. This patch implements the irq_chip functionality (edge detection only). The driver has been tested on an Arcom Zeus. [akpm@linux-foundation.org: the compiler does inlining for us nowadays] Signed-off-by: Marc Zyngier <maz@misterjones.org> Cc: Eric Miao <eric.y.miao@gmail.com> Cc: Haojian Zhuang <haojian.zhuang@gmail.com> Cc: David Brownell <david-b@pacbell.net> Cc: Nate Case <ncase@xes-inc.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/pca953x.c249
-rw-r--r--include/linux/i2c/pca953x.h3
3 files changed, 247 insertions, 12 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f3549b8779d8..c5cc7d9d88e3 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -134,6 +134,13 @@ config GPIO_PCA953X
134 This driver can also be built as a module. If so, the module 134 This driver can also be built as a module. If so, the module
135 will be called pca953x. 135 will be called pca953x.
136 136
137config GPIO_PCA953X_IRQ
138 bool "Interrupt controller support for PCA953x"
139 depends on GPIO_PCA953X=y
140 help
141 Say yes here to enable the pca953x to be used as an interrupt
142 controller. It requires the driver to be built in the kernel.
143
137config GPIO_PCF857X 144config GPIO_PCF857X
138 tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" 145 tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
139 depends on I2C 146 depends on I2C
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 6a2fb3fbb3d9..ab5daab14bc2 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -14,6 +14,8 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/interrupt.h>
18#include <linux/irq.h>
17#include <linux/i2c.h> 19#include <linux/i2c.h>
18#include <linux/i2c/pca953x.h> 20#include <linux/i2c/pca953x.h>
19#ifdef CONFIG_OF_GPIO 21#ifdef CONFIG_OF_GPIO
@@ -26,23 +28,28 @@
26#define PCA953X_INVERT 2 28#define PCA953X_INVERT 2
27#define PCA953X_DIRECTION 3 29#define PCA953X_DIRECTION 3
28 30
31#define PCA953X_GPIOS 0x00FF
32#define PCA953X_INT 0x0100
33
29static const struct i2c_device_id pca953x_id[] = { 34static const struct i2c_device_id pca953x_id[] = {
30 { "pca9534", 8, }, 35 { "pca9534", 8 | PCA953X_INT, },
31 { "pca9535", 16, }, 36 { "pca9535", 16 | PCA953X_INT, },
32 { "pca9536", 4, }, 37 { "pca9536", 4, },
33 { "pca9537", 4, }, 38 { "pca9537", 4 | PCA953X_INT, },
34 { "pca9538", 8, }, 39 { "pca9538", 8 | PCA953X_INT, },
35 { "pca9539", 16, }, 40 { "pca9539", 16 | PCA953X_INT, },
36 { "pca9554", 8, }, 41 { "pca9554", 8 | PCA953X_INT, },
37 { "pca9555", 16, }, 42 { "pca9555", 16 | PCA953X_INT, },
38 { "pca9556", 8, }, 43 { "pca9556", 8, },
39 { "pca9557", 8, }, 44 { "pca9557", 8, },
40 45
41 { "max7310", 8, }, 46 { "max7310", 8, },
42 { "max7315", 8, }, 47 { "max7312", 16 | PCA953X_INT, },
43 { "pca6107", 8, }, 48 { "max7313", 16 | PCA953X_INT, },
44 { "tca6408", 8, }, 49 { "max7315", 8 | PCA953X_INT, },
45 { "tca6416", 16, }, 50 { "pca6107", 8 | PCA953X_INT, },
51 { "tca6408", 8 | PCA953X_INT, },
52 { "tca6416", 16 | PCA953X_INT, },
46 /* NYET: { "tca6424", 24, }, */ 53 /* NYET: { "tca6424", 24, }, */
47 { } 54 { }
48}; 55};
@@ -53,6 +60,15 @@ struct pca953x_chip {
53 uint16_t reg_output; 60 uint16_t reg_output;
54 uint16_t reg_direction; 61 uint16_t reg_direction;
55 62
63#ifdef CONFIG_GPIO_PCA953X_IRQ
64 struct mutex irq_lock;
65 uint16_t irq_mask;
66 uint16_t irq_stat;
67 uint16_t irq_trig_raise;
68 uint16_t irq_trig_fall;
69 int irq_base;
70#endif
71
56 struct i2c_client *client; 72 struct i2c_client *client;
57 struct pca953x_platform_data *dyn_pdata; 73 struct pca953x_platform_data *dyn_pdata;
58 struct gpio_chip gpio_chip; 74 struct gpio_chip gpio_chip;
@@ -202,6 +218,210 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
202 gc->names = chip->names; 218 gc->names = chip->names;
203} 219}
204 220
221#ifdef CONFIG_GPIO_PCA953X_IRQ
222static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
223{
224 struct pca953x_chip *chip;
225
226 chip = container_of(gc, struct pca953x_chip, gpio_chip);
227 return chip->irq_base + off;
228}
229
230static void pca953x_irq_mask(unsigned int irq)
231{
232 struct pca953x_chip *chip = get_irq_chip_data(irq);
233
234 chip->irq_mask &= ~(1 << (irq - chip->irq_base));
235}
236
237static void pca953x_irq_unmask(unsigned int irq)
238{
239 struct pca953x_chip *chip = get_irq_chip_data(irq);
240
241 chip->irq_mask |= 1 << (irq - chip->irq_base);
242}
243
244static void pca953x_irq_bus_lock(unsigned int irq)
245{
246 struct pca953x_chip *chip = get_irq_chip_data(irq);
247
248 mutex_lock(&chip->irq_lock);
249}
250
251static void pca953x_irq_bus_sync_unlock(unsigned int irq)
252{
253 struct pca953x_chip *chip = get_irq_chip_data(irq);
254
255 mutex_unlock(&chip->irq_lock);
256}
257
258static int pca953x_irq_set_type(unsigned int irq, unsigned int type)
259{
260 struct pca953x_chip *chip = get_irq_chip_data(irq);
261 uint16_t level = irq - chip->irq_base;
262 uint16_t mask = 1 << level;
263
264 if (!(type & IRQ_TYPE_EDGE_BOTH)) {
265 dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
266 irq, type);
267 return -EINVAL;
268 }
269
270 if (type & IRQ_TYPE_EDGE_FALLING)
271 chip->irq_trig_fall |= mask;
272 else
273 chip->irq_trig_fall &= ~mask;
274
275 if (type & IRQ_TYPE_EDGE_RISING)
276 chip->irq_trig_raise |= mask;
277 else
278 chip->irq_trig_raise &= ~mask;
279
280 return pca953x_gpio_direction_input(&chip->gpio_chip, level);
281}
282
283static struct irq_chip pca953x_irq_chip = {
284 .name = "pca953x",
285 .mask = pca953x_irq_mask,
286 .unmask = pca953x_irq_unmask,
287 .bus_lock = pca953x_irq_bus_lock,
288 .bus_sync_unlock = pca953x_irq_bus_sync_unlock,
289 .set_type = pca953x_irq_set_type,
290};
291
292static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
293{
294 uint16_t cur_stat;
295 uint16_t old_stat;
296 uint16_t pending;
297 uint16_t trigger;
298 int ret;
299
300 ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat);
301 if (ret)
302 return 0;
303
304 /* Remove output pins from the equation */
305 cur_stat &= chip->reg_direction;
306
307 old_stat = chip->irq_stat;
308 trigger = (cur_stat ^ old_stat) & chip->irq_mask;
309
310 if (!trigger)
311 return 0;
312
313 chip->irq_stat = cur_stat;
314
315 pending = (old_stat & chip->irq_trig_fall) |
316 (cur_stat & chip->irq_trig_raise);
317 pending &= trigger;
318
319 return pending;
320}
321
322static irqreturn_t pca953x_irq_handler(int irq, void *devid)
323{
324 struct pca953x_chip *chip = devid;
325 uint16_t pending;
326 uint16_t level;
327
328 pending = pca953x_irq_pending(chip);
329
330 if (!pending)
331 return IRQ_HANDLED;
332
333 do {
334 level = __ffs(pending);
335 handle_nested_irq(level + chip->irq_base);
336
337 pending &= ~(1 << level);
338 } while (pending);
339
340 return IRQ_HANDLED;
341}
342
343static int pca953x_irq_setup(struct pca953x_chip *chip,
344 const struct i2c_device_id *id)
345{
346 struct i2c_client *client = chip->client;
347 struct pca953x_platform_data *pdata = client->dev.platform_data;
348 int ret;
349
350 if (pdata->irq_base && (id->driver_data & PCA953X_INT)) {
351 int lvl;
352
353 ret = pca953x_read_reg(chip, PCA953X_INPUT,
354 &chip->irq_stat);
355 if (ret)
356 goto out_failed;
357
358 /*
359 * There is no way to know which GPIO line generated the
360 * interrupt. We have to rely on the previous read for
361 * this purpose.
362 */
363 chip->irq_stat &= chip->reg_direction;
364 chip->irq_base = pdata->irq_base;
365 mutex_init(&chip->irq_lock);
366
367 for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
368 int irq = lvl + chip->irq_base;
369
370 set_irq_chip_data(irq, chip);
371 set_irq_chip_and_handler(irq, &pca953x_irq_chip,
372 handle_edge_irq);
373 set_irq_nested_thread(irq, 1);
374#ifdef CONFIG_ARM
375 set_irq_flags(irq, IRQF_VALID);
376#else
377 set_irq_noprobe(irq);
378#endif
379 }
380
381 ret = request_threaded_irq(client->irq,
382 NULL,
383 pca953x_irq_handler,
384 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
385 dev_name(&client->dev), chip);
386 if (ret) {
387 dev_err(&client->dev, "failed to request irq %d\n",
388 client->irq);
389 goto out_failed;
390 }
391
392 chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
393 }
394
395 return 0;
396
397out_failed:
398 chip->irq_base = 0;
399 return ret;
400}
401
402static void pca953x_irq_teardown(struct pca953x_chip *chip)
403{
404 if (chip->irq_base)
405 free_irq(chip->client->irq, chip);
406}
407#else /* CONFIG_GPIO_PCA953X_IRQ */
408static int pca953x_irq_setup(struct pca953x_chip *chip,
409 const struct i2c_device_id *id)
410{
411 struct i2c_client *client = chip->client;
412 struct pca953x_platform_data *pdata = client->dev.platform_data;
413
414 if (pdata->irq_base && (id->driver_data & PCA953X_INT))
415 dev_warn(&client->dev, "interrupt support not compiled in\n");
416
417 return 0;
418}
419
420static void pca953x_irq_teardown(struct pca953x_chip *chip)
421{
422}
423#endif
424
205/* 425/*
206 * Handlers for alternative sources of platform_data 426 * Handlers for alternative sources of platform_data
207 */ 427 */
@@ -286,7 +506,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
286 /* initialize cached registers from their original values. 506 /* initialize cached registers from their original values.
287 * we can't share this chip with another i2c master. 507 * we can't share this chip with another i2c master.
288 */ 508 */
289 pca953x_setup_gpio(chip, id->driver_data); 509 pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS);
290 510
291 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); 511 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
292 if (ret) 512 if (ret)
@@ -301,6 +521,9 @@ static int __devinit pca953x_probe(struct i2c_client *client,
301 if (ret) 521 if (ret)
302 goto out_failed; 522 goto out_failed;
303 523
524 ret = pca953x_irq_setup(chip, id);
525 if (ret)
526 goto out_failed;
304 527
305 ret = gpiochip_add(&chip->gpio_chip); 528 ret = gpiochip_add(&chip->gpio_chip);
306 if (ret) 529 if (ret)
@@ -317,6 +540,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
317 return 0; 540 return 0;
318 541
319out_failed: 542out_failed:
543 pca953x_irq_teardown(chip);
320 kfree(chip->dyn_pdata); 544 kfree(chip->dyn_pdata);
321 kfree(chip); 545 kfree(chip);
322 return ret; 546 return ret;
@@ -345,6 +569,7 @@ static int pca953x_remove(struct i2c_client *client)
345 return ret; 569 return ret;
346 } 570 }
347 571
572 pca953x_irq_teardown(chip);
348 kfree(chip->dyn_pdata); 573 kfree(chip->dyn_pdata);
349 kfree(chip); 574 kfree(chip);
350 return 0; 575 return 0;
diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h
index 29699f8dc5a4..d5c5a60c8a0b 100644
--- a/include/linux/i2c/pca953x.h
+++ b/include/linux/i2c/pca953x.h
@@ -13,6 +13,9 @@ struct pca953x_platform_data {
13 /* initial polarity inversion setting */ 13 /* initial polarity inversion setting */
14 uint16_t invert; 14 uint16_t invert;
15 15
16 /* interrupt base */
17 int irq_base;
18
16 void *context; /* param to setup/teardown */ 19 void *context; /* param to setup/teardown */
17 20
18 int (*setup)(struct i2c_client *client, 21 int (*setup)(struct i2c_client *client,