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