On 09/10/15 14:31, Cristina Opriceana wrote: > This patch moves the reference IIO dummy driver from drivers/staging/iio > into a separate folder, drivers/iio/dummy and adds the proper Kconfig > and Makefile for it. > > A new config menu entry called IIO dummy driver has also been added > in the Industrial I/O support menu, corresponding to this driver. > > Signed-off-by: Cristina Opriceana <cristina.oprice...@gmail.com> Applied to the togreg branch of iio.git - pushed out as testing. Note that there is a build fix in the fixes-togreg branch which might cause some fun later. Ah well.
Jonathan > --- > drivers/iio/Kconfig | 1 + > drivers/iio/Makefile | 1 + > drivers/iio/dummy/Kconfig | 35 ++ > drivers/iio/dummy/Makefile | 10 + > drivers/iio/dummy/iio_dummy_evgen.c | 262 +++++++++ > drivers/iio/dummy/iio_dummy_evgen.h | 13 + > drivers/iio/dummy/iio_simple_dummy.c | 748 > ++++++++++++++++++++++++++ > drivers/iio/dummy/iio_simple_dummy.h | 129 +++++ > drivers/iio/dummy/iio_simple_dummy_buffer.c | 192 +++++++ > drivers/iio/dummy/iio_simple_dummy_events.c | 276 ++++++++++ > drivers/staging/iio/Kconfig | 54 +- > drivers/staging/iio/Makefile | 10 +- > drivers/staging/iio/iio_dummy_evgen.c | 262 --------- > drivers/staging/iio/iio_dummy_evgen.h | 13 - > drivers/staging/iio/iio_simple_dummy.c | 748 > -------------------------- > drivers/staging/iio/iio_simple_dummy.h | 129 ----- > drivers/staging/iio/iio_simple_dummy_buffer.c | 192 ------- > drivers/staging/iio/iio_simple_dummy_events.c | 276 ---------- > 18 files changed, 1699 insertions(+), 1652 deletions(-) > create mode 100644 drivers/iio/dummy/Kconfig > create mode 100644 drivers/iio/dummy/Makefile > create mode 100644 drivers/iio/dummy/iio_dummy_evgen.c > create mode 100644 drivers/iio/dummy/iio_dummy_evgen.h > create mode 100644 drivers/iio/dummy/iio_simple_dummy.c > create mode 100644 drivers/iio/dummy/iio_simple_dummy.h > create mode 100644 drivers/iio/dummy/iio_simple_dummy_buffer.c > create mode 100644 drivers/iio/dummy/iio_simple_dummy_events.c > delete mode 100644 drivers/staging/iio/iio_dummy_evgen.c > delete mode 100644 drivers/staging/iio/iio_dummy_evgen.h > delete mode 100644 drivers/staging/iio/iio_simple_dummy.c > delete mode 100644 drivers/staging/iio/iio_simple_dummy.h > delete mode 100644 drivers/staging/iio/iio_simple_dummy_buffer.c > delete mode 100644 drivers/staging/iio/iio_simple_dummy_events.c > > diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig > index 66792e7..6b8c77c9 100644 > --- a/drivers/iio/Kconfig > +++ b/drivers/iio/Kconfig > @@ -50,6 +50,7 @@ source "drivers/iio/amplifiers/Kconfig" > source "drivers/iio/chemical/Kconfig" > source "drivers/iio/common/Kconfig" > source "drivers/iio/dac/Kconfig" > +source "drivers/iio/dummy/Kconfig" > source "drivers/iio/frequency/Kconfig" > source "drivers/iio/gyro/Kconfig" > source "drivers/iio/humidity/Kconfig" > diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile > index aeca726..6769f2f 100644 > --- a/drivers/iio/Makefile > +++ b/drivers/iio/Makefile > @@ -16,6 +16,7 @@ obj-y += buffer/ > obj-y += chemical/ > obj-y += common/ > obj-y += dac/ > +obj-y += dummy/ > obj-y += gyro/ > obj-y += frequency/ > obj-y += humidity/ > diff --git a/drivers/iio/dummy/Kconfig b/drivers/iio/dummy/Kconfig > new file mode 100644 > index 0000000..e8676aa > --- /dev/null > +++ b/drivers/iio/dummy/Kconfig > @@ -0,0 +1,35 @@ > +# > +# Industrial I/O subsystem Dummy Driver configuration > +# > +menu "IIO dummy driver" > + depends on IIO > + > +config IIO_DUMMY_EVGEN > + tristate > + > +config IIO_SIMPLE_DUMMY > + tristate "An example driver with no hardware requirements" > + help > + Driver intended mainly as documentation for how to write > + a driver. May also be useful for testing userspace code > + without hardware. > + > +if IIO_SIMPLE_DUMMY > + > +config IIO_SIMPLE_DUMMY_EVENTS > + bool "Event generation support" > + select IIO_DUMMY_EVGEN > + help > + Add some dummy events to the simple dummy driver. > + > +config IIO_SIMPLE_DUMMY_BUFFER > + bool "Buffered capture support" > + select IIO_BUFFER > + select IIO_TRIGGER > + select IIO_KFIFO_BUF > + help > + Add buffered data capture to the simple dummy driver. > + > +endif # IIO_SIMPLE_DUMMY > + > +endmenu > diff --git a/drivers/iio/dummy/Makefile b/drivers/iio/dummy/Makefile > new file mode 100644 > index 0000000..0765e93 > --- /dev/null > +++ b/drivers/iio/dummy/Makefile > @@ -0,0 +1,10 @@ > +# > +# Makefile for the IIO Dummy Driver > +# > + > +obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o > +iio_dummy-y := iio_simple_dummy.o > +iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o > +iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o > + > +obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o > diff --git a/drivers/iio/dummy/iio_dummy_evgen.c > b/drivers/iio/dummy/iio_dummy_evgen.c > new file mode 100644 > index 0000000..9e83f34 > --- /dev/null > +++ b/drivers/iio/dummy/iio_dummy_evgen.c > @@ -0,0 +1,262 @@ > +/** > + * Copyright (c) 2011 Jonathan Cameron > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published > by > + * the Free Software Foundation. > + * > + * Companion module to the iio simple dummy example driver. > + * The purpose of this is to generate 'fake' event interrupts thus > + * allowing that driver's code to be as close as possible to that of > + * a normal driver talking to hardware. The approach used here > + * is not intended to be general and just happens to work for this > + * particular use case. > + */ > + > +#include <linux/kernel.h> > +#include <linux/slab.h> > +#include <linux/interrupt.h> > +#include <linux/irq.h> > +#include <linux/mutex.h> > +#include <linux/module.h> > +#include <linux/sysfs.h> > + > +#include "iio_dummy_evgen.h" > +#include <linux/iio/iio.h> > +#include <linux/iio/sysfs.h> > +#include <linux/irq_work.h> > + > +/* Fiddly bit of faking and irq without hardware */ > +#define IIO_EVENTGEN_NO 10 > + > +/** > + * struct iio_dummy_handle_irq - helper struct to simulate interrupt > generation > + * @work: irq_work used to run handlers from hardirq context > + * @irq: fake irq line number to trigger an interrupt > + */ > +struct iio_dummy_handle_irq { > + struct irq_work work; > + int irq; > +}; > + > +/** > + * struct iio_dummy_evgen - evgen state > + * @chip: irq chip we are faking > + * @base: base of irq range > + * @enabled: mask of which irqs are enabled > + * @inuse: mask of which irqs are connected > + * @regs: irq regs we are faking > + * @lock: protect the evgen state > + * @handler: helper for a 'hardware-like' interrupt simulation > + */ > +struct iio_dummy_eventgen { > + struct irq_chip chip; > + int base; > + bool enabled[IIO_EVENTGEN_NO]; > + bool inuse[IIO_EVENTGEN_NO]; > + struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; > + struct mutex lock; > + struct iio_dummy_handle_irq handler; > +}; > + > +/* We can only ever have one instance of this 'device' */ > +static struct iio_dummy_eventgen *iio_evgen; > +static const char *iio_evgen_name = "iio_dummy_evgen"; > + > +static void iio_dummy_event_irqmask(struct irq_data *d) > +{ > + struct irq_chip *chip = irq_data_get_irq_chip(d); > + struct iio_dummy_eventgen *evgen = > + container_of(chip, struct iio_dummy_eventgen, chip); > + > + evgen->enabled[d->irq - evgen->base] = false; > +} > + > +static void iio_dummy_event_irqunmask(struct irq_data *d) > +{ > + struct irq_chip *chip = irq_data_get_irq_chip(d); > + struct iio_dummy_eventgen *evgen = > + container_of(chip, struct iio_dummy_eventgen, chip); > + > + evgen->enabled[d->irq - evgen->base] = true; > +} > + > +static void iio_dummy_work_handler(struct irq_work *work) > +{ > + struct iio_dummy_handle_irq *irq_handler; > + > + irq_handler = container_of(work, struct iio_dummy_handle_irq, work); > + handle_simple_irq(irq_to_desc(irq_handler->irq)); > +} > + > +static int iio_dummy_evgen_create(void) > +{ > + int ret, i; > + > + iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL); > + if (!iio_evgen) > + return -ENOMEM; > + > + iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0); > + if (iio_evgen->base < 0) { > + ret = iio_evgen->base; > + kfree(iio_evgen); > + return ret; > + } > + iio_evgen->chip.name = iio_evgen_name; > + iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask; > + iio_evgen->chip.irq_unmask = &iio_dummy_event_irqunmask; > + for (i = 0; i < IIO_EVENTGEN_NO; i++) { > + irq_set_chip(iio_evgen->base + i, &iio_evgen->chip); > + irq_set_handler(iio_evgen->base + i, &handle_simple_irq); > + irq_modify_status(iio_evgen->base + i, > + IRQ_NOREQUEST | IRQ_NOAUTOEN, > + IRQ_NOPROBE); > + } > + init_irq_work(&iio_evgen->handler.work, iio_dummy_work_handler); > + mutex_init(&iio_evgen->lock); > + return 0; > +} > + > +/** > + * iio_dummy_evgen_get_irq() - get an evgen provided irq for a device > + * > + * This function will give a free allocated irq to a client device. > + * That irq can then be caused to 'fire' by using the associated sysfs file. > + */ > +int iio_dummy_evgen_get_irq(void) > +{ > + int i, ret = 0; > + > + if (!iio_evgen) > + return -ENODEV; > + > + mutex_lock(&iio_evgen->lock); > + for (i = 0; i < IIO_EVENTGEN_NO; i++) > + if (!iio_evgen->inuse[i]) { > + ret = iio_evgen->base + i; > + iio_evgen->inuse[i] = true; > + break; > + } > + mutex_unlock(&iio_evgen->lock); > + if (i == IIO_EVENTGEN_NO) > + return -ENOMEM; > + return ret; > +} > +EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq); > + > +/** > + * iio_dummy_evgen_release_irq() - give the irq back. > + * @irq: irq being returned to the pool > + * > + * Used by client driver instances to give the irqs back when they disconnect > + */ > +void iio_dummy_evgen_release_irq(int irq) > +{ > + mutex_lock(&iio_evgen->lock); > + iio_evgen->inuse[irq - iio_evgen->base] = false; > + mutex_unlock(&iio_evgen->lock); > +} > +EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); > + > +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq) > +{ > + return &iio_evgen->regs[irq - iio_evgen->base]; > +} > +EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs); > + > +static void iio_dummy_evgen_free(void) > +{ > + irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); > + kfree(iio_evgen); > +} > + > +static void iio_evgen_release(struct device *dev) > +{ > + iio_dummy_evgen_free(); > +} > + > +static ssize_t iio_evgen_poke(struct device *dev, > + struct device_attribute *attr, > + const char *buf, > + size_t len) > +{ > + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); > + unsigned long event; > + int ret; > + > + ret = kstrtoul(buf, 10, &event); > + if (ret) > + return ret; > + > + iio_evgen->regs[this_attr->address].reg_id = this_attr->address; > + iio_evgen->regs[this_attr->address].reg_data = event; > + > + iio_evgen->handler.irq = iio_evgen->base + this_attr->address; > + if (iio_evgen->enabled[this_attr->address]) > + irq_work_queue(&iio_evgen->handler.work); > + > + return len; > +} > + > +static IIO_DEVICE_ATTR(poke_ev0, S_IWUSR, NULL, &iio_evgen_poke, 0); > +static IIO_DEVICE_ATTR(poke_ev1, S_IWUSR, NULL, &iio_evgen_poke, 1); > +static IIO_DEVICE_ATTR(poke_ev2, S_IWUSR, NULL, &iio_evgen_poke, 2); > +static IIO_DEVICE_ATTR(poke_ev3, S_IWUSR, NULL, &iio_evgen_poke, 3); > +static IIO_DEVICE_ATTR(poke_ev4, S_IWUSR, NULL, &iio_evgen_poke, 4); > +static IIO_DEVICE_ATTR(poke_ev5, S_IWUSR, NULL, &iio_evgen_poke, 5); > +static IIO_DEVICE_ATTR(poke_ev6, S_IWUSR, NULL, &iio_evgen_poke, 6); > +static IIO_DEVICE_ATTR(poke_ev7, S_IWUSR, NULL, &iio_evgen_poke, 7); > +static IIO_DEVICE_ATTR(poke_ev8, S_IWUSR, NULL, &iio_evgen_poke, 8); > +static IIO_DEVICE_ATTR(poke_ev9, S_IWUSR, NULL, &iio_evgen_poke, 9); > + > +static struct attribute *iio_evgen_attrs[] = { > + &iio_dev_attr_poke_ev0.dev_attr.attr, > + &iio_dev_attr_poke_ev1.dev_attr.attr, > + &iio_dev_attr_poke_ev2.dev_attr.attr, > + &iio_dev_attr_poke_ev3.dev_attr.attr, > + &iio_dev_attr_poke_ev4.dev_attr.attr, > + &iio_dev_attr_poke_ev5.dev_attr.attr, > + &iio_dev_attr_poke_ev6.dev_attr.attr, > + &iio_dev_attr_poke_ev7.dev_attr.attr, > + &iio_dev_attr_poke_ev8.dev_attr.attr, > + &iio_dev_attr_poke_ev9.dev_attr.attr, > + NULL, > +}; > + > +static const struct attribute_group iio_evgen_group = { > + .attrs = iio_evgen_attrs, > +}; > + > +static const struct attribute_group *iio_evgen_groups[] = { > + &iio_evgen_group, > + NULL > +}; > + > +static struct device iio_evgen_dev = { > + .bus = &iio_bus_type, > + .groups = iio_evgen_groups, > + .release = &iio_evgen_release, > +}; > + > +static __init int iio_dummy_evgen_init(void) > +{ > + int ret = iio_dummy_evgen_create(); > + > + if (ret < 0) > + return ret; > + device_initialize(&iio_evgen_dev); > + dev_set_name(&iio_evgen_dev, "iio_evgen"); > + return device_add(&iio_evgen_dev); > +} > +module_init(iio_dummy_evgen_init); > + > +static __exit void iio_dummy_evgen_exit(void) > +{ > + device_unregister(&iio_evgen_dev); > +} > +module_exit(iio_dummy_evgen_exit); > + > +MODULE_AUTHOR("Jonathan Cameron <ji...@kernel.org>"); > +MODULE_DESCRIPTION("IIO dummy driver"); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/iio/dummy/iio_dummy_evgen.h > b/drivers/iio/dummy/iio_dummy_evgen.h > new file mode 100644 > index 0000000..d044b94 > --- /dev/null > +++ b/drivers/iio/dummy/iio_dummy_evgen.h > @@ -0,0 +1,13 @@ > +#ifndef _IIO_DUMMY_EVGEN_H_ > +#define _IIO_DUMMY_EVGEN_H_ > + > +struct iio_dummy_regs { > + u32 reg_id; > + u32 reg_data; > +}; > + > +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq); > +int iio_dummy_evgen_get_irq(void); > +void iio_dummy_evgen_release_irq(int irq); > + > +#endif /* _IIO_DUMMY_EVGEN_H_ */ > diff --git a/drivers/iio/dummy/iio_simple_dummy.c > b/drivers/iio/dummy/iio_simple_dummy.c > new file mode 100644 > index 0000000..381f90f > --- /dev/null > +++ b/drivers/iio/dummy/iio_simple_dummy.c > @@ -0,0 +1,748 @@ > +/** > + * Copyright (c) 2011 Jonathan Cameron > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published > by > + * the Free Software Foundation. > + * > + * A reference industrial I/O driver to illustrate the functionality > available. > + * > + * There are numerous real drivers to illustrate the finer points. > + * The purpose of this driver is to provide a driver with far more comments > + * and explanatory notes than any 'real' driver would have. > + * Anyone starting out writing an IIO driver should first make sure they > + * understand all of this driver except those bits specifically marked > + * as being present to allow us to 'fake' the presence of hardware. > + */ > +#include <linux/kernel.h> > +#include <linux/slab.h> > +#include <linux/module.h> > + > +#include <linux/iio/iio.h> > +#include <linux/iio/sysfs.h> > +#include <linux/iio/events.h> > +#include <linux/iio/buffer.h> > +#include "iio_simple_dummy.h" > + > +/* > + * A few elements needed to fake a bus for this driver > + * Note instances parameter controls how many of these > + * dummy devices are registered. > + */ > +static unsigned instances = 1; > +module_param(instances, uint, 0); > + > +/* Pointer array used to fake bus elements */ > +static struct iio_dev **iio_dummy_devs; > + > +/* Fake a name for the part number, usually obtained from the id table */ > +static const char *iio_dummy_part_number = "iio_dummy_part_no"; > + > +/** > + * struct iio_dummy_accel_calibscale - realworld to register mapping > + * @val: first value in read_raw - here integer part. > + * @val2: second value in read_raw etc - here micro part. > + * @regval: register value - magic device specific numbers. > + */ > +struct iio_dummy_accel_calibscale { > + int val; > + int val2; > + int regval; /* what would be written to hardware */ > +}; > + > +static const struct iio_dummy_accel_calibscale dummy_scales[] = { > + { 0, 100, 0x8 }, /* 0.000100 */ > + { 0, 133, 0x7 }, /* 0.000133 */ > + { 733, 13, 0x9 }, /* 733.000013 */ > +}; > + > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + > +/* > + * simple event - triggered when value rises above > + * a threshold > + */ > +static const struct iio_event_spec iio_dummy_event = { > + .type = IIO_EV_TYPE_THRESH, > + .dir = IIO_EV_DIR_RISING, > + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), > +}; > + > +/* > + * simple step detect event - triggered when a step is detected > + */ > +static const struct iio_event_spec step_detect_event = { > + .type = IIO_EV_TYPE_CHANGE, > + .dir = IIO_EV_DIR_NONE, > + .mask_separate = BIT(IIO_EV_INFO_ENABLE), > +}; > + > +/* > + * simple transition event - triggered when the reported running confidence > + * value rises above a threshold value > + */ > +static const struct iio_event_spec iio_running_event = { > + .type = IIO_EV_TYPE_THRESH, > + .dir = IIO_EV_DIR_RISING, > + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), > +}; > + > +/* > + * simple transition event - triggered when the reported walking confidence > + * value falls under a threshold value > + */ > +static const struct iio_event_spec iio_walking_event = { > + .type = IIO_EV_TYPE_THRESH, > + .dir = IIO_EV_DIR_FALLING, > + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), > +}; > +#endif > + > +/* > + * iio_dummy_channels - Description of available channels > + * > + * This array of structures tells the IIO core about what the device > + * actually provides for a given channel. > + */ > +static const struct iio_chan_spec iio_dummy_channels[] = { > + /* indexed ADC channel in_voltage0_raw etc */ > + { > + .type = IIO_VOLTAGE, > + /* Channel has a numeric index of 0 */ > + .indexed = 1, > + .channel = 0, > + /* What other information is available? */ > + .info_mask_separate = > + /* > + * in_voltage0_raw > + * Raw (unscaled no bias removal etc) measurement > + * from the device. > + */ > + BIT(IIO_CHAN_INFO_RAW) | > + /* > + * in_voltage0_offset > + * Offset for userspace to apply prior to scale > + * when converting to standard units (microvolts) > + */ > + BIT(IIO_CHAN_INFO_OFFSET) | > + /* > + * in_voltage0_scale > + * Multipler for userspace to apply post offset > + * when converting to standard units (microvolts) > + */ > + BIT(IIO_CHAN_INFO_SCALE), > + /* > + * sampling_frequency > + * The frequency in Hz at which the channels are sampled > + */ > + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), > + /* The ordering of elements in the buffer via an enum */ > + .scan_index = voltage0, > + .scan_type = { /* Description of storage in buffer */ > + .sign = 'u', /* unsigned */ > + .realbits = 13, /* 13 bits */ > + .storagebits = 16, /* 16 bits used for storage */ > + .shift = 0, /* zero shift */ > + }, > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + .event_spec = &iio_dummy_event, > + .num_event_specs = 1, > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > + }, > + /* Differential ADC channel in_voltage1-voltage2_raw etc*/ > + { > + .type = IIO_VOLTAGE, > + .differential = 1, > + /* > + * Indexing for differential channels uses channel > + * for the positive part, channel2 for the negative. > + */ > + .indexed = 1, > + .channel = 1, > + .channel2 = 2, > + /* > + * in_voltage1-voltage2_raw > + * Raw (unscaled no bias removal etc) measurement > + * from the device. > + */ > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > + /* > + * in_voltage-voltage_scale > + * Shared version of scale - shared by differential > + * input channels of type IIO_VOLTAGE. > + */ > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), > + /* > + * sampling_frequency > + * The frequency in Hz at which the channels are sampled > + */ > + .scan_index = diffvoltage1m2, > + .scan_type = { /* Description of storage in buffer */ > + .sign = 's', /* signed */ > + .realbits = 12, /* 12 bits */ > + .storagebits = 16, /* 16 bits used for storage */ > + .shift = 0, /* zero shift */ > + }, > + }, > + /* Differential ADC channel in_voltage3-voltage4_raw etc*/ > + { > + .type = IIO_VOLTAGE, > + .differential = 1, > + .indexed = 1, > + .channel = 3, > + .channel2 = 4, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), > + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), > + .scan_index = diffvoltage3m4, > + .scan_type = { > + .sign = 's', > + .realbits = 11, > + .storagebits = 16, > + .shift = 0, > + }, > + }, > + /* > + * 'modified' (i.e. axis specified) acceleration channel > + * in_accel_z_raw > + */ > + { > + .type = IIO_ACCEL, > + .modified = 1, > + /* Channel 2 is use for modifiers */ > + .channel2 = IIO_MOD_X, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > + /* > + * Internal bias and gain correction values. Applied > + * by the hardware or driver prior to userspace > + * seeing the readings. Typically part of hardware > + * calibration. > + */ > + BIT(IIO_CHAN_INFO_CALIBSCALE) | > + BIT(IIO_CHAN_INFO_CALIBBIAS), > + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), > + .scan_index = accelx, > + .scan_type = { /* Description of storage in buffer */ > + .sign = 's', /* signed */ > + .realbits = 16, /* 16 bits */ > + .storagebits = 16, /* 16 bits used for storage */ > + .shift = 0, /* zero shift */ > + }, > + }, > + /* > + * Convenience macro for timestamps. 4 is the index in > + * the buffer. > + */ > + IIO_CHAN_SOFT_TIMESTAMP(4), > + /* DAC channel out_voltage0_raw */ > + { > + .type = IIO_VOLTAGE, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > + .scan_index = -1, /* No buffer support */ > + .output = 1, > + .indexed = 1, > + .channel = 0, > + }, > + { > + .type = IIO_STEPS, > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | > + BIT(IIO_CHAN_INFO_CALIBHEIGHT), > + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > + .scan_index = -1, /* No buffer support */ > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + .event_spec = &step_detect_event, > + .num_event_specs = 1, > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > + }, > + { > + .type = IIO_ACTIVITY, > + .modified = 1, > + .channel2 = IIO_MOD_RUNNING, > + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > + .scan_index = -1, /* No buffer support */ > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + .event_spec = &iio_running_event, > + .num_event_specs = 1, > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > + }, > + { > + .type = IIO_ACTIVITY, > + .modified = 1, > + .channel2 = IIO_MOD_WALKING, > + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > + .scan_index = -1, /* No buffer support */ > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + .event_spec = &iio_walking_event, > + .num_event_specs = 1, > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > + }, > +}; > + > +/** > + * iio_dummy_read_raw() - data read function. > + * @indio_dev: the struct iio_dev associated with this device instance > + * @chan: the channel whose data is to be read > + * @val: first element of returned value (typically INT) > + * @val2: second element of returned value (typically MICRO) > + * @mask: what we actually want to read as per the info_mask_* > + * in iio_chan_spec. > + */ > +static int iio_dummy_read_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int *val, > + int *val2, > + long mask) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + int ret = -EINVAL; > + > + mutex_lock(&st->lock); > + switch (mask) { > + case IIO_CHAN_INFO_RAW: /* magic value - channel value read */ > + switch (chan->type) { > + case IIO_VOLTAGE: > + if (chan->output) { > + /* Set integer part to cached value */ > + *val = st->dac_val; > + ret = IIO_VAL_INT; > + } else if (chan->differential) { > + if (chan->channel == 1) > + *val = st->differential_adc_val[0]; > + else > + *val = st->differential_adc_val[1]; > + ret = IIO_VAL_INT; > + } else { > + *val = st->single_ended_adc_val; > + ret = IIO_VAL_INT; > + } > + break; > + case IIO_ACCEL: > + *val = st->accel_val; > + ret = IIO_VAL_INT; > + break; > + default: > + break; > + } > + break; > + case IIO_CHAN_INFO_PROCESSED: > + switch (chan->type) { > + case IIO_STEPS: > + *val = st->steps; > + ret = IIO_VAL_INT; > + break; > + case IIO_ACTIVITY: > + switch (chan->channel2) { > + case IIO_MOD_RUNNING: > + *val = st->activity_running; > + ret = IIO_VAL_INT; > + break; > + case IIO_MOD_WALKING: > + *val = st->activity_walking; > + ret = IIO_VAL_INT; > + break; > + default: > + break; > + } > + break; > + default: > + break; > + } > + break; > + case IIO_CHAN_INFO_OFFSET: > + /* only single ended adc -> 7 */ > + *val = 7; > + ret = IIO_VAL_INT; > + break; > + case IIO_CHAN_INFO_SCALE: > + switch (chan->type) { > + case IIO_VOLTAGE: > + switch (chan->differential) { > + case 0: > + /* only single ended adc -> 0.001333 */ > + *val = 0; > + *val2 = 1333; > + ret = IIO_VAL_INT_PLUS_MICRO; > + break; > + case 1: > + /* all differential adc channels -> > + * 0.000001344 */ > + *val = 0; > + *val2 = 1344; > + ret = IIO_VAL_INT_PLUS_NANO; > + } > + break; > + default: > + break; > + } > + break; > + case IIO_CHAN_INFO_CALIBBIAS: > + /* only the acceleration axis - read from cache */ > + *val = st->accel_calibbias; > + ret = IIO_VAL_INT; > + break; > + case IIO_CHAN_INFO_CALIBSCALE: > + *val = st->accel_calibscale->val; > + *val2 = st->accel_calibscale->val2; > + ret = IIO_VAL_INT_PLUS_MICRO; > + break; > + case IIO_CHAN_INFO_SAMP_FREQ: > + *val = 3; > + *val2 = 33; > + ret = IIO_VAL_INT_PLUS_NANO; > + break; > + case IIO_CHAN_INFO_ENABLE: > + switch (chan->type) { > + case IIO_STEPS: > + *val = st->steps_enabled; > + ret = IIO_VAL_INT; > + break; > + default: > + break; > + } > + break; > + case IIO_CHAN_INFO_CALIBHEIGHT: > + switch (chan->type) { > + case IIO_STEPS: > + *val = st->height; > + ret = IIO_VAL_INT; > + break; > + default: > + break; > + } > + break; > + > + default: > + break; > + } > + mutex_unlock(&st->lock); > + return ret; > +} > + > +/** > + * iio_dummy_write_raw() - data write function. > + * @indio_dev: the struct iio_dev associated with this device instance > + * @chan: the channel whose data is to be written > + * @val: first element of value to set (typically INT) > + * @val2: second element of value to set (typically MICRO) > + * @mask: what we actually want to write as per the info_mask_* > + * in iio_chan_spec. > + * > + * Note that all raw writes are assumed IIO_VAL_INT and info mask elements > + * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt > + * in struct iio_info is provided by the driver. > + */ > +static int iio_dummy_write_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int val, > + int val2, > + long mask) > +{ > + int i; > + int ret = 0; > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + switch (mask) { > + case IIO_CHAN_INFO_RAW: > + switch (chan->type) { > + case IIO_VOLTAGE: > + if (chan->output == 0) > + return -EINVAL; > + > + /* Locking not required as writing single value */ > + mutex_lock(&st->lock); > + st->dac_val = val; > + mutex_unlock(&st->lock); > + return 0; > + default: > + return -EINVAL; > + } > + case IIO_CHAN_INFO_PROCESSED: > + switch (chan->type) { > + case IIO_STEPS: > + mutex_lock(&st->lock); > + st->steps = val; > + mutex_unlock(&st->lock); > + return 0; > + case IIO_ACTIVITY: > + if (val < 0) > + val = 0; > + if (val > 100) > + val = 100; > + switch (chan->channel2) { > + case IIO_MOD_RUNNING: > + st->activity_running = val; > + return 0; > + case IIO_MOD_WALKING: > + st->activity_walking = val; > + return 0; > + default: > + return -EINVAL; > + } > + break; > + default: > + return -EINVAL; > + } > + case IIO_CHAN_INFO_CALIBSCALE: > + mutex_lock(&st->lock); > + /* Compare against table - hard matching here */ > + for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) > + if (val == dummy_scales[i].val && > + val2 == dummy_scales[i].val2) > + break; > + if (i == ARRAY_SIZE(dummy_scales)) > + ret = -EINVAL; > + else > + st->accel_calibscale = &dummy_scales[i]; > + mutex_unlock(&st->lock); > + return ret; > + case IIO_CHAN_INFO_CALIBBIAS: > + mutex_lock(&st->lock); > + st->accel_calibbias = val; > + mutex_unlock(&st->lock); > + return 0; > + case IIO_CHAN_INFO_ENABLE: > + switch (chan->type) { > + case IIO_STEPS: > + mutex_lock(&st->lock); > + st->steps_enabled = val; > + mutex_unlock(&st->lock); > + return 0; > + default: > + return -EINVAL; > + } > + case IIO_CHAN_INFO_CALIBHEIGHT: > + switch (chan->type) { > + case IIO_STEPS: > + st->height = val; > + return 0; > + default: > + return -EINVAL; > + } > + > + default: > + return -EINVAL; > + } > +} > + > +/* > + * Device type specific information. > + */ > +static const struct iio_info iio_dummy_info = { > + .driver_module = THIS_MODULE, > + .read_raw = &iio_dummy_read_raw, > + .write_raw = &iio_dummy_write_raw, > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + .read_event_config = &iio_simple_dummy_read_event_config, > + .write_event_config = &iio_simple_dummy_write_event_config, > + .read_event_value = &iio_simple_dummy_read_event_value, > + .write_event_value = &iio_simple_dummy_write_event_value, > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > +}; > + > +/** > + * iio_dummy_init_device() - device instance specific init > + * @indio_dev: the iio device structure > + * > + * Most drivers have one of these to set up default values, > + * reset the device to known state etc. > + */ > +static int iio_dummy_init_device(struct iio_dev *indio_dev) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + st->dac_val = 0; > + st->single_ended_adc_val = 73; > + st->differential_adc_val[0] = 33; > + st->differential_adc_val[1] = -34; > + st->accel_val = 34; > + st->accel_calibbias = -7; > + st->accel_calibscale = &dummy_scales[0]; > + st->steps = 47; > + st->activity_running = 98; > + st->activity_walking = 4; > + > + return 0; > +} > + > +/** > + * iio_dummy_probe() - device instance probe > + * @index: an id number for this instance. > + * > + * Arguments are bus type specific. > + * I2C: iio_dummy_probe(struct i2c_client *client, > + * const struct i2c_device_id *id) > + * SPI: iio_dummy_probe(struct spi_device *spi) > + */ > +static int iio_dummy_probe(int index) > +{ > + int ret; > + struct iio_dev *indio_dev; > + struct iio_dummy_state *st; > + > + /* > + * Allocate an IIO device. > + * > + * This structure contains all generic state > + * information about the device instance. > + * It also has a region (accessed by iio_priv() > + * for chip specific state information. > + */ > + indio_dev = iio_device_alloc(sizeof(*st)); > + if (!indio_dev) { > + ret = -ENOMEM; > + goto error_ret; > + } > + > + st = iio_priv(indio_dev); > + mutex_init(&st->lock); > + > + iio_dummy_init_device(indio_dev); > + /* > + * With hardware: Set the parent device. > + * indio_dev->dev.parent = &spi->dev; > + * indio_dev->dev.parent = &client->dev; > + */ > + > + /* > + * Make the iio_dev struct available to remove function. > + * Bus equivalents > + * i2c_set_clientdata(client, indio_dev); > + * spi_set_drvdata(spi, indio_dev); > + */ > + iio_dummy_devs[index] = indio_dev; > + > + /* > + * Set the device name. > + * > + * This is typically a part number and obtained from the module > + * id table. > + * e.g. for i2c and spi: > + * indio_dev->name = id->name; > + * indio_dev->name = spi_get_device_id(spi)->name; > + */ > + indio_dev->name = iio_dummy_part_number; > + > + /* Provide description of available channels */ > + indio_dev->channels = iio_dummy_channels; > + indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels); > + > + /* > + * Provide device type specific interface functions and > + * constant data. > + */ > + indio_dev->info = &iio_dummy_info; > + > + /* Specify that device provides sysfs type interfaces */ > + indio_dev->modes = INDIO_DIRECT_MODE; > + > + ret = iio_simple_dummy_events_register(indio_dev); > + if (ret < 0) > + goto error_free_device; > + > + ret = iio_simple_dummy_configure_buffer(indio_dev); > + if (ret < 0) > + goto error_unregister_events; > + > + ret = iio_device_register(indio_dev); > + if (ret < 0) > + goto error_unconfigure_buffer; > + > + return 0; > +error_unconfigure_buffer: > + iio_simple_dummy_unconfigure_buffer(indio_dev); > +error_unregister_events: > + iio_simple_dummy_events_unregister(indio_dev); > +error_free_device: > + iio_device_free(indio_dev); > +error_ret: > + return ret; > +} > + > +/** > + * iio_dummy_remove() - device instance removal function > + * @index: device index. > + * > + * Parameters follow those of iio_dummy_probe for buses. > + */ > +static void iio_dummy_remove(int index) > +{ > + /* > + * Get a pointer to the device instance iio_dev structure > + * from the bus subsystem. E.g. > + * struct iio_dev *indio_dev = i2c_get_clientdata(client); > + * struct iio_dev *indio_dev = spi_get_drvdata(spi); > + */ > + struct iio_dev *indio_dev = iio_dummy_devs[index]; > + > + /* Unregister the device */ > + iio_device_unregister(indio_dev); > + > + /* Device specific code to power down etc */ > + > + /* Buffered capture related cleanup */ > + iio_simple_dummy_unconfigure_buffer(indio_dev); > + > + iio_simple_dummy_events_unregister(indio_dev); > + > + /* Free all structures */ > + iio_device_free(indio_dev); > +} > + > +/** > + * iio_dummy_init() - device driver registration > + * > + * Varies depending on bus type of the device. As there is no device > + * here, call probe directly. For information on device registration > + * i2c: > + * Documentation/i2c/writing-clients > + * spi: > + * Documentation/spi/spi-summary > + */ > +static __init int iio_dummy_init(void) > +{ > + int i, ret; > + > + if (instances > 10) { > + instances = 1; > + return -EINVAL; > + } > + > + /* Fake a bus */ > + iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs), > + GFP_KERNEL); > + /* Here we have no actual device so call probe */ > + for (i = 0; i < instances; i++) { > + ret = iio_dummy_probe(i); > + if (ret < 0) > + goto error_remove_devs; > + } > + return 0; > + > +error_remove_devs: > + while (i--) > + iio_dummy_remove(i); > + > + kfree(iio_dummy_devs); > + return ret; > +} > +module_init(iio_dummy_init); > + > +/** > + * iio_dummy_exit() - device driver removal > + * > + * Varies depending on bus type of the device. > + * As there is no device here, call remove directly. > + */ > +static __exit void iio_dummy_exit(void) > +{ > + int i; > + > + for (i = 0; i < instances; i++) > + iio_dummy_remove(i); > + kfree(iio_dummy_devs); > +} > +module_exit(iio_dummy_exit); > + > +MODULE_AUTHOR("Jonathan Cameron <ji...@kernel.org>"); > +MODULE_DESCRIPTION("IIO dummy driver"); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/iio/dummy/iio_simple_dummy.h > b/drivers/iio/dummy/iio_simple_dummy.h > new file mode 100644 > index 0000000..5c2f4d0 > --- /dev/null > +++ b/drivers/iio/dummy/iio_simple_dummy.h > @@ -0,0 +1,129 @@ > +/** > + * Copyright (c) 2011 Jonathan Cameron > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published > by > + * the Free Software Foundation. > + * > + * Join together the various functionality of iio_simple_dummy driver > + */ > + > +#ifndef _IIO_SIMPLE_DUMMY_H_ > +#define _IIO_SIMPLE_DUMMY_H_ > +#include <linux/kernel.h> > + > +struct iio_dummy_accel_calibscale; > +struct iio_dummy_regs; > + > +/** > + * struct iio_dummy_state - device instance specific state. > + * @dac_val: cache for dac value > + * @single_ended_adc_val: cache for single ended adc value > + * @differential_adc_val: cache for differential adc value > + * @accel_val: cache for acceleration value > + * @accel_calibbias: cache for acceleration calibbias > + * @accel_calibscale: cache for acceleration calibscale > + * @lock: lock to ensure state is consistent > + * @event_irq: irq number for event line (faked) > + * @event_val: cache for event threshold value > + * @event_en: cache of whether event is enabled > + */ > +struct iio_dummy_state { > + int dac_val; > + int single_ended_adc_val; > + int differential_adc_val[2]; > + int accel_val; > + int accel_calibbias; > + int activity_running; > + int activity_walking; > + const struct iio_dummy_accel_calibscale *accel_calibscale; > + struct mutex lock; > + struct iio_dummy_regs *regs; > + int steps_enabled; > + int steps; > + int height; > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + int event_irq; > + int event_val; > + bool event_en; > + s64 event_timestamp; > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > +}; > + > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > + > +struct iio_dev; > + > +int 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); > + > +int 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); > + > +int 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); > + > +int 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); > + > +int iio_simple_dummy_events_register(struct iio_dev *indio_dev); > +void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev); > + > +#else /* Stubs for when events are disabled at compile time */ > + > +static inline int > +iio_simple_dummy_events_register(struct iio_dev *indio_dev) > +{ > + return 0; > +}; > + > +static inline void > +iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) > +{ }; > + > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS*/ > + > +/** > + * enum iio_simple_dummy_scan_elements - scan index enum > + * @voltage0: the single ended voltage channel > + * @diffvoltage1m2: first differential channel > + * @diffvoltage3m4: second differenial channel > + * @accelx: acceleration channel > + * > + * Enum provides convenient numbering for the scan index. > + */ > +enum iio_simple_dummy_scan_elements { > + voltage0, > + diffvoltage1m2, > + diffvoltage3m4, > + accelx, > +}; > + > +#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER > +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); > +void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); > +#else > +static inline int iio_simple_dummy_configure_buffer(struct iio_dev > *indio_dev) > +{ > + return 0; > +}; > + > +static inline > +void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) > +{}; > + > +#endif /* CONFIG_IIO_SIMPLE_DUMMY_BUFFER */ > +#endif /* _IIO_SIMPLE_DUMMY_H_ */ > diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c > b/drivers/iio/dummy/iio_simple_dummy_buffer.c > new file mode 100644 > index 0000000..00ed774 > --- /dev/null > +++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c > @@ -0,0 +1,192 @@ > +/** > + * Copyright (c) 2011 Jonathan Cameron > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published > by > + * the Free Software Foundation. > + * > + * Buffer handling elements of industrial I/O reference driver. > + * Uses the kfifo buffer. > + * > + * To test without hardware use the sysfs trigger. > + */ > + > +#include <linux/kernel.h> > +#include <linux/export.h> > +#include <linux/slab.h> > +#include <linux/interrupt.h> > +#include <linux/irq.h> > +#include <linux/bitmap.h> > + > +#include <linux/iio/iio.h> > +#include <linux/iio/trigger_consumer.h> > +#include <linux/iio/kfifo_buf.h> > + > +#include "iio_simple_dummy.h" > + > +/* Some fake data */ > + > +static const s16 fakedata[] = { > + [voltage0] = 7, > + [diffvoltage1m2] = -33, > + [diffvoltage3m4] = -2, > + [accelx] = 344, > +}; > + > +/** > + * iio_simple_dummy_trigger_h() - the trigger handler function > + * @irq: the interrupt number > + * @p: private data - always a pointer to the poll func. > + * > + * This is the guts of buffered capture. On a trigger event occurring, > + * if the pollfunc is attached then this handler is called as a threaded > + * interrupt (and hence may sleep). It is responsible for grabbing data > + * from the device and pushing it into the associated buffer. > + */ > +static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) > +{ > + struct iio_poll_func *pf = p; > + struct iio_dev *indio_dev = pf->indio_dev; > + int len = 0; > + u16 *data; > + > + data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); > + if (!data) > + goto done; > + > + if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { > + /* > + * Three common options here: > + * hardware scans: certain combinations of channels make > + * up a fast read. The capture will consist of all of them. > + * Hence we just call the grab data function and fill the > + * buffer without processing. > + * software scans: can be considered to be random access > + * so efficient reading is just a case of minimal bus > + * transactions. > + * software culled hardware scans: > + * occasionally a driver may process the nearest hardware > + * scan to avoid storing elements that are not desired. This > + * is the fiddliest option by far. > + * Here let's pretend we have random access. And the values are > + * in the constant table fakedata. > + */ > + int i, j; > + > + for (i = 0, j = 0; > + i < bitmap_weight(indio_dev->active_scan_mask, > + indio_dev->masklength); > + i++, j++) { > + j = find_next_bit(indio_dev->active_scan_mask, > + indio_dev->masklength, j); > + /* random access read from the 'device' */ > + data[i] = fakedata[j]; > + len += 2; > + } > + } > + > + iio_push_to_buffers_with_timestamp(indio_dev, data, iio_get_time_ns()); > + > + kfree(data); > + > +done: > + /* > + * Tell the core we are done with this trigger and ready for the > + * next one. > + */ > + iio_trigger_notify_done(indio_dev->trig); > + > + return IRQ_HANDLED; > +} > + > +static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = > { > + /* > + * iio_triggered_buffer_postenable: > + * Generic function that simply attaches the pollfunc to the trigger. > + * Replace this to mess with hardware state before we attach the > + * trigger. > + */ > + .postenable = &iio_triggered_buffer_postenable, > + /* > + * iio_triggered_buffer_predisable: > + * Generic function that simple detaches the pollfunc from the trigger. > + * Replace this to put hardware state back again after the trigger is > + * detached but before userspace knows we have disabled the ring. > + */ > + .predisable = &iio_triggered_buffer_predisable, > +}; > + > +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) > +{ > + int ret; > + struct iio_buffer *buffer; > + > + /* Allocate a buffer to use - here a kfifo */ > + buffer = iio_kfifo_allocate(); > + if (!buffer) { > + ret = -ENOMEM; > + goto error_ret; > + } > + > + iio_device_attach_buffer(indio_dev, buffer); > + > + /* Enable timestamps by default */ > + buffer->scan_timestamp = true; > + > + /* > + * Tell the core what device type specific functions should > + * be run on either side of buffer capture enable / disable. > + */ > + indio_dev->setup_ops = &iio_simple_dummy_buffer_setup_ops; > + > + /* > + * Configure a polling function. > + * When a trigger event with this polling function connected > + * occurs, this function is run. Typically this grabs data > + * from the device. > + * > + * NULL for the bottom half. This is normally implemented only if we > + * either want to ping a capture now pin (no sleeping) or grab > + * a timestamp as close as possible to a data ready trigger firing. > + * > + * IRQF_ONESHOT ensures irqs are masked such that only one instance > + * of the handler can run at a time. > + * > + * "iio_simple_dummy_consumer%d" formatting string for the irq 'name' > + * as seen under /proc/interrupts. Remaining parameters as per printk. > + */ > + indio_dev->pollfunc = iio_alloc_pollfunc(NULL, > + &iio_simple_dummy_trigger_h, > + IRQF_ONESHOT, > + indio_dev, > + "iio_simple_dummy_consumer%d", > + indio_dev->id); > + > + if (!indio_dev->pollfunc) { > + ret = -ENOMEM; > + goto error_free_buffer; > + } > + > + /* > + * Notify the core that this device is capable of buffered capture > + * driven by a trigger. > + */ > + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; > + > + return 0; > + > +error_free_buffer: > + iio_kfifo_free(indio_dev->buffer); > +error_ret: > + return ret; > +} > + > +/** > + * iio_simple_dummy_unconfigure_buffer() - release buffer resources > + * @indo_dev: device instance state > + */ > +void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) > +{ > + iio_dealloc_pollfunc(indio_dev->pollfunc); > + iio_kfifo_free(indio_dev->buffer); > +} > diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c > b/drivers/iio/dummy/iio_simple_dummy_events.c > new file mode 100644 > index 0000000..bfbf1c5 > --- /dev/null > +++ b/drivers/iio/dummy/iio_simple_dummy_events.c > @@ -0,0 +1,276 @@ > +/** > + * Copyright (c) 2011 Jonathan Cameron > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License version 2 as published > by > + * the Free Software Foundation. > + * > + * Event handling elements of industrial I/O reference driver. > + */ > +#include <linux/kernel.h> > +#include <linux/slab.h> > +#include <linux/interrupt.h> > +#include <linux/irq.h> > + > +#include <linux/iio/iio.h> > +#include <linux/iio/sysfs.h> > +#include <linux/iio/events.h> > +#include "iio_simple_dummy.h" > + > +/* Evgen 'fakes' interrupt events for this example */ > +#include "iio_dummy_evgen.h" > + > +/** > + * iio_simple_dummy_read_event_config() - is event enabled? > + * @indio_dev: the device instance data > + * @chan: channel for the event whose state is being queried > + * @type: type of the event whose state is being queried > + * @dir: direction of the vent whose state is being queried > + * > + * This function would normally query the relevant registers or a cache to > + * discover if the event generation is enabled on the device. > + */ > +int 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) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + return st->event_en; > +} > + > +/** > + * iio_simple_dummy_write_event_config() - set whether event is enabled > + * @indio_dev: the device instance data > + * @chan: channel for the event whose state is being set > + * @type: type of the event whose state is being set > + * @dir: direction of the vent whose state is being set > + * @state: whether to enable or disable the device. > + * > + * This function would normally set the relevant registers on the devices > + * so that it generates the specified event. Here it just sets up a cached > + * value. > + */ > +int 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) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + /* > + * Deliberately over the top code splitting to illustrate > + * how this is done when multiple events exist. > + */ > + switch (chan->type) { > + case IIO_VOLTAGE: > + switch (type) { > + case IIO_EV_TYPE_THRESH: > + if (dir == IIO_EV_DIR_RISING) > + st->event_en = state; > + else > + return -EINVAL; > + default: > + return -EINVAL; > + } > + break; > + case IIO_ACTIVITY: > + switch (type) { > + case IIO_EV_TYPE_THRESH: > + st->event_en = state; > + break; > + default: > + return -EINVAL; > + } > + break; > + case IIO_STEPS: > + switch (type) { > + case IIO_EV_TYPE_CHANGE: > + st->event_en = state; > + break; > + default: > + return -EINVAL; > + } > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +/** > + * iio_simple_dummy_read_event_value() - get value associated with event > + * @indio_dev: device instance specific data > + * @chan: channel for the event whose value is being read > + * @type: type of the event whose value is being read > + * @dir: direction of the vent whose value is being read > + * @info: info type of the event whose value is being read > + * @val: value for the event code. > + * > + * Many devices provide a large set of events of which only a subset may > + * be enabled at a time, with value registers whose meaning changes depending > + * on the event enabled. This often means that the driver must cache the > values > + * associated with each possible events so that the right value is in place > when > + * the enabled event is changed. > + */ > +int 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) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + *val = st->event_val; > + > + return IIO_VAL_INT; > +} > + > +/** > + * iio_simple_dummy_write_event_value() - set value associate with event > + * @indio_dev: device instance specific data > + * @chan: channel for the event whose value is being set > + * @type: type of the event whose value is being set > + * @dir: direction of the vent whose value is being set > + * @info: info type of the event whose value is being set > + * @val: the value to be set. > + */ > +int 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) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + st->event_val = val; > + > + return 0; > +} > + > +static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private) > +{ > + struct iio_dev *indio_dev = private; > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + st->event_timestamp = iio_get_time_ns(); > + return IRQ_HANDLED; > +} > + > +/** > + * iio_simple_dummy_event_handler() - identify and pass on event > + * @irq: irq of event line > + * @private: pointer to device instance state. > + * > + * This handler is responsible for querying the device to find out what > + * event occurred and for then pushing that event towards userspace. > + * Here only one event occurs so we push that directly on with locally > + * grabbed timestamp. > + */ > +static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) > +{ > + struct iio_dev *indio_dev = private; > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + dev_dbg(&indio_dev->dev, "id %x event %x\n", > + st->regs->reg_id, st->regs->reg_data); > + > + switch (st->regs->reg_data) { > + case 0: > + iio_push_event(indio_dev, > + IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, > + IIO_EV_DIR_RISING, > + IIO_EV_TYPE_THRESH, 0, 0, 0), > + st->event_timestamp); > + break; > + case 1: > + if (st->activity_running > st->event_val) > + iio_push_event(indio_dev, > + IIO_EVENT_CODE(IIO_ACTIVITY, 0, > + IIO_MOD_RUNNING, > + IIO_EV_DIR_RISING, > + IIO_EV_TYPE_THRESH, > + 0, 0, 0), > + st->event_timestamp); > + break; > + case 2: > + if (st->activity_walking < st->event_val) > + iio_push_event(indio_dev, > + IIO_EVENT_CODE(IIO_ACTIVITY, 0, > + IIO_MOD_WALKING, > + IIO_EV_DIR_FALLING, > + IIO_EV_TYPE_THRESH, > + 0, 0, 0), > + st->event_timestamp); > + break; > + case 3: > + iio_push_event(indio_dev, > + IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, > + IIO_EV_DIR_NONE, > + IIO_EV_TYPE_CHANGE, 0, 0, 0), > + st->event_timestamp); > + break; > + default: > + break; > + } > + > + return IRQ_HANDLED; > +} > + > +/** > + * iio_simple_dummy_events_register() - setup interrupt handling for events > + * @indio_dev: device instance data > + * > + * This function requests the threaded interrupt to handle the events. > + * Normally the irq is a hardware interrupt and the number comes > + * from board configuration files. Here we get it from a companion > + * module that fakes the interrupt for us. Note that module in > + * no way forms part of this example. Just assume that events magically > + * appear via the provided interrupt. > + */ > +int iio_simple_dummy_events_register(struct iio_dev *indio_dev) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + int ret; > + > + /* Fire up event source - normally not present */ > + st->event_irq = iio_dummy_evgen_get_irq(); > + if (st->event_irq < 0) { > + ret = st->event_irq; > + goto error_ret; > + } > + st->regs = iio_dummy_evgen_get_regs(st->event_irq); > + > + ret = request_threaded_irq(st->event_irq, > + &iio_simple_dummy_get_timestamp, > + &iio_simple_dummy_event_handler, > + IRQF_ONESHOT, > + "iio_simple_event", > + indio_dev); > + if (ret < 0) > + goto error_free_evgen; > + return 0; > + > +error_free_evgen: > + iio_dummy_evgen_release_irq(st->event_irq); > +error_ret: > + return ret; > +} > + > +/** > + * iio_simple_dummy_events_unregister() - tidy up interrupt handling on > remove > + * @indio_dev: device instance data > + */ > +void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) > +{ > + struct iio_dummy_state *st = iio_priv(indio_dev); > + > + free_irq(st->event_irq, indio_dev); > + /* Not part of normal driver */ > + iio_dummy_evgen_release_irq(st->event_irq); > +} > diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig > index 6d5b38d..85de198 100644 > --- a/drivers/staging/iio/Kconfig > +++ b/drivers/staging/iio/Kconfig > @@ -17,32 +17,32 @@ source "drivers/staging/iio/meter/Kconfig" > source "drivers/staging/iio/resolver/Kconfig" > source "drivers/staging/iio/trigger/Kconfig" > > -config IIO_DUMMY_EVGEN > - tristate > - > -config IIO_SIMPLE_DUMMY > - tristate "An example driver with no hardware requirements" > - help > - Driver intended mainly as documentation for how to write > - a driver. May also be useful for testing userspace code > - without hardware. > - > -if IIO_SIMPLE_DUMMY > - > -config IIO_SIMPLE_DUMMY_EVENTS > - bool "Event generation support" > - select IIO_DUMMY_EVGEN > - help > - Add some dummy events to the simple dummy driver. > - > -config IIO_SIMPLE_DUMMY_BUFFER > - bool "Buffered capture support" > - select IIO_BUFFER > - select IIO_TRIGGER > - select IIO_KFIFO_BUF > - help > - Add buffered data capture to the simple dummy driver. > - > -endif # IIO_SIMPLE_DUMMY > +#config IIO_DUMMY_EVGEN > +# tristate > +# > +#config IIO_SIMPLE_DUMMY > +# tristate "An example driver with no hardware requirements" > +# help > +# Driver intended mainly as documentation for how to write > +# a driver. May also be useful for testing userspace code > +# without hardware. > + > +#if IIO_SIMPLE_DUMMY > + > +#config IIO_SIMPLE_DUMMY_EVENTS > +# bool "Event generation support" > +# select IIO_DUMMY_EVGEN > +# help > +# Add some dummy events to the simple dummy driver. > + > +#config IIO_SIMPLE_DUMMY_BUFFER > +# bool "Buffered capture support" > +# select IIO_BUFFER > +# select IIO_TRIGGER > +# select IIO_KFIFO_BUF > +# help > +# Add buffered data capture to the simple dummy driver. > + > +#endif # IIO_SIMPLE_DUMMY > > endmenu > diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile > index d871061..355824a 100644 > --- a/drivers/staging/iio/Makefile > +++ b/drivers/staging/iio/Makefile > @@ -2,12 +2,12 @@ > # Makefile for the industrial I/O core. > # > > -obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o > -iio_dummy-y := iio_simple_dummy.o > -iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o > -iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o > +#obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o > +#iio_dummy-y := iio_simple_dummy.o > +#iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o > +#iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o > > -obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o > +#obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o > > obj-y += accel/ > obj-y += adc/ > diff --git a/drivers/staging/iio/iio_dummy_evgen.c > b/drivers/staging/iio/iio_dummy_evgen.c > deleted file mode 100644 > index 9e83f34..0000000 > --- a/drivers/staging/iio/iio_dummy_evgen.c > +++ /dev/null > @@ -1,262 +0,0 @@ > -/** > - * Copyright (c) 2011 Jonathan Cameron > - * > - * This program is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License version 2 as published > by > - * the Free Software Foundation. > - * > - * Companion module to the iio simple dummy example driver. > - * The purpose of this is to generate 'fake' event interrupts thus > - * allowing that driver's code to be as close as possible to that of > - * a normal driver talking to hardware. The approach used here > - * is not intended to be general and just happens to work for this > - * particular use case. > - */ > - > -#include <linux/kernel.h> > -#include <linux/slab.h> > -#include <linux/interrupt.h> > -#include <linux/irq.h> > -#include <linux/mutex.h> > -#include <linux/module.h> > -#include <linux/sysfs.h> > - > -#include "iio_dummy_evgen.h" > -#include <linux/iio/iio.h> > -#include <linux/iio/sysfs.h> > -#include <linux/irq_work.h> > - > -/* Fiddly bit of faking and irq without hardware */ > -#define IIO_EVENTGEN_NO 10 > - > -/** > - * struct iio_dummy_handle_irq - helper struct to simulate interrupt > generation > - * @work: irq_work used to run handlers from hardirq context > - * @irq: fake irq line number to trigger an interrupt > - */ > -struct iio_dummy_handle_irq { > - struct irq_work work; > - int irq; > -}; > - > -/** > - * struct iio_dummy_evgen - evgen state > - * @chip: irq chip we are faking > - * @base: base of irq range > - * @enabled: mask of which irqs are enabled > - * @inuse: mask of which irqs are connected > - * @regs: irq regs we are faking > - * @lock: protect the evgen state > - * @handler: helper for a 'hardware-like' interrupt simulation > - */ > -struct iio_dummy_eventgen { > - struct irq_chip chip; > - int base; > - bool enabled[IIO_EVENTGEN_NO]; > - bool inuse[IIO_EVENTGEN_NO]; > - struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; > - struct mutex lock; > - struct iio_dummy_handle_irq handler; > -}; > - > -/* We can only ever have one instance of this 'device' */ > -static struct iio_dummy_eventgen *iio_evgen; > -static const char *iio_evgen_name = "iio_dummy_evgen"; > - > -static void iio_dummy_event_irqmask(struct irq_data *d) > -{ > - struct irq_chip *chip = irq_data_get_irq_chip(d); > - struct iio_dummy_eventgen *evgen = > - container_of(chip, struct iio_dummy_eventgen, chip); > - > - evgen->enabled[d->irq - evgen->base] = false; > -} > - > -static void iio_dummy_event_irqunmask(struct irq_data *d) > -{ > - struct irq_chip *chip = irq_data_get_irq_chip(d); > - struct iio_dummy_eventgen *evgen = > - container_of(chip, struct iio_dummy_eventgen, chip); > - > - evgen->enabled[d->irq - evgen->base] = true; > -} > - > -static void iio_dummy_work_handler(struct irq_work *work) > -{ > - struct iio_dummy_handle_irq *irq_handler; > - > - irq_handler = container_of(work, struct iio_dummy_handle_irq, work); > - handle_simple_irq(irq_to_desc(irq_handler->irq)); > -} > - > -static int iio_dummy_evgen_create(void) > -{ > - int ret, i; > - > - iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL); > - if (!iio_evgen) > - return -ENOMEM; > - > - iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0); > - if (iio_evgen->base < 0) { > - ret = iio_evgen->base; > - kfree(iio_evgen); > - return ret; > - } > - iio_evgen->chip.name = iio_evgen_name; > - iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask; > - iio_evgen->chip.irq_unmask = &iio_dummy_event_irqunmask; > - for (i = 0; i < IIO_EVENTGEN_NO; i++) { > - irq_set_chip(iio_evgen->base + i, &iio_evgen->chip); > - irq_set_handler(iio_evgen->base + i, &handle_simple_irq); > - irq_modify_status(iio_evgen->base + i, > - IRQ_NOREQUEST | IRQ_NOAUTOEN, > - IRQ_NOPROBE); > - } > - init_irq_work(&iio_evgen->handler.work, iio_dummy_work_handler); > - mutex_init(&iio_evgen->lock); > - return 0; > -} > - > -/** > - * iio_dummy_evgen_get_irq() - get an evgen provided irq for a device > - * > - * This function will give a free allocated irq to a client device. > - * That irq can then be caused to 'fire' by using the associated sysfs file. > - */ > -int iio_dummy_evgen_get_irq(void) > -{ > - int i, ret = 0; > - > - if (!iio_evgen) > - return -ENODEV; > - > - mutex_lock(&iio_evgen->lock); > - for (i = 0; i < IIO_EVENTGEN_NO; i++) > - if (!iio_evgen->inuse[i]) { > - ret = iio_evgen->base + i; > - iio_evgen->inuse[i] = true; > - break; > - } > - mutex_unlock(&iio_evgen->lock); > - if (i == IIO_EVENTGEN_NO) > - return -ENOMEM; > - return ret; > -} > -EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq); > - > -/** > - * iio_dummy_evgen_release_irq() - give the irq back. > - * @irq: irq being returned to the pool > - * > - * Used by client driver instances to give the irqs back when they disconnect > - */ > -void iio_dummy_evgen_release_irq(int irq) > -{ > - mutex_lock(&iio_evgen->lock); > - iio_evgen->inuse[irq - iio_evgen->base] = false; > - mutex_unlock(&iio_evgen->lock); > -} > -EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); > - > -struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq) > -{ > - return &iio_evgen->regs[irq - iio_evgen->base]; > -} > -EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs); > - > -static void iio_dummy_evgen_free(void) > -{ > - irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); > - kfree(iio_evgen); > -} > - > -static void iio_evgen_release(struct device *dev) > -{ > - iio_dummy_evgen_free(); > -} > - > -static ssize_t iio_evgen_poke(struct device *dev, > - struct device_attribute *attr, > - const char *buf, > - size_t len) > -{ > - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); > - unsigned long event; > - int ret; > - > - ret = kstrtoul(buf, 10, &event); > - if (ret) > - return ret; > - > - iio_evgen->regs[this_attr->address].reg_id = this_attr->address; > - iio_evgen->regs[this_attr->address].reg_data = event; > - > - iio_evgen->handler.irq = iio_evgen->base + this_attr->address; > - if (iio_evgen->enabled[this_attr->address]) > - irq_work_queue(&iio_evgen->handler.work); > - > - return len; > -} > - > -static IIO_DEVICE_ATTR(poke_ev0, S_IWUSR, NULL, &iio_evgen_poke, 0); > -static IIO_DEVICE_ATTR(poke_ev1, S_IWUSR, NULL, &iio_evgen_poke, 1); > -static IIO_DEVICE_ATTR(poke_ev2, S_IWUSR, NULL, &iio_evgen_poke, 2); > -static IIO_DEVICE_ATTR(poke_ev3, S_IWUSR, NULL, &iio_evgen_poke, 3); > -static IIO_DEVICE_ATTR(poke_ev4, S_IWUSR, NULL, &iio_evgen_poke, 4); > -static IIO_DEVICE_ATTR(poke_ev5, S_IWUSR, NULL, &iio_evgen_poke, 5); > -static IIO_DEVICE_ATTR(poke_ev6, S_IWUSR, NULL, &iio_evgen_poke, 6); > -static IIO_DEVICE_ATTR(poke_ev7, S_IWUSR, NULL, &iio_evgen_poke, 7); > -static IIO_DEVICE_ATTR(poke_ev8, S_IWUSR, NULL, &iio_evgen_poke, 8); > -static IIO_DEVICE_ATTR(poke_ev9, S_IWUSR, NULL, &iio_evgen_poke, 9); > - > -static struct attribute *iio_evgen_attrs[] = { > - &iio_dev_attr_poke_ev0.dev_attr.attr, > - &iio_dev_attr_poke_ev1.dev_attr.attr, > - &iio_dev_attr_poke_ev2.dev_attr.attr, > - &iio_dev_attr_poke_ev3.dev_attr.attr, > - &iio_dev_attr_poke_ev4.dev_attr.attr, > - &iio_dev_attr_poke_ev5.dev_attr.attr, > - &iio_dev_attr_poke_ev6.dev_attr.attr, > - &iio_dev_attr_poke_ev7.dev_attr.attr, > - &iio_dev_attr_poke_ev8.dev_attr.attr, > - &iio_dev_attr_poke_ev9.dev_attr.attr, > - NULL, > -}; > - > -static const struct attribute_group iio_evgen_group = { > - .attrs = iio_evgen_attrs, > -}; > - > -static const struct attribute_group *iio_evgen_groups[] = { > - &iio_evgen_group, > - NULL > -}; > - > -static struct device iio_evgen_dev = { > - .bus = &iio_bus_type, > - .groups = iio_evgen_groups, > - .release = &iio_evgen_release, > -}; > - > -static __init int iio_dummy_evgen_init(void) > -{ > - int ret = iio_dummy_evgen_create(); > - > - if (ret < 0) > - return ret; > - device_initialize(&iio_evgen_dev); > - dev_set_name(&iio_evgen_dev, "iio_evgen"); > - return device_add(&iio_evgen_dev); > -} > -module_init(iio_dummy_evgen_init); > - > -static __exit void iio_dummy_evgen_exit(void) > -{ > - device_unregister(&iio_evgen_dev); > -} > -module_exit(iio_dummy_evgen_exit); > - > -MODULE_AUTHOR("Jonathan Cameron <ji...@kernel.org>"); > -MODULE_DESCRIPTION("IIO dummy driver"); > -MODULE_LICENSE("GPL v2"); > diff --git a/drivers/staging/iio/iio_dummy_evgen.h > b/drivers/staging/iio/iio_dummy_evgen.h > deleted file mode 100644 > index d044b94..0000000 > --- a/drivers/staging/iio/iio_dummy_evgen.h > +++ /dev/null > @@ -1,13 +0,0 @@ > -#ifndef _IIO_DUMMY_EVGEN_H_ > -#define _IIO_DUMMY_EVGEN_H_ > - > -struct iio_dummy_regs { > - u32 reg_id; > - u32 reg_data; > -}; > - > -struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq); > -int iio_dummy_evgen_get_irq(void); > -void iio_dummy_evgen_release_irq(int irq); > - > -#endif /* _IIO_DUMMY_EVGEN_H_ */ > diff --git a/drivers/staging/iio/iio_simple_dummy.c > b/drivers/staging/iio/iio_simple_dummy.c > deleted file mode 100644 > index 381f90f..0000000 > --- a/drivers/staging/iio/iio_simple_dummy.c > +++ /dev/null > @@ -1,748 +0,0 @@ > -/** > - * Copyright (c) 2011 Jonathan Cameron > - * > - * This program is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License version 2 as published > by > - * the Free Software Foundation. > - * > - * A reference industrial I/O driver to illustrate the functionality > available. > - * > - * There are numerous real drivers to illustrate the finer points. > - * The purpose of this driver is to provide a driver with far more comments > - * and explanatory notes than any 'real' driver would have. > - * Anyone starting out writing an IIO driver should first make sure they > - * understand all of this driver except those bits specifically marked > - * as being present to allow us to 'fake' the presence of hardware. > - */ > -#include <linux/kernel.h> > -#include <linux/slab.h> > -#include <linux/module.h> > - > -#include <linux/iio/iio.h> > -#include <linux/iio/sysfs.h> > -#include <linux/iio/events.h> > -#include <linux/iio/buffer.h> > -#include "iio_simple_dummy.h" > - > -/* > - * A few elements needed to fake a bus for this driver > - * Note instances parameter controls how many of these > - * dummy devices are registered. > - */ > -static unsigned instances = 1; > -module_param(instances, uint, 0); > - > -/* Pointer array used to fake bus elements */ > -static struct iio_dev **iio_dummy_devs; > - > -/* Fake a name for the part number, usually obtained from the id table */ > -static const char *iio_dummy_part_number = "iio_dummy_part_no"; > - > -/** > - * struct iio_dummy_accel_calibscale - realworld to register mapping > - * @val: first value in read_raw - here integer part. > - * @val2: second value in read_raw etc - here micro part. > - * @regval: register value - magic device specific numbers. > - */ > -struct iio_dummy_accel_calibscale { > - int val; > - int val2; > - int regval; /* what would be written to hardware */ > -}; > - > -static const struct iio_dummy_accel_calibscale dummy_scales[] = { > - { 0, 100, 0x8 }, /* 0.000100 */ > - { 0, 133, 0x7 }, /* 0.000133 */ > - { 733, 13, 0x9 }, /* 733.000013 */ > -}; > - > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - > -/* > - * simple event - triggered when value rises above > - * a threshold > - */ > -static const struct iio_event_spec iio_dummy_event = { > - .type = IIO_EV_TYPE_THRESH, > - .dir = IIO_EV_DIR_RISING, > - .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), > -}; > - > -/* > - * simple step detect event - triggered when a step is detected > - */ > -static const struct iio_event_spec step_detect_event = { > - .type = IIO_EV_TYPE_CHANGE, > - .dir = IIO_EV_DIR_NONE, > - .mask_separate = BIT(IIO_EV_INFO_ENABLE), > -}; > - > -/* > - * simple transition event - triggered when the reported running confidence > - * value rises above a threshold value > - */ > -static const struct iio_event_spec iio_running_event = { > - .type = IIO_EV_TYPE_THRESH, > - .dir = IIO_EV_DIR_RISING, > - .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), > -}; > - > -/* > - * simple transition event - triggered when the reported walking confidence > - * value falls under a threshold value > - */ > -static const struct iio_event_spec iio_walking_event = { > - .type = IIO_EV_TYPE_THRESH, > - .dir = IIO_EV_DIR_FALLING, > - .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), > -}; > -#endif > - > -/* > - * iio_dummy_channels - Description of available channels > - * > - * This array of structures tells the IIO core about what the device > - * actually provides for a given channel. > - */ > -static const struct iio_chan_spec iio_dummy_channels[] = { > - /* indexed ADC channel in_voltage0_raw etc */ > - { > - .type = IIO_VOLTAGE, > - /* Channel has a numeric index of 0 */ > - .indexed = 1, > - .channel = 0, > - /* What other information is available? */ > - .info_mask_separate = > - /* > - * in_voltage0_raw > - * Raw (unscaled no bias removal etc) measurement > - * from the device. > - */ > - BIT(IIO_CHAN_INFO_RAW) | > - /* > - * in_voltage0_offset > - * Offset for userspace to apply prior to scale > - * when converting to standard units (microvolts) > - */ > - BIT(IIO_CHAN_INFO_OFFSET) | > - /* > - * in_voltage0_scale > - * Multipler for userspace to apply post offset > - * when converting to standard units (microvolts) > - */ > - BIT(IIO_CHAN_INFO_SCALE), > - /* > - * sampling_frequency > - * The frequency in Hz at which the channels are sampled > - */ > - .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), > - /* The ordering of elements in the buffer via an enum */ > - .scan_index = voltage0, > - .scan_type = { /* Description of storage in buffer */ > - .sign = 'u', /* unsigned */ > - .realbits = 13, /* 13 bits */ > - .storagebits = 16, /* 16 bits used for storage */ > - .shift = 0, /* zero shift */ > - }, > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - .event_spec = &iio_dummy_event, > - .num_event_specs = 1, > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > - }, > - /* Differential ADC channel in_voltage1-voltage2_raw etc*/ > - { > - .type = IIO_VOLTAGE, > - .differential = 1, > - /* > - * Indexing for differential channels uses channel > - * for the positive part, channel2 for the negative. > - */ > - .indexed = 1, > - .channel = 1, > - .channel2 = 2, > - /* > - * in_voltage1-voltage2_raw > - * Raw (unscaled no bias removal etc) measurement > - * from the device. > - */ > - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > - /* > - * in_voltage-voltage_scale > - * Shared version of scale - shared by differential > - * input channels of type IIO_VOLTAGE. > - */ > - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), > - /* > - * sampling_frequency > - * The frequency in Hz at which the channels are sampled > - */ > - .scan_index = diffvoltage1m2, > - .scan_type = { /* Description of storage in buffer */ > - .sign = 's', /* signed */ > - .realbits = 12, /* 12 bits */ > - .storagebits = 16, /* 16 bits used for storage */ > - .shift = 0, /* zero shift */ > - }, > - }, > - /* Differential ADC channel in_voltage3-voltage4_raw etc*/ > - { > - .type = IIO_VOLTAGE, > - .differential = 1, > - .indexed = 1, > - .channel = 3, > - .channel2 = 4, > - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), > - .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), > - .scan_index = diffvoltage3m4, > - .scan_type = { > - .sign = 's', > - .realbits = 11, > - .storagebits = 16, > - .shift = 0, > - }, > - }, > - /* > - * 'modified' (i.e. axis specified) acceleration channel > - * in_accel_z_raw > - */ > - { > - .type = IIO_ACCEL, > - .modified = 1, > - /* Channel 2 is use for modifiers */ > - .channel2 = IIO_MOD_X, > - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > - /* > - * Internal bias and gain correction values. Applied > - * by the hardware or driver prior to userspace > - * seeing the readings. Typically part of hardware > - * calibration. > - */ > - BIT(IIO_CHAN_INFO_CALIBSCALE) | > - BIT(IIO_CHAN_INFO_CALIBBIAS), > - .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), > - .scan_index = accelx, > - .scan_type = { /* Description of storage in buffer */ > - .sign = 's', /* signed */ > - .realbits = 16, /* 16 bits */ > - .storagebits = 16, /* 16 bits used for storage */ > - .shift = 0, /* zero shift */ > - }, > - }, > - /* > - * Convenience macro for timestamps. 4 is the index in > - * the buffer. > - */ > - IIO_CHAN_SOFT_TIMESTAMP(4), > - /* DAC channel out_voltage0_raw */ > - { > - .type = IIO_VOLTAGE, > - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > - .scan_index = -1, /* No buffer support */ > - .output = 1, > - .indexed = 1, > - .channel = 0, > - }, > - { > - .type = IIO_STEPS, > - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | > - BIT(IIO_CHAN_INFO_CALIBHEIGHT), > - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > - .scan_index = -1, /* No buffer support */ > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - .event_spec = &step_detect_event, > - .num_event_specs = 1, > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > - }, > - { > - .type = IIO_ACTIVITY, > - .modified = 1, > - .channel2 = IIO_MOD_RUNNING, > - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > - .scan_index = -1, /* No buffer support */ > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - .event_spec = &iio_running_event, > - .num_event_specs = 1, > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > - }, > - { > - .type = IIO_ACTIVITY, > - .modified = 1, > - .channel2 = IIO_MOD_WALKING, > - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > - .scan_index = -1, /* No buffer support */ > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - .event_spec = &iio_walking_event, > - .num_event_specs = 1, > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > - }, > -}; > - > -/** > - * iio_dummy_read_raw() - data read function. > - * @indio_dev: the struct iio_dev associated with this device instance > - * @chan: the channel whose data is to be read > - * @val: first element of returned value (typically INT) > - * @val2: second element of returned value (typically MICRO) > - * @mask: what we actually want to read as per the info_mask_* > - * in iio_chan_spec. > - */ > -static int iio_dummy_read_raw(struct iio_dev *indio_dev, > - struct iio_chan_spec const *chan, > - int *val, > - int *val2, > - long mask) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - int ret = -EINVAL; > - > - mutex_lock(&st->lock); > - switch (mask) { > - case IIO_CHAN_INFO_RAW: /* magic value - channel value read */ > - switch (chan->type) { > - case IIO_VOLTAGE: > - if (chan->output) { > - /* Set integer part to cached value */ > - *val = st->dac_val; > - ret = IIO_VAL_INT; > - } else if (chan->differential) { > - if (chan->channel == 1) > - *val = st->differential_adc_val[0]; > - else > - *val = st->differential_adc_val[1]; > - ret = IIO_VAL_INT; > - } else { > - *val = st->single_ended_adc_val; > - ret = IIO_VAL_INT; > - } > - break; > - case IIO_ACCEL: > - *val = st->accel_val; > - ret = IIO_VAL_INT; > - break; > - default: > - break; > - } > - break; > - case IIO_CHAN_INFO_PROCESSED: > - switch (chan->type) { > - case IIO_STEPS: > - *val = st->steps; > - ret = IIO_VAL_INT; > - break; > - case IIO_ACTIVITY: > - switch (chan->channel2) { > - case IIO_MOD_RUNNING: > - *val = st->activity_running; > - ret = IIO_VAL_INT; > - break; > - case IIO_MOD_WALKING: > - *val = st->activity_walking; > - ret = IIO_VAL_INT; > - break; > - default: > - break; > - } > - break; > - default: > - break; > - } > - break; > - case IIO_CHAN_INFO_OFFSET: > - /* only single ended adc -> 7 */ > - *val = 7; > - ret = IIO_VAL_INT; > - break; > - case IIO_CHAN_INFO_SCALE: > - switch (chan->type) { > - case IIO_VOLTAGE: > - switch (chan->differential) { > - case 0: > - /* only single ended adc -> 0.001333 */ > - *val = 0; > - *val2 = 1333; > - ret = IIO_VAL_INT_PLUS_MICRO; > - break; > - case 1: > - /* all differential adc channels -> > - * 0.000001344 */ > - *val = 0; > - *val2 = 1344; > - ret = IIO_VAL_INT_PLUS_NANO; > - } > - break; > - default: > - break; > - } > - break; > - case IIO_CHAN_INFO_CALIBBIAS: > - /* only the acceleration axis - read from cache */ > - *val = st->accel_calibbias; > - ret = IIO_VAL_INT; > - break; > - case IIO_CHAN_INFO_CALIBSCALE: > - *val = st->accel_calibscale->val; > - *val2 = st->accel_calibscale->val2; > - ret = IIO_VAL_INT_PLUS_MICRO; > - break; > - case IIO_CHAN_INFO_SAMP_FREQ: > - *val = 3; > - *val2 = 33; > - ret = IIO_VAL_INT_PLUS_NANO; > - break; > - case IIO_CHAN_INFO_ENABLE: > - switch (chan->type) { > - case IIO_STEPS: > - *val = st->steps_enabled; > - ret = IIO_VAL_INT; > - break; > - default: > - break; > - } > - break; > - case IIO_CHAN_INFO_CALIBHEIGHT: > - switch (chan->type) { > - case IIO_STEPS: > - *val = st->height; > - ret = IIO_VAL_INT; > - break; > - default: > - break; > - } > - break; > - > - default: > - break; > - } > - mutex_unlock(&st->lock); > - return ret; > -} > - > -/** > - * iio_dummy_write_raw() - data write function. > - * @indio_dev: the struct iio_dev associated with this device instance > - * @chan: the channel whose data is to be written > - * @val: first element of value to set (typically INT) > - * @val2: second element of value to set (typically MICRO) > - * @mask: what we actually want to write as per the info_mask_* > - * in iio_chan_spec. > - * > - * Note that all raw writes are assumed IIO_VAL_INT and info mask elements > - * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt > - * in struct iio_info is provided by the driver. > - */ > -static int iio_dummy_write_raw(struct iio_dev *indio_dev, > - struct iio_chan_spec const *chan, > - int val, > - int val2, > - long mask) > -{ > - int i; > - int ret = 0; > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - switch (mask) { > - case IIO_CHAN_INFO_RAW: > - switch (chan->type) { > - case IIO_VOLTAGE: > - if (chan->output == 0) > - return -EINVAL; > - > - /* Locking not required as writing single value */ > - mutex_lock(&st->lock); > - st->dac_val = val; > - mutex_unlock(&st->lock); > - return 0; > - default: > - return -EINVAL; > - } > - case IIO_CHAN_INFO_PROCESSED: > - switch (chan->type) { > - case IIO_STEPS: > - mutex_lock(&st->lock); > - st->steps = val; > - mutex_unlock(&st->lock); > - return 0; > - case IIO_ACTIVITY: > - if (val < 0) > - val = 0; > - if (val > 100) > - val = 100; > - switch (chan->channel2) { > - case IIO_MOD_RUNNING: > - st->activity_running = val; > - return 0; > - case IIO_MOD_WALKING: > - st->activity_walking = val; > - return 0; > - default: > - return -EINVAL; > - } > - break; > - default: > - return -EINVAL; > - } > - case IIO_CHAN_INFO_CALIBSCALE: > - mutex_lock(&st->lock); > - /* Compare against table - hard matching here */ > - for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) > - if (val == dummy_scales[i].val && > - val2 == dummy_scales[i].val2) > - break; > - if (i == ARRAY_SIZE(dummy_scales)) > - ret = -EINVAL; > - else > - st->accel_calibscale = &dummy_scales[i]; > - mutex_unlock(&st->lock); > - return ret; > - case IIO_CHAN_INFO_CALIBBIAS: > - mutex_lock(&st->lock); > - st->accel_calibbias = val; > - mutex_unlock(&st->lock); > - return 0; > - case IIO_CHAN_INFO_ENABLE: > - switch (chan->type) { > - case IIO_STEPS: > - mutex_lock(&st->lock); > - st->steps_enabled = val; > - mutex_unlock(&st->lock); > - return 0; > - default: > - return -EINVAL; > - } > - case IIO_CHAN_INFO_CALIBHEIGHT: > - switch (chan->type) { > - case IIO_STEPS: > - st->height = val; > - return 0; > - default: > - return -EINVAL; > - } > - > - default: > - return -EINVAL; > - } > -} > - > -/* > - * Device type specific information. > - */ > -static const struct iio_info iio_dummy_info = { > - .driver_module = THIS_MODULE, > - .read_raw = &iio_dummy_read_raw, > - .write_raw = &iio_dummy_write_raw, > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - .read_event_config = &iio_simple_dummy_read_event_config, > - .write_event_config = &iio_simple_dummy_write_event_config, > - .read_event_value = &iio_simple_dummy_read_event_value, > - .write_event_value = &iio_simple_dummy_write_event_value, > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > -}; > - > -/** > - * iio_dummy_init_device() - device instance specific init > - * @indio_dev: the iio device structure > - * > - * Most drivers have one of these to set up default values, > - * reset the device to known state etc. > - */ > -static int iio_dummy_init_device(struct iio_dev *indio_dev) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - st->dac_val = 0; > - st->single_ended_adc_val = 73; > - st->differential_adc_val[0] = 33; > - st->differential_adc_val[1] = -34; > - st->accel_val = 34; > - st->accel_calibbias = -7; > - st->accel_calibscale = &dummy_scales[0]; > - st->steps = 47; > - st->activity_running = 98; > - st->activity_walking = 4; > - > - return 0; > -} > - > -/** > - * iio_dummy_probe() - device instance probe > - * @index: an id number for this instance. > - * > - * Arguments are bus type specific. > - * I2C: iio_dummy_probe(struct i2c_client *client, > - * const struct i2c_device_id *id) > - * SPI: iio_dummy_probe(struct spi_device *spi) > - */ > -static int iio_dummy_probe(int index) > -{ > - int ret; > - struct iio_dev *indio_dev; > - struct iio_dummy_state *st; > - > - /* > - * Allocate an IIO device. > - * > - * This structure contains all generic state > - * information about the device instance. > - * It also has a region (accessed by iio_priv() > - * for chip specific state information. > - */ > - indio_dev = iio_device_alloc(sizeof(*st)); > - if (!indio_dev) { > - ret = -ENOMEM; > - goto error_ret; > - } > - > - st = iio_priv(indio_dev); > - mutex_init(&st->lock); > - > - iio_dummy_init_device(indio_dev); > - /* > - * With hardware: Set the parent device. > - * indio_dev->dev.parent = &spi->dev; > - * indio_dev->dev.parent = &client->dev; > - */ > - > - /* > - * Make the iio_dev struct available to remove function. > - * Bus equivalents > - * i2c_set_clientdata(client, indio_dev); > - * spi_set_drvdata(spi, indio_dev); > - */ > - iio_dummy_devs[index] = indio_dev; > - > - /* > - * Set the device name. > - * > - * This is typically a part number and obtained from the module > - * id table. > - * e.g. for i2c and spi: > - * indio_dev->name = id->name; > - * indio_dev->name = spi_get_device_id(spi)->name; > - */ > - indio_dev->name = iio_dummy_part_number; > - > - /* Provide description of available channels */ > - indio_dev->channels = iio_dummy_channels; > - indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels); > - > - /* > - * Provide device type specific interface functions and > - * constant data. > - */ > - indio_dev->info = &iio_dummy_info; > - > - /* Specify that device provides sysfs type interfaces */ > - indio_dev->modes = INDIO_DIRECT_MODE; > - > - ret = iio_simple_dummy_events_register(indio_dev); > - if (ret < 0) > - goto error_free_device; > - > - ret = iio_simple_dummy_configure_buffer(indio_dev); > - if (ret < 0) > - goto error_unregister_events; > - > - ret = iio_device_register(indio_dev); > - if (ret < 0) > - goto error_unconfigure_buffer; > - > - return 0; > -error_unconfigure_buffer: > - iio_simple_dummy_unconfigure_buffer(indio_dev); > -error_unregister_events: > - iio_simple_dummy_events_unregister(indio_dev); > -error_free_device: > - iio_device_free(indio_dev); > -error_ret: > - return ret; > -} > - > -/** > - * iio_dummy_remove() - device instance removal function > - * @index: device index. > - * > - * Parameters follow those of iio_dummy_probe for buses. > - */ > -static void iio_dummy_remove(int index) > -{ > - /* > - * Get a pointer to the device instance iio_dev structure > - * from the bus subsystem. E.g. > - * struct iio_dev *indio_dev = i2c_get_clientdata(client); > - * struct iio_dev *indio_dev = spi_get_drvdata(spi); > - */ > - struct iio_dev *indio_dev = iio_dummy_devs[index]; > - > - /* Unregister the device */ > - iio_device_unregister(indio_dev); > - > - /* Device specific code to power down etc */ > - > - /* Buffered capture related cleanup */ > - iio_simple_dummy_unconfigure_buffer(indio_dev); > - > - iio_simple_dummy_events_unregister(indio_dev); > - > - /* Free all structures */ > - iio_device_free(indio_dev); > -} > - > -/** > - * iio_dummy_init() - device driver registration > - * > - * Varies depending on bus type of the device. As there is no device > - * here, call probe directly. For information on device registration > - * i2c: > - * Documentation/i2c/writing-clients > - * spi: > - * Documentation/spi/spi-summary > - */ > -static __init int iio_dummy_init(void) > -{ > - int i, ret; > - > - if (instances > 10) { > - instances = 1; > - return -EINVAL; > - } > - > - /* Fake a bus */ > - iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs), > - GFP_KERNEL); > - /* Here we have no actual device so call probe */ > - for (i = 0; i < instances; i++) { > - ret = iio_dummy_probe(i); > - if (ret < 0) > - goto error_remove_devs; > - } > - return 0; > - > -error_remove_devs: > - while (i--) > - iio_dummy_remove(i); > - > - kfree(iio_dummy_devs); > - return ret; > -} > -module_init(iio_dummy_init); > - > -/** > - * iio_dummy_exit() - device driver removal > - * > - * Varies depending on bus type of the device. > - * As there is no device here, call remove directly. > - */ > -static __exit void iio_dummy_exit(void) > -{ > - int i; > - > - for (i = 0; i < instances; i++) > - iio_dummy_remove(i); > - kfree(iio_dummy_devs); > -} > -module_exit(iio_dummy_exit); > - > -MODULE_AUTHOR("Jonathan Cameron <ji...@kernel.org>"); > -MODULE_DESCRIPTION("IIO dummy driver"); > -MODULE_LICENSE("GPL v2"); > diff --git a/drivers/staging/iio/iio_simple_dummy.h > b/drivers/staging/iio/iio_simple_dummy.h > deleted file mode 100644 > index 5c2f4d0..0000000 > --- a/drivers/staging/iio/iio_simple_dummy.h > +++ /dev/null > @@ -1,129 +0,0 @@ > -/** > - * Copyright (c) 2011 Jonathan Cameron > - * > - * This program is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License version 2 as published > by > - * the Free Software Foundation. > - * > - * Join together the various functionality of iio_simple_dummy driver > - */ > - > -#ifndef _IIO_SIMPLE_DUMMY_H_ > -#define _IIO_SIMPLE_DUMMY_H_ > -#include <linux/kernel.h> > - > -struct iio_dummy_accel_calibscale; > -struct iio_dummy_regs; > - > -/** > - * struct iio_dummy_state - device instance specific state. > - * @dac_val: cache for dac value > - * @single_ended_adc_val: cache for single ended adc value > - * @differential_adc_val: cache for differential adc value > - * @accel_val: cache for acceleration value > - * @accel_calibbias: cache for acceleration calibbias > - * @accel_calibscale: cache for acceleration calibscale > - * @lock: lock to ensure state is consistent > - * @event_irq: irq number for event line (faked) > - * @event_val: cache for event threshold value > - * @event_en: cache of whether event is enabled > - */ > -struct iio_dummy_state { > - int dac_val; > - int single_ended_adc_val; > - int differential_adc_val[2]; > - int accel_val; > - int accel_calibbias; > - int activity_running; > - int activity_walking; > - const struct iio_dummy_accel_calibscale *accel_calibscale; > - struct mutex lock; > - struct iio_dummy_regs *regs; > - int steps_enabled; > - int steps; > - int height; > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - int event_irq; > - int event_val; > - bool event_en; > - s64 event_timestamp; > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ > -}; > - > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS > - > -struct iio_dev; > - > -int 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); > - > -int 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); > - > -int 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); > - > -int 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); > - > -int iio_simple_dummy_events_register(struct iio_dev *indio_dev); > -void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev); > - > -#else /* Stubs for when events are disabled at compile time */ > - > -static inline int > -iio_simple_dummy_events_register(struct iio_dev *indio_dev) > -{ > - return 0; > -}; > - > -static inline void > -iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) > -{ }; > - > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS*/ > - > -/** > - * enum iio_simple_dummy_scan_elements - scan index enum > - * @voltage0: the single ended voltage channel > - * @diffvoltage1m2: first differential channel > - * @diffvoltage3m4: second differenial channel > - * @accelx: acceleration channel > - * > - * Enum provides convenient numbering for the scan index. > - */ > -enum iio_simple_dummy_scan_elements { > - voltage0, > - diffvoltage1m2, > - diffvoltage3m4, > - accelx, > -}; > - > -#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER > -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); > -void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); > -#else > -static inline int iio_simple_dummy_configure_buffer(struct iio_dev > *indio_dev) > -{ > - return 0; > -}; > - > -static inline > -void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) > -{}; > - > -#endif /* CONFIG_IIO_SIMPLE_DUMMY_BUFFER */ > -#endif /* _IIO_SIMPLE_DUMMY_H_ */ > diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c > b/drivers/staging/iio/iio_simple_dummy_buffer.c > deleted file mode 100644 > index 00ed774..0000000 > --- a/drivers/staging/iio/iio_simple_dummy_buffer.c > +++ /dev/null > @@ -1,192 +0,0 @@ > -/** > - * Copyright (c) 2011 Jonathan Cameron > - * > - * This program is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License version 2 as published > by > - * the Free Software Foundation. > - * > - * Buffer handling elements of industrial I/O reference driver. > - * Uses the kfifo buffer. > - * > - * To test without hardware use the sysfs trigger. > - */ > - > -#include <linux/kernel.h> > -#include <linux/export.h> > -#include <linux/slab.h> > -#include <linux/interrupt.h> > -#include <linux/irq.h> > -#include <linux/bitmap.h> > - > -#include <linux/iio/iio.h> > -#include <linux/iio/trigger_consumer.h> > -#include <linux/iio/kfifo_buf.h> > - > -#include "iio_simple_dummy.h" > - > -/* Some fake data */ > - > -static const s16 fakedata[] = { > - [voltage0] = 7, > - [diffvoltage1m2] = -33, > - [diffvoltage3m4] = -2, > - [accelx] = 344, > -}; > - > -/** > - * iio_simple_dummy_trigger_h() - the trigger handler function > - * @irq: the interrupt number > - * @p: private data - always a pointer to the poll func. > - * > - * This is the guts of buffered capture. On a trigger event occurring, > - * if the pollfunc is attached then this handler is called as a threaded > - * interrupt (and hence may sleep). It is responsible for grabbing data > - * from the device and pushing it into the associated buffer. > - */ > -static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) > -{ > - struct iio_poll_func *pf = p; > - struct iio_dev *indio_dev = pf->indio_dev; > - int len = 0; > - u16 *data; > - > - data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); > - if (!data) > - goto done; > - > - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { > - /* > - * Three common options here: > - * hardware scans: certain combinations of channels make > - * up a fast read. The capture will consist of all of them. > - * Hence we just call the grab data function and fill the > - * buffer without processing. > - * software scans: can be considered to be random access > - * so efficient reading is just a case of minimal bus > - * transactions. > - * software culled hardware scans: > - * occasionally a driver may process the nearest hardware > - * scan to avoid storing elements that are not desired. This > - * is the fiddliest option by far. > - * Here let's pretend we have random access. And the values are > - * in the constant table fakedata. > - */ > - int i, j; > - > - for (i = 0, j = 0; > - i < bitmap_weight(indio_dev->active_scan_mask, > - indio_dev->masklength); > - i++, j++) { > - j = find_next_bit(indio_dev->active_scan_mask, > - indio_dev->masklength, j); > - /* random access read from the 'device' */ > - data[i] = fakedata[j]; > - len += 2; > - } > - } > - > - iio_push_to_buffers_with_timestamp(indio_dev, data, iio_get_time_ns()); > - > - kfree(data); > - > -done: > - /* > - * Tell the core we are done with this trigger and ready for the > - * next one. > - */ > - iio_trigger_notify_done(indio_dev->trig); > - > - return IRQ_HANDLED; > -} > - > -static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = > { > - /* > - * iio_triggered_buffer_postenable: > - * Generic function that simply attaches the pollfunc to the trigger. > - * Replace this to mess with hardware state before we attach the > - * trigger. > - */ > - .postenable = &iio_triggered_buffer_postenable, > - /* > - * iio_triggered_buffer_predisable: > - * Generic function that simple detaches the pollfunc from the trigger. > - * Replace this to put hardware state back again after the trigger is > - * detached but before userspace knows we have disabled the ring. > - */ > - .predisable = &iio_triggered_buffer_predisable, > -}; > - > -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) > -{ > - int ret; > - struct iio_buffer *buffer; > - > - /* Allocate a buffer to use - here a kfifo */ > - buffer = iio_kfifo_allocate(); > - if (!buffer) { > - ret = -ENOMEM; > - goto error_ret; > - } > - > - iio_device_attach_buffer(indio_dev, buffer); > - > - /* Enable timestamps by default */ > - buffer->scan_timestamp = true; > - > - /* > - * Tell the core what device type specific functions should > - * be run on either side of buffer capture enable / disable. > - */ > - indio_dev->setup_ops = &iio_simple_dummy_buffer_setup_ops; > - > - /* > - * Configure a polling function. > - * When a trigger event with this polling function connected > - * occurs, this function is run. Typically this grabs data > - * from the device. > - * > - * NULL for the bottom half. This is normally implemented only if we > - * either want to ping a capture now pin (no sleeping) or grab > - * a timestamp as close as possible to a data ready trigger firing. > - * > - * IRQF_ONESHOT ensures irqs are masked such that only one instance > - * of the handler can run at a time. > - * > - * "iio_simple_dummy_consumer%d" formatting string for the irq 'name' > - * as seen under /proc/interrupts. Remaining parameters as per printk. > - */ > - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, > - &iio_simple_dummy_trigger_h, > - IRQF_ONESHOT, > - indio_dev, > - "iio_simple_dummy_consumer%d", > - indio_dev->id); > - > - if (!indio_dev->pollfunc) { > - ret = -ENOMEM; > - goto error_free_buffer; > - } > - > - /* > - * Notify the core that this device is capable of buffered capture > - * driven by a trigger. > - */ > - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; > - > - return 0; > - > -error_free_buffer: > - iio_kfifo_free(indio_dev->buffer); > -error_ret: > - return ret; > -} > - > -/** > - * iio_simple_dummy_unconfigure_buffer() - release buffer resources > - * @indo_dev: device instance state > - */ > -void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) > -{ > - iio_dealloc_pollfunc(indio_dev->pollfunc); > - iio_kfifo_free(indio_dev->buffer); > -} > diff --git a/drivers/staging/iio/iio_simple_dummy_events.c > b/drivers/staging/iio/iio_simple_dummy_events.c > deleted file mode 100644 > index bfbf1c5..0000000 > --- a/drivers/staging/iio/iio_simple_dummy_events.c > +++ /dev/null > @@ -1,276 +0,0 @@ > -/** > - * Copyright (c) 2011 Jonathan Cameron > - * > - * This program is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License version 2 as published > by > - * the Free Software Foundation. > - * > - * Event handling elements of industrial I/O reference driver. > - */ > -#include <linux/kernel.h> > -#include <linux/slab.h> > -#include <linux/interrupt.h> > -#include <linux/irq.h> > - > -#include <linux/iio/iio.h> > -#include <linux/iio/sysfs.h> > -#include <linux/iio/events.h> > -#include "iio_simple_dummy.h" > - > -/* Evgen 'fakes' interrupt events for this example */ > -#include "iio_dummy_evgen.h" > - > -/** > - * iio_simple_dummy_read_event_config() - is event enabled? > - * @indio_dev: the device instance data > - * @chan: channel for the event whose state is being queried > - * @type: type of the event whose state is being queried > - * @dir: direction of the vent whose state is being queried > - * > - * This function would normally query the relevant registers or a cache to > - * discover if the event generation is enabled on the device. > - */ > -int 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) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - return st->event_en; > -} > - > -/** > - * iio_simple_dummy_write_event_config() - set whether event is enabled > - * @indio_dev: the device instance data > - * @chan: channel for the event whose state is being set > - * @type: type of the event whose state is being set > - * @dir: direction of the vent whose state is being set > - * @state: whether to enable or disable the device. > - * > - * This function would normally set the relevant registers on the devices > - * so that it generates the specified event. Here it just sets up a cached > - * value. > - */ > -int 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) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - /* > - * Deliberately over the top code splitting to illustrate > - * how this is done when multiple events exist. > - */ > - switch (chan->type) { > - case IIO_VOLTAGE: > - switch (type) { > - case IIO_EV_TYPE_THRESH: > - if (dir == IIO_EV_DIR_RISING) > - st->event_en = state; > - else > - return -EINVAL; > - default: > - return -EINVAL; > - } > - break; > - case IIO_ACTIVITY: > - switch (type) { > - case IIO_EV_TYPE_THRESH: > - st->event_en = state; > - break; > - default: > - return -EINVAL; > - } > - break; > - case IIO_STEPS: > - switch (type) { > - case IIO_EV_TYPE_CHANGE: > - st->event_en = state; > - break; > - default: > - return -EINVAL; > - } > - break; > - default: > - return -EINVAL; > - } > - > - return 0; > -} > - > -/** > - * iio_simple_dummy_read_event_value() - get value associated with event > - * @indio_dev: device instance specific data > - * @chan: channel for the event whose value is being read > - * @type: type of the event whose value is being read > - * @dir: direction of the vent whose value is being read > - * @info: info type of the event whose value is being read > - * @val: value for the event code. > - * > - * Many devices provide a large set of events of which only a subset may > - * be enabled at a time, with value registers whose meaning changes depending > - * on the event enabled. This often means that the driver must cache the > values > - * associated with each possible events so that the right value is in place > when > - * the enabled event is changed. > - */ > -int 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) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - *val = st->event_val; > - > - return IIO_VAL_INT; > -} > - > -/** > - * iio_simple_dummy_write_event_value() - set value associate with event > - * @indio_dev: device instance specific data > - * @chan: channel for the event whose value is being set > - * @type: type of the event whose value is being set > - * @dir: direction of the vent whose value is being set > - * @info: info type of the event whose value is being set > - * @val: the value to be set. > - */ > -int 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) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - st->event_val = val; > - > - return 0; > -} > - > -static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private) > -{ > - struct iio_dev *indio_dev = private; > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - st->event_timestamp = iio_get_time_ns(); > - return IRQ_HANDLED; > -} > - > -/** > - * iio_simple_dummy_event_handler() - identify and pass on event > - * @irq: irq of event line > - * @private: pointer to device instance state. > - * > - * This handler is responsible for querying the device to find out what > - * event occurred and for then pushing that event towards userspace. > - * Here only one event occurs so we push that directly on with locally > - * grabbed timestamp. > - */ > -static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) > -{ > - struct iio_dev *indio_dev = private; > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - dev_dbg(&indio_dev->dev, "id %x event %x\n", > - st->regs->reg_id, st->regs->reg_data); > - > - switch (st->regs->reg_data) { > - case 0: > - iio_push_event(indio_dev, > - IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, > - IIO_EV_DIR_RISING, > - IIO_EV_TYPE_THRESH, 0, 0, 0), > - st->event_timestamp); > - break; > - case 1: > - if (st->activity_running > st->event_val) > - iio_push_event(indio_dev, > - IIO_EVENT_CODE(IIO_ACTIVITY, 0, > - IIO_MOD_RUNNING, > - IIO_EV_DIR_RISING, > - IIO_EV_TYPE_THRESH, > - 0, 0, 0), > - st->event_timestamp); > - break; > - case 2: > - if (st->activity_walking < st->event_val) > - iio_push_event(indio_dev, > - IIO_EVENT_CODE(IIO_ACTIVITY, 0, > - IIO_MOD_WALKING, > - IIO_EV_DIR_FALLING, > - IIO_EV_TYPE_THRESH, > - 0, 0, 0), > - st->event_timestamp); > - break; > - case 3: > - iio_push_event(indio_dev, > - IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, > - IIO_EV_DIR_NONE, > - IIO_EV_TYPE_CHANGE, 0, 0, 0), > - st->event_timestamp); > - break; > - default: > - break; > - } > - > - return IRQ_HANDLED; > -} > - > -/** > - * iio_simple_dummy_events_register() - setup interrupt handling for events > - * @indio_dev: device instance data > - * > - * This function requests the threaded interrupt to handle the events. > - * Normally the irq is a hardware interrupt and the number comes > - * from board configuration files. Here we get it from a companion > - * module that fakes the interrupt for us. Note that module in > - * no way forms part of this example. Just assume that events magically > - * appear via the provided interrupt. > - */ > -int iio_simple_dummy_events_register(struct iio_dev *indio_dev) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - int ret; > - > - /* Fire up event source - normally not present */ > - st->event_irq = iio_dummy_evgen_get_irq(); > - if (st->event_irq < 0) { > - ret = st->event_irq; > - goto error_ret; > - } > - st->regs = iio_dummy_evgen_get_regs(st->event_irq); > - > - ret = request_threaded_irq(st->event_irq, > - &iio_simple_dummy_get_timestamp, > - &iio_simple_dummy_event_handler, > - IRQF_ONESHOT, > - "iio_simple_event", > - indio_dev); > - if (ret < 0) > - goto error_free_evgen; > - return 0; > - > -error_free_evgen: > - iio_dummy_evgen_release_irq(st->event_irq); > -error_ret: > - return ret; > -} > - > -/** > - * iio_simple_dummy_events_unregister() - tidy up interrupt handling on > remove > - * @indio_dev: device instance data > - */ > -void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) > -{ > - struct iio_dummy_state *st = iio_priv(indio_dev); > - > - free_irq(st->event_irq, indio_dev); > - /* Not part of normal driver */ > - iio_dummy_evgen_release_irq(st->event_irq); > -} > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/