Commit | Line | Data |
---|---|---|
e6477000 JC |
1 | /** |
2 | * Copyright (c) 2011 Jonathan Cameron | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of the GNU General Public License version 2 as published by | |
6 | * the Free Software Foundation. | |
7 | * | |
8 | * Event handling elements of industrial I/O reference driver. | |
9 | */ | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/slab.h> | |
12 | #include <linux/interrupt.h> | |
13 | #include <linux/irq.h> | |
14 | ||
06458e27 JC |
15 | #include <linux/iio/iio.h> |
16 | #include <linux/iio/sysfs.h> | |
17 | #include <linux/iio/events.h> | |
e6477000 JC |
18 | #include "iio_simple_dummy.h" |
19 | ||
20 | /* Evgen 'fakes' interrupt events for this example */ | |
21 | #include "iio_dummy_evgen.h" | |
22 | ||
23 | /** | |
24 | * iio_simple_dummy_read_event_config() - is event enabled? | |
25 | * @indio_dev: the device instance data | |
26 | * @event_code: event code of the event being queried | |
27 | * | |
28 | * This function would normally query the relevant registers or a cache to | |
29 | * discover if the event generation is enabled on the device. | |
30 | */ | |
31 | int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, | |
32 | u64 event_code) | |
33 | { | |
34 | struct iio_dummy_state *st = iio_priv(indio_dev); | |
35 | ||
36 | return st->event_en; | |
37 | } | |
38 | ||
39 | /** | |
40 | * iio_simple_dummy_write_event_config() - set whether event is enabled | |
41 | * @indio_dev: the device instance data | |
42 | * @event_code: event code of event being enabled/disabled | |
43 | * @state: whether to enable or disable the device. | |
44 | * | |
45 | * This function would normally set the relevant registers on the devices | |
46 | * so that it generates the specified event. Here it just sets up a cached | |
47 | * value. | |
48 | */ | |
49 | int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, | |
50 | u64 event_code, | |
51 | int state) | |
52 | { | |
53 | struct iio_dummy_state *st = iio_priv(indio_dev); | |
54 | ||
55 | /* | |
56 | * Deliberately over the top code splitting to illustrate | |
57 | * how this is done when multiple events exist. | |
58 | */ | |
59 | switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { | |
60 | case IIO_VOLTAGE: | |
61 | switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { | |
62 | case IIO_EV_TYPE_THRESH: | |
63 | if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == | |
64 | IIO_EV_DIR_RISING) | |
65 | st->event_en = state; | |
66 | else | |
67 | return -EINVAL; | |
68 | break; | |
69 | default: | |
70 | return -EINVAL; | |
71 | } | |
72 | default: | |
73 | return -EINVAL; | |
74 | } | |
75 | ||
76 | return 0; | |
77 | } | |
78 | ||
79 | /** | |
80 | * iio_simple_dummy_read_event_value() - get value associated with event | |
81 | * @indio_dev: device instance specific data | |
82 | * @event_code: event code for the event whose value is being queried | |
83 | * @val: value for the event code. | |
84 | * | |
85 | * Many devices provide a large set of events of which only a subset may | |
86 | * be enabled at a time, with value registers whose meaning changes depending | |
87 | * on the event enabled. This often means that the driver must cache the values | |
88 | * associated with each possible events so that the right value is in place when | |
89 | * the enabled event is changed. | |
90 | */ | |
91 | int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, | |
92 | u64 event_code, | |
93 | int *val) | |
94 | { | |
95 | struct iio_dummy_state *st = iio_priv(indio_dev); | |
96 | ||
97 | *val = st->event_val; | |
98 | ||
99 | return 0; | |
100 | } | |
101 | ||
102 | /** | |
103 | * iio_simple_dummy_write_event_value() - set value associate with event | |
104 | * @indio_dev: device instance specific data | |
105 | * @event_code: event code for the event whose value is being set | |
106 | * @val: the value to be set. | |
107 | */ | |
108 | int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, | |
109 | u64 event_code, | |
110 | int val) | |
111 | { | |
112 | struct iio_dummy_state *st = iio_priv(indio_dev); | |
113 | ||
114 | st->event_val = val; | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
119 | /** | |
120 | * iio_simple_dummy_event_handler() - identify and pass on event | |
121 | * @irq: irq of event line | |
122 | * @private: pointer to device instance state. | |
123 | * | |
124 | * This handler is responsible for querying the device to find out what | |
99de0c2b | 125 | * event occurred and for then pushing that event towards userspace. |
e6477000 JC |
126 | * Here only one event occurs so we push that directly on with locally |
127 | * grabbed timestamp. | |
128 | */ | |
129 | static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) | |
130 | { | |
131 | struct iio_dev *indio_dev = private; | |
132 | iio_push_event(indio_dev, | |
133 | IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, | |
134 | IIO_EV_DIR_RISING, | |
135 | IIO_EV_TYPE_THRESH, 0, 0, 0), | |
136 | iio_get_time_ns()); | |
137 | return IRQ_HANDLED; | |
138 | } | |
139 | ||
140 | /** | |
141 | * iio_simple_dummy_events_register() - setup interrupt handling for events | |
142 | * @indio_dev: device instance data | |
143 | * | |
144 | * This function requests the threaded interrupt to handle the events. | |
145 | * Normally the irq is a hardware interrupt and the number comes | |
146 | * from board configuration files. Here we get it from a companion | |
147 | * module that fakes the interrupt for us. Note that module in | |
148 | * no way forms part of this example. Just assume that events magically | |
149 | * appear via the provided interrupt. | |
150 | */ | |
151 | int iio_simple_dummy_events_register(struct iio_dev *indio_dev) | |
152 | { | |
153 | struct iio_dummy_state *st = iio_priv(indio_dev); | |
154 | int ret; | |
155 | ||
156 | /* Fire up event source - normally not present */ | |
157 | st->event_irq = iio_dummy_evgen_get_irq(); | |
158 | if (st->event_irq < 0) { | |
159 | ret = st->event_irq; | |
160 | goto error_ret; | |
161 | } | |
162 | ret = request_threaded_irq(st->event_irq, | |
163 | NULL, | |
164 | &iio_simple_dummy_event_handler, | |
165 | IRQF_ONESHOT, | |
166 | "iio_simple_event", | |
167 | indio_dev); | |
168 | if (ret < 0) | |
169 | goto error_free_evgen; | |
170 | return 0; | |
171 | ||
172 | error_free_evgen: | |
173 | iio_dummy_evgen_release_irq(st->event_irq); | |
174 | error_ret: | |
175 | return ret; | |
176 | } | |
177 | ||
178 | /** | |
179 | * iio_simple_dummy_events_unregister() - tidy up interrupt handling on remove | |
180 | * @indio_dev: device instance data | |
181 | */ | |
182 | int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) | |
183 | { | |
184 | struct iio_dummy_state *st = iio_priv(indio_dev); | |
185 | ||
186 | free_irq(st->event_irq, indio_dev); | |
187 | /* Not part of normal driver */ | |
188 | iio_dummy_evgen_release_irq(st->event_irq); | |
189 | ||
190 | return 0; | |
191 | } |