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 
15 #include <linux/iio/iio.h>
16 #include <linux/iio/sysfs.h>
17 #include <linux/iio/events.h>
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  * @chan: channel for the event whose state is being queried
27  * @type: type of the event whose state is being queried
28  * @dir: direction of the vent whose state is being queried
29  *
30  * This function would normally query the relevant registers or a cache to
31  * discover if the event generation is enabled on the device.
32  */
33 int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
34 				       const struct iio_chan_spec *chan,
35 				       enum iio_event_type type,
36 				       enum iio_event_direction dir)
37 {
38 	struct iio_dummy_state *st = iio_priv(indio_dev);
39 
40 	return st->event_en;
41 }
42 
43 /**
44  * iio_simple_dummy_write_event_config() - set whether event is enabled
45  * @indio_dev: the device instance data
46  * @chan: channel for the event whose state is being set
47  * @type: type of the event whose state is being set
48  * @dir: direction of the vent whose state is being set
49  * @state: whether to enable or disable the device.
50  *
51  * This function would normally set the relevant registers on the devices
52  * so that it generates the specified event. Here it just sets up a cached
53  * value.
54  */
55 int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
56 					const struct iio_chan_spec *chan,
57 					enum iio_event_type type,
58 					enum iio_event_direction dir,
59 					int state)
60 {
61 	struct iio_dummy_state *st = iio_priv(indio_dev);
62 
63 	/*
64 	 *  Deliberately over the top code splitting to illustrate
65 	 * how this is done when multiple events exist.
66 	 */
67 	switch (chan->type) {
68 	case IIO_VOLTAGE:
69 		switch (type) {
70 		case IIO_EV_TYPE_THRESH:
71 			if (dir == IIO_EV_DIR_RISING)
72 				st->event_en = state;
73 			else
74 				return -EINVAL;
75 			break;
76 		default:
77 			return -EINVAL;
78 		}
79 		break;
80 	case IIO_ACTIVITY:
81 		switch (type) {
82 		case IIO_EV_TYPE_THRESH:
83 			st->event_en = state;
84 			break;
85 		default:
86 			return -EINVAL;
87 		}
88 		break;
89 	case IIO_STEPS:
90 		switch (type) {
91 		case IIO_EV_TYPE_CHANGE:
92 			st->event_en = state;
93 			break;
94 		default:
95 			return -EINVAL;
96 		}
97 		break;
98 	default:
99 		return -EINVAL;
100 	}
101 
102 	return 0;
103 }
104 
105 /**
106  * iio_simple_dummy_read_event_value() - get value associated with event
107  * @indio_dev: device instance specific data
108  * @chan: channel for the event whose value is being read
109  * @type: type of the event whose value is being read
110  * @dir: direction of the vent whose value is being read
111  * @info: info type of the event whose value is being read
112  * @val: value for the event code.
113  *
114  * Many devices provide a large set of events of which only a subset may
115  * be enabled at a time, with value registers whose meaning changes depending
116  * on the event enabled. This often means that the driver must cache the values
117  * associated with each possible events so that the right value is in place when
118  * the enabled event is changed.
119  */
120 int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
121 				      const struct iio_chan_spec *chan,
122 				      enum iio_event_type type,
123 				      enum iio_event_direction dir,
124 				      enum iio_event_info info,
125 				      int *val, int *val2)
126 {
127 	struct iio_dummy_state *st = iio_priv(indio_dev);
128 
129 	*val = st->event_val;
130 
131 	return IIO_VAL_INT;
132 }
133 
134 /**
135  * iio_simple_dummy_write_event_value() - set value associate with event
136  * @indio_dev: device instance specific data
137  * @chan: channel for the event whose value is being set
138  * @type: type of the event whose value is being set
139  * @dir: direction of the vent whose value is being set
140  * @info: info type of the event whose value is being set
141  * @val: the value to be set.
142  */
143 int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
144 				       const struct iio_chan_spec *chan,
145 				       enum iio_event_type type,
146 				       enum iio_event_direction dir,
147 				       enum iio_event_info info,
148 				       int val, int val2)
149 {
150 	struct iio_dummy_state *st = iio_priv(indio_dev);
151 
152 	st->event_val = val;
153 
154 	return 0;
155 }
156 
157 static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
158 {
159 	struct iio_dev *indio_dev = private;
160 	struct iio_dummy_state *st = iio_priv(indio_dev);
161 
162 	st->event_timestamp = iio_get_time_ns(indio_dev);
163 	return IRQ_WAKE_THREAD;
164 }
165 
166 /**
167  * iio_simple_dummy_event_handler() - identify and pass on event
168  * @irq: irq of event line
169  * @private: pointer to device instance state.
170  *
171  * This handler is responsible for querying the device to find out what
172  * event occurred and for then pushing that event towards userspace.
173  * Here only one event occurs so we push that directly on with locally
174  * grabbed timestamp.
175  */
176 static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
177 {
178 	struct iio_dev *indio_dev = private;
179 	struct iio_dummy_state *st = iio_priv(indio_dev);
180 
181 	dev_dbg(&indio_dev->dev, "id %x event %x\n",
182 		st->regs->reg_id, st->regs->reg_data);
183 
184 	switch (st->regs->reg_data) {
185 	case 0:
186 		iio_push_event(indio_dev,
187 			       IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
188 					      IIO_EV_DIR_RISING,
189 					      IIO_EV_TYPE_THRESH, 0, 0, 0),
190 			       st->event_timestamp);
191 		break;
192 	case 1:
193 		if (st->activity_running > st->event_val)
194 			iio_push_event(indio_dev,
195 				       IIO_EVENT_CODE(IIO_ACTIVITY, 0,
196 						      IIO_MOD_RUNNING,
197 						      IIO_EV_DIR_RISING,
198 						      IIO_EV_TYPE_THRESH,
199 						      0, 0, 0),
200 				       st->event_timestamp);
201 		break;
202 	case 2:
203 		if (st->activity_walking < st->event_val)
204 			iio_push_event(indio_dev,
205 				       IIO_EVENT_CODE(IIO_ACTIVITY, 0,
206 						      IIO_MOD_WALKING,
207 						      IIO_EV_DIR_FALLING,
208 						      IIO_EV_TYPE_THRESH,
209 						      0, 0, 0),
210 				       st->event_timestamp);
211 		break;
212 	case 3:
213 		iio_push_event(indio_dev,
214 			       IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
215 					      IIO_EV_DIR_NONE,
216 					      IIO_EV_TYPE_CHANGE, 0, 0, 0),
217 			       st->event_timestamp);
218 		break;
219 	default:
220 		break;
221 	}
222 
223 	return IRQ_HANDLED;
224 }
225 
226 /**
227  * iio_simple_dummy_events_register() - setup interrupt handling for events
228  * @indio_dev: device instance data
229  *
230  * This function requests the threaded interrupt to handle the events.
231  * Normally the irq is a hardware interrupt and the number comes
232  * from board configuration files.  Here we get it from a companion
233  * module that fakes the interrupt for us. Note that module in
234  * no way forms part of this example. Just assume that events magically
235  * appear via the provided interrupt.
236  */
237 int iio_simple_dummy_events_register(struct iio_dev *indio_dev)
238 {
239 	struct iio_dummy_state *st = iio_priv(indio_dev);
240 	int ret;
241 
242 	/* Fire up event source - normally not present */
243 	st->event_irq = iio_dummy_evgen_get_irq();
244 	if (st->event_irq < 0) {
245 		ret = st->event_irq;
246 		goto error_ret;
247 	}
248 	st->regs = iio_dummy_evgen_get_regs(st->event_irq);
249 
250 	ret = request_threaded_irq(st->event_irq,
251 				   &iio_simple_dummy_get_timestamp,
252 				   &iio_simple_dummy_event_handler,
253 				   IRQF_ONESHOT,
254 				   "iio_simple_event",
255 				   indio_dev);
256 	if (ret < 0)
257 		goto error_free_evgen;
258 	return 0;
259 
260 error_free_evgen:
261 	iio_dummy_evgen_release_irq(st->event_irq);
262 error_ret:
263 	return ret;
264 }
265 
266 /**
267  * iio_simple_dummy_events_unregister() - tidy up interrupt handling on remove
268  * @indio_dev: device instance data
269  */
270 void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev)
271 {
272 	struct iio_dummy_state *st = iio_priv(indio_dev);
273 
274 	free_irq(st->event_irq, indio_dev);
275 	/* Not part of normal driver */
276 	iio_dummy_evgen_release_irq(st->event_irq);
277 }
278