diff options
author | Barry Song <Barry.Song@analog.com> | 2010-05-04 09:43:15 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-11 14:36:06 -0400 |
commit | a9d26f00b8b1b2a79e42cfa4ca20ec9a1c11c1d2 (patch) | |
tree | 8137bf4691da0ad7d11d3fb2d44d146d7bf9f47f /drivers/staging/iio/imu/adis16400_trigger.c | |
parent | 1e3864e63576e33dd1b26ab750ffaab3066aaba9 (diff) |
staging:iio:imu ADIS16400 and ADIS16405 driver
Signed-off-by: Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
Signed-off-by: Barry Song <Barry.Song@analog.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/iio/imu/adis16400_trigger.c')
-rw-r--r-- | drivers/staging/iio/imu/adis16400_trigger.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c new file mode 100644 index 00000000000..3b3250ac768 --- /dev/null +++ b/drivers/staging/iio/imu/adis16400_trigger.c | |||
@@ -0,0 +1,127 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../trigger.h" | ||
13 | #include "adis16400.h" | ||
14 | |||
15 | /** | ||
16 | * adis16400_data_rdy_trig_poll() the event handler for the data rdy trig | ||
17 | **/ | ||
18 | static int adis16400_data_rdy_trig_poll(struct iio_dev *dev_info, | ||
19 | int index, | ||
20 | s64 timestamp, | ||
21 | int no_test) | ||
22 | { | ||
23 | struct adis16400_state *st = iio_dev_get_devdata(dev_info); | ||
24 | struct iio_trigger *trig = st->trig; | ||
25 | |||
26 | trig->timestamp = timestamp; | ||
27 | iio_trigger_poll(trig); | ||
28 | |||
29 | return IRQ_HANDLED; | ||
30 | } | ||
31 | |||
32 | IIO_EVENT_SH(data_rdy_trig, &adis16400_data_rdy_trig_poll); | ||
33 | |||
34 | static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); | ||
35 | |||
36 | static struct attribute *adis16400_trigger_attrs[] = { | ||
37 | &dev_attr_name.attr, | ||
38 | NULL, | ||
39 | }; | ||
40 | |||
41 | static const struct attribute_group adis16400_trigger_attr_group = { | ||
42 | .attrs = adis16400_trigger_attrs, | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * adis16400_data_rdy_trigger_set_state() set datardy interrupt state | ||
47 | **/ | ||
48 | static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
49 | bool state) | ||
50 | { | ||
51 | struct adis16400_state *st = trig->private_data; | ||
52 | struct iio_dev *indio_dev = st->indio_dev; | ||
53 | int ret = 0; | ||
54 | |||
55 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
56 | ret = adis16400_set_irq(&st->indio_dev->dev, state); | ||
57 | if (state == false) { | ||
58 | iio_remove_event_from_list(&iio_event_data_rdy_trig, | ||
59 | &indio_dev->interrupts[0] | ||
60 | ->ev_list); | ||
61 | /* possible quirk with handler currently worked around | ||
62 | by ensuring the work queue is empty */ | ||
63 | flush_scheduled_work(); | ||
64 | } else { | ||
65 | iio_add_event_to_list(&iio_event_data_rdy_trig, | ||
66 | &indio_dev->interrupts[0]->ev_list); | ||
67 | } | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * adis16400_trig_try_reen() try renabling irq for data rdy trigger | ||
73 | * @trig: the datardy trigger | ||
74 | **/ | ||
75 | static int adis16400_trig_try_reen(struct iio_trigger *trig) | ||
76 | { | ||
77 | struct adis16400_state *st = trig->private_data; | ||
78 | enable_irq(st->us->irq); | ||
79 | /* irq reenabled so success! */ | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | int adis16400_probe_trigger(struct iio_dev *indio_dev) | ||
84 | { | ||
85 | int ret; | ||
86 | struct adis16400_state *st = indio_dev->dev_data; | ||
87 | |||
88 | st->trig = iio_allocate_trigger(); | ||
89 | st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL); | ||
90 | if (!st->trig->name) { | ||
91 | ret = -ENOMEM; | ||
92 | goto error_free_trig; | ||
93 | } | ||
94 | snprintf((char *)st->trig->name, | ||
95 | IIO_TRIGGER_NAME_LENGTH, | ||
96 | "adis16400-dev%d", indio_dev->id); | ||
97 | st->trig->dev.parent = &st->us->dev; | ||
98 | st->trig->owner = THIS_MODULE; | ||
99 | st->trig->private_data = st; | ||
100 | st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state; | ||
101 | st->trig->try_reenable = &adis16400_trig_try_reen; | ||
102 | st->trig->control_attrs = &adis16400_trigger_attr_group; | ||
103 | ret = iio_trigger_register(st->trig); | ||
104 | |||
105 | /* select default trigger */ | ||
106 | indio_dev->trig = st->trig; | ||
107 | if (ret) | ||
108 | goto error_free_trig_name; | ||
109 | |||
110 | return 0; | ||
111 | |||
112 | error_free_trig_name: | ||
113 | kfree(st->trig->name); | ||
114 | error_free_trig: | ||
115 | iio_free_trigger(st->trig); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | void adis16400_remove_trigger(struct iio_dev *indio_dev) | ||
121 | { | ||
122 | struct adis16400_state *state = indio_dev->dev_data; | ||
123 | |||
124 | iio_trigger_unregister(state->trig); | ||
125 | kfree(state->trig->name); | ||
126 | iio_free_trigger(state->trig); | ||
127 | } | ||