Commit aa256f8d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.15b' of...

Merge tag 'iio-for-3.15b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

Second round of IIO new driver, functionality and cleanups for the 3.15 series.

There are a few fixes in here that might, earlier in a cycle, have gone
to Greg as fixes. Given they are either minor or have never actually
been observed as causing trouble (the locking bug in the event code) and
are invasive, I have included them in this pull request, targeting the
3.15 merge window instead.

The rest are pretty uncontroversial new drivers, a handy little tool for
the example code in our documentation and little cleanups.

New drivers
* Freescale Vybrid and i.MX6SLX ADC driver.
* HID Sensor hub proximity sensors.
* HID Sensor hub pressure sensors.
* LPS25H Pressure sensors added to the ST micro pressure sensor driver.

New functionality
* lsiio tool.  This is added to the staging tree as we haven't yet moved
  the example code it sits with out.  Moving this code out is now a reasonably
  high priority but holding up this tool in the meantime did not seem
  worthwhile.
* mag3110 - add missing scale factor for temperature output to userspace.

Cleanups
* Fix a bug in the event reporting in which a spin lock might be held over
  when a sleep occured.  A similar bug was found by Lars in the buffer code.
  It has not to our knowledge been observed as actually occuring and is
  a little too invasive to push out as a fix.
* Drop the IIO_ST macro after clearing out all users.  This macro was a very
  bad idea leading to a number of bugs after it stopped covering all elements
  of the structure being assigned and people started making assumptions about
  what it did cover.  Glad to see it go!
* Avoid applying extended name to shared attributes as it makes no sense.
  No in tree drivers were using the combination, hence not pushed out as
  a fix.
* ad799x - move to devm_request_threaded_irq to reduce boilerplate clean up.
* bma180 - make the low_pass_filter_3db_frequency info element shared rather
  than per attribute.  The old approach was valid but not as clean as it might
  be and was setting a bad example.  Hence the cleanup.
* mxs-lradc - propogate the error code form a platform_get_irq call rather than
  eating it up by returning -EINVAL on all errors.
* ad799x - typo fix in the copyright message. Either that or Michael was
  asserting a copyright that moved backwards in time by about a thousand years.
* ad799x - use a regulator for vref rather than platform data.  The driver
  dates from just as the regulator framework was coming into common use so
  provides an alternative way of specifying the reference voltage.  We no
  longer need that approach so drop it in favour of a regulator only approach.
* max1363 - some internal vref values were out by a small amount.  The effect
  would have been tiny and no one noticed hence not pushing this through as
  a fix.
* core - replace some pointless goto error_ret (with no clean up) lines with
  direct returns.  This is my bad coding style so I'm glad to see it cleaned
  up.
* core - avoid a kasprintf that just directly prints a string with no
  formatting elements.  This has always been there but Lars just noticed it.
  Oops.
