aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorDaniel Glöckner <dg@emlix.com>2009-09-22 19:46:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:48 -0400
commitff77c352ae17768c61cfc36357f0a3904552f11c (patch)
tree195c102f75445654e87453cbce284b2f658d13a8 /drivers/gpio
parentd120c17faeb391f5b4b99af8b1e190619934ecdd (diff)
gpiolib: allow poll() on value
Many gpio chips allow to generate interrupts when the value of a pin changes. This patch gives usermode application the opportunity to make use of this feature by calling poll(2) on the /sys/class/gpio/gpioN/value sysfs file. The edge to trigger can be set in the edge file in the same directory. Possible values are "none", "rising", "falling", and "both". Using level triggers is not possible with current sysfs since nothing changes the GPIO value (and the IRQ keeps triggering). Edge triggering will "just work". Note that if there was an event between read() and poll(), the poll() returns immediately. Also note that this version only supports true GPIO interrupts. Some later patch might be able to synthesize this behavior by timer-driven polling; some systems seem to need that. [dbrownell@users.sourceforge.net: align ids to 16 bit ids; whitespace] Signed-off-by: Daniel Glöckner <dg@emlix.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib.c208
1 files changed, 203 insertions, 5 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index aef6b3d8e2cf..bb11a429394a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1,5 +1,6 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/module.h> 2#include <linux/module.h>
3#include <linux/interrupt.h>
3#include <linux/irq.h> 4#include <linux/irq.h>
4#include <linux/spinlock.h> 5#include <linux/spinlock.h>
5#include <linux/device.h> 6#include <linux/device.h>
@@ -7,6 +8,7 @@
7#include <linux/debugfs.h> 8#include <linux/debugfs.h>
8#include <linux/seq_file.h> 9#include <linux/seq_file.h>
9#include <linux/gpio.h> 10#include <linux/gpio.h>
11#include <linux/idr.h>
10 12
11 13
12/* Optional implementation infrastructure for GPIO interfaces. 14/* Optional implementation infrastructure for GPIO interfaces.
@@ -49,6 +51,13 @@ struct gpio_desc {
49#define FLAG_RESERVED 2 51#define FLAG_RESERVED 2
50#define FLAG_EXPORT 3 /* protected by sysfs_lock */ 52#define FLAG_EXPORT 3 /* protected by sysfs_lock */
51#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ 53#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
54#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
55#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
56
57#define PDESC_ID_SHIFT 16 /* add new flags before this one */
58
59#define GPIO_FLAGS_MASK ((1 << PDESC_ID_SHIFT) - 1)
60#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
52 61
53#ifdef CONFIG_DEBUG_FS 62#ifdef CONFIG_DEBUG_FS
54 const char *label; 63 const char *label;
@@ -56,6 +65,15 @@ struct gpio_desc {
56}; 65};
57static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; 66static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
58 67
68#ifdef CONFIG_GPIO_SYSFS
69struct poll_desc {
70 struct work_struct work;
71 struct sysfs_dirent *value_sd;
72};
73
74static struct idr pdesc_idr;
75#endif
76
59static inline void desc_set_label(struct gpio_desc *d, const char *label) 77static inline void desc_set_label(struct gpio_desc *d, const char *label)
60{ 78{
61#ifdef CONFIG_DEBUG_FS 79#ifdef CONFIG_DEBUG_FS
@@ -188,10 +206,10 @@ static DEFINE_MUTEX(sysfs_lock);
188 * /value 206 * /value
189 * * always readable, subject to hardware behavior 207 * * always readable, subject to hardware behavior
190 * * may be writable, as zero/nonzero 208 * * may be writable, as zero/nonzero
191 * 209 * /edge
192 * REVISIT there will likely be an attribute for configuring async 210 * * configures behavior of poll(2) on /value
193 * notifications, e.g. to specify polling interval or IRQ trigger type 211 * * available only if pin can generate IRQs on input
194 * that would for example trigger a poll() on the "value". 212 * * is read/write as "none", "falling", "rising", or "both"
195 */ 213 */
196 214
197static ssize_t gpio_direction_show(struct device *dev, 215static ssize_t gpio_direction_show(struct device *dev,
@@ -288,6 +306,175 @@ static ssize_t gpio_value_store(struct device *dev,
288static /*const*/ DEVICE_ATTR(value, 0644, 306static /*const*/ DEVICE_ATTR(value, 0644,
289 gpio_value_show, gpio_value_store); 307 gpio_value_show, gpio_value_store);
290 308
309static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
310{
311 struct work_struct *work = priv;
312
313 schedule_work(work);
314 return IRQ_HANDLED;
315}
316
317static void gpio_notify_sysfs(struct work_struct *work)
318{
319 struct poll_desc *pdesc;
320
321 pdesc = container_of(work, struct poll_desc, work);
322 sysfs_notify_dirent(pdesc->value_sd);
323}
324
325static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
326 unsigned long gpio_flags)
327{
328 struct poll_desc *pdesc;
329 unsigned long irq_flags;
330 int ret, irq, id;
331
332 if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
333 return 0;
334
335 irq = gpio_to_irq(desc - gpio_desc);
336 if (irq < 0)
337 return -EIO;
338
339 id = desc->flags >> PDESC_ID_SHIFT;
340 pdesc = idr_find(&pdesc_idr, id);
341 if (pdesc) {
342 free_irq(irq, &pdesc->work);
343 cancel_work_sync(&pdesc->work);
344 }
345
346 desc->flags &= ~GPIO_TRIGGER_MASK;
347
348 if (!gpio_flags) {
349 ret = 0;
350 goto free_sd;
351 }
352
353 irq_flags = IRQF_SHARED;
354 if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
355 irq_flags |= IRQF_TRIGGER_FALLING;
356 if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
357 irq_flags |= IRQF_TRIGGER_RISING;
358
359 if (!pdesc) {
360 pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL);
361 if (!pdesc) {
362 ret = -ENOMEM;
363 goto err_out;
364 }
365
366 do {
367 ret = -ENOMEM;
368 if (idr_pre_get(&pdesc_idr, GFP_KERNEL))
369 ret = idr_get_new_above(&pdesc_idr,
370 pdesc, 1, &id);
371 } while (ret == -EAGAIN);
372
373 if (ret)
374 goto free_mem;
375
376 desc->flags &= GPIO_FLAGS_MASK;
377 desc->flags |= (unsigned long)id << PDESC_ID_SHIFT;
378
379 if (desc->flags >> PDESC_ID_SHIFT != id) {
380 ret = -ERANGE;
381 goto free_id;
382 }
383
384 pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
385 if (!pdesc->value_sd) {
386 ret = -ENODEV;
387 goto free_id;
388 }
389 INIT_WORK(&pdesc->work, gpio_notify_sysfs);
390 }
391
392 ret = request_irq(irq, gpio_sysfs_irq, irq_flags,
393 "gpiolib", &pdesc->work);
394 if (ret)
395 goto free_sd;
396
397 desc->flags |= gpio_flags;
398 return 0;
399
400free_sd:
401 sysfs_put(pdesc->value_sd);
402free_id:
403 idr_remove(&pdesc_idr, id);
404 desc->flags &= GPIO_FLAGS_MASK;
405free_mem:
406 kfree(pdesc);
407err_out:
408 return ret;
409}
410
411static const struct {
412 const char *name;
413 unsigned long flags;
414} trigger_types[] = {
415 { "none", 0 },
416 { "falling", BIT(FLAG_TRIG_FALL) },
417 { "rising", BIT(FLAG_TRIG_RISE) },
418 { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) },
419};
420
421static ssize_t gpio_edge_show(struct device *dev,
422 struct device_attribute *attr, char *buf)
423{
424 const struct gpio_desc *desc = dev_get_drvdata(dev);
425 ssize_t status;
426
427 mutex_lock(&sysfs_lock);
428
429 if (!test_bit(FLAG_EXPORT, &desc->flags))
430 status = -EIO;
431 else {
432 int i;
433
434 status = 0;
435 for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
436 if ((desc->flags & GPIO_TRIGGER_MASK)
437 == trigger_types[i].flags) {
438 status = sprintf(buf, "%s\n",
439 trigger_types[i].name);
440 break;
441 }
442 }
443
444 mutex_unlock(&sysfs_lock);
445 return status;
446}
447
448static ssize_t gpio_edge_store(struct device *dev,
449 struct device_attribute *attr, const char *buf, size_t size)
450{
451 struct gpio_desc *desc = dev_get_drvdata(dev);
452 ssize_t status;
453 int i;
454
455 for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
456 if (sysfs_streq(trigger_types[i].name, buf))
457 goto found;
458 return -EINVAL;
459
460found:
461 mutex_lock(&sysfs_lock);
462
463 if (!test_bit(FLAG_EXPORT, &desc->flags))
464 status = -EIO;
465 else {
466 status = gpio_setup_irq(desc, dev, trigger_types[i].flags);
467 if (!status)
468 status = size;
469 }
470
471 mutex_unlock(&sysfs_lock);
472
473 return status;
474}
475
476static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
477
291static const struct attribute *gpio_attrs[] = { 478static const struct attribute *gpio_attrs[] = {
292 &dev_attr_direction.attr, 479 &dev_attr_direction.attr,
293 &dev_attr_value.attr, 480 &dev_attr_value.attr,
@@ -473,7 +660,7 @@ int gpio_export(unsigned gpio, bool direction_may_change)
473 struct device *dev; 660 struct device *dev;
474 661
475 dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), 662 dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
476 desc, ioname ? ioname : "gpio%d", gpio); 663 desc, ioname ? ioname : "gpio%d", gpio);
477 if (dev) { 664 if (dev) {
478 if (direction_may_change) 665 if (direction_may_change)
479 status = sysfs_create_group(&dev->kobj, 666 status = sysfs_create_group(&dev->kobj,
@@ -481,6 +668,14 @@ int gpio_export(unsigned gpio, bool direction_may_change)
481 else 668 else
482 status = device_create_file(dev, 669 status = device_create_file(dev,
483 &dev_attr_value); 670 &dev_attr_value);
671
672 if (!status && gpio_to_irq(gpio) >= 0
673 && (direction_may_change
674 || !test_bit(FLAG_IS_OUT,
675 &desc->flags)))
676 status = device_create_file(dev,
677 &dev_attr_edge);
678
484 if (status != 0) 679 if (status != 0)
485 device_unregister(dev); 680 device_unregister(dev);
486 } else 681 } else
@@ -572,6 +767,7 @@ void gpio_unexport(unsigned gpio)
572 767
573 dev = class_find_device(&gpio_class, NULL, desc, match_export); 768 dev = class_find_device(&gpio_class, NULL, desc, match_export);
574 if (dev) { 769 if (dev) {
770 gpio_setup_irq(desc, dev, 0);
575 clear_bit(FLAG_EXPORT, &desc->flags); 771 clear_bit(FLAG_EXPORT, &desc->flags);
576 put_device(dev); 772 put_device(dev);
577 device_unregister(dev); 773 device_unregister(dev);
@@ -656,6 +852,8 @@ static int __init gpiolib_sysfs_init(void)
656 unsigned long flags; 852 unsigned long flags;
657 unsigned gpio; 853 unsigned gpio;
658 854
855 idr_init(&pdesc_idr);
856
659 status = class_register(&gpio_class); 857 status = class_register(&gpio_class);
660 if (status < 0) 858 if (status < 0)
661 return status; 859 return status;