1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2011 Analog Devices Inc.
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/slab.h>
10 #include <linux/list.h>
11 #include <linux/irq_work.h>
13 #include <linux/iio/iio.h>
14 #include <linux/iio/trigger.h>
16 struct iio_sysfs_trig {
17 struct iio_trigger *trig;
23 static LIST_HEAD(iio_sysfs_trig_list);
24 static DEFINE_MUTEX(iio_sysfs_trig_list_mut);
26 static int iio_sysfs_trigger_probe(int id);
27 static ssize_t iio_sysfs_trig_add(struct device *dev,
28 struct device_attribute *attr,
35 ret = kstrtoul(buf, 10, &input);
38 ret = iio_sysfs_trigger_probe(input);
43 static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
45 static int iio_sysfs_trigger_remove(int id);
46 static ssize_t iio_sysfs_trig_remove(struct device *dev,
47 struct device_attribute *attr,
54 ret = kstrtoul(buf, 10, &input);
57 ret = iio_sysfs_trigger_remove(input);
63 static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
65 static struct attribute *iio_sysfs_trig_attrs[] = {
66 &dev_attr_add_trigger.attr,
67 &dev_attr_remove_trigger.attr,
71 static const struct attribute_group iio_sysfs_trig_group = {
72 .attrs = iio_sysfs_trig_attrs,
75 static const struct attribute_group *iio_sysfs_trig_groups[] = {
76 &iio_sysfs_trig_group,
81 /* Nothing to actually do upon release */
82 static void iio_trigger_sysfs_release(struct device *dev)
86 static struct device iio_sysfs_trig_dev = {
88 .groups = iio_sysfs_trig_groups,
89 .release = &iio_trigger_sysfs_release,
92 static void iio_sysfs_trigger_work(struct irq_work *work)
94 struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig,
97 iio_trigger_poll(trig->trig);
100 static ssize_t iio_sysfs_trigger_poll(struct device *dev,
101 struct device_attribute *attr, const char *buf, size_t count)
103 struct iio_trigger *trig = to_iio_trigger(dev);
104 struct iio_sysfs_trig *sysfs_trig = iio_trigger_get_drvdata(trig);
106 irq_work_queue(&sysfs_trig->work);
111 static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
113 static struct attribute *iio_sysfs_trigger_attrs[] = {
114 &dev_attr_trigger_now.attr,
118 static const struct attribute_group iio_sysfs_trigger_attr_group = {
119 .attrs = iio_sysfs_trigger_attrs,
122 static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
123 &iio_sysfs_trigger_attr_group,
127 static int iio_sysfs_trigger_probe(int id)
129 struct iio_sysfs_trig *t;
131 bool foundit = false;
133 mutex_lock(&iio_sysfs_trig_list_mut);
134 list_for_each_entry(t, &iio_sysfs_trig_list, l)
143 t = kmalloc(sizeof(*t), GFP_KERNEL);
149 t->trig = iio_trigger_alloc(&iio_sysfs_trig_dev, "sysfstrig%d", id);
152 goto err_free_sys_trig;
155 t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
156 iio_trigger_set_drvdata(t->trig, t);
158 t->work = IRQ_WORK_INIT_HARD(iio_sysfs_trigger_work);
160 ret = iio_trigger_register(t->trig);
163 list_add(&t->l, &iio_sysfs_trig_list);
164 __module_get(THIS_MODULE);
165 mutex_unlock(&iio_sysfs_trig_list_mut);
169 iio_trigger_free(t->trig);
173 mutex_unlock(&iio_sysfs_trig_list_mut);
177 static int iio_sysfs_trigger_remove(int id)
179 struct iio_sysfs_trig *t = NULL, *iter;
181 mutex_lock(&iio_sysfs_trig_list_mut);
182 list_for_each_entry(iter, &iio_sysfs_trig_list, l)
183 if (id == iter->id) {
188 mutex_unlock(&iio_sysfs_trig_list_mut);
192 iio_trigger_unregister(t->trig);
193 irq_work_sync(&t->work);
194 iio_trigger_free(t->trig);
198 module_put(THIS_MODULE);
199 mutex_unlock(&iio_sysfs_trig_list_mut);
204 static int __init iio_sysfs_trig_init(void)
207 device_initialize(&iio_sysfs_trig_dev);
208 dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
209 ret = device_add(&iio_sysfs_trig_dev);
211 put_device(&iio_sysfs_trig_dev);
214 module_init(iio_sysfs_trig_init);
216 static void __exit iio_sysfs_trig_exit(void)
218 device_unregister(&iio_sysfs_trig_dev);
220 module_exit(iio_sysfs_trig_exit);
223 MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
224 MODULE_LICENSE("GPL v2");
225 MODULE_ALIAS("platform:iio-trig-sysfs");