parents c36d44ac b91accaf
Freescale vf610 Analog to Digital Converter bindings
The devicetree bindings are for the new ADC driver written for
vf610/i.MX6slx and upward SoCs from Freescale.
Required properties:
- compatible: Should contain "fsl,vf610-adc"
- reg: Offset and length of the register set for the device
- interrupts: Should contain the interrupt for the device
- clocks: The clock is needed by the ADC controller, ADC clock source is ipg clock.
- clock-names: Must contain "adc", matching entry in the clocks property.
- vref-supply: The regulator supply ADC refrence voltage.
Example:
adc0: adc@4003b000 {
compatible = "fsl,vf610-adc";
reg = <0x4003b000 0x1000>;
interrupts = <0 53 0x04>;
clocks = <&clks VF610_CLK_ADC0>;
clock-names = "adc";
vref-supply = <&reg_vcc_3v3_mcu>;
};
......@@ -451,9 +451,9 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##_axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = AXIS_##_axis, \
.scan_type = { \
.sign = 's', \
......
......@@ -197,6 +197,16 @@ config TWL6030_GPADC
This driver can also be built as a module. If so, the module will be
called twl6030-gpadc.
config VF610_ADC
tristate "Freescale vf610 ADC driver"
depends on OF
help
Say yes here to support for Vybrid board analog-to-digital converter.
Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
This driver can also be built as a module. If so, the module will be
called vf610_adc.
config VIPERBOARD_ADC
tristate "Viperboard ADC support"
depends on MFD_VIPERBOARD && USB
......
......@@ -21,4 +21,5 @@ obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
obj-$(CONFIG_VF610_ADC) += vf610_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
......@@ -1247,7 +1247,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11604] = {
.bits = 8,
.int_vref_mv = 4098,
.int_vref_mv = 4096,
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
......@@ -1307,7 +1307,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11610] = {
.bits = 10,
.int_vref_mv = 4098,
.int_vref_mv = 4096,
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
......@@ -1367,7 +1367,7 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
[max11616] = {
.bits = 12,
.int_vref_mv = 4098,
.int_vref_mv = 4096,
.mode_list = max1238_mode_list,
.num_modes = ARRAY_SIZE(max1238_mode_list),
.default_mode = s0to11,
......
This diff is collapsed.
......@@ -46,10 +46,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
struct iio_channel *chan;
cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL);
if (cb_buff == NULL) {
ret = -ENOMEM;
goto error_ret;
}
if (cb_buff == NULL)
return ERR_PTR(-ENOMEM);
iio_buffer_init(&cb_buff->buffer);
......@@ -91,7 +89,6 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
iio_channel_release_all(cb_buff->channels);
error_free_cb_buff:
kfree(cb_buff);
error_ret:
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(iio_channel_get_all_cb);
......
......@@ -264,7 +264,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
&indio_dev->dev,
&buffer->scan_el_dev_attr_list);
if (ret)
goto error_ret;
return ret;
attrcount++;
ret = __iio_add_chan_devattr("type",
chan,
......@@ -275,7 +275,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
&indio_dev->dev,
&buffer->scan_el_dev_attr_list);
if (ret)
goto error_ret;
return ret;
attrcount++;
if (chan->type != IIO_TIMESTAMP)
ret = __iio_add_chan_devattr("en",
......@@ -296,10 +296,9 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
&indio_dev->dev,
&buffer->scan_el_dev_attr_list);
if (ret)
goto error_ret;
return ret;
attrcount++;
ret = attrcount;
error_ret:
return ret;
}
......@@ -553,13 +552,13 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
if (indio_dev->setup_ops->predisable) {
ret = indio_dev->setup_ops->predisable(indio_dev);
if (ret)
goto error_ret;
return ret;
}
indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable) {
ret = indio_dev->setup_ops->postdisable(indio_dev);
if (ret)
goto error_ret;
return ret;
}
}
/* Keep a copy of current setup to allow roll back */
......@@ -613,7 +612,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
else {
kfree(compound_mask);
ret = -EINVAL;
goto error_ret;
return ret;
}
}
} else {
......@@ -696,13 +695,10 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
if (indio_dev->setup_ops->postdisable)
indio_dev->setup_ops->postdisable(indio_dev);
error_remove_inserted:
if (insert_buffer)
iio_buffer_deactivate(insert_buffer);
indio_dev->active_scan_mask = old_mask;
kfree(compound_mask);
error_ret:
return ret;
}
......
......@@ -540,7 +540,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
enum iio_shared_by shared_by)
{
int ret = 0;
char *name_format = NULL;
char *name = NULL;
char *full_postfix;
sysfs_attr_init(&dev_attr->attr);
......@@ -558,7 +558,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
->channel2],
postfix);
} else {
if (chan->extend_name == NULL)
if (chan->extend_name == NULL || shared_by != IIO_SEPARATE)
full_postfix = kstrdup(postfix, GFP_KERNEL);
else
full_postfix = kasprintf(GFP_KERNEL,
......@@ -572,16 +572,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
if (chan->differential) { /* Differential can not have modifier */
switch (shared_by) {
case IIO_SHARED_BY_ALL:
name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
name = kasprintf(GFP_KERNEL, "%s", full_postfix);
break;
case IIO_SHARED_BY_DIR:
name_format = kasprintf(GFP_KERNEL, "%s_%s",
name = kasprintf(GFP_KERNEL, "%s_%s",
iio_direction[chan->output],
full_postfix);
break;
case IIO_SHARED_BY_TYPE:
name_format
= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
name = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
iio_chan_type_name_spec[chan->type],
......@@ -593,8 +592,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
ret = -EINVAL;
goto error_free_full_postfix;
}
name_format
= kasprintf(GFP_KERNEL,
name = kasprintf(GFP_KERNEL,
"%s_%s%d-%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
......@@ -607,16 +605,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
} else { /* Single ended */
switch (shared_by) {
case IIO_SHARED_BY_ALL:
name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
name = kasprintf(GFP_KERNEL, "%s", full_postfix);
break;
case IIO_SHARED_BY_DIR:
name_format = kasprintf(GFP_KERNEL, "%s_%s",
name = kasprintf(GFP_KERNEL, "%s_%s",
iio_direction[chan->output],
full_postfix);
break;
case IIO_SHARED_BY_TYPE:
name_format
= kasprintf(GFP_KERNEL, "%s_%s_%s",
name = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
......@@ -624,33 +621,24 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
case IIO_SEPARATE:
if (chan->indexed)
name_format
= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
name = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
chan->channel,
full_postfix);
else
name_format
= kasprintf(GFP_KERNEL, "%s_%s_%s",
name = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
break;
}
}
if (name_format == NULL) {
if (name == NULL) {
ret = -ENOMEM;
goto error_free_full_postfix;
}
dev_attr->attr.name = kasprintf(GFP_KERNEL,
name_format,
chan->channel,
chan->channel2);
if (dev_attr->attr.name == NULL) {
ret = -ENOMEM;
goto error_free_name_format;
}
dev_attr->attr.name = name;
if (readfunc) {
dev_attr->attr.mode |= S_IRUGO;
......@@ -661,8 +649,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
dev_attr->attr.mode |= S_IWUSR;
dev_attr->store = writefunc;
}
error_free_name_format:
kfree(name_format);
error_free_full_postfix:
kfree(full_postfix);
......@@ -692,10 +679,8 @@ int __iio_add_chan_devattr(const char *postfix,
struct iio_dev_attr *iio_attr, *t;
iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
if (iio_attr == NULL) {
ret = -ENOMEM;
goto error_ret;
}
if (iio_attr == NULL)
return -ENOMEM;
ret = __iio_device_attr_init(&iio_attr->dev_attr,
postfix, chan,
readfunc, writefunc, shared_by);
......@@ -720,7 +705,6 @@ int __iio_add_chan_devattr(const char *postfix,
__iio_device_attr_deinit(&iio_attr->dev_attr);
error_iio_dev_attr_free:
kfree(iio_attr);
error_ret:
return ret;
}
......@@ -1134,7 +1118,7 @@ int iio_device_register(struct iio_dev *indio_dev)
if (ret) {
dev_err(indio_dev->dev.parent,
"Failed to register debugfs interfaces\n");
goto error_ret;
return ret;
}
ret = iio_device_register_sysfs(indio_dev);
if (ret) {
......@@ -1175,7 +1159,6 @@ int iio_device_register(struct iio_dev *indio_dev)
iio_device_unregister_sysfs(indio_dev);
error_unreg_debugfs:
iio_device_unregister_debugfs(indio_dev);
error_ret:
return ret;
}
EXPORT_SYMBOL(iio_device_register);
......
......@@ -40,6 +40,7 @@ struct iio_event_interface {
struct list_head dev_attr_list;
unsigned long flags;
struct attribute_group group;
struct mutex read_lock;
};
/**
......@@ -47,16 +48,17 @@ struct iio_event_interface {
* @indio_dev: IIO device structure
* @ev_code: What event
* @timestamp: When the event occurred
*
* Note: The caller must make sure that this function is not running
* concurrently for the same indio_dev more than once.
**/
int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
{
struct iio_event_interface *ev_int = indio_dev->event_interface;
struct iio_event_data ev;
unsigned long flags;
int copied;
/* Does anyone care? */
spin_lock_irqsave(&ev_int->wait.lock, flags);
if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
ev.id = ev_code;
......@@ -64,9 +66,8 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
copied = kfifo_put(&ev_int->det_events, ev);
if (copied != 0)
wake_up_locked_poll(&ev_int->wait, POLLIN);
wake_up_poll(&ev_int->wait, POLLIN);
}
spin_unlock_irqrestore(&ev_int->wait.lock, flags);
return 0;
}
......@@ -87,10 +88,8 @@ static unsigned int iio_event_poll(struct file *filep,
poll_wait(filep, &ev_int->wait, wait);
spin_lock_irq(&ev_int->wait.lock);
if (!kfifo_is_empty(&ev_int->det_events))
events = POLLIN | POLLRDNORM;
spin_unlock_irq(&ev_int->wait.lock);
return events;
}
......@@ -111,31 +110,40 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
if (count < sizeof(struct iio_event_data))
return -EINVAL;
spin_lock_irq(&ev_int->wait.lock);
do {
if (kfifo_is_empty(&ev_int->det_events)) {
if (filep->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
goto error_unlock;
}
/* Blocking on device; waiting for something to be there */
ret = wait_event_interruptible_locked_irq(ev_int->wait,
if (filep->f_flags & O_NONBLOCK)
return -EAGAIN;
ret = wait_event_interruptible(ev_int->wait,
!kfifo_is_empty(&ev_int->det_events) ||
indio_dev->info == NULL);
if (ret)
goto error_unlock;
if (indio_dev->info == NULL) {
ret = -ENODEV;
goto error_unlock;
}
/* Single access device so no one else can get the data */
return ret;
if (indio_dev->info == NULL)
return -ENODEV;
}
if (mutex_lock_interruptible(&ev_int->read_lock))
return -ERESTARTSYS;
ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);
mutex_unlock(&ev_int->read_lock);
error_unlock:
spin_unlock_irq(&ev_int->wait.lock);
if (ret)
return ret;
/*
* If we couldn't read anything from the fifo (a different
* thread might have been faster) we either return -EAGAIN if
* the file descriptor is non-blocking, otherwise we go back to
* sleep and wait for more data to arrive.
*/
if (copied == 0 && (filep->f_flags & O_NONBLOCK))
return -EAGAIN;
return ret ? ret : copied;
} while (copied == 0);
return copied;
}
static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
......@@ -143,15 +151,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
/*
* In order to maintain a clean state for reopening,
* clear out any awaiting events. The mask will prevent
* any new __iio_push_event calls running.
*/
kfifo_reset_out(&ev_int->det_events);
spin_unlock_irq(&ev_int->wait.lock);
clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
iio_device_put(indio_dev);
......@@ -174,22 +174,20 @@ int iio_event_getfd(struct iio_dev *indio_dev)
if (ev_int == NULL)
return -ENODEV;
spin_lock_irq(&ev_int->wait.lock);
if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
spin_unlock_irq(&ev_int->wait.lock);
if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags))
return -EBUSY;
}
spin_unlock_irq(&ev_int->wait.lock);
iio_device_get(indio_dev);
fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
indio_dev, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
spin_unlock_irq(&ev_int->wait.lock);
clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
iio_device_put(indio_dev);
} else {
kfifo_reset_out(&ev_int->det_events);
}
return fd;
}
......@@ -366,32 +364,31 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
ret = iio_device_add_event(indio_dev, chan, i, type, dir,
IIO_SEPARATE, &chan->event_spec[i].mask_separate);
if (ret < 0)
goto error_ret;
return ret;
attrcount += ret;
ret = iio_device_add_event(indio_dev, chan, i, type, dir,
IIO_SHARED_BY_TYPE,
&chan->event_spec[i].mask_shared_by_type);
if (ret < 0)
goto error_ret;
return ret;
attrcount += ret;
ret = iio_device_add_event(indio_dev, chan, i, type, dir,
IIO_SHARED_BY_DIR,
&chan->event_spec[i].mask_shared_by_dir);
if (ret < 0)
goto error_ret;
return ret;
attrcount += ret;
ret = iio_device_add_event(indio_dev, chan, i, type, dir,
IIO_SHARED_BY_ALL,
&chan->event_spec[i].mask_shared_by_all);
if (ret < 0)
goto error_ret;
return ret;
attrcount += ret;
}
ret = attrcount;
error_ret:
return ret;
}
......@@ -425,6 +422,7 @@ static void iio_setup_ev_int(struct iio_event_interface *ev_int)
{
INIT_KFIFO(ev_int->det_events);
init_waitqueue_head(&ev_int->wait);
mutex_init(&ev_int->read_lock);
}
static const char *iio_event_group_name = "events";
......@@ -440,10 +438,8 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
indio_dev->event_interface =
kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL);
if (indio_dev->event_interface == NULL) {
ret = -ENOMEM;
goto error_ret;
}
if (indio_dev->event_interface == NULL)
return -ENOMEM;
INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
......@@ -489,8 +485,6 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
error_free_setup_event_lines:
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
kfree(indio_dev->event_interface);
error_ret:
return ret;
}
......
......@@ -62,10 +62,9 @@ int iio_trigger_register(struct iio_trigger *trig_info)
int ret;
trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL);
if (trig_info->id < 0) {
ret = trig_info->id;
goto error_ret;
}
if (trig_info->id < 0)
return trig_info->id;
/* Set the name used for the sysfs directory etc */
dev_set_name(&trig_info->dev, "trigger%ld",
(unsigned long) trig_info->id);
......@@ -83,7 +82,6 @@ int iio_trigger_register(struct iio_trigger *trig_info)
error_unregister_id:
ida_simple_remove(&iio_trigger_ida, trig_info->id);
error_ret:
return ret;
}
EXPORT_SYMBOL(iio_trigger_register);
......@@ -234,13 +232,12 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
if (trig->ops && trig->ops->set_trigger_state && no_other_users) {
ret = trig->ops->set_trigger_state(trig, false);
if (ret)
goto error_ret;
return ret;
}
iio_trigger_put_irq(trig, pf->irq);
free_irq(pf->irq, pf);
module_put(pf->indio_dev->info->driver_module);
error_ret:
return ret;
}
......
......@@ -73,6 +73,20 @@ config HID_SENSOR_ALS
Say yes here to build support for the HID SENSOR
Ambient light sensor.
config HID_SENSOR_PROX
depends on HID_SENSOR_HUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID PROX"
help
Say yes here to build support for the HID SENSOR
Proximity sensor.
To compile this driver as a module, choose M here: the
module will be called hid-sensor-prox.
config SENSORS_LM3533
tristate "LM3533 ambient light sensor"
depends on MFD_LM3533
......
......@@ -9,6 +9,7 @@ obj-$(CONFIG_CM32181) += cm32181.o
obj-$(CONFIG_CM36651) += cm36651.o
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
......
This diff is collapsed.
......@@ -183,9 +183,18 @@ static int mag3110_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_MAGN:
*val = 0;
*val2 = 1000;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_TEMP:
*val = 1000;
return IIO_VAL_INT;
default:
return -EINVAL;
}
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
*val = mag3110_samp_freq[i][0];
......@@ -270,7 +279,8 @@ static const struct iio_chan_spec mag3110_channels[] = {
MAG3110_CHANNEL(Z, 2),
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 3,
.scan_type = {
.sign = 's',
......
......@@ -5,6 +5,20 @@
menu "Pressure sensors"
config HID_SENSOR_PRESS
depends on HID_SENSOR_HUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID PRESS"
help
Say yes here to build support for the HID SENSOR
Pressure driver
To compile this driver as a module, choose M here: the module
will be called hid-sensor-press.
config MPL3115
tristate "Freescale MPL3115A2 pressure sensor driver"
depends on I2C
......@@ -26,7 +40,7 @@ config IIO_ST_PRESS
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
help
Say yes here to build support for STMicroelectronics pressure
sensors: LPS001WP, LPS331AP.
sensors: LPS001WP, LPS25H, LPS331AP.
This driver can also be built as a module. If so, these modules
will be created:
......
......@@ -3,6 +3,7 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o
obj-$(CONFIG_MPL3115) += mpl3115.o
obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
st_pressure-y := st_pressure_core.o
......
This diff is collapsed.
......@@ -15,6 +15,7 @@
#include <linux/iio/common/st_sensors.h>
#define LPS001WP_PRESS_DEV_NAME "lps001wp"
#define LPS25H_PRESS_DEV_NAME "lps25h"
#define LPS331AP_PRESS_DEV_NAME "lps331ap"
/**
......
......@@ -40,6 +40,9 @@
/* FULLSCALE */
#define ST_PRESS_FS_AVL_1260MB 1260
#define ST_PRESS_1_OUT_XL_ADDR 0x28
#define ST_TEMP_1_OUT_L_ADDR 0x2b
/* CUSTOM VALUES FOR LPS331AP SENSOR */
#define ST_PRESS_LPS331AP_WAI_EXP 0xbb
#define ST_PRESS_LPS331AP_ODR_ADDR 0x20
......@@ -62,8 +65,6 @@
#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20
#define ST_PRESS_LPS331AP_MULTIREAD_BIT true
#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500
#define ST_PRESS_LPS331AP_OUT_XL_ADDR 0x28
#define ST_TEMP_LPS331AP_OUT_L_ADDR 0x2b
/* CUSTOM VALUES FOR LPS001WP SENSOR */
#define ST_PRESS_LPS001WP_WAI_EXP 0xba
......@@ -80,11 +81,36 @@
#define ST_PRESS_LPS001WP_OUT_L_ADDR 0x28
#define ST_TEMP_LPS001WP_OUT_L_ADDR 0x2a
static const struct iio_chan_spec st_press_lps331ap_channels[] = {
/* CUSTOM VALUES FOR LPS25H SENSOR */
#define ST_PRESS_LPS25H_WAI_EXP 0xbd
#define ST_PRESS_LPS25H_ODR_ADDR 0x20
#define ST_PRESS_LPS25H_ODR_MASK 0x70
#define ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL 0x01
#define ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL 0x02
#define ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL 0x03
#define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL 0x04
#define ST_PRESS_LPS25H_PW_ADDR 0x20
#define ST_PRESS_LPS25H_PW_MASK 0x80
#define ST_PRESS_LPS25H_FS_ADDR 0x00
#define ST_PRESS_LPS25H_FS_MASK 0x00
#define ST_PRESS_LPS25H_FS_AVL_1260_VAL 0x00
#define ST_PRESS_LPS25H_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE
#define ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE
#define ST_PRESS_LPS25H_BDU_ADDR 0x20
#define ST_PRESS_LPS25H_BDU_MASK 0x04
#define ST_PRESS_LPS25H_DRDY_IRQ_ADDR 0x23
#define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK 0x01
#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10
#define ST_PRESS_LPS25H_MULTIREAD_BIT true
#define ST_PRESS_LPS25H_TEMP_OFFSET 42500
#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28
#define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b
static const struct iio_chan_spec st_press_1_channels[] = {
{
.type = IIO_PRESSURE,
.channel2 = IIO_NO_MOD,
.address = ST_PRESS_LPS331AP_OUT_XL_ADDR,
.address = ST_PRESS_1_OUT_XL_ADDR,
.scan_index = ST_SENSORS_SCAN_X,
.scan_type = {
.sign = 'u',
......@@ -99,7 +125,7 @@ static const struct iio_chan_spec st_press_lps331ap_channels[] = {
{
.type = IIO_TEMP,
.channel2 = IIO_NO_MOD,
.address = ST_TEMP_LPS331AP_OUT_L_ADDR,
.address = ST_TEMP_1_OUT_L_ADDR,
.scan_index = -1,
.scan_type = {
.sign = 'u',
......@@ -156,8 +182,8 @@ static const struct st_sensors st_press_sensors[] = {
.sensors_supported = {
[0] = LPS331AP_PRESS_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_press_lps331ap_channels,
.num_ch = ARRAY_SIZE(st_press_lps331ap_channels),
.ch = (struct iio_chan_spec *)st_press_1_channels,
.num_ch = ARRAY_SIZE(st_press_1_channels),
.odr = {
.addr = ST_PRESS_LPS331AP_ODR_ADDR,
.mask = ST_PRESS_LPS331AP_ODR_MASK,
......@@ -233,6 +259,53 @@ static const struct st_sensors st_press_sensors[] = {
.multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT,
.bootime = 2,
},
{
.wai = ST_PRESS_LPS25H_WAI_EXP,
.sensors_supported = {
[0] = LPS25H_PRESS_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_press_1_channels,
.num_ch = ARRAY_SIZE(st_press_1_channels),
.odr = {
.addr = ST_PRESS_LPS25H_ODR_ADDR,
.mask = ST_PRESS_LPS25H_ODR_MASK,
.odr_avl = {
{ 1, ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL, },
{ 7, ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL, },
{ 13, ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL, },
{ 25, ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL, },
},
},
.pw = {
.addr = ST_PRESS_LPS25H_PW_ADDR,
.mask = ST_PRESS_LPS25H_PW_MASK,
.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.fs = {
.addr = ST_PRESS_LPS25H_FS_ADDR,
.mask = ST_PRESS_LPS25H_FS_MASK,
.fs_avl = {
[0] = {
.num = ST_PRESS_FS_AVL_1260MB,
.value = ST_PRESS_LPS25H_FS_AVL_1260_VAL,
.gain = ST_PRESS_LPS25H_FS_AVL_1260_GAIN,
.gain2 = ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN,
},
},
},
.bdu = {
.addr = ST_PRESS_LPS25H_BDU_ADDR,
.mask = ST_PRESS_LPS25H_BDU_MASK,
},
.drdy_irq = {
.addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR,
.mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
},
.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
.bootime = 2,
},
};
static int st_press_read_raw(struct iio_dev *indio_dev,
......
......@@ -50,6 +50,7 @@ static int st_press_i2c_remove(struct i2c_client *client)
static const struct i2c_device_id st_press_id_table[] = {
{ LPS001WP_PRESS_DEV_NAME },
{ LPS25H_PRESS_DEV_NAME },
{ LPS331AP_PRESS_DEV_NAME },
{},
};
......
......@@ -49,6 +49,7 @@ static int st_press_spi_remove(struct spi_device *spi)
static const struct spi_device_id st_press_id_table[] = {
{ LPS001WP_PRESS_DEV_NAME },
{ LPS25H_PRESS_DEV_NAME },
{ LPS331AP_PRESS_DEV_NAME },
{},
};
......
......@@ -652,3 +652,25 @@ int read_sysfs_float(char *filename, char *basedir, float *val)
free(temp);
return ret;
}
read_sysfs_string(const char *filename, const char *basedir, char *str)
{
float ret = 0;
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL) {
printf("Memory allocation failed");
return -ENOMEM;
}
sprintf(temp, "%s/%s", basedir, filename);
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
ret = -errno;
goto error_free;
}
fscanf(sysfsfp, "%s\n", str);
fclose(sysfsfp);
error_free:
free(temp);
return ret;
}
/*
* Industrial I/O utilities - lsiio.c
*
* Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
*
* 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.
*/
#include <string.h>
#include <dirent.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include "iio_utils.h"
static enum verbosity {
VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */
VERBLEVEL_SENSORS, /* 1 lists sensors */
} verblevel = VERBLEVEL_DEFAULT;
const char *type_device = "iio:device";
const char *type_trigger = "trigger";
static inline int check_prefix(const char *str, const char *prefix)
{
return strlen(str) > strlen(prefix) &&
strncmp(str, prefix, strlen(prefix)) == 0;
}
static inline int check_postfix(const char *str, const char *postfix)
{
return strlen(str) > strlen(postfix) &&
strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
}
static int dump_channels(const char *dev_dir_name)
{
DIR *dp;
const struct dirent *ent;
dp = opendir(dev_dir_name);
if (dp == NULL)
return -errno;
while (ent = readdir(dp), ent != NULL)
if (check_prefix(ent->d_name, "in_") &&
check_postfix(ent->d_name, "_raw")) {
printf(" %-10s\n", ent->d_name);
}
return 0;
}
static int dump_one_device(const char *dev_dir_name)
{
char name[IIO_MAX_NAME_LENGTH];
int dev_idx;
sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
"%i", &dev_idx);
read_sysfs_string("name", dev_dir_name, name);
printf("Device %03d: %s\n", dev_idx, name);
if (verblevel >= VERBLEVEL_SENSORS) {
int ret = dump_channels(dev_dir_name);
if (ret)
return ret;
}
return 0;
}
static int dump_one_trigger(const char *dev_dir_name)
{
char name[IIO_MAX_NAME_LENGTH];
int dev_idx;
sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
"%i", &dev_idx);
read_sysfs_string("name", dev_dir_name, name);
printf("Trigger %03d: %s\n", dev_idx, name);
return 0;
}
static void dump_devices(void)
{
const struct dirent *ent;
int number, numstrlen;
FILE *nameFile;
DIR *dp;
char thisname[IIO_MAX_NAME_LENGTH];
char *filename;
dp = opendir(iio_dir);
if (dp == NULL) {
printf("No industrial I/O devices available\n");
return;
}
while (ent = readdir(dp), ent != NULL) {
if (check_prefix(ent->d_name, type_device)) {
char *dev_dir_name;
asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
dump_one_device(dev_dir_name);
free(dev_dir_name);
if (verblevel >= VERBLEVEL_SENSORS)
printf("\n");
}
}
rewinddir(dp);
while (ent = readdir(dp), ent != NULL) {
if (check_prefix(ent->d_name, type_trigger)) {
char *dev_dir_name;
asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
dump_one_trigger(dev_dir_name);
free(dev_dir_name);
}
}
closedir(dp);
}
int main(int argc, char **argv)
{
int c, err = 0;
while ((c = getopt(argc, argv, "d:D:v")) != EOF) {
switch (c) {
case 'v':
verblevel++;
break;
case '?':
default:
err++;
break;
}
}
if (err || argc > optind) {
fprintf(stderr, "Usage: lsiio [options]...\n"
"List industrial I/O devices\n"
" -v, --verbose\n"
" Increase verbosity (may be given multiple times)\n"
);
exit(1);
}
dump_devices();
return 0;
}
......@@ -95,7 +95,7 @@ struct ad799x_state {
struct i2c_client *client;
const struct ad799x_chip_info *chip_info;
struct regulator *reg;
u16 int_vref_mv;
struct regulator *vref;
unsigned id;
u16 config;
......@@ -103,14 +103,6 @@ struct ad799x_state {
unsigned int transfer_size;
};
/*
* TODO: struct ad799x_platform_data needs to go into include/linux/iio
*/
struct ad799x_platform_data {
u16 vref_mv;
};
#ifdef CONFIG_AD799X_RING_BUFFER
int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad799x_ring_cleanup(struct iio_dev *indio_dev);
......
/*
* iio/adc/ad799x.c
* Copyright (C) 2010-1011 Michael Hennerich, Analog Devices Inc.
* Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
*
* based on iio/adc/max1363
* Copyright (C) 2008-2010 Jonathan Cameron
......@@ -179,7 +179,10 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
RES_MASK(chan->scan_type.realbits);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = st->int_vref_mv;
ret = regulator_get_voltage(st->vref);
if (ret < 0)
return ret;
*val = ret / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
......@@ -533,7 +536,6 @@ static int ad799x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct ad799x_platform_data *pdata = client->dev.platform_data;
struct ad799x_state *st;
struct iio_dev *indio_dev;
......@@ -551,17 +553,21 @@ static int ad799x_probe(struct i2c_client *client,
/* TODO: Add pdata options for filtering and bit delay */
if (!pdata)
return -EINVAL;
st->int_vref_mv = pdata->vref_mv;
st->reg = devm_regulator_get(&client->dev, "vcc");
if (!IS_ERR(st->reg)) {
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret)
return ret;
st->vref = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(st->vref)) {
ret = PTR_ERR(st->vref);
goto error_disable_reg;
}
ret = regulator_enable(st->vref);
if (ret)
goto error_disable_reg;
st->client = client;
indio_dev->dev.parent = &client->dev;
......@@ -577,7 +583,8 @@ static int ad799x_probe(struct i2c_client *client,
goto error_disable_reg;
if (client->irq > 0) {
ret = request_threaded_irq(client->irq,
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL,
ad799x_event_handler,
IRQF_TRIGGER_FALLING |
......@@ -589,16 +596,15 @@ static int ad799x_probe(struct i2c_client *client,
}
ret = iio_device_register(indio_dev);
if (ret)
goto error_free_irq;
goto error_cleanup_ring;
return 0;
error_free_irq:
if (client->irq > 0)
free_irq(client->irq, indio_dev);
error_cleanup_ring:
ad799x_ring_cleanup(indio_dev);
error_disable_reg:
if (!IS_ERR(st->vref))
regulator_disable(st->vref);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
......@@ -611,10 +617,10 @@ static int ad799x_remove(struct i2c_client *client)
struct ad799x_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (client->irq > 0)
free_irq(client->irq, indio_dev);
ad799x_ring_cleanup(indio_dev);
if (!IS_ERR(st->vref))
regulator_disable(st->vref);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
kfree(st->rx_buf);
......
......@@ -1558,7 +1558,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
for (i = 0; i < of_cfg->irq_count; i++) {
lradc->irq[i] = platform_get_irq(pdev, i);
if (lradc->irq[i] < 0)
return -EINVAL;
return lradc->irq[i];
ret = devm_request_irq(dev, lradc->irq[i],
mxs_lradc_handle_irq, 0,
......
......@@ -33,6 +33,16 @@
#define HID_USAGE_SENSOR_DATA_LIGHT 0x2004d0
#define HID_USAGE_SENSOR_LIGHT_ILLUM 0x2004d1
/* PROX (200011) */
#define HID_USAGE_SENSOR_PROX 0x200011
#define HID_USAGE_SENSOR_DATA_PRESENCE 0x2004b0
#define HID_USAGE_SENSOR_HUMAN_PRESENCE 0x2004b1
/* Pressure (200031) */
#define HID_USAGE_SENSOR_PRESSURE 0x200031
#define HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE 0x200430
#define HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE 0x200431
/* Gyro 3D: (200076) */
#define HID_USAGE_SENSOR_GYRO_3D 0x200076
#define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456
......
......@@ -254,12 +254,16 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
(chan->info_mask_shared_by_all & BIT(type));
}
#define IIO_ST(si, rb, sb, sh) \
{ .sign = si, .realbits = rb, .storagebits = sb, .shift = sh }
#define IIO_CHAN_SOFT_TIMESTAMP(_si) \
{ .type = IIO_TIMESTAMP, .channel = -1, \
.scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) }
#define IIO_CHAN_SOFT_TIMESTAMP(_si) { \
.type = IIO_TIMESTAMP, \
.channel = -1, \
.scan_index = _si, \
.scan_type = { \
.sign = 's', \
.realbits = 64, \
.storagebits = 64, \
}, \
}
/**
* iio_get_time_ns() - utility function to get a time stamp for events etc
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment