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
);
222 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
223 MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
224 MODULE_LICENSE("GPL v2");
225 MODULE_ALIAS("platform:iio-trig-sysfs");