aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@cam.ac.uk>2011-10-14 11:34:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-17 18:36:29 -0400
commit3a84331db23b4cb4c497ef5aa5f7aea65d936309 (patch)
treed502afefaba4cffec0646779c6aa684e6371e358 /drivers
parent9c95e01e84e31178b9a83b683a501ed76166c259 (diff)
staging:iio:Documentation Simple dummy driver to explain the basics
The documenation explaining how to go about writing a driver is lagging horribly, so here is another approach; an actual driver with lots of explanatory comments. Note it is currently minimal in that there are no events and no buffer. With care they can probably be added in additional files without messing up the clarity of what we have here. V2: Addressed some of Manuel Stahl's feedback. Fixed up kernel doc. Added more general description. Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/iio/Kconfig8
-rw-r--r--drivers/staging/iio/Makefile2
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c481
3 files changed, 491 insertions, 0 deletions
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index db4a79ff2ec6..0accc21d4e91 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -70,4 +70,12 @@ source "drivers/staging/iio/meter/Kconfig"
70source "drivers/staging/iio/resolver/Kconfig" 70source "drivers/staging/iio/resolver/Kconfig"
71source "drivers/staging/iio/trigger/Kconfig" 71source "drivers/staging/iio/trigger/Kconfig"
72 72
73config IIO_SIMPLE_DUMMY
74 tristate "An example driver with no hardware requirements"
75 help
76 Driver intended mainly as documentation for how to write
77 a driver. May also be useful for testing userspace code
78 without hardward.
79
80
73endif # IIO 81endif # IIO
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
index 788397d1a4ba..014d8f1bf61e 100644
--- a/drivers/staging/iio/Makefile
+++ b/drivers/staging/iio/Makefile
@@ -10,6 +10,8 @@ industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
10obj-$(CONFIG_IIO_SW_RING) += ring_sw.o 10obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
11obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o 11obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
12 12
13obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_simple_dummy.o
14
13obj-y += accel/ 15obj-y += accel/
14obj-y += adc/ 16obj-y += adc/
15obj-y += addac/ 17obj-y += addac/
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
new file mode 100644
index 000000000000..314a4a6d3aea
--- /dev/null
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -0,0 +1,481 @@
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 * A reference industrial I/O driver to illustrate the functionality available.
9 *
10 * There are numerous real drivers to illustrate the finer points.
11 * The purpose of this driver is to provide a driver with far more comments
12 * and explanatory notes than any 'real' driver would have.
13 * Anyone starting out writing an IIO driver should first make sure they
14 * understand all of this driver except those bits specifically marked
15 * as being present to allow us to 'fake' the presence of hardware.
16 */
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21
22#include "iio.h"
23
24/*
25 * A few elements needed to fake a bus for this driver
26 * Note instances parmeter controls how many of these
27 * dummy devices are registered.
28 */
29static unsigned instances = 1;
30module_param(instances, int, 0);
31
32/* Pointer array used to fake bus elements */
33static struct iio_dev **iio_dummy_devs;
34
35/* Fake a name for the part number, usually obtained from the id table */
36static const char *iio_dummy_part_number = "iio_dummy_part_no";
37
38/**
39 * struct iio_dummy_accel_calibscale - realworld to register mapping
40 * @val: first value in read_raw - here integer part.
41 * @val2: second value in read_raw etc - here micro part.
42 * @regval: register value - magic device specific numbers.
43 */
44struct iio_dummy_accel_calibscale {
45 int val;
46 int val2;
47 int regval; /* what would be written to hardware */
48};
49
50static const struct iio_dummy_accel_calibscale dummy_scales[] = {
51 { 0, 100, 0x8 }, /* 0.000100 */
52 { 0, 133, 0x7 }, /* 0.000133 */
53 { 733, 13, 0x9 }, /* 733.00013 */
54};
55
56/**
57 * struct iio_dummy_state - device instance specific state.
58 * @dac_val: cache for dac value
59 * @single_ended_adc_val: cache for single ended adc value
60 * @differential_adc_val: cache for differential adc value
61 * @accel_val: cache for acceleration value
62 * @accel_calibbias: cache for acceleration calibbias
63 * @accel_calibscale: cache for acceleration calibscale
64 * @lock: lock to ensure state is consistent
65 */
66struct iio_dummy_state {
67 int dac_val;
68 int single_ended_adc_val;
69 int differential_adc_val[2];
70 int accel_val;
71 int accel_calibbias;
72 const struct iio_dummy_accel_calibscale *accel_calibscale;
73 struct mutex lock;
74};
75
76/*
77 * iio_dummy_channels - Description of available channels
78 *
79 * This array of structures tells the IIO core about what the device
80 * actually provides for a given channel.
81 */
82static struct iio_chan_spec iio_dummy_channels[] = {
83 /* indexed ADC channel in_voltage0_raw etc */
84 {
85 .type = IIO_VOLTAGE,
86 /* Channel has a numeric index of 0 */
87 .indexed = 1,
88 .channel = 0,
89 /* What other information is available? */
90 .info_mask =
91 /*
92 * in_voltage0_offset
93 * Offset for userspace to apply prior to scale
94 * when converting to standard units (microvolts)
95 */
96 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
97 /*
98 * in_voltage0_scale
99 * Multipler for userspace to apply post offset
100 * when converting to standard units (microvolts)
101 */
102 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
103
104 },
105 /* Differential ADC channel in_voltage1-voltage2_raw etc*/
106 {
107 .type = IIO_VOLTAGE,
108 .differential = 1,
109 /*
110 * Indexing for differential channels uses channel
111 * for the positive part, channel2 for the negative.
112 */
113 .indexed = 1,
114 .channel = 1,
115 .channel2 = 2,
116 .info_mask =
117 /*
118 * in_voltage-voltage_scale
119 * Shared version of scale - shared by differential
120 * input channels of type IIO_VOLTAGE.
121 */
122 (1 << IIO_CHAN_INFO_SCALE_SHARED),
123 },
124 /* Differential ADC channel in_voltage3-voltage4_raw etc*/
125 {
126 .type = IIO_VOLTAGE,
127 .differential = 1,
128 .indexed = 1,
129 .channel = 3,
130 .channel2 = 4,
131 .info_mask =
132 (1 << IIO_CHAN_INFO_SCALE_SHARED),
133 },
134 /* DAC channel out_voltage0_raw */
135 {
136 .type = IIO_VOLTAGE,
137 .output = 1,
138 .indexed = 1,
139 .channel = 0,
140 },
141 /*
142 * 'modified' (i.e. axis specified) acceleration channel
143 * in_accel_z_raw
144 */
145 {
146 .type = IIO_ACCEL,
147 .modified = 1,
148 /* Channel 2 is use for modifiers */
149 .channel2 = IIO_MOD_X,
150 .info_mask =
151 /*
152 * Internal bias correction value. Applied
153 * by the hardware or driver prior to userspace
154 * seeing the readings. Typically part of hardware
155 * calibration.
156 */
157 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
158 },
159};
160
161/**
162 * iio_dummy_read_raw() - data read function.
163 * @indio_dev: the struct iio_dev associated with this device instance
164 * @chan: the channel whose data is to be read
165 * @val: first element of returned value (typically INT)
166 * @val2: second element of returned value (typically MICRO)
167 * @mask: what we actually want to read. 0 is the channel, everything else
168 * is as per the info_mask in iio_chan_spec.
169 */
170static int iio_dummy_read_raw(struct iio_dev *indio_dev,
171 struct iio_chan_spec const *chan,
172 int *val,
173 int *val2,
174 long mask)
175{
176 struct iio_dummy_state *st = iio_priv(indio_dev);
177 int ret = -EINVAL;
178
179 mutex_lock(&st->lock);
180 switch (mask) {
181 case 0: /* magic value - channel value read */
182 switch (chan->type) {
183 case IIO_VOLTAGE:
184 if (chan->output) {
185 /* Set integer part to cached value */
186 *val = st->dac_val;
187 ret = IIO_VAL_INT;
188 } else if (chan->differential) {
189 if (chan->channel == 1)
190 *val = st->differential_adc_val[0];
191 else
192 *val = st->differential_adc_val[1];
193 ret = IIO_VAL_INT;
194 } else {
195 *val = st->single_ended_adc_val;
196 ret = IIO_VAL_INT;
197 }
198 break;
199 case IIO_ACCEL:
200 *val = st->accel_val;
201 ret = IIO_VAL_INT;
202 break;
203 default:
204 break;
205 }
206 break;
207 case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
208 /* only single ended adc -> 7 */
209 *val = 7;
210 ret = IIO_VAL_INT;
211 break;
212 case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
213 /* only single ended adc -> 0.001333 */
214 *val = 0;
215 *val2 = 1333;
216 ret = IIO_VAL_INT_PLUS_MICRO;
217 break;
218 case (1 << IIO_CHAN_INFO_SCALE_SHARED):
219 /* all differential adc channels -> 0.000001344 */
220 *val = 0;
221 *val2 = 1344;
222 ret = IIO_VAL_INT_PLUS_NANO;
223 break;
224 case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
225 /* only the acceleration axis - read from cache */
226 *val = st->accel_calibbias;
227 ret = IIO_VAL_INT;
228 break;
229 case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
230 *val = st->accel_calibscale->val;
231 *val2 = st->accel_calibscale->val2;
232 ret = IIO_VAL_INT_PLUS_MICRO;
233 break;
234 default:
235 break;
236 }
237 mutex_unlock(&st->lock);
238 return ret;
239}
240
241/**
242 * iio_dummy_write_raw() - data write function.
243 * @indio_dev: the struct iio_dev associated with this device instance
244 * @chan: the channel whose data is to be read
245 * @val: first element of returned value (typically INT)
246 * @val2: second element of returned value (typically MICRO)
247 * @mask: what we actually want to read. 0 is the channel, everything else
248 * is as per the info_mask in iio_chan_spec.
249 *
250 * Note that all raw writes are assumed IIO_VAL_INT and info mask elements
251 * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt
252 * in struct iio_info is provided by the driver.
253 */
254static int iio_dummy_write_raw(struct iio_dev *indio_dev,
255 struct iio_chan_spec const *chan,
256 int val,
257 int val2,
258 long mask)
259{
260 int i;
261 int ret = 0;
262 struct iio_dummy_state *st = iio_priv(indio_dev);
263
264 switch (mask) {
265 case 0:
266 if (chan->output == 0)
267 return -EINVAL;
268
269 /* Locking not required as writing single value */
270 mutex_lock(&st->lock);
271 st->dac_val = val;
272 mutex_unlock(&st->lock);
273 return 0;
274 case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
275 mutex_lock(&st->lock);
276 /* Compare against table - hard matching here */
277 for (i = 0; i < ARRAY_SIZE(dummy_scales); i++)
278 if (val == dummy_scales[i].val &&
279 val2 == dummy_scales[i].val2)
280 break;
281 if (i == ARRAY_SIZE(dummy_scales))
282 ret = -EINVAL;
283 else
284 st->accel_calibscale = &dummy_scales[i];
285 mutex_unlock(&st->lock);
286 return ret;
287 default:
288 return -EINVAL;
289 }
290}
291
292/*
293 * Device type specific information.
294 */
295static const struct iio_info iio_dummy_info = {
296 .driver_module = THIS_MODULE,
297 .read_raw = &iio_dummy_read_raw,
298 .write_raw = &iio_dummy_write_raw,
299};
300
301/**
302 * iio_dummy_init_device() - device instance specific init
303 * @indio_dev: the iio device structure
304 *
305 * Most drivers have one of these to set up default values,
306 * reset the device to known state etc.
307 */
308static int iio_dummy_init_device(struct iio_dev *indio_dev)
309{
310 struct iio_dummy_state *st = iio_priv(indio_dev);
311
312 st->dac_val = 0;
313 st->single_ended_adc_val = 73;
314 st->differential_adc_val[0] = 33;
315 st->differential_adc_val[1] = -34;
316 st->accel_val = 34;
317 st->accel_calibbias = -7;
318 st->accel_calibscale = &dummy_scales[0];
319
320 return 0;
321}
322
323/**
324 * iio_dummy_probe() - device instance probe
325 * @index: an id number for this instance.
326 *
327 * Arguments are bus type specific.
328 * I2C: iio_dummy_probe(struct i2c_client *client,
329 * const struct i2c_device_id *id)
330 * SPI: iio_dummy_probe(struct spi_device *spi)
331 */
332static int __devinit iio_dummy_probe(int index)
333{
334 int ret;
335 struct iio_dev *indio_dev;
336 struct iio_dummy_state *st;
337
338 /*
339 * Allocate an IIO device.
340 *
341 * This structure contains all generic state
342 * information about the device instance.
343 * It also has a region (accessed by iio_priv()
344 * for chip specific state information.
345 */
346 indio_dev = iio_allocate_device(sizeof(*st));
347 if (indio_dev == NULL) {
348 ret = -ENOMEM;
349 goto error_ret;
350 }
351
352 st = iio_priv(indio_dev);
353 mutex_init(&st->lock);
354
355 iio_dummy_init_device(indio_dev);
356 /*
357 * With hardware: Set the parent device.
358 * indio_dev->dev.parent = &spi->dev;
359 * indio_dev->dev.parent = &client->dev;
360 */
361
362 /*
363 * Make the iio_dev struct available to remove function.
364 * Bus equivalents
365 * i2c_set_clientdata(client, indio_dev);
366 * spi_set_drvdata(spi, indio_dev);
367 */
368 iio_dummy_devs[index] = indio_dev;
369
370
371 /*
372 * Set the device name.
373 *
374 * This is typically a part number and obtained from the module
375 * id table.
376 * e.g. for i2c and spi:
377 * indio_dev->name = id->name;
378 * indio_dev->name = spi_get_device_id(spi)->name;
379 */
380 indio_dev->name = iio_dummy_part_number;
381
382 /* Provide description of available channels */
383 indio_dev->channels = iio_dummy_channels;
384 indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels);
385
386 /*
387 * Provide device type specific interface functions and
388 * constant data.
389 */
390 indio_dev->info = &iio_dummy_info;
391
392 /* Specify that device provides sysfs type interfaces */
393 indio_dev->modes = INDIO_DIRECT_MODE;
394
395 ret = iio_device_register(indio_dev);
396 if (ret < 0)
397 goto error_free_device;
398
399 return 0;
400error_free_device:
401 /* Note free device should only be called, before registration
402 * has succeeded. */
403 iio_free_device(indio_dev);
404error_ret:
405 return ret;
406}
407
408/**
409 * iio_dummy_remove() - device instance removal function
410 * @index: device index.
411 *
412 * Parameters follow those of iio_dummy_probe for buses.
413 */
414static int iio_dummy_remove(int index)
415{
416 /*
417 * Get a pointer to the device instance iio_dev structure
418 * from the bus subsystem. E.g.
419 * struct iio_dev *indio_dev = i2c_get_clientdata(client);
420 * struct iio_dev *indio_dev = spi_get_drvdata(spi);
421 */
422 struct iio_dev *indio_dev = iio_dummy_devs[index];
423
424 /* Unregister the device */
425 iio_device_unregister(indio_dev);
426
427 /* Device specific code to power down etc */
428
429 /* Free all structures */
430 iio_free_device(indio_dev);
431
432 return 0;
433}
434
435/**
436 * iio_dummy_init() - device driver registration
437 *
438 * Varies depending on bus type of the device. As there is no device
439 * here, call probe directly. For information on device registration
440 * i2c:
441 * Documentation/i2c/writing-clients
442 * spi:
443 * Documentation/spi/spi-summary
444 */
445static __init int iio_dummy_init(void)
446{
447 int i, ret;
448 if (instances > 10) {
449 instances = 1;
450 return -EINVAL;
451 }
452 /* Fake a bus */
453 iio_dummy_devs = kzalloc(sizeof(*iio_dummy_devs)*instances, GFP_KERNEL);
454 /* Here we have no actual device so call probe */
455 for (i = 0; i < instances; i++) {
456 ret = iio_dummy_probe(i);
457 if (ret < 0)
458 return ret;
459 }
460 return 0;
461}
462module_init(iio_dummy_init);
463
464/**
465 * iio_dummy_exit() - device driver removal
466 *
467 * Varies depending on bus type of the device.
468 * As there is no device here, call remove directly.
469 */
470static __exit void iio_dummy_exit(void)
471{
472 int i;
473 for (i = 0; i < instances; i++)
474 iio_dummy_remove(i);
475 kfree(iio_dummy_devs);
476}
477module_exit(iio_dummy_exit);
478
479MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
480MODULE_DESCRIPTION("IIO dummy driver");
481MODULE_LICENSE("GPL v2");