1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2011 Jonathan Cameron
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * A reference industrial I/O driver to illustrate the functionality available.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * There are numerous real drivers to illustrate the finer points.
8*4882a593Smuzhiyun * The purpose of this driver is to provide a driver with far more comments
9*4882a593Smuzhiyun * and explanatory notes than any 'real' driver would have.
10*4882a593Smuzhiyun * Anyone starting out writing an IIO driver should first make sure they
11*4882a593Smuzhiyun * understand all of this driver except those bits specifically marked
12*4882a593Smuzhiyun * as being present to allow us to 'fake' the presence of hardware.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/string.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <linux/iio/iio.h>
20*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
21*4882a593Smuzhiyun #include <linux/iio/events.h>
22*4882a593Smuzhiyun #include <linux/iio/buffer.h>
23*4882a593Smuzhiyun #include <linux/iio/sw_device.h>
24*4882a593Smuzhiyun #include "iio_simple_dummy.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static const struct config_item_type iio_dummy_type = {
27*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /**
31*4882a593Smuzhiyun * struct iio_dummy_accel_calibscale - realworld to register mapping
32*4882a593Smuzhiyun * @val: first value in read_raw - here integer part.
33*4882a593Smuzhiyun * @val2: second value in read_raw etc - here micro part.
34*4882a593Smuzhiyun * @regval: register value - magic device specific numbers.
35*4882a593Smuzhiyun */
36*4882a593Smuzhiyun struct iio_dummy_accel_calibscale {
37*4882a593Smuzhiyun int val;
38*4882a593Smuzhiyun int val2;
39*4882a593Smuzhiyun int regval; /* what would be written to hardware */
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static const struct iio_dummy_accel_calibscale dummy_scales[] = {
43*4882a593Smuzhiyun { 0, 100, 0x8 }, /* 0.000100 */
44*4882a593Smuzhiyun { 0, 133, 0x7 }, /* 0.000133 */
45*4882a593Smuzhiyun { 733, 13, 0x9 }, /* 733.000013 */
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * simple event - triggered when value rises above
52*4882a593Smuzhiyun * a threshold
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun static const struct iio_event_spec iio_dummy_event = {
55*4882a593Smuzhiyun .type = IIO_EV_TYPE_THRESH,
56*4882a593Smuzhiyun .dir = IIO_EV_DIR_RISING,
57*4882a593Smuzhiyun .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun * simple step detect event - triggered when a step is detected
62*4882a593Smuzhiyun */
63*4882a593Smuzhiyun static const struct iio_event_spec step_detect_event = {
64*4882a593Smuzhiyun .type = IIO_EV_TYPE_CHANGE,
65*4882a593Smuzhiyun .dir = IIO_EV_DIR_NONE,
66*4882a593Smuzhiyun .mask_separate = BIT(IIO_EV_INFO_ENABLE),
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun * simple transition event - triggered when the reported running confidence
71*4882a593Smuzhiyun * value rises above a threshold value
72*4882a593Smuzhiyun */
73*4882a593Smuzhiyun static const struct iio_event_spec iio_running_event = {
74*4882a593Smuzhiyun .type = IIO_EV_TYPE_THRESH,
75*4882a593Smuzhiyun .dir = IIO_EV_DIR_RISING,
76*4882a593Smuzhiyun .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /*
80*4882a593Smuzhiyun * simple transition event - triggered when the reported walking confidence
81*4882a593Smuzhiyun * value falls under a threshold value
82*4882a593Smuzhiyun */
83*4882a593Smuzhiyun static const struct iio_event_spec iio_walking_event = {
84*4882a593Smuzhiyun .type = IIO_EV_TYPE_THRESH,
85*4882a593Smuzhiyun .dir = IIO_EV_DIR_FALLING,
86*4882a593Smuzhiyun .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun #endif
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun * iio_dummy_channels - Description of available channels
92*4882a593Smuzhiyun *
93*4882a593Smuzhiyun * This array of structures tells the IIO core about what the device
94*4882a593Smuzhiyun * actually provides for a given channel.
95*4882a593Smuzhiyun */
96*4882a593Smuzhiyun static const struct iio_chan_spec iio_dummy_channels[] = {
97*4882a593Smuzhiyun /* indexed ADC channel in_voltage0_raw etc */
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun .type = IIO_VOLTAGE,
100*4882a593Smuzhiyun /* Channel has a numeric index of 0 */
101*4882a593Smuzhiyun .indexed = 1,
102*4882a593Smuzhiyun .channel = 0,
103*4882a593Smuzhiyun /* What other information is available? */
104*4882a593Smuzhiyun .info_mask_separate =
105*4882a593Smuzhiyun /*
106*4882a593Smuzhiyun * in_voltage0_raw
107*4882a593Smuzhiyun * Raw (unscaled no bias removal etc) measurement
108*4882a593Smuzhiyun * from the device.
109*4882a593Smuzhiyun */
110*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_RAW) |
111*4882a593Smuzhiyun /*
112*4882a593Smuzhiyun * in_voltage0_offset
113*4882a593Smuzhiyun * Offset for userspace to apply prior to scale
114*4882a593Smuzhiyun * when converting to standard units (microvolts)
115*4882a593Smuzhiyun */
116*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OFFSET) |
117*4882a593Smuzhiyun /*
118*4882a593Smuzhiyun * in_voltage0_scale
119*4882a593Smuzhiyun * Multipler for userspace to apply post offset
120*4882a593Smuzhiyun * when converting to standard units (microvolts)
121*4882a593Smuzhiyun */
122*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_SCALE),
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun * sampling_frequency
125*4882a593Smuzhiyun * The frequency in Hz at which the channels are sampled
126*4882a593Smuzhiyun */
127*4882a593Smuzhiyun .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
128*4882a593Smuzhiyun /* The ordering of elements in the buffer via an enum */
129*4882a593Smuzhiyun .scan_index = DUMMY_INDEX_VOLTAGE_0,
130*4882a593Smuzhiyun .scan_type = { /* Description of storage in buffer */
131*4882a593Smuzhiyun .sign = 'u', /* unsigned */
132*4882a593Smuzhiyun .realbits = 13, /* 13 bits */
133*4882a593Smuzhiyun .storagebits = 16, /* 16 bits used for storage */
134*4882a593Smuzhiyun .shift = 0, /* zero shift */
135*4882a593Smuzhiyun },
136*4882a593Smuzhiyun #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
137*4882a593Smuzhiyun .event_spec = &iio_dummy_event,
138*4882a593Smuzhiyun .num_event_specs = 1,
139*4882a593Smuzhiyun #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
140*4882a593Smuzhiyun },
141*4882a593Smuzhiyun /* Differential ADC channel in_voltage1-voltage2_raw etc*/
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun .type = IIO_VOLTAGE,
144*4882a593Smuzhiyun .differential = 1,
145*4882a593Smuzhiyun /*
146*4882a593Smuzhiyun * Indexing for differential channels uses channel
147*4882a593Smuzhiyun * for the positive part, channel2 for the negative.
148*4882a593Smuzhiyun */
149*4882a593Smuzhiyun .indexed = 1,
150*4882a593Smuzhiyun .channel = 1,
151*4882a593Smuzhiyun .channel2 = 2,
152*4882a593Smuzhiyun /*
153*4882a593Smuzhiyun * in_voltage1-voltage2_raw
154*4882a593Smuzhiyun * Raw (unscaled no bias removal etc) measurement
155*4882a593Smuzhiyun * from the device.
156*4882a593Smuzhiyun */
157*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
158*4882a593Smuzhiyun /*
159*4882a593Smuzhiyun * in_voltage-voltage_scale
160*4882a593Smuzhiyun * Shared version of scale - shared by differential
161*4882a593Smuzhiyun * input channels of type IIO_VOLTAGE.
162*4882a593Smuzhiyun */
163*4882a593Smuzhiyun .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
164*4882a593Smuzhiyun /*
165*4882a593Smuzhiyun * sampling_frequency
166*4882a593Smuzhiyun * The frequency in Hz at which the channels are sampled
167*4882a593Smuzhiyun */
168*4882a593Smuzhiyun .scan_index = DUMMY_INDEX_DIFFVOLTAGE_1M2,
169*4882a593Smuzhiyun .scan_type = { /* Description of storage in buffer */
170*4882a593Smuzhiyun .sign = 's', /* signed */
171*4882a593Smuzhiyun .realbits = 12, /* 12 bits */
172*4882a593Smuzhiyun .storagebits = 16, /* 16 bits used for storage */
173*4882a593Smuzhiyun .shift = 0, /* zero shift */
174*4882a593Smuzhiyun },
175*4882a593Smuzhiyun },
176*4882a593Smuzhiyun /* Differential ADC channel in_voltage3-voltage4_raw etc*/
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun .type = IIO_VOLTAGE,
179*4882a593Smuzhiyun .differential = 1,
180*4882a593Smuzhiyun .indexed = 1,
181*4882a593Smuzhiyun .channel = 3,
182*4882a593Smuzhiyun .channel2 = 4,
183*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
184*4882a593Smuzhiyun .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
185*4882a593Smuzhiyun .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
186*4882a593Smuzhiyun .scan_index = DUMMY_INDEX_DIFFVOLTAGE_3M4,
187*4882a593Smuzhiyun .scan_type = {
188*4882a593Smuzhiyun .sign = 's',
189*4882a593Smuzhiyun .realbits = 11,
190*4882a593Smuzhiyun .storagebits = 16,
191*4882a593Smuzhiyun .shift = 0,
192*4882a593Smuzhiyun },
193*4882a593Smuzhiyun },
194*4882a593Smuzhiyun /*
195*4882a593Smuzhiyun * 'modified' (i.e. axis specified) acceleration channel
196*4882a593Smuzhiyun * in_accel_z_raw
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun .type = IIO_ACCEL,
200*4882a593Smuzhiyun .modified = 1,
201*4882a593Smuzhiyun /* Channel 2 is use for modifiers */
202*4882a593Smuzhiyun .channel2 = IIO_MOD_X,
203*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
204*4882a593Smuzhiyun /*
205*4882a593Smuzhiyun * Internal bias and gain correction values. Applied
206*4882a593Smuzhiyun * by the hardware or driver prior to userspace
207*4882a593Smuzhiyun * seeing the readings. Typically part of hardware
208*4882a593Smuzhiyun * calibration.
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBSCALE) |
211*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBBIAS),
212*4882a593Smuzhiyun .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
213*4882a593Smuzhiyun .scan_index = DUMMY_INDEX_ACCELX,
214*4882a593Smuzhiyun .scan_type = { /* Description of storage in buffer */
215*4882a593Smuzhiyun .sign = 's', /* signed */
216*4882a593Smuzhiyun .realbits = 16, /* 16 bits */
217*4882a593Smuzhiyun .storagebits = 16, /* 16 bits used for storage */
218*4882a593Smuzhiyun .shift = 0, /* zero shift */
219*4882a593Smuzhiyun },
220*4882a593Smuzhiyun },
221*4882a593Smuzhiyun /*
222*4882a593Smuzhiyun * Convenience macro for timestamps. 4 is the index in
223*4882a593Smuzhiyun * the buffer.
224*4882a593Smuzhiyun */
225*4882a593Smuzhiyun IIO_CHAN_SOFT_TIMESTAMP(4),
226*4882a593Smuzhiyun /* DAC channel out_voltage0_raw */
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun .type = IIO_VOLTAGE,
229*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
230*4882a593Smuzhiyun .scan_index = -1, /* No buffer support */
231*4882a593Smuzhiyun .output = 1,
232*4882a593Smuzhiyun .indexed = 1,
233*4882a593Smuzhiyun .channel = 0,
234*4882a593Smuzhiyun },
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun .type = IIO_STEPS,
237*4882a593Smuzhiyun .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) |
238*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBHEIGHT),
239*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
240*4882a593Smuzhiyun .scan_index = -1, /* No buffer support */
241*4882a593Smuzhiyun #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
242*4882a593Smuzhiyun .event_spec = &step_detect_event,
243*4882a593Smuzhiyun .num_event_specs = 1,
244*4882a593Smuzhiyun #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
245*4882a593Smuzhiyun },
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun .type = IIO_ACTIVITY,
248*4882a593Smuzhiyun .modified = 1,
249*4882a593Smuzhiyun .channel2 = IIO_MOD_RUNNING,
250*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
251*4882a593Smuzhiyun .scan_index = -1, /* No buffer support */
252*4882a593Smuzhiyun #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
253*4882a593Smuzhiyun .event_spec = &iio_running_event,
254*4882a593Smuzhiyun .num_event_specs = 1,
255*4882a593Smuzhiyun #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
256*4882a593Smuzhiyun },
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun .type = IIO_ACTIVITY,
259*4882a593Smuzhiyun .modified = 1,
260*4882a593Smuzhiyun .channel2 = IIO_MOD_WALKING,
261*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
262*4882a593Smuzhiyun .scan_index = -1, /* No buffer support */
263*4882a593Smuzhiyun #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
264*4882a593Smuzhiyun .event_spec = &iio_walking_event,
265*4882a593Smuzhiyun .num_event_specs = 1,
266*4882a593Smuzhiyun #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
267*4882a593Smuzhiyun },
268*4882a593Smuzhiyun };
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /**
271*4882a593Smuzhiyun * iio_dummy_read_raw() - data read function.
272*4882a593Smuzhiyun * @indio_dev: the struct iio_dev associated with this device instance
273*4882a593Smuzhiyun * @chan: the channel whose data is to be read
274*4882a593Smuzhiyun * @val: first element of returned value (typically INT)
275*4882a593Smuzhiyun * @val2: second element of returned value (typically MICRO)
276*4882a593Smuzhiyun * @mask: what we actually want to read as per the info_mask_*
277*4882a593Smuzhiyun * in iio_chan_spec.
278*4882a593Smuzhiyun */
iio_dummy_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)279*4882a593Smuzhiyun static int iio_dummy_read_raw(struct iio_dev *indio_dev,
280*4882a593Smuzhiyun struct iio_chan_spec const *chan,
281*4882a593Smuzhiyun int *val,
282*4882a593Smuzhiyun int *val2,
283*4882a593Smuzhiyun long mask)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun struct iio_dummy_state *st = iio_priv(indio_dev);
286*4882a593Smuzhiyun int ret = -EINVAL;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun mutex_lock(&st->lock);
289*4882a593Smuzhiyun switch (mask) {
290*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW: /* magic value - channel value read */
291*4882a593Smuzhiyun switch (chan->type) {
292*4882a593Smuzhiyun case IIO_VOLTAGE:
293*4882a593Smuzhiyun if (chan->output) {
294*4882a593Smuzhiyun /* Set integer part to cached value */
295*4882a593Smuzhiyun *val = st->dac_val;
296*4882a593Smuzhiyun ret = IIO_VAL_INT;
297*4882a593Smuzhiyun } else if (chan->differential) {
298*4882a593Smuzhiyun if (chan->channel == 1)
299*4882a593Smuzhiyun *val = st->differential_adc_val[0];
300*4882a593Smuzhiyun else
301*4882a593Smuzhiyun *val = st->differential_adc_val[1];
302*4882a593Smuzhiyun ret = IIO_VAL_INT;
303*4882a593Smuzhiyun } else {
304*4882a593Smuzhiyun *val = st->single_ended_adc_val;
305*4882a593Smuzhiyun ret = IIO_VAL_INT;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun case IIO_ACCEL:
309*4882a593Smuzhiyun *val = st->accel_val;
310*4882a593Smuzhiyun ret = IIO_VAL_INT;
311*4882a593Smuzhiyun break;
312*4882a593Smuzhiyun default:
313*4882a593Smuzhiyun break;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun case IIO_CHAN_INFO_PROCESSED:
317*4882a593Smuzhiyun switch (chan->type) {
318*4882a593Smuzhiyun case IIO_STEPS:
319*4882a593Smuzhiyun *val = st->steps;
320*4882a593Smuzhiyun ret = IIO_VAL_INT;
321*4882a593Smuzhiyun break;
322*4882a593Smuzhiyun case IIO_ACTIVITY:
323*4882a593Smuzhiyun switch (chan->channel2) {
324*4882a593Smuzhiyun case IIO_MOD_RUNNING:
325*4882a593Smuzhiyun *val = st->activity_running;
326*4882a593Smuzhiyun ret = IIO_VAL_INT;
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun case IIO_MOD_WALKING:
329*4882a593Smuzhiyun *val = st->activity_walking;
330*4882a593Smuzhiyun ret = IIO_VAL_INT;
331*4882a593Smuzhiyun break;
332*4882a593Smuzhiyun default:
333*4882a593Smuzhiyun break;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun break;
336*4882a593Smuzhiyun default:
337*4882a593Smuzhiyun break;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun case IIO_CHAN_INFO_OFFSET:
341*4882a593Smuzhiyun /* only single ended adc -> 7 */
342*4882a593Smuzhiyun *val = 7;
343*4882a593Smuzhiyun ret = IIO_VAL_INT;
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
346*4882a593Smuzhiyun switch (chan->type) {
347*4882a593Smuzhiyun case IIO_VOLTAGE:
348*4882a593Smuzhiyun switch (chan->differential) {
349*4882a593Smuzhiyun case 0:
350*4882a593Smuzhiyun /* only single ended adc -> 0.001333 */
351*4882a593Smuzhiyun *val = 0;
352*4882a593Smuzhiyun *val2 = 1333;
353*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
354*4882a593Smuzhiyun break;
355*4882a593Smuzhiyun case 1:
356*4882a593Smuzhiyun /* all differential adc -> 0.000001344 */
357*4882a593Smuzhiyun *val = 0;
358*4882a593Smuzhiyun *val2 = 1344;
359*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_NANO;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun break;
362*4882a593Smuzhiyun default:
363*4882a593Smuzhiyun break;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun break;
366*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBBIAS:
367*4882a593Smuzhiyun /* only the acceleration axis - read from cache */
368*4882a593Smuzhiyun *val = st->accel_calibbias;
369*4882a593Smuzhiyun ret = IIO_VAL_INT;
370*4882a593Smuzhiyun break;
371*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBSCALE:
372*4882a593Smuzhiyun *val = st->accel_calibscale->val;
373*4882a593Smuzhiyun *val2 = st->accel_calibscale->val2;
374*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun case IIO_CHAN_INFO_SAMP_FREQ:
377*4882a593Smuzhiyun *val = 3;
378*4882a593Smuzhiyun *val2 = 33;
379*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_NANO;
380*4882a593Smuzhiyun break;
381*4882a593Smuzhiyun case IIO_CHAN_INFO_ENABLE:
382*4882a593Smuzhiyun switch (chan->type) {
383*4882a593Smuzhiyun case IIO_STEPS:
384*4882a593Smuzhiyun *val = st->steps_enabled;
385*4882a593Smuzhiyun ret = IIO_VAL_INT;
386*4882a593Smuzhiyun break;
387*4882a593Smuzhiyun default:
388*4882a593Smuzhiyun break;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun break;
391*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBHEIGHT:
392*4882a593Smuzhiyun switch (chan->type) {
393*4882a593Smuzhiyun case IIO_STEPS:
394*4882a593Smuzhiyun *val = st->height;
395*4882a593Smuzhiyun ret = IIO_VAL_INT;
396*4882a593Smuzhiyun break;
397*4882a593Smuzhiyun default:
398*4882a593Smuzhiyun break;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun break;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun default:
403*4882a593Smuzhiyun break;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun mutex_unlock(&st->lock);
406*4882a593Smuzhiyun return ret;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun /**
410*4882a593Smuzhiyun * iio_dummy_write_raw() - data write function.
411*4882a593Smuzhiyun * @indio_dev: the struct iio_dev associated with this device instance
412*4882a593Smuzhiyun * @chan: the channel whose data is to be written
413*4882a593Smuzhiyun * @val: first element of value to set (typically INT)
414*4882a593Smuzhiyun * @val2: second element of value to set (typically MICRO)
415*4882a593Smuzhiyun * @mask: what we actually want to write as per the info_mask_*
416*4882a593Smuzhiyun * in iio_chan_spec.
417*4882a593Smuzhiyun *
418*4882a593Smuzhiyun * Note that all raw writes are assumed IIO_VAL_INT and info mask elements
419*4882a593Smuzhiyun * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt
420*4882a593Smuzhiyun * in struct iio_info is provided by the driver.
421*4882a593Smuzhiyun */
iio_dummy_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)422*4882a593Smuzhiyun static int iio_dummy_write_raw(struct iio_dev *indio_dev,
423*4882a593Smuzhiyun struct iio_chan_spec const *chan,
424*4882a593Smuzhiyun int val,
425*4882a593Smuzhiyun int val2,
426*4882a593Smuzhiyun long mask)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun int i;
429*4882a593Smuzhiyun int ret = 0;
430*4882a593Smuzhiyun struct iio_dummy_state *st = iio_priv(indio_dev);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun switch (mask) {
433*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
434*4882a593Smuzhiyun switch (chan->type) {
435*4882a593Smuzhiyun case IIO_VOLTAGE:
436*4882a593Smuzhiyun if (chan->output == 0)
437*4882a593Smuzhiyun return -EINVAL;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /* Locking not required as writing single value */
440*4882a593Smuzhiyun mutex_lock(&st->lock);
441*4882a593Smuzhiyun st->dac_val = val;
442*4882a593Smuzhiyun mutex_unlock(&st->lock);
443*4882a593Smuzhiyun return 0;
444*4882a593Smuzhiyun default:
445*4882a593Smuzhiyun return -EINVAL;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun case IIO_CHAN_INFO_PROCESSED:
448*4882a593Smuzhiyun switch (chan->type) {
449*4882a593Smuzhiyun case IIO_STEPS:
450*4882a593Smuzhiyun mutex_lock(&st->lock);
451*4882a593Smuzhiyun st->steps = val;
452*4882a593Smuzhiyun mutex_unlock(&st->lock);
453*4882a593Smuzhiyun return 0;
454*4882a593Smuzhiyun case IIO_ACTIVITY:
455*4882a593Smuzhiyun if (val < 0)
456*4882a593Smuzhiyun val = 0;
457*4882a593Smuzhiyun if (val > 100)
458*4882a593Smuzhiyun val = 100;
459*4882a593Smuzhiyun switch (chan->channel2) {
460*4882a593Smuzhiyun case IIO_MOD_RUNNING:
461*4882a593Smuzhiyun st->activity_running = val;
462*4882a593Smuzhiyun return 0;
463*4882a593Smuzhiyun case IIO_MOD_WALKING:
464*4882a593Smuzhiyun st->activity_walking = val;
465*4882a593Smuzhiyun return 0;
466*4882a593Smuzhiyun default:
467*4882a593Smuzhiyun return -EINVAL;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun break;
470*4882a593Smuzhiyun default:
471*4882a593Smuzhiyun return -EINVAL;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBSCALE:
474*4882a593Smuzhiyun mutex_lock(&st->lock);
475*4882a593Smuzhiyun /* Compare against table - hard matching here */
476*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(dummy_scales); i++)
477*4882a593Smuzhiyun if (val == dummy_scales[i].val &&
478*4882a593Smuzhiyun val2 == dummy_scales[i].val2)
479*4882a593Smuzhiyun break;
480*4882a593Smuzhiyun if (i == ARRAY_SIZE(dummy_scales))
481*4882a593Smuzhiyun ret = -EINVAL;
482*4882a593Smuzhiyun else
483*4882a593Smuzhiyun st->accel_calibscale = &dummy_scales[i];
484*4882a593Smuzhiyun mutex_unlock(&st->lock);
485*4882a593Smuzhiyun return ret;
486*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBBIAS:
487*4882a593Smuzhiyun mutex_lock(&st->lock);
488*4882a593Smuzhiyun st->accel_calibbias = val;
489*4882a593Smuzhiyun mutex_unlock(&st->lock);
490*4882a593Smuzhiyun return 0;
491*4882a593Smuzhiyun case IIO_CHAN_INFO_ENABLE:
492*4882a593Smuzhiyun switch (chan->type) {
493*4882a593Smuzhiyun case IIO_STEPS:
494*4882a593Smuzhiyun mutex_lock(&st->lock);
495*4882a593Smuzhiyun st->steps_enabled = val;
496*4882a593Smuzhiyun mutex_unlock(&st->lock);
497*4882a593Smuzhiyun return 0;
498*4882a593Smuzhiyun default:
499*4882a593Smuzhiyun return -EINVAL;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBHEIGHT:
502*4882a593Smuzhiyun switch (chan->type) {
503*4882a593Smuzhiyun case IIO_STEPS:
504*4882a593Smuzhiyun st->height = val;
505*4882a593Smuzhiyun return 0;
506*4882a593Smuzhiyun default:
507*4882a593Smuzhiyun return -EINVAL;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun default:
511*4882a593Smuzhiyun return -EINVAL;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /*
516*4882a593Smuzhiyun * Device type specific information.
517*4882a593Smuzhiyun */
518*4882a593Smuzhiyun static const struct iio_info iio_dummy_info = {
519*4882a593Smuzhiyun .read_raw = &iio_dummy_read_raw,
520*4882a593Smuzhiyun .write_raw = &iio_dummy_write_raw,
521*4882a593Smuzhiyun #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
522*4882a593Smuzhiyun .read_event_config = &iio_simple_dummy_read_event_config,
523*4882a593Smuzhiyun .write_event_config = &iio_simple_dummy_write_event_config,
524*4882a593Smuzhiyun .read_event_value = &iio_simple_dummy_read_event_value,
525*4882a593Smuzhiyun .write_event_value = &iio_simple_dummy_write_event_value,
526*4882a593Smuzhiyun #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
527*4882a593Smuzhiyun };
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /**
530*4882a593Smuzhiyun * iio_dummy_init_device() - device instance specific init
531*4882a593Smuzhiyun * @indio_dev: the iio device structure
532*4882a593Smuzhiyun *
533*4882a593Smuzhiyun * Most drivers have one of these to set up default values,
534*4882a593Smuzhiyun * reset the device to known state etc.
535*4882a593Smuzhiyun */
iio_dummy_init_device(struct iio_dev * indio_dev)536*4882a593Smuzhiyun static int iio_dummy_init_device(struct iio_dev *indio_dev)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun struct iio_dummy_state *st = iio_priv(indio_dev);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun st->dac_val = 0;
541*4882a593Smuzhiyun st->single_ended_adc_val = 73;
542*4882a593Smuzhiyun st->differential_adc_val[0] = 33;
543*4882a593Smuzhiyun st->differential_adc_val[1] = -34;
544*4882a593Smuzhiyun st->accel_val = 34;
545*4882a593Smuzhiyun st->accel_calibbias = -7;
546*4882a593Smuzhiyun st->accel_calibscale = &dummy_scales[0];
547*4882a593Smuzhiyun st->steps = 47;
548*4882a593Smuzhiyun st->activity_running = 98;
549*4882a593Smuzhiyun st->activity_walking = 4;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun return 0;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /**
555*4882a593Smuzhiyun * iio_dummy_probe() - device instance probe
556*4882a593Smuzhiyun * @name: name of this instance.
557*4882a593Smuzhiyun *
558*4882a593Smuzhiyun * Arguments are bus type specific.
559*4882a593Smuzhiyun * I2C: iio_dummy_probe(struct i2c_client *client,
560*4882a593Smuzhiyun * const struct i2c_device_id *id)
561*4882a593Smuzhiyun * SPI: iio_dummy_probe(struct spi_device *spi)
562*4882a593Smuzhiyun */
iio_dummy_probe(const char * name)563*4882a593Smuzhiyun static struct iio_sw_device *iio_dummy_probe(const char *name)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun int ret;
566*4882a593Smuzhiyun struct iio_dev *indio_dev;
567*4882a593Smuzhiyun struct iio_dummy_state *st;
568*4882a593Smuzhiyun struct iio_sw_device *swd;
569*4882a593Smuzhiyun struct device *parent = NULL;
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /*
572*4882a593Smuzhiyun * With hardware: Set the parent device.
573*4882a593Smuzhiyun * parent = &spi->dev;
574*4882a593Smuzhiyun * parent = &client->dev;
575*4882a593Smuzhiyun */
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun swd = kzalloc(sizeof(*swd), GFP_KERNEL);
578*4882a593Smuzhiyun if (!swd)
579*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun /*
582*4882a593Smuzhiyun * Allocate an IIO device.
583*4882a593Smuzhiyun *
584*4882a593Smuzhiyun * This structure contains all generic state
585*4882a593Smuzhiyun * information about the device instance.
586*4882a593Smuzhiyun * It also has a region (accessed by iio_priv()
587*4882a593Smuzhiyun * for chip specific state information.
588*4882a593Smuzhiyun */
589*4882a593Smuzhiyun indio_dev = iio_device_alloc(parent, sizeof(*st));
590*4882a593Smuzhiyun if (!indio_dev) {
591*4882a593Smuzhiyun ret = -ENOMEM;
592*4882a593Smuzhiyun goto error_free_swd;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun st = iio_priv(indio_dev);
596*4882a593Smuzhiyun mutex_init(&st->lock);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun iio_dummy_init_device(indio_dev);
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun /*
601*4882a593Smuzhiyun * Make the iio_dev struct available to remove function.
602*4882a593Smuzhiyun * Bus equivalents
603*4882a593Smuzhiyun * i2c_set_clientdata(client, indio_dev);
604*4882a593Smuzhiyun * spi_set_drvdata(spi, indio_dev);
605*4882a593Smuzhiyun */
606*4882a593Smuzhiyun swd->device = indio_dev;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun /*
609*4882a593Smuzhiyun * Set the device name.
610*4882a593Smuzhiyun *
611*4882a593Smuzhiyun * This is typically a part number and obtained from the module
612*4882a593Smuzhiyun * id table.
613*4882a593Smuzhiyun * e.g. for i2c and spi:
614*4882a593Smuzhiyun * indio_dev->name = id->name;
615*4882a593Smuzhiyun * indio_dev->name = spi_get_device_id(spi)->name;
616*4882a593Smuzhiyun */
617*4882a593Smuzhiyun indio_dev->name = kstrdup(name, GFP_KERNEL);
618*4882a593Smuzhiyun if (!indio_dev->name) {
619*4882a593Smuzhiyun ret = -ENOMEM;
620*4882a593Smuzhiyun goto error_free_device;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun /* Provide description of available channels */
624*4882a593Smuzhiyun indio_dev->channels = iio_dummy_channels;
625*4882a593Smuzhiyun indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels);
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun /*
628*4882a593Smuzhiyun * Provide device type specific interface functions and
629*4882a593Smuzhiyun * constant data.
630*4882a593Smuzhiyun */
631*4882a593Smuzhiyun indio_dev->info = &iio_dummy_info;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun /* Specify that device provides sysfs type interfaces */
634*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun ret = iio_simple_dummy_events_register(indio_dev);
637*4882a593Smuzhiyun if (ret < 0)
638*4882a593Smuzhiyun goto error_free_name;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun ret = iio_simple_dummy_configure_buffer(indio_dev);
641*4882a593Smuzhiyun if (ret < 0)
642*4882a593Smuzhiyun goto error_unregister_events;
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun ret = iio_device_register(indio_dev);
645*4882a593Smuzhiyun if (ret < 0)
646*4882a593Smuzhiyun goto error_unconfigure_buffer;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun iio_swd_group_init_type_name(swd, name, &iio_dummy_type);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun return swd;
651*4882a593Smuzhiyun error_unconfigure_buffer:
652*4882a593Smuzhiyun iio_simple_dummy_unconfigure_buffer(indio_dev);
653*4882a593Smuzhiyun error_unregister_events:
654*4882a593Smuzhiyun iio_simple_dummy_events_unregister(indio_dev);
655*4882a593Smuzhiyun error_free_name:
656*4882a593Smuzhiyun kfree(indio_dev->name);
657*4882a593Smuzhiyun error_free_device:
658*4882a593Smuzhiyun iio_device_free(indio_dev);
659*4882a593Smuzhiyun error_free_swd:
660*4882a593Smuzhiyun kfree(swd);
661*4882a593Smuzhiyun return ERR_PTR(ret);
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /**
665*4882a593Smuzhiyun * iio_dummy_remove() - device instance removal function
666*4882a593Smuzhiyun * @swd: pointer to software IIO device abstraction
667*4882a593Smuzhiyun *
668*4882a593Smuzhiyun * Parameters follow those of iio_dummy_probe for buses.
669*4882a593Smuzhiyun */
iio_dummy_remove(struct iio_sw_device * swd)670*4882a593Smuzhiyun static int iio_dummy_remove(struct iio_sw_device *swd)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun /*
673*4882a593Smuzhiyun * Get a pointer to the device instance iio_dev structure
674*4882a593Smuzhiyun * from the bus subsystem. E.g.
675*4882a593Smuzhiyun * struct iio_dev *indio_dev = i2c_get_clientdata(client);
676*4882a593Smuzhiyun * struct iio_dev *indio_dev = spi_get_drvdata(spi);
677*4882a593Smuzhiyun */
678*4882a593Smuzhiyun struct iio_dev *indio_dev = swd->device;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun /* Unregister the device */
681*4882a593Smuzhiyun iio_device_unregister(indio_dev);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun /* Device specific code to power down etc */
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun /* Buffered capture related cleanup */
686*4882a593Smuzhiyun iio_simple_dummy_unconfigure_buffer(indio_dev);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun iio_simple_dummy_events_unregister(indio_dev);
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun /* Free all structures */
691*4882a593Smuzhiyun kfree(indio_dev->name);
692*4882a593Smuzhiyun iio_device_free(indio_dev);
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun return 0;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun /*
698*4882a593Smuzhiyun * module_iio_sw_device_driver() - device driver registration
699*4882a593Smuzhiyun *
700*4882a593Smuzhiyun * Varies depending on bus type of the device. As there is no device
701*4882a593Smuzhiyun * here, call probe directly. For information on device registration
702*4882a593Smuzhiyun * i2c:
703*4882a593Smuzhiyun * Documentation/i2c/writing-clients.rst
704*4882a593Smuzhiyun * spi:
705*4882a593Smuzhiyun * Documentation/spi/spi-summary.rst
706*4882a593Smuzhiyun */
707*4882a593Smuzhiyun static const struct iio_sw_device_ops iio_dummy_device_ops = {
708*4882a593Smuzhiyun .probe = iio_dummy_probe,
709*4882a593Smuzhiyun .remove = iio_dummy_remove,
710*4882a593Smuzhiyun };
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun static struct iio_sw_device_type iio_dummy_device = {
713*4882a593Smuzhiyun .name = "dummy",
714*4882a593Smuzhiyun .owner = THIS_MODULE,
715*4882a593Smuzhiyun .ops = &iio_dummy_device_ops,
716*4882a593Smuzhiyun };
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun module_iio_sw_device_driver(iio_dummy_device);
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
721*4882a593Smuzhiyun MODULE_DESCRIPTION("IIO dummy driver");
722*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
723