aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@kernel.org>2013-04-14 07:54:00 -0400
committerJonathan Cameron <jic23@kernel.org>2013-05-22 17:16:48 -0400
commite64e7d5c8c86ead27ed51a95687ba8327a9c4d2a (patch)
tree538e59226f90d6fe150364be1cd29622c5266614 /drivers/iio
parentf4914e5ef087961b3bf17cdf166e947f69cc9089 (diff)
iio:trigger:sysfs Move out of staging.
This simple driver is rather useful. No issues about its interface have been raised for some time hence the proposal to move it out of staging. Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/Kconfig3
-rw-r--r--drivers/iio/Makefile1
-rw-r--r--drivers/iio/trigger/Kconfig17
-rw-r--r--drivers/iio/trigger/Makefile5
-rw-r--r--drivers/iio/trigger/iio-trig-sysfs.c227
5 files changed, 253 insertions, 0 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index b2f963be3993..daa3dddbc77f 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -70,5 +70,8 @@ source "drivers/iio/gyro/Kconfig"
70source "drivers/iio/imu/Kconfig" 70source "drivers/iio/imu/Kconfig"
71source "drivers/iio/light/Kconfig" 71source "drivers/iio/light/Kconfig"
72source "drivers/iio/magnetometer/Kconfig" 72source "drivers/iio/magnetometer/Kconfig"
73if IIO_TRIGGER
74 source "drivers/iio/trigger/Kconfig"
75endif #IIO_TRIGGER
73 76
74endif # IIO 77endif # IIO
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index a0e8cdd67e4d..a349a9605d1f 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -21,3 +21,4 @@ obj-y += frequency/
21obj-y += imu/ 21obj-y += imu/
22obj-y += light/ 22obj-y += light/
23obj-y += magnetometer/ 23obj-y += magnetometer/
24obj-y += trigger/
diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig
new file mode 100644
index 000000000000..a4e68db2f23f
--- /dev/null
+++ b/drivers/iio/trigger/Kconfig
@@ -0,0 +1,17 @@
1#
2# Industrial I/O standalone triggers
3#
4menu "Triggers - standalone"
5
6config IIO_SYSFS_TRIGGER
7 tristate "SYSFS trigger"
8 depends on SYSFS
9 select IRQ_WORK
10 help
11 Provides support for using SYSFS entry as IIO triggers.
12 If unsure, say N (but it's safe to say "Y").
13
14 To compile this driver as a module, choose M here: the
15 module will be called iio-trig-sysfs.
16
17endmenu
diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile
new file mode 100644
index 000000000000..e0b21831072f
--- /dev/null
+++ b/drivers/iio/trigger/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for triggers not associated with iio-devices
3#
4
5obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c
new file mode 100644
index 000000000000..b727bde8b7fe
--- /dev/null
+++ b/drivers/iio/trigger/iio-trig-sysfs.c
@@ -0,0 +1,227 @@
1/*
2 * Copyright 2011 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2.
5 *
6 */
7
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/platform_device.h>
11#include <linux/slab.h>
12#include <linux/list.h>
13#include <linux/irq_work.h>
14
15#include <linux/iio/iio.h>
16#include <linux/iio/trigger.h>
17
18struct iio_sysfs_trig {
19 struct iio_trigger *trig;
20 struct irq_work work;
21 int id;
22 struct list_head l;
23};
24
25static LIST_HEAD(iio_sysfs_trig_list);
26static DEFINE_MUTEX(iio_syfs_trig_list_mut);
27
28static int iio_sysfs_trigger_probe(int id);
29static ssize_t iio_sysfs_trig_add(struct device *dev,
30 struct device_attribute *attr,
31 const char *buf,
32 size_t len)
33{
34 int ret;
35 unsigned long input;
36
37 ret = strict_strtoul(buf, 10, &input);
38 if (ret)
39 return ret;
40 ret = iio_sysfs_trigger_probe(input);
41 if (ret)
42 return ret;
43 return len;
44}
45static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
46
47static int iio_sysfs_trigger_remove(int id);
48static ssize_t iio_sysfs_trig_remove(struct device *dev,
49 struct device_attribute *attr,
50 const char *buf,
51 size_t len)
52{
53 int ret;
54 unsigned long input;
55
56 ret = strict_strtoul(buf, 10, &input);
57 if (ret)
58 return ret;
59 ret = iio_sysfs_trigger_remove(input);
60 if (ret)
61 return ret;
62 return len;
63}
64
65static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
66
67static struct attribute *iio_sysfs_trig_attrs[] = {
68 &dev_attr_add_trigger.attr,
69 &dev_attr_remove_trigger.attr,
70 NULL,
71};
72
73static const struct attribute_group iio_sysfs_trig_group = {
74 .attrs = iio_sysfs_trig_attrs,
75};
76
77static const struct attribute_group *iio_sysfs_trig_groups[] = {
78 &iio_sysfs_trig_group,
79 NULL
80};
81
82
83/* Nothing to actually do upon release */
84static void iio_trigger_sysfs_release(struct device *dev)
85{
86}
87
88static struct device iio_sysfs_trig_dev = {
89 .bus = &iio_bus_type,
90 .groups = iio_sysfs_trig_groups,
91 .release = &iio_trigger_sysfs_release,
92};
93
94static void iio_sysfs_trigger_work(struct irq_work *work)
95{
96 struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig,
97 work);
98
99 iio_trigger_poll(trig->trig, 0);
100}
101
102static ssize_t iio_sysfs_trigger_poll(struct device *dev,
103 struct device_attribute *attr, const char *buf, size_t count)
104{
105 struct iio_trigger *trig = to_iio_trigger(dev);
106 struct iio_sysfs_trig *sysfs_trig = iio_trigger_get_drvdata(trig);
107
108 irq_work_queue(&sysfs_trig->work);
109
110 return count;
111}
112
113static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
114
115static struct attribute *iio_sysfs_trigger_attrs[] = {
116 &dev_attr_trigger_now.attr,
117 NULL,
118};
119
120static const struct attribute_group iio_sysfs_trigger_attr_group = {
121 .attrs = iio_sysfs_trigger_attrs,
122};
123
124static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
125 &iio_sysfs_trigger_attr_group,
126 NULL
127};
128
129static const struct iio_trigger_ops iio_sysfs_trigger_ops = {
130 .owner = THIS_MODULE,
131};
132
133static int iio_sysfs_trigger_probe(int id)
134{
135 struct iio_sysfs_trig *t;
136 int ret;
137 bool foundit = false;
138 mutex_lock(&iio_syfs_trig_list_mut);
139 list_for_each_entry(t, &iio_sysfs_trig_list, l)
140 if (id == t->id) {
141 foundit = true;
142 break;
143 }
144 if (foundit) {
145 ret = -EINVAL;
146 goto out1;
147 }
148 t = kmalloc(sizeof(*t), GFP_KERNEL);
149 if (t == NULL) {
150 ret = -ENOMEM;
151 goto out1;
152 }
153 t->id = id;
154 t->trig = iio_trigger_alloc("sysfstrig%d", id);
155 if (!t->trig) {
156 ret = -ENOMEM;
157 goto free_t;
158 }
159
160 t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
161 t->trig->ops = &iio_sysfs_trigger_ops;
162 t->trig->dev.parent = &iio_sysfs_trig_dev;
163 iio_trigger_set_drvdata(t->trig, t);
164
165 init_irq_work(&t->work, iio_sysfs_trigger_work);
166
167 ret = iio_trigger_register(t->trig);
168 if (ret)
169 goto out2;
170 list_add(&t->l, &iio_sysfs_trig_list);
171 __module_get(THIS_MODULE);
172 mutex_unlock(&iio_syfs_trig_list_mut);
173 return 0;
174
175out2:
176 iio_trigger_put(t->trig);
177free_t:
178 kfree(t);
179out1:
180 mutex_unlock(&iio_syfs_trig_list_mut);
181 return ret;
182}
183
184static int iio_sysfs_trigger_remove(int id)
185{
186 bool foundit = false;
187 struct iio_sysfs_trig *t;
188 mutex_lock(&iio_syfs_trig_list_mut);
189 list_for_each_entry(t, &iio_sysfs_trig_list, l)
190 if (id == t->id) {
191 foundit = true;
192 break;
193 }
194 if (!foundit) {
195 mutex_unlock(&iio_syfs_trig_list_mut);
196 return -EINVAL;
197 }
198
199 iio_trigger_unregister(t->trig);
200 iio_trigger_free(t->trig);
201
202 list_del(&t->l);
203 kfree(t);
204 module_put(THIS_MODULE);
205 mutex_unlock(&iio_syfs_trig_list_mut);
206 return 0;
207}
208
209
210static int __init iio_sysfs_trig_init(void)
211{
212 device_initialize(&iio_sysfs_trig_dev);
213 dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
214 return device_add(&iio_sysfs_trig_dev);
215}
216module_init(iio_sysfs_trig_init);
217
218static void __exit iio_sysfs_trig_exit(void)
219{
220 device_unregister(&iio_sysfs_trig_dev);
221}
222module_exit(iio_sysfs_trig_exit);
223
224MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
225MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
226MODULE_LICENSE("GPL v2");
227MODULE_ALIAS("platform:iio-trig-sysfs");