diff options
Diffstat (limited to 'drivers/iio/trigger')
-rw-r--r-- | drivers/iio/trigger/Kconfig | 9 | ||||
-rw-r--r-- | drivers/iio/trigger/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/trigger/iio-trig-interrupt.c | 121 |
3 files changed, 131 insertions, 0 deletions
diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig index a4e68db2f23f..360fd508b088 100644 --- a/drivers/iio/trigger/Kconfig +++ b/drivers/iio/trigger/Kconfig | |||
@@ -3,6 +3,15 @@ | |||
3 | # | 3 | # |
4 | menu "Triggers - standalone" | 4 | menu "Triggers - standalone" |
5 | 5 | ||
6 | config IIO_INTERRUPT_TRIGGER | ||
7 | tristate "Generic interrupt trigger" | ||
8 | help | ||
9 | Provides support for using an interrupt of any type as an IIO | ||
10 | trigger. This may be provided by a gpio driver for example. | ||
11 | |||
12 | To compile this driver as a module, choose M here: the | ||
13 | module will be called iio-trig-interrupt. | ||
14 | |||
6 | config IIO_SYSFS_TRIGGER | 15 | config IIO_SYSFS_TRIGGER |
7 | tristate "SYSFS trigger" | 16 | tristate "SYSFS trigger" |
8 | depends on SYSFS | 17 | depends on SYSFS |
diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile index e0b21831072f..ce319a51b6af 100644 --- a/drivers/iio/trigger/Makefile +++ b/drivers/iio/trigger/Makefile | |||
@@ -2,4 +2,5 @@ | |||
2 | # Makefile for triggers not associated with iio-devices | 2 | # Makefile for triggers not associated with iio-devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o | ||
5 | obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o | 6 | obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o |
diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c new file mode 100644 index 000000000000..84bf397ec465 --- /dev/null +++ b/drivers/iio/trigger/iio-trig-interrupt.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * Industrial I/O - generic interrupt based trigger support | ||
3 | * | ||
4 | * Copyright (c) 2008-2013 Jonathan Cameron | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | #include <linux/iio/iio.h> | ||
18 | #include <linux/iio/trigger.h> | ||
19 | |||
20 | |||
21 | struct iio_interrupt_trigger_info { | ||
22 | unsigned int irq; | ||
23 | }; | ||
24 | |||
25 | static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private) | ||
26 | { | ||
27 | /* Timestamp not currently provided */ | ||
28 | iio_trigger_poll(private, 0); | ||
29 | return IRQ_HANDLED; | ||
30 | } | ||
31 | |||
32 | static const struct iio_trigger_ops iio_interrupt_trigger_ops = { | ||
33 | .owner = THIS_MODULE, | ||
34 | }; | ||
35 | |||
36 | static int iio_interrupt_trigger_probe(struct platform_device *pdev) | ||
37 | { | ||
38 | struct iio_interrupt_trigger_info *trig_info; | ||
39 | struct iio_trigger *trig; | ||
40 | unsigned long irqflags; | ||
41 | struct resource *irq_res; | ||
42 | int irq, ret = 0; | ||
43 | |||
44 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
45 | |||
46 | if (irq_res == NULL) | ||
47 | return -ENODEV; | ||
48 | |||
49 | irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED; | ||
50 | |||
51 | irq = irq_res->start; | ||
52 | |||
53 | trig = iio_trigger_alloc("irqtrig%d", irq_res->start); | ||
54 | if (!trig) { | ||
55 | ret = -ENOMEM; | ||
56 | goto error_ret; | ||
57 | } | ||
58 | |||
59 | trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); | ||
60 | if (!trig_info) { | ||
61 | ret = -ENOMEM; | ||
62 | goto error_put_trigger; | ||
63 | } | ||
64 | iio_trigger_set_drvdata(trig, trig_info); | ||
65 | trig_info->irq = irq; | ||
66 | trig->ops = &iio_interrupt_trigger_ops; | ||
67 | ret = request_irq(irq, iio_interrupt_trigger_poll, | ||
68 | irqflags, trig->name, trig); | ||
69 | if (ret) { | ||
70 | dev_err(&pdev->dev, | ||
71 | "request IRQ-%d failed", irq); | ||
72 | goto error_free_trig_info; | ||
73 | } | ||
74 | |||
75 | ret = iio_trigger_register(trig); | ||
76 | if (ret) | ||
77 | goto error_release_irq; | ||
78 | platform_set_drvdata(pdev, trig); | ||
79 | |||
80 | return 0; | ||
81 | |||
82 | /* First clean up the partly allocated trigger */ | ||
83 | error_release_irq: | ||
84 | free_irq(irq, trig); | ||
85 | error_free_trig_info: | ||
86 | kfree(trig_info); | ||
87 | error_put_trigger: | ||
88 | iio_trigger_put(trig); | ||
89 | error_ret: | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static int iio_interrupt_trigger_remove(struct platform_device *pdev) | ||
94 | { | ||
95 | struct iio_trigger *trig; | ||
96 | struct iio_interrupt_trigger_info *trig_info; | ||
97 | |||
98 | trig = platform_get_drvdata(pdev); | ||
99 | trig_info = iio_trigger_get_drvdata(trig); | ||
100 | iio_trigger_unregister(trig); | ||
101 | free_irq(trig_info->irq, trig); | ||
102 | kfree(trig_info); | ||
103 | iio_trigger_put(trig); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static struct platform_driver iio_interrupt_trigger_driver = { | ||
109 | .probe = iio_interrupt_trigger_probe, | ||
110 | .remove = iio_interrupt_trigger_remove, | ||
111 | .driver = { | ||
112 | .name = "iio_interrupt_trigger", | ||
113 | .owner = THIS_MODULE, | ||
114 | }, | ||
115 | }; | ||
116 | |||
117 | module_platform_driver(iio_interrupt_trigger_driver); | ||
118 | |||
119 | MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); | ||
120 | MODULE_DESCRIPTION("Interrupt trigger for the iio subsystem"); | ||
121 | MODULE_LICENSE("GPL v2"); | ||