Commit 2ef9d838 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.12d' of...

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

Jonathan writes:

Fourth round of IIO new drivers, functionality and cleanups for the 3.13 cycle.

New Drivers
* cm36651 combined RGB light and proximity sensor.

Core improvements

* Some more fixes and cleanups related to buffers.  These include the second
  half of a series which went is as fixes.  The basis for delaying until the
  next merge window is that some are too invasive for this late in a cycle
  and others only effect code paths current unused in the mainline tree.
  In this case we have:
   * protecting against concurrent userspace access
   * fixing a memory leak if a device goes away
   * avoiding always reallocating the buffer whether or not it has changed
     (a bug fix, but one with no functional changes other than a small speed
     improvement.)
   * Add reference counting for buffers to ensure they hang around if open
     from userspace or in kernel when the device is forcefully removed.
   * Return -ENODEV for buffer access operations when the device has gone
     away.
   * Add proper locking for iio_update_buffers (currently we only have one
     buffer per device in mainline, but an input bridge driver is under
     development which would make this bug 'real'.)
   * Wake up anyone waiting on a buffer if the device is unregistered.  A
     subsequent read will fail, notifying userspace that the device is no
     longer there rather than having it wait possibly for ever.

* Move the iio_sw_preenable functionality into the core.  This avoids drivers
  having to 'know' about how the buffers are implemented and is called by
  almost all drivers anyway.  Those that don't call it are not harmed by it
  being called.
* New registration approach for information (i.e. sysfs attributes) about
  events.  Much more generic and now similar to how the equivalent is
  handled for channel information.  The events infrastructure had been left
  behind by other changes so this brings it back in line.
* Using the new events registration approach, add a hysterisis event_info
  element and apply this to those drivers with this property.
* A little unitialized variable bug in the generic_buffer.c example.
* Factor out the code for freeing lists of IIO Device attributes to avoid
  some repitition.

Driver cleanups
* At91 driver gains touch screen support and some related fixes.
* Follow up series of patches removing the now redundant
  iio_sw_buffer_preenable calls.
* Lots of conversions to the new event registration methods.
* Another round of hmc5843 cleanups as that driver moves towards graduating
  from staging.
* Make some SoC drivers buildable if COMPILE_TEST is used.  Follow up fixes
  for a few bits and bobs that revealed.
* Add explicit includes of linux/of.h to those drivers making us of linux/of.h
parents 1c3e56f9 43e01bed
......@@ -537,6 +537,62 @@ Description:
value is in raw device units or in processed units (as _raw
and _input do on sysfs direct channel read attributes).
What: /sys/.../events/in_accel_x_thresh_rising_hysteresis
What: /sys/.../events/in_accel_x_thresh_falling_hysteresis
What: /sys/.../events/in_accel_x_thresh_either_hysteresis
What: /sys/.../events/in_accel_y_thresh_rising_hysteresis
What: /sys/.../events/in_accel_y_thresh_falling_hysteresis
What: /sys/.../events/in_accel_y_thresh_either_hysteresis
What: /sys/.../events/in_accel_z_thresh_rising_hysteresis
What: /sys/.../events/in_accel_z_thresh_falling_hysteresis
What: /sys/.../events/in_accel_z_thresh_either_hysteresis
What: /sys/.../events/in_anglvel_x_thresh_rising_hysteresis
What: /sys/.../events/in_anglvel_x_thresh_falling_hysteresis
What: /sys/.../events/in_anglvel_x_thresh_either_hysteresis
What: /sys/.../events/in_anglvel_y_thresh_rising_hysteresis
What: /sys/.../events/in_anglvel_y_thresh_falling_hysteresis
What: /sys/.../events/in_anglvel_y_thresh_either_hysteresis
What: /sys/.../events/in_anglvel_z_thresh_rising_hysteresis
What: /sys/.../events/in_anglvel_z_thresh_falling_hysteresis
What: /sys/.../events/in_anglvel_z_thresh_either_hysteresis
What: /sys/.../events/in_magn_x_thresh_rising_hysteresis
What: /sys/.../events/in_magn_x_thresh_falling_hysteresis
What: /sys/.../events/in_magn_x_thresh_either_hysteresis
What: /sys/.../events/in_magn_y_thresh_rising_hysteresis
What: /sys/.../events/in_magn_y_thresh_falling_hysteresis
What: /sys/.../events/in_magn_y_thresh_either_hysteresis
What: /sys/.../events/in_magn_z_thresh_rising_hysteresis
What: /sys/.../events/in_magn_z_thresh_falling_hysteresis
What: /sys/.../events/in_magn_z_thresh_either_hysteresis
What: /sys/.../events/in_voltageY_thresh_rising_hysteresis
What: /sys/.../events/in_voltageY_thresh_falling_hysteresis
What: /sys/.../events/in_voltageY_thresh_either_hysteresis
What: /sys/.../events/in_tempY_thresh_rising_hysteresis
What: /sys/.../events/in_tempY_thresh_falling_hysteresis
What: /sys/.../events/in_tempY_thresh_either_hysteresis
What: /sys/.../events/in_illuminance0_thresh_falling_hysteresis
what: /sys/.../events/in_illuminance0_thresh_rising_hysteresis
what: /sys/.../events/in_illuminance0_thresh_either_hysteresis
what: /sys/.../events/in_proximity0_thresh_falling_hysteresis
what: /sys/.../events/in_proximity0_thresh_rising_hysteresis
what: /sys/.../events/in_proximity0_thresh_either_hysteresis
KernelVersion: 3.13
Contact: linux-iio@vger.kernel.org
Description:
Specifies the hysteresis of threshold that the device is comparing
against for the events enabled by
<type>Y[_name]_thresh[_(rising|falling)]_hysteresis.
If separate attributes exist for the two directions, but
direction is not specified for this attribute, then a single
hysteresis value applies to both directions.
For falling events the hysteresis is added to the _value attribute for
this event to get the upper threshold for when the event goes back to
normal, for rising events the hysteresis is subtracted from the _value
attribute. E.g. if in_voltage0_raw_thresh_rising_value is set to 1200
and in_voltage0_raw_thresh_rising_hysteresis is set to 50. The event
will get activated once in_voltage0_raw goes above 1200 and will become
deactived again once the value falls below 1150.
What: /sys/.../events/in_accel_x_raw_roc_rising_value
What: /sys/.../events/in_accel_x_raw_roc_falling_value
What: /sys/.../events/in_accel_y_raw_roc_rising_value
......
......@@ -7,7 +7,6 @@ Required properties:
- interrupts: Should contain the IRQ line for the ADC
- atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
device
- atmel,adc-num-channels: Number of channels available in the ADC
- atmel,adc-startup-time: Startup Time of the ADC in microseconds as
defined in the datasheet
- atmel,adc-vref: Reference voltage in millivolts for the conversions
......@@ -24,6 +23,13 @@ Optional properties:
resolution will be used.
- atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
- atmel,adc-sample-hold-time: Sample and Hold Time in microseconds
- atmel,adc-ts-wires: Number of touch screen wires. Should be 4 or 5. If this
value is set, then adc driver will enable touch screen
support.
NOTE: when adc touch screen enabled, the adc hardware trigger will be
disabled. Since touch screen will occupied the trigger register.
- atmel,adc-ts-pressure-threshold: a pressure threshold for touchscreen. It
make touch detect more precision.
Optional trigger Nodes:
- Required properties:
......
* Capella CM36651 I2C Proximity and Color Light sensor
Required properties:
- compatible: must be "capella,cm36651"
- reg: the I2C address of the device
- interrupts: interrupt-specifier for the sole interrupt
generated by the device
- vled-supply: regulator for the IR LED. IR_LED is a part
of the cm36651 for proximity detection.
As covered in ../../regulator/regulator.txt
Example:
i2c_cm36651: i2c-gpio {
/* ... */
cm36651@18 {
compatible = "capella,cm36651";
reg = <0x18>;
interrupt-parent = <&gpx0>;
interrupts = <2 0>;
vled-supply = <&ps_als_reg>;
};
/* ... */
};
......@@ -15,6 +15,7 @@ atmel Atmel Corporation
avago Avago Technologies
bosch Bosch Sensortec GmbH
brcm Broadcom Corporation
capella Capella Microsystems, Inc
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cirrus Cirrus Logic, Inc.
......
......@@ -60,14 +60,48 @@
#define AT91_ADC_IER 0x24 /* Interrupt Enable Register */
#define AT91_ADC_IDR 0x28 /* Interrupt Disable Register */
#define AT91_ADC_IMR 0x2C /* Interrupt Mask Register */
#define AT91_ADC_IER_PEN (1 << 29)
#define AT91_ADC_IER_NOPEN (1 << 30)
#define AT91_ADC_IER_XRDY (1 << 20)
#define AT91_ADC_IER_YRDY (1 << 21)
#define AT91_ADC_IER_PRDY (1 << 22)
#define AT91_ADC_ISR_PENS (1 << 31)
#define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */
#define AT91_ADC_DATA (0x3ff)
#define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */
#define AT91_ADC_ACR 0x94 /* Analog Control Register */
#define AT91_ADC_ACR_PENDETSENS (0x3 << 0) /* pull-up resistor */
#define AT91_ADC_TSMR 0xB0
#define AT91_ADC_TSMR_TSMODE (3 << 0) /* Touch Screen Mode */
#define AT91_ADC_TSMR_TSMODE_NONE (0 << 0)
#define AT91_ADC_TSMR_TSMODE_4WIRE_NO_PRESS (1 << 0)
#define AT91_ADC_TSMR_TSMODE_4WIRE_PRESS (2 << 0)
#define AT91_ADC_TSMR_TSMODE_5WIRE (3 << 0)
#define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */
#define AT91_ADC_TSMR_TSAV_(x) ((x) << 4)
#define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */
#define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */
#define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28)
#define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */
#define AT91_ADC_TSMR_PENDET_DIS (0 << 24) /* Pen contact detection disable */
#define AT91_ADC_TSMR_PENDET_ENA (1 << 24) /* Pen contact detection enable */
#define AT91_ADC_TSXPOSR 0xB4
#define AT91_ADC_TSYPOSR 0xB8
#define AT91_ADC_TSPRESSR 0xBC
#define AT91_ADC_TRGR_9260 AT91_ADC_MR
#define AT91_ADC_TRGR_9G45 0x08
#define AT91_ADC_TRGR_9X5 0xC0
/* Trigger Register bit field */
#define AT91_ADC_TRGR_TRGPER (0xffff << 16)
#define AT91_ADC_TRGR_TRGPER_(x) ((x) << 16)
#define AT91_ADC_TRGR_TRGMOD (0x7 << 0)
#define AT91_ADC_TRGR_MOD_PERIOD_TRIG (5 << 0)
#endif
......@@ -32,16 +32,7 @@ int st_accel_trig_set_state(struct iio_trigger *trig, bool state)
static int st_accel_buffer_preenable(struct iio_dev *indio_dev)
{
int err;
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_accel_set_enable_error;
err = iio_sw_buffer_preenable(indio_dev);
st_accel_set_enable_error:
return err;
return st_sensors_set_enable(indio_dev, true);
}
static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
......
......@@ -61,17 +61,7 @@ static int ad7266_powerdown(struct ad7266_state *st)
static int ad7266_preenable(struct iio_dev *indio_dev)
{
struct ad7266_state *st = iio_priv(indio_dev);
int ret;
ret = ad7266_wakeup(st);
if (ret)
return ret;
ret = iio_sw_buffer_preenable(indio_dev);
if (ret)
ad7266_powerdown(st);
return ret;
return ad7266_wakeup(st);
}
static int ad7266_postdisable(struct iio_dev *indio_dev)
......
......@@ -78,11 +78,6 @@ enum ad7887_supported_device_ids {
static int ad7887_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7887_state *st = iio_priv(indio_dev);
int ret;
ret = iio_sw_buffer_preenable(indio_dev);
if (ret < 0)
return ret;
/* We know this is a single long so can 'cheat' */
switch (*indio_dev->active_scan_mask) {
......
......@@ -397,7 +397,6 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
}
static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &ad_sd_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
.postdisable = &ad_sd_buffer_postdisable,
......
This diff is collapsed.
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/sysfs.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......
......@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/log2.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......
......@@ -9,6 +9,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
......
......@@ -166,7 +166,7 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
for (i = 0; i < fifo1count; i++)
read = tiadc_readl(adc_dev, REG_FIFO1);
return iio_sw_buffer_preenable(indio_dev);
return 0;
}
static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
......
......@@ -12,17 +12,27 @@ struct iio_cb_buffer {
struct iio_channel *channels;
};
static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)
static struct iio_cb_buffer *buffer_to_cb_buffer(struct iio_buffer *buffer)
{
struct iio_cb_buffer *cb_buff = container_of(buffer,
struct iio_cb_buffer,
buffer);
return container_of(buffer, struct iio_cb_buffer, buffer);
}
static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)
{
struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
return cb_buff->cb(data, cb_buff->private);
}
static void iio_buffer_cb_release(struct iio_buffer *buffer)
{
struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
kfree(cb_buff->buffer.scan_mask);
kfree(cb_buff);
}
static const struct iio_buffer_access_funcs iio_cb_access = {
.store_to = &iio_buffer_cb_store_to,
.release = &iio_buffer_cb_release,
};
struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
......@@ -104,9 +114,8 @@ EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb);
void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)
{
kfree(cb_buff->buffer.scan_mask);
iio_channel_release_all(cb_buff->channels);
kfree(cb_buff);
iio_buffer_put(&cb_buff->buffer);
}
EXPORT_SYMBOL_GPL(iio_channel_release_all_cb);
......
......@@ -80,6 +80,29 @@ struct ad5421_state {
} data[2] ____cacheline_aligned;
};
static const struct iio_event_spec ad5421_current_event[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_event_spec ad5421_temp_event[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_chan_spec ad5421_channels[] = {
{
.type = IIO_CURRENT,
......@@ -92,13 +115,14 @@ static const struct iio_chan_spec ad5421_channels[] = {
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.scan_type = IIO_ST('u', 16, 16, 0),
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
.event_spec = ad5421_current_event,
.num_event_specs = ARRAY_SIZE(ad5421_current_event),
},
{
.type = IIO_TEMP,
.channel = -1,
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
.event_spec = ad5421_temp_event,
.num_event_specs = ARRAY_SIZE(ad5421_temp_event),
},
};
......@@ -353,15 +377,15 @@ static int ad5421_write_raw(struct iio_dev *indio_dev,
}
static int ad5421_write_event_config(struct iio_dev *indio_dev,
u64 event_code, int state)
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int mask;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_CURRENT:
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
mask = AD5421_FAULT_OVER_CURRENT;
else
mask = AD5421_FAULT_UNDER_CURRENT;
......@@ -384,15 +408,15 @@ static int ad5421_write_event_config(struct iio_dev *indio_dev,
}
static int ad5421_read_event_config(struct iio_dev *indio_dev,
u64 event_code)
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir)
{
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int mask;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_CURRENT:
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
mask = AD5421_FAULT_OVER_CURRENT;
else
mask = AD5421_FAULT_UNDER_CURRENT;
......@@ -407,12 +431,14 @@ static int ad5421_read_event_config(struct iio_dev *indio_dev,
return (bool)(st->fault_mask & mask);
}
static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code,
int *val)
static int ad5421_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 ret;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_CURRENT:
ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA);
if (ret < 0)
......@@ -426,15 +452,15 @@ static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code,
return -EINVAL;
}
return 0;
return IIO_VAL_INT;
}
static const struct iio_info ad5421_info = {
.read_raw = ad5421_read_raw,
.write_raw = ad5421_write_raw,
.read_event_config = ad5421_read_event_config,
.write_event_config = ad5421_write_event_config,
.read_event_value = ad5421_read_event_value,
.read_event_config_new = ad5421_read_event_config,
.write_event_config_new = ad5421_write_event_config,
.read_event_value_new = ad5421_read_event_value,
.driver_module = THIS_MODULE,
};
......
......@@ -32,16 +32,7 @@ int st_gyro_trig_set_state(struct iio_trigger *trig, bool state)
static int st_gyro_buffer_preenable(struct iio_dev *indio_dev)
{
int err;
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_gyro_set_enable_error;
err = iio_sw_buffer_preenable(indio_dev);
st_gyro_set_enable_error:
return err;
return st_sensors_set_enable(indio_dev, true);
}
static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
......
......@@ -33,6 +33,9 @@ int __iio_add_chan_devattr(const char *postfix,
enum iio_shared_by shared_by,
struct device *dev,
struct list_head *attr_list);
void iio_free_chan_devattr_list(struct list_head *attr_list);
ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2);
/* Event interface flags */
#define IIO_BUSY_BIT_POS 1
......@@ -50,6 +53,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer)
void iio_disable_all_buffers(struct iio_dev *indio_dev);
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
#else
......@@ -57,11 +61,13 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev);
#define iio_buffer_read_first_n_outer_addr NULL
static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
#endif
int iio_device_register_eventset(struct iio_dev *indio_dev);
void iio_device_unregister_eventset(struct iio_dev *indio_dev);
void iio_device_wakeup_eventset(struct iio_dev *indio_dev);
int iio_event_getfd(struct iio_dev *indio_dev);
#endif
......@@ -20,6 +20,7 @@
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/iio/iio.h>
#include "iio_core.h"
......@@ -48,6 +49,9 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
struct iio_dev *indio_dev = filp->private_data;
struct iio_buffer *rb = indio_dev->buffer;
if (!indio_dev->info)
return -ENODEV;
if (!rb || !rb->access->read_first_n)
return -EINVAL;
return rb->access->read_first_n(rb, n, buf);
......@@ -62,6 +66,9 @@ unsigned int iio_buffer_poll(struct file *filp,
struct iio_dev *indio_dev = filp->private_data;
struct iio_buffer *rb = indio_dev->buffer;
if (!indio_dev->info)
return -ENODEV;
poll_wait(filp, &rb->pollq, wait);
if (rb->stufftoread)
return POLLIN | POLLRDNORM;
......@@ -69,11 +76,27 @@ unsigned int iio_buffer_poll(struct file *filp,
return 0;
}
/**
* iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
* @indio_dev: The IIO device
*
* Wakes up the event waitqueue used for poll(). Should usually
* be called when the device is unregistered.
*/
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
{
if (!indio_dev->buffer)
return;
wake_up(&indio_dev->buffer->pollq);
}
void iio_buffer_init(struct iio_buffer *buffer)
{
INIT_LIST_HEAD(&buffer->demux_list);
INIT_LIST_HEAD(&buffer->buffer_list);
init_waitqueue_head(&buffer->pollq);
kref_init(&buffer->ref);
}
EXPORT_SYMBOL(iio_buffer_init);
......@@ -251,23 +274,6 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
return ret;
}
static void iio_buffer_remove_and_free_scan_dev_attr(struct iio_dev *indio_dev,
struct iio_dev_attr *p)
{
kfree(p->dev_attr.attr.name);
kfree(p);
}
static void __iio_buffer_attr_cleanup(struct iio_dev *indio_dev)
{
struct iio_dev_attr *p, *n;
struct iio_buffer *buffer = indio_dev->buffer;
list_for_each_entry_safe(p, n,
&buffer->scan_el_dev_attr_list, l)
iio_buffer_remove_and_free_scan_dev_attr(indio_dev, p);
}
static const char * const iio_scan_elements_group_name = "scan_elements";
int iio_buffer_register(struct iio_dev *indio_dev,
......@@ -344,7 +350,7 @@ int iio_buffer_register(struct iio_dev *indio_dev,
error_free_scan_mask:
kfree(buffer->scan_mask);
error_cleanup_dynamic:
__iio_buffer_attr_cleanup(indio_dev);
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
return ret;
}
......@@ -354,7 +360,7 @@ void iio_buffer_unregister(struct iio_dev *indio_dev)
{
kfree(indio_dev->buffer->scan_mask);
kfree(indio_dev->buffer->scan_el_group.attrs);
__iio_buffer_attr_cleanup(indio_dev);
iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list);
}
EXPORT_SYMBOL(iio_buffer_unregister);
......@@ -454,6 +460,19 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
return bytes;
}
static void iio_buffer_activate(struct iio_dev *indio_dev,
struct iio_buffer *buffer)
{
iio_buffer_get(buffer);
list_add(&buffer->buffer_list, &indio_dev->buffer_list);
}
static void iio_buffer_deactivate(struct iio_buffer *buffer)
{
list_del_init(&buffer->buffer_list);
iio_buffer_put(buffer);
}
void iio_disable_all_buffers(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer, *_buffer;
......@@ -466,14 +485,28 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev)
list_for_each_entry_safe(buffer, _buffer,
&indio_dev->buffer_list, buffer_list)
list_del_init(&buffer->buffer_list);
iio_buffer_deactivate(buffer);
indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable)
indio_dev->setup_ops->postdisable(indio_dev);
}
int iio_update_buffers(struct iio_dev *indio_dev,
static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
struct iio_buffer *buffer)
{
unsigned int bytes;
if (!buffer->access->set_bytes_per_datum)
return;
bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
buffer->scan_timestamp);
buffer->access->set_bytes_per_datum(buffer, bytes);
}
static int __iio_update_buffers(struct iio_dev *indio_dev,
struct iio_buffer *insert_buffer,
struct iio_buffer *remove_buffer)
{
......@@ -503,9 +536,9 @@ int iio_update_buffers(struct iio_dev *indio_dev,
indio_dev->active_scan_mask = NULL;
if (remove_buffer)
list_del_init(&remove_buffer->buffer_list);
iio_buffer_deactivate(remove_buffer);
if (insert_buffer)
list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list);
iio_buffer_activate(indio_dev, insert_buffer);
/* If no buffers in list, we are done */
if (list_empty(&indio_dev->buffer_list)) {
......@@ -540,7 +573,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
* Roll back.
* Note can only occur when adding a buffer.
*/
list_del_init(&insert_buffer->buffer_list);
iio_buffer_deactivate(insert_buffer);
if (old_mask) {
indio_dev->active_scan_mask = old_mask;
success = -EINVAL;
......@@ -570,7 +603,8 @@ int iio_update_buffers(struct iio_dev *indio_dev,
iio_compute_scan_bytes(indio_dev,
indio_dev->active_scan_mask,
indio_dev->scan_timestamp);
list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
iio_buffer_update_bytes_per_datum(indio_dev, buffer);
if (buffer->access->request_update) {
ret = buffer->access->request_update(buffer);
if (ret) {
......@@ -579,6 +613,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
goto error_run_postdisable;
}
}
}
if (indio_dev->info->update_scan_mode) {
ret = indio_dev->info
->update_scan_mode(indio_dev,
......@@ -631,13 +666,50 @@ int iio_update_buffers(struct iio_dev *indio_dev,
error_remove_inserted:
if (insert_buffer)
list_del_init(&insert_buffer->buffer_list);
iio_buffer_deactivate(insert_buffer);
indio_dev->active_scan_mask = old_mask;
kfree(compound_mask);
error_ret:
return ret;
}
int iio_update_buffers(struct iio_dev *indio_dev,
struct iio_buffer *insert_buffer,
struct iio_buffer *remove_buffer)
{
int ret;
if (insert_buffer == remove_buffer)
return 0;
mutex_lock(&indio_dev->info_exist_lock);
mutex_lock(&indio_dev->mlock);
if (insert_buffer && iio_buffer_is_active(insert_buffer))
insert_buffer = NULL;
if (remove_buffer && !iio_buffer_is_active(remove_buffer))
remove_buffer = NULL;
if (!insert_buffer && !remove_buffer) {
ret = 0;
goto out_unlock;
}
if (indio_dev->info == NULL) {
ret = -ENODEV;
goto out_unlock;
}
ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer);
out_unlock:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&indio_dev->info_exist_lock);
return ret;
}
EXPORT_SYMBOL_GPL(iio_update_buffers);
ssize_t iio_buffer_store_enable(struct device *dev,
......@@ -663,10 +735,10 @@ ssize_t iio_buffer_store_enable(struct device *dev,
goto done;
if (requested_state)
ret = iio_update_buffers(indio_dev,
ret = __iio_update_buffers(indio_dev,
indio_dev->buffer, NULL);
else
ret = iio_update_buffers(indio_dev,
ret = __iio_update_buffers(indio_dev,
NULL, indio_dev->buffer);
if (ret < 0)
......@@ -677,24 +749,6 @@ ssize_t iio_buffer_store_enable(struct device *dev,
}
EXPORT_SYMBOL(iio_buffer_store_enable);
int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer;
unsigned bytes;
dev_dbg(&indio_dev->dev, "%s\n", __func__);
list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
if (buffer->access->set_bytes_per_datum) {
bytes = iio_compute_scan_bytes(indio_dev,
buffer->scan_mask,
buffer->scan_timestamp);
buffer->access->set_bytes_per_datum(buffer, bytes);
}
return 0;
}
EXPORT_SYMBOL(iio_sw_buffer_preenable);
/**
* iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
* @indio_dev: the iio device
......@@ -952,3 +1006,45 @@ int iio_update_demux(struct iio_dev *indio_dev)
return ret;
}
EXPORT_SYMBOL_GPL(iio_update_demux);
/**
* iio_buffer_release() - Free a buffer's resources
* @ref: Pointer to the kref embedded in the iio_buffer struct
*
* This function is called when the last reference to the buffer has been
* dropped. It will typically free all resources allocated by the buffer. Do not
* call this function manually, always use iio_buffer_put() when done using a
* buffer.
*/
static void iio_buffer_release(struct kref *ref)
{
struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref);
buffer->access->release(buffer);
}
/**
* iio_buffer_get() - Grab a reference to the buffer
* @buffer: The buffer to grab a reference for, may be NULL
*
* Returns the pointer to the buffer that was passed into the function.
*/
struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)
{
if (buffer)
kref_get(&buffer->ref);
return buffer;
}
EXPORT_SYMBOL_GPL(iio_buffer_get);
/**
* iio_buffer_put() - Release the reference to the buffer
* @buffer: The buffer to release the reference for, may be NULL
*/
void iio_buffer_put(struct iio_buffer *buffer)
{
if (buffer)
kref_put(&buffer->ref, iio_buffer_release);
}
EXPORT_SYMBOL_GPL(iio_buffer_put);
......@@ -28,6 +28,7 @@
#include "iio_core_trigger.h"
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/iio/buffer.h>
/* IDA to assign each registered device a unique id */
static DEFINE_IDA(iio_ida);
......@@ -362,22 +363,20 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
}
EXPORT_SYMBOL_GPL(iio_enum_write);
static ssize_t iio_read_channel_info(struct device *dev,
struct device_attribute *attr,
char *buf)
/**
* iio_format_value() - Formats a IIO value into its string representation
* @buf: The buffer to which the formated value gets written
* @type: One of the IIO_VAL_... constants. This decides how the val and val2
* parameters are formatted.
* @val: First part of the value, exact meaning depends on the type parameter.
* @val2: Second part of the value, exact meaning depends on the type parameter.
*/
ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned long long tmp;
int val, val2;
bool scale_db = false;
int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
&val, &val2, this_attr->address);
if (ret < 0)
return ret;
switch (ret) {
switch (type) {
case IIO_VAL_INT:
return sprintf(buf, "%d\n", val);
case IIO_VAL_INT_PLUS_MICRO_DB:
......@@ -409,6 +408,22 @@ static ssize_t iio_read_channel_info(struct device *dev,
}
}
static ssize_t iio_read_channel_info(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, val2;
int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
&val, &val2, this_attr->address);
if (ret < 0)
return ret;
return iio_format_value(buf, ret, val, val2);
}
/**
* iio_str_to_fixpoint() - Parse a fixed-point number from a string
* @str: The string to parse
......@@ -793,11 +808,22 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
return attrcount;
}
static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
struct iio_dev_attr *p)
/**
* iio_free_chan_devattr_list() - Free a list of IIO device attributes
* @attr_list: List of IIO device attributes
*
* This function frees the memory allocated for each of the IIO device
* attributes in the list. Note: if you want to reuse the list after calling
* this function you have to reinitialize it using INIT_LIST_HEAD().
*/
void iio_free_chan_devattr_list(struct list_head *attr_list)
{
kfree(p->dev_attr.attr.name);
kfree(p);
struct iio_dev_attr *p, *n;
list_for_each_entry_safe(p, n, attr_list, l) {
kfree(p->dev_attr.attr.name);
kfree(p);
}
}
static ssize_t iio_show_dev_name(struct device *dev,
......@@ -813,7 +839,7 @@ static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
static int iio_device_register_sysfs(struct iio_dev *indio_dev)
{
int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
struct iio_dev_attr *p, *n;
struct iio_dev_attr *p;
struct attribute **attr;
/* First count elements in any existing group */
......@@ -866,11 +892,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
return 0;
error_clear_attrs:
list_for_each_entry_safe(p, n,
&indio_dev->channel_attr_list, l) {
list_del(&p->l);
iio_device_remove_and_free_read_attr(indio_dev, p);
}
iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
return ret;
}
......@@ -878,12 +900,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
{
struct iio_dev_attr *p, *n;
list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) {
list_del(&p->l);
iio_device_remove_and_free_read_attr(indio_dev, p);
}
iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
kfree(indio_dev->chan_attr_group.attrs);
}
......@@ -895,6 +912,8 @@ static void iio_dev_release(struct device *device)
iio_device_unregister_eventset(indio_dev);
iio_device_unregister_sysfs(indio_dev);
iio_buffer_put(indio_dev->buffer);
ida_simple_remove(&iio_ida, indio_dev->id);
kfree(indio_dev);
}
......@@ -1037,6 +1056,9 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
int __user *ip = (int __user *)arg;
int fd;
if (!indio_dev->info)
return -ENODEV;
if (cmd == IIO_GET_EVENT_FD_IOCTL) {
fd = iio_event_getfd(indio_dev);
if (copy_to_user(ip, &fd, sizeof(fd)))
......@@ -1133,6 +1155,10 @@ void iio_device_unregister(struct iio_dev *indio_dev)
iio_disable_all_buffers(indio_dev);
indio_dev->info = NULL;
iio_device_wakeup_eventset(indio_dev);
iio_buffer_wakeup_poll(indio_dev);
mutex_unlock(&indio_dev->info_exist_lock);
}
EXPORT_SYMBOL(iio_device_unregister);
......
......@@ -76,6 +76,9 @@ static unsigned int iio_event_poll(struct file *filep,
struct iio_event_interface *ev_int = indio_dev->event_interface;
unsigned int events = 0;
if (!indio_dev->info)
return -ENODEV;
poll_wait(filep, &ev_int->wait, wait);
spin_lock_irq(&ev_int->wait.lock);
......@@ -96,6 +99,9 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
unsigned int copied;
int ret;
if (!indio_dev->info)
return -ENODEV;
if (count < sizeof(struct iio_event_data))
return -EINVAL;
......@@ -107,9 +113,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
}
/* Blocking on device; waiting for something to be there */
ret = wait_event_interruptible_locked_irq(ev_int->wait,
!kfifo_is_empty(&ev_int->det_events));
!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 */
}
......@@ -190,6 +201,27 @@ static const char * const iio_ev_dir_text[] = {
[IIO_EV_DIR_FALLING] = "falling"
};
static const char * const iio_ev_info_text[] = {
[IIO_EV_INFO_ENABLE] = "en",
[IIO_EV_INFO_VALUE] = "value",
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
};
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
{
return attr->c->event_spec[attr->address & 0xffff].dir;
}
static enum iio_event_type iio_ev_attr_type(struct iio_dev_attr *attr)
{
return attr->c->event_spec[attr->address & 0xffff].type;
}
static enum iio_event_info iio_ev_attr_info(struct iio_dev_attr *attr)
{
return (attr->address >> 16) & 0xffff;
}
static ssize_t iio_ev_state_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
......@@ -204,9 +236,14 @@ static ssize_t iio_ev_state_store(struct device *dev,
if (ret < 0)
return ret;
ret = indio_dev->info->write_event_config(indio_dev,
this_attr->address,
val);
if (indio_dev->info->write_event_config)
ret = indio_dev->info->write_event_config(indio_dev,
this_attr->address, val);
else
ret = indio_dev->info->write_event_config_new(indio_dev,
this_attr->c, iio_ev_attr_type(this_attr),
iio_ev_attr_dir(this_attr), val);
return (ret < 0) ? ret : len;
}
......@@ -216,9 +253,15 @@ static ssize_t iio_ev_state_show(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val = indio_dev->info->read_event_config(indio_dev,
this_attr->address);
int val;
if (indio_dev->info->read_event_config)
val = indio_dev->info->read_event_config(indio_dev,
this_attr->address);
else
val = indio_dev->info->read_event_config_new(indio_dev,
this_attr->c, iio_ev_attr_type(this_attr),
iio_ev_attr_dir(this_attr));
if (val < 0)
return val;
else
......@@ -231,14 +274,24 @@ static ssize_t iio_ev_value_show(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, ret;
ret = indio_dev->info->read_event_value(indio_dev,
this_attr->address, &val);
if (ret < 0)
return ret;
int val, val2;
int ret;
return sprintf(buf, "%d\n", val);
if (indio_dev->info->read_event_value) {
ret = indio_dev->info->read_event_value(indio_dev,
this_attr->address, &val);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", val);
} else {
ret = indio_dev->info->read_event_value_new(indio_dev,
this_attr->c, iio_ev_attr_type(this_attr),
iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),
&val, &val2);
if (ret < 0)
return ret;
return iio_format_value(buf, ret, val, val2);
}
}
static ssize_t iio_ev_value_store(struct device *dev,
......@@ -248,25 +301,120 @@ static ssize_t iio_ev_value_store(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val;
int val, val2;
int ret;
if (!indio_dev->info->write_event_value)
if (!indio_dev->info->write_event_value &&
!indio_dev->info->write_event_value_new)
return -EINVAL;
ret = kstrtoint(buf, 10, &val);
if (ret)
return ret;
ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
val);
if (indio_dev->info->write_event_value) {
ret = kstrtoint(buf, 10, &val);
if (ret)
return ret;
ret = indio_dev->info->write_event_value(indio_dev,
this_attr->address, val);
} else {
ret = iio_str_to_fixpoint(buf, 100000, &val, &val2);
if (ret)
return ret;
ret = indio_dev->info->write_event_value_new(indio_dev,
this_attr->c, iio_ev_attr_type(this_attr),
iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),
val, val2);
}
if (ret < 0)
return ret;
return len;
}
static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
static int iio_device_add_event(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int spec_index,
enum iio_event_type type, enum iio_event_direction dir,
enum iio_shared_by shared_by, const unsigned long *mask)
{
ssize_t (*show)(struct device *, struct device_attribute *, char *);
ssize_t (*store)(struct device *, struct device_attribute *,
const char *, size_t);
unsigned int attrcount = 0;
unsigned int i;
char *postfix;
int ret;
for_each_set_bit(i, mask, sizeof(*mask)) {
postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_ev_type_text[type], iio_ev_dir_text[dir],
iio_ev_info_text[i]);
if (postfix == NULL)
return -ENOMEM;
if (i == IIO_EV_INFO_ENABLE) {
show = iio_ev_state_show;
store = iio_ev_state_store;
} else {
show = iio_ev_value_show;
store = iio_ev_value_store;
}
ret = __iio_add_chan_devattr(postfix, chan, show, store,
(i << 16) | spec_index, shared_by, &indio_dev->dev,
&indio_dev->event_interface->dev_attr_list);
kfree(postfix);
if (ret)
return ret;
attrcount++;
}
return attrcount;
}
static int iio_device_add_event_sysfs_new(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
int ret = 0, i, attrcount = 0;
enum iio_event_direction dir;
enum iio_event_type type;
for (i = 0; i < chan->num_event_specs; i++) {
type = chan->event_spec[i].type;
dir = chan->event_spec[i].dir;
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;
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;
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;
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;
attrcount += ret;
}
ret = attrcount;
error_ret:
return ret;
}
static int iio_device_add_event_sysfs_old(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
int ret = 0, i, attrcount = 0;
......@@ -339,15 +487,14 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
return ret;
}
static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev)
static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
struct iio_dev_attr *p, *n;
list_for_each_entry_safe(p, n,
&indio_dev->event_interface->
dev_attr_list, l) {
kfree(p->dev_attr.attr.name);
kfree(p);
}
if (chan->event_mask)
return iio_device_add_event_sysfs_old(indio_dev, chan);
else
return iio_device_add_event_sysfs_new(indio_dev, chan);
}
static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
......@@ -369,9 +516,12 @@ static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
{
int j;
for (j = 0; j < indio_dev->num_channels; j++)
for (j = 0; j < indio_dev->num_channels; j++) {
if (indio_dev->channels[j].event_mask != 0)
return true;
if (indio_dev->channels[j].num_event_specs != 0)
return true;
}
return false;
}
......@@ -441,18 +591,32 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
return 0;
error_free_setup_event_lines:
__iio_remove_event_config_attrs(indio_dev);
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
kfree(indio_dev->event_interface);
error_ret:
return ret;
}
/**
* iio_device_wakeup_eventset - Wakes up the event waitqueue
* @indio_dev: The IIO device
*
* Wakes up the event waitqueue used for poll() and blocking read().
* Should usually be called when the device is unregistered.
*/
void iio_device_wakeup_eventset(struct iio_dev *indio_dev)
{
if (indio_dev->event_interface == NULL)
return;
wake_up(&indio_dev->event_interface->wait);
}
void iio_device_unregister_eventset(struct iio_dev *indio_dev)
{
if (indio_dev->event_interface == NULL)
return;
__iio_remove_event_config_attrs(indio_dev);
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
kfree(indio_dev->event_interface->group.attrs);
kfree(indio_dev->event_interface);
}
......@@ -17,7 +17,6 @@
#include <linux/iio/trigger_consumer.h>
static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
......@@ -47,14 +46,17 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
irqreturn_t (*pollfunc_th)(int irq, void *p),
const struct iio_buffer_setup_ops *setup_ops)
{
struct iio_buffer *buffer;
int ret;
indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
buffer = iio_kfifo_allocate(indio_dev);
if (!buffer) {
ret = -ENOMEM;
goto error_ret;
}
iio_device_attach_buffer(indio_dev, buffer);
indio_dev->pollfunc = iio_alloc_pollfunc(pollfunc_bh,
pollfunc_th,
IRQF_ONESHOT,
......
......@@ -12,6 +12,7 @@
struct iio_kfifo {
struct iio_buffer buffer;
struct kfifo kf;
struct mutex user_lock;
int update_needed;
};
......@@ -32,13 +33,18 @@ static int iio_request_update_kfifo(struct iio_buffer *r)
int ret = 0;
struct iio_kfifo *buf = iio_to_kfifo(r);
if (!buf->update_needed)
goto error_ret;
kfifo_free(&buf->kf);
ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
mutex_lock(&buf->user_lock);
if (buf->update_needed) {
kfifo_free(&buf->kf);
ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
buf->buffer.length);
buf->update_needed = false;
} else {
kfifo_reset_out(&buf->kf);
}
r->stufftoread = false;
error_ret:
mutex_unlock(&buf->user_lock);
return ret;
}
......@@ -114,12 +120,13 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r,
int ret, copied;
struct iio_kfifo *kf = iio_to_kfifo(r);
if (n < r->bytes_per_datum || r->bytes_per_datum == 0)
return -EINVAL;
if (mutex_lock_interruptible(&kf->user_lock))
return -ERESTARTSYS;
ret = kfifo_to_user(&kf->kf, buf, n, &copied);
if (ret < 0)
return ret;
if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf))
ret = -EINVAL;
else
ret = kfifo_to_user(&kf->kf, buf, n, &copied);
if (kfifo_is_empty(&kf->kf))
r->stufftoread = false;
......@@ -127,9 +134,22 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r,
if (!kfifo_is_empty(&kf->kf))
r->stufftoread = true;
mutex_unlock(&kf->user_lock);
if (ret < 0)
return ret;
return copied;
}
static void iio_kfifo_buffer_release(struct iio_buffer *buffer)
{
struct iio_kfifo *kf = iio_to_kfifo(buffer);
mutex_destroy(&kf->user_lock);
kfifo_free(&kf->kf);
kfree(kf);
}
static const struct iio_buffer_access_funcs kfifo_access_funcs = {
.store_to = &iio_store_to_kfifo,
.read_first_n = &iio_read_first_n_kfifo,
......@@ -138,6 +158,7 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = {
.set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
.get_length = &iio_get_length_kfifo,
.set_length = &iio_set_length_kfifo,
.release = &iio_kfifo_buffer_release,
};
struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
......@@ -152,13 +173,14 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
kf->buffer.attrs = &iio_kfifo_attribute_group;
kf->buffer.access = &kfifo_access_funcs;
kf->buffer.length = 2;
mutex_init(&kf->user_lock);
return &kf->buffer;
}
EXPORT_SYMBOL(iio_kfifo_allocate);
void iio_kfifo_free(struct iio_buffer *r)
{
kfree(iio_to_kfifo(r));
iio_buffer_put(r);
}
EXPORT_SYMBOL(iio_kfifo_free);
......
......@@ -27,6 +27,17 @@ config APDS9300
To compile this driver as a module, choose M here: the
module will be called apds9300.
config CM36651
depends on I2C
tristate "CM36651 driver"
help
Say Y here if you use cm36651.
This option enables proximity & RGB sensor using
Capella cm36651 device driver.
To compile this driver as a module, choose M here:
the module will be called cm36651.
config GP2AP020A00F
tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
depends on I2C
......
......@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADJD_S311) += adjd_s311.o
obj-$(CONFIG_APDS9300) += apds9300.o
obj-$(CONFIG_CM36651) += cm36651.o
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
......
......@@ -273,12 +273,14 @@ static int apds9300_read_raw(struct iio_dev *indio_dev,
return ret;
}
static int apds9300_read_thresh(struct iio_dev *indio_dev, u64 event_code,
int *val)
static int apds9300_read_thresh(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 apds9300_data *data = iio_priv(indio_dev);
switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
switch (dir) {
case IIO_EV_DIR_RISING:
*val = data->thresh_hi;
break;
......@@ -289,17 +291,19 @@ static int apds9300_read_thresh(struct iio_dev *indio_dev, u64 event_code,
return -EINVAL;
}
return 0;
return IIO_VAL_INT;
}
static int apds9300_write_thresh(struct iio_dev *indio_dev, u64 event_code,
int val)
static int apds9300_write_thresh(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 apds9300_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->mutex);
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
ret = apds9300_set_thresh_hi(data, val);
else
ret = apds9300_set_thresh_low(data, val);
......@@ -309,7 +313,9 @@ static int apds9300_write_thresh(struct iio_dev *indio_dev, u64 event_code,
}
static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
u64 event_code)
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{
struct apds9300_data *data = iio_priv(indio_dev);
......@@ -317,7 +323,8 @@ static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
}
static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
u64 event_code, int state)
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
struct apds9300_data *data = iio_priv(indio_dev);
int ret;
......@@ -337,10 +344,24 @@ static const struct iio_info apds9300_info_no_irq = {
static const struct iio_info apds9300_info = {
.driver_module = THIS_MODULE,
.read_raw = apds9300_read_raw,
.read_event_value = apds9300_read_thresh,
.write_event_value = apds9300_write_thresh,
.read_event_config = apds9300_read_interrupt_config,
.write_event_config = apds9300_write_interrupt_config,
.read_event_value_new = apds9300_read_thresh,
.write_event_value_new = apds9300_write_thresh,
.read_event_config_new = apds9300_read_interrupt_config,
.write_event_config_new = apds9300_write_interrupt_config,
};
static const struct iio_event_spec apds9300_event_spec[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_chan_spec apds9300_channels[] = {
......@@ -355,10 +376,8 @@ static const struct iio_chan_spec apds9300_channels[] = {
.channel2 = IIO_MOD_LIGHT_BOTH,
.indexed = true,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING)),
.event_spec = apds9300_event_spec,
.num_event_specs = ARRAY_SIZE(apds9300_event_spec),
}, {
.type = IIO_INTENSITY,
.channel = 1,
......
This diff is collapsed.
......@@ -42,6 +42,7 @@
#include <linux/irq_work.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
......@@ -996,11 +997,10 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
return IRQ_HANDLED;
}
static u8 gp2ap020a00f_get_reg_by_event_code(u64 event_code)
static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
enum iio_event_direction event_dir)
{
int event_dir = IIO_EVENT_CODE_EXTRACT_DIR(event_code);
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_PROXIMITY:
if (event_dir == IIO_EV_DIR_RISING)
return GP2AP020A00F_PH_L_REG;
......@@ -1011,13 +1011,19 @@ static u8 gp2ap020a00f_get_reg_by_event_code(u64 event_code)
return GP2AP020A00F_TH_L_REG;
else
return GP2AP020A00F_TL_L_REG;
default:
break;
}
return -EINVAL;
}
static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
u64 event_code, int val)
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 gp2ap020a00f_data *data = iio_priv(indio_dev);
bool event_en = false;
......@@ -1027,7 +1033,7 @@ static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
mutex_lock(&data->lock);
thresh_reg_l = gp2ap020a00f_get_reg_by_event_code(event_code);
thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
if (thresh_val_id > GP2AP020A00F_THRESH_PH) {
......@@ -1072,15 +1078,19 @@ static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
}
static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
u64 event_code, int *val)
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 gp2ap020a00f_data *data = iio_priv(indio_dev);
u8 thresh_reg_l;
int err = 0;
int err = IIO_VAL_INT;
mutex_lock(&data->lock);
thresh_reg_l = gp2ap020a00f_get_reg_by_event_code(event_code);
thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
if (thresh_reg_l > GP2AP020A00F_PH_L_REG) {
err = -EINVAL;
......@@ -1096,7 +1106,7 @@ static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
}
static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
u64 event_code, int state)
int state)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
enum gp2ap020a00f_cmd cmd_high_ev, cmd_low_ev;
......@@ -1151,7 +1161,10 @@ static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
}
static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
u64 event_code, int state)
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
enum gp2ap020a00f_cmd cmd;
......@@ -1159,14 +1172,12 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
mutex_lock(&data->lock);
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_PROXIMITY:
err = gp2ap020a00f_write_prox_event_config(indio_dev,
event_code, state);
err = gp2ap020a00f_write_prox_event_config(indio_dev, state);
break;
case IIO_LIGHT:
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code)
== IIO_EV_DIR_RISING) {
if (dir == IIO_EV_DIR_RISING) {
cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN :
GP2AP020A00F_CMD_ALS_HIGH_EV_DIS;
err = gp2ap020a00f_exec_cmd(data, cmd);
......@@ -1186,17 +1197,18 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
}
static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
u64 event_code)
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
int event_en = 0;
mutex_lock(&data->lock);
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_PROXIMITY:
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code)
== IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
&data->flags);
else
......@@ -1204,14 +1216,16 @@ static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
&data->flags);
break;
case IIO_LIGHT:
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code)
== IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
&data->flags);
else
event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
&data->flags);
break;
default:
event_en = -EINVAL;
break;
}
mutex_unlock(&data->lock);
......@@ -1292,6 +1306,34 @@ static int gp2ap020a00f_read_raw(struct iio_dev *indio_dev,
return err < 0 ? err : IIO_VAL_INT;
}
static const struct iio_event_spec gp2ap020a00f_event_spec_light[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_event_spec gp2ap020a00f_event_spec_prox[] = {
{
.type = IIO_EV_TYPE_ROC,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_ROC,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_chan_spec gp2ap020a00f_channels[] = {
{
.type = IIO_LIGHT,
......@@ -1307,10 +1349,8 @@ static const struct iio_chan_spec gp2ap020a00f_channels[] = {
},
.scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
.address = GP2AP020A00F_D0_L_REG,
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
.event_spec = gp2ap020a00f_event_spec_light,
.num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_light),
},
{
.type = IIO_LIGHT,
......@@ -1340,20 +1380,18 @@ static const struct iio_chan_spec gp2ap020a00f_channels[] = {
},
.scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY,
.address = GP2AP020A00F_D2_L_REG,
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_ROC,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_ROC,
IIO_EV_DIR_FALLING),
.event_spec = gp2ap020a00f_event_spec_prox,
.num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_prox),
},
IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
};
static const struct iio_info gp2ap020a00f_info = {
.read_raw = &gp2ap020a00f_read_raw,
.read_event_value = &gp2ap020a00f_read_event_val,
.read_event_config = &gp2ap020a00f_read_event_config,
.write_event_value = &gp2ap020a00f_write_event_val,
.write_event_config = &gp2ap020a00f_write_event_config,
.read_event_value_new = &gp2ap020a00f_read_event_val,
.read_event_config_new = &gp2ap020a00f_read_event_config,
.write_event_value_new = &gp2ap020a00f_write_event_val,
.write_event_config_new = &gp2ap020a00f_write_event_config,
.driver_module = THIS_MODULE,
};
......@@ -1446,7 +1484,6 @@ static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
}
static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &gp2ap020a00f_buffer_postenable,
.predisable = &gp2ap020a00f_buffer_predisable,
};
......
......@@ -526,6 +526,20 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
return ret;
}
static const struct iio_event_spec tsl2563_events[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_chan_spec tsl2563_channels[] = {
{
.type = IIO_LIGHT,
......@@ -538,10 +552,8 @@ static const struct iio_chan_spec tsl2563_channels[] = {
.channel2 = IIO_MOD_LIGHT_BOTH,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_CALIBSCALE),
.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING)),
.event_spec = tsl2563_events,
.num_event_specs = ARRAY_SIZE(tsl2563_events),
}, {
.type = IIO_INTENSITY,
.modified = 1,
......@@ -552,12 +564,13 @@ static const struct iio_chan_spec tsl2563_channels[] = {
};
static int tsl2563_read_thresh(struct iio_dev *indio_dev,
u64 event_code,
int *val)
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 tsl2563_chip *chip = iio_priv(indio_dev);
switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
switch (dir) {
case IIO_EV_DIR_RISING:
*val = chip->high_thres;
break;
......@@ -568,18 +581,19 @@ static int tsl2563_read_thresh(struct iio_dev *indio_dev,
return -EINVAL;
}
return 0;
return IIO_VAL_INT;
}
static int tsl2563_write_thresh(struct iio_dev *indio_dev,
u64 event_code,
int val)
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 tsl2563_chip *chip = iio_priv(indio_dev);
int ret;
u8 address;
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
address = TSL2563_REG_HIGHLOW;
else
address = TSL2563_REG_LOWLOW;
......@@ -591,7 +605,7 @@ static int tsl2563_write_thresh(struct iio_dev *indio_dev,
ret = i2c_smbus_write_byte_data(chip->client,
TSL2563_CMD | (address + 1),
(val >> 8) & 0xFF);
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
if (dir == IIO_EV_DIR_RISING)
chip->high_thres = val;
else
chip->low_thres = val;
......@@ -620,8 +634,8 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
}
static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
u64 event_code,
int state)
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret = 0;
......@@ -662,7 +676,8 @@ static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
}
static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev,
u64 event_code)
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret;
......@@ -687,10 +702,10 @@ static const struct iio_info tsl2563_info = {
.driver_module = THIS_MODULE,
.read_raw = &tsl2563_read_raw,
.write_raw = &tsl2563_write_raw,
.read_event_value = &tsl2563_read_thresh,
.write_event_value = &tsl2563_write_thresh,
.read_event_config = &tsl2563_read_interrupt_config,
.write_event_config = &tsl2563_write_interrupt_config,
.read_event_value_new = &tsl2563_read_thresh,
.write_event_value_new = &tsl2563_write_thresh,
.read_event_config_new = &tsl2563_read_interrupt_config,
.write_event_config_new = &tsl2563_write_interrupt_config,
};
static int tsl2563_probe(struct i2c_client *client,
......
......@@ -25,16 +25,7 @@
static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
{
int err;
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_magn_set_enable_error;
err = iio_sw_buffer_preenable(indio_dev);
st_magn_set_enable_error:
return err;
return st_sensors_set_enable(indio_dev, true);
}
static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
......
......@@ -32,16 +32,7 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state)
static int st_press_buffer_preenable(struct iio_dev *indio_dev)
{
int err;
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_press_set_enable_error;
err = iio_sw_buffer_preenable(indio_dev);
st_press_set_enable_error:
return err;
return st_sensors_set_enable(indio_dev, true);
}
static int st_press_buffer_postenable(struct iio_dev *indio_dev)
......
......@@ -502,7 +502,7 @@ inline int find_type_by_name(const char *name, const char *type)
inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
{
int ret;
int ret = 0;
FILE *sysfsfp;
int test;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
......
......@@ -190,15 +190,26 @@ static u8 lis3l02dq_axis_map[3][3] = {
};
static int lis3l02dq_read_thresh(struct iio_dev *indio_dev,
u64 e,
int *val)
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)
{
return lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
int ret;
ret = lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
if (ret)
return ret;
return IIO_VAL_INT;
}
static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
u64 event_code,
int val)
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)
{
u16 value = val;
return lis3l02dq_spi_write_reg_s16(indio_dev,
......@@ -503,9 +514,19 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
#define LIS3L02DQ_EVENT_MASK \
(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
static const struct iio_event_spec lis3l02dq_event[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
}
};
#define LIS3L02DQ_CHAN(index, mod) \
{ \
......@@ -523,7 +544,8 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
.realbits = 12, \
.storagebits = 16, \
}, \
.event_mask = LIS3L02DQ_EVENT_MASK, \
.event_spec = lis3l02dq_event, \
.num_event_specs = ARRAY_SIZE(lis3l02dq_event), \
}
static const struct iio_chan_spec lis3l02dq_channels[] = {
......@@ -535,14 +557,14 @@ static const struct iio_chan_spec lis3l02dq_channels[] = {
static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
u64 event_code)
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{
u8 val;
int ret;
u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)));
u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
ret = lis3l02dq_spi_read_reg_8(indio_dev,
LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
&val);
......@@ -587,16 +609,16 @@ int lis3l02dq_disable_all_events(struct iio_dev *indio_dev)
}
static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
u64 event_code,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state)
{
int ret = 0;
u8 val, control;
u8 currentlyset;
bool changed = false;
u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
IIO_EV_DIR_RISING)));
u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
mutex_lock(&indio_dev->mlock);
/* read current control */
......@@ -654,10 +676,10 @@ static const struct attribute_group lis3l02dq_attribute_group = {
static const struct iio_info lis3l02dq_info = {
.read_raw = &lis3l02dq_read_raw,
.write_raw = &lis3l02dq_write_raw,
.read_event_value = &lis3l02dq_read_thresh,
.write_event_value = &lis3l02dq_write_thresh,
.write_event_config = &lis3l02dq_write_event_config,
.read_event_config = &lis3l02dq_read_event_config,
.read_event_value_new = &lis3l02dq_read_thresh,
.write_event_value_new = &lis3l02dq_write_thresh,
.write_event_config_new = &lis3l02dq_write_event_config,
.read_event_config_new = &lis3l02dq_read_event_config,
.driver_module = THIS_MODULE,
.attrs = &lis3l02dq_attribute_group,
};
......
......@@ -382,7 +382,6 @@ static int lis3l02dq_buffer_predisable(struct iio_dev *indio_dev)
}
static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &lis3l02dq_buffer_postenable,
.predisable = &lis3l02dq_buffer_predisable,
};
......@@ -396,7 +395,7 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
if (!buffer)
return -ENOMEM;
indio_dev->buffer = buffer;
iio_device_attach_buffer(indio_dev, buffer);
buffer->scan_timestamp = true;
indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops;
......
......@@ -419,8 +419,11 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
#define SCA3000_EVENT_MASK \
(IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING))
static const struct iio_event_spec sca3000_event = {
.type = IIO_EV_TYPE_MAG,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
};
#define SCA3000_CHAN(index, mod) \
{ \
......@@ -437,7 +440,8 @@ static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
.storagebits = 16, \
.shift = 5, \
}, \
.event_mask = SCA3000_EVENT_MASK, \
.event_spec = &sca3000_event, \
.num_event_specs = 1, \
}
static const struct iio_chan_spec sca3000_channels[] = {
......@@ -703,12 +707,15 @@ static IIO_CONST_ATTR_TEMP_OFFSET("-214.6");
* sca3000_read_thresh() - query of a threshold
**/
static int sca3000_read_thresh(struct iio_dev *indio_dev,
u64 e,
int *val)
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 ret, i;
struct sca3000_state *st = iio_priv(indio_dev);
int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
int num = chan->channel2;
mutex_lock(&st->lock);
ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]);
mutex_unlock(&st->lock);
......@@ -724,18 +731,21 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev,
ARRAY_SIZE(st->info->mot_det_mult_xz))
*val += st->info->mot_det_mult_xz[i];
return 0;
return IIO_VAL_INT;
}
/**
* sca3000_write_thresh() control of threshold
**/
static int sca3000_write_thresh(struct iio_dev *indio_dev,
u64 e,
int val)
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 sca3000_state *st = iio_priv(indio_dev);
int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
int num = chan->channel2;
int ret;
int i;
u8 nonlinear = 0;
......@@ -866,12 +876,14 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
* sca3000_read_event_config() what events are enabled
**/
static int sca3000_read_event_config(struct iio_dev *indio_dev,
u64 e)
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
u8 protect_mask = 0x03;
int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
int num = chan->channel2;
/* read current value of mode register */
mutex_lock(&st->lock);
......@@ -969,13 +981,15 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
* this mode is disabled. Currently normal mode is assumed.
**/
static int sca3000_write_event_config(struct iio_dev *indio_dev,
u64 e,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret, ctrlval;
u8 protect_mask = 0x03;
int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
int num = chan->channel2;
mutex_lock(&st->lock);
/* First read the motion detector config to find out if
......@@ -1112,20 +1126,20 @@ static const struct iio_info sca3000_info = {
.attrs = &sca3000_attribute_group,
.read_raw = &sca3000_read_raw,
.event_attrs = &sca3000_event_attribute_group,
.read_event_value = &sca3000_read_thresh,
.write_event_value = &sca3000_write_thresh,
.read_event_config = &sca3000_read_event_config,
.write_event_config = &sca3000_write_event_config,
.read_event_value_new = &sca3000_read_thresh,
.write_event_value_new = &sca3000_write_thresh,
.read_event_config_new = &sca3000_read_event_config,
.write_event_config_new = &sca3000_write_event_config,
.driver_module = THIS_MODULE,
};
static const struct iio_info sca3000_info_with_temp = {
.attrs = &sca3000_attribute_group_with_temp,
.read_raw = &sca3000_read_raw,
.read_event_value = &sca3000_read_thresh,
.write_event_value = &sca3000_write_thresh,
.read_event_config = &sca3000_read_event_config,
.write_event_config = &sca3000_write_event_config,
.read_event_value_new = &sca3000_read_thresh,
.write_event_value_new = &sca3000_write_thresh,
.read_event_config_new = &sca3000_read_event_config,
.write_event_config_new = &sca3000_write_event_config,
.driver_module = THIS_MODULE,
};
......
......@@ -265,7 +265,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev)
return buf;
}
static inline void sca3000_rb_free(struct iio_buffer *r)
static void sca3000_ring_release(struct iio_buffer *r)
{
kfree(iio_to_hw_buf(r));
}
......@@ -274,23 +274,28 @@ static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = {
.read_first_n = &sca3000_read_first_n_hw_rb,
.get_length = &sca3000_ring_get_length,
.get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum,
.release = sca3000_ring_release,
};
int sca3000_configure_ring(struct iio_dev *indio_dev)
{
indio_dev->buffer = sca3000_rb_allocate(indio_dev);
if (indio_dev->buffer == NULL)
struct iio_buffer *buffer;
buffer = sca3000_rb_allocate(indio_dev);
if (buffer == NULL)
return -ENOMEM;
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
indio_dev->buffer->access = &sca3000_ring_access_funcs;
iio_device_attach_buffer(indio_dev, buffer);
return 0;
}
void sca3000_unconfigure_ring(struct iio_dev *indio_dev)
{
sca3000_rb_free(indio_dev->buffer);
iio_buffer_put(indio_dev->buffer);
}
static inline
......
......@@ -102,7 +102,7 @@ config AD7280
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX
depends on ARCH_LPC32XX || COMPILE_TEST
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
......@@ -113,7 +113,8 @@ config LPC32XX_ADC
config MXS_LRADC
tristate "Freescale i.MX23/i.MX28 LRADC"
depends on ARCH_MXS
depends on ARCH_MXS || COMPILE_TEST
select STMP_DEVICE
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
......@@ -125,7 +126,7 @@ config MXS_LRADC
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR
depends on PLAT_SPEAR || COMPILE_TEST
help
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
......
......@@ -164,97 +164,14 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
static inline ssize_t ad7291_show_hyst(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7291_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 data;
int ret;
ret = ad7291_i2c_read(chip, this_attr->address, &data);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", data & AD7291_VALUE_MASK);
}
static inline ssize_t ad7291_set_hyst(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7291_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 data;
int ret;
ret = kstrtou16(buf, 10, &data);
if (ret < 0)
return ret;
if (data > AD7291_VALUE_MASK)
return -EINVAL;
ret = ad7291_i2c_write(chip, this_attr->address, data);
if (ret < 0)
return ret;
return len;
}
static IIO_DEVICE_ATTR(in_temp0_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst,
AD7291_HYST(8));
static IIO_DEVICE_ATTR(in_voltage0_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(0));
static IIO_DEVICE_ATTR(in_voltage1_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(1));
static IIO_DEVICE_ATTR(in_voltage2_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(2));
static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(3));
static IIO_DEVICE_ATTR(in_voltage4_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(4));
static IIO_DEVICE_ATTR(in_voltage5_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(5));
static IIO_DEVICE_ATTR(in_voltage6_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(6));
static IIO_DEVICE_ATTR(in_voltage7_thresh_both_hyst_raw,
S_IRUGO | S_IWUSR,
ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(7));
static struct attribute *ad7291_event_attributes[] = {
&iio_dev_attr_in_temp0_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage1_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage2_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage3_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage4_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage5_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage6_thresh_both_hyst_raw.dev_attr.attr,
&iio_dev_attr_in_voltage7_thresh_both_hyst_raw.dev_attr.attr,
NULL,
};
static unsigned int ad7291_threshold_reg(u64 event_code)
static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
enum iio_event_direction dir, enum iio_event_info info)
{
unsigned int offset;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_VOLTAGE:
offset = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
offset = chan->channel;
break;
case IIO_TEMP:
offset = 8;
......@@ -263,69 +180,78 @@ static unsigned int ad7291_threshold_reg(u64 event_code)
return 0;
}
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
return AD7291_DATA_LOW(offset);
else
return AD7291_DATA_HIGH(offset);
switch (info) {
case IIO_EV_INFO_VALUE:
if (dir == IIO_EV_DIR_FALLING)
return AD7291_DATA_HIGH(offset);
else
return AD7291_DATA_LOW(offset);
case IIO_EV_INFO_HYSTERESIS:
return AD7291_HYST(offset);
default:
break;
}
return 0;
}
static int ad7291_read_event_value(struct iio_dev *indio_dev,
u64 event_code,
int *val)
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 ad7291_chip_info *chip = iio_priv(indio_dev);
int ret;
u16 uval;
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(event_code), &uval);
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
&uval);
if (ret < 0)
return ret;
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
case IIO_VOLTAGE:
if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE)
*val = uval & AD7291_VALUE_MASK;
return 0;
case IIO_TEMP:
else
*val = sign_extend32(uval, 11);
return 0;
default:
return -EINVAL;
}
return IIO_VAL_INT;
}
static int ad7291_write_event_value(struct iio_dev *indio_dev,
u64 event_code,
int val)
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 ad7291_chip_info *chip = iio_priv(indio_dev);
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
case IIO_VOLTAGE:
if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) {
if (val > AD7291_VALUE_MASK || val < 0)
return -EINVAL;
break;
case IIO_TEMP:
} else {
if (val > 2047 || val < -2048)
return -EINVAL;
break;
default:
return -EINVAL;
}
return ad7291_i2c_write(chip, ad7291_threshold_reg(event_code), val);
return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
val);
}
static int ad7291_read_event_config(struct iio_dev *indio_dev,
u64 event_code)
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir)
{
struct ad7291_chip_info *chip = iio_priv(indio_dev);
/* To be enabled the channel must simply be on. If any are enabled
we are in continuous sampling mode */
switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
switch (chan->type) {
case IIO_VOLTAGE:
if (chip->c_mask &
(1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN(event_code))))
if (chip->c_mask & (1 << (15 - chan->channel)))
return 1;
else
return 0;
......@@ -339,11 +265,14 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev,
}
static int ad7291_write_event_config(struct iio_dev *indio_dev,
u64 event_code,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state)
{
int ret = 0;
struct ad7291_chip_info *chip = iio_priv(indio_dev);
unsigned int mask;
u16 regval;
mutex_lock(&chip->state_lock);
......@@ -354,16 +283,14 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev,
* Possible to disable temp as well but that makes single read tricky.
*/
switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
mask = BIT(15 - chan->channel);
switch (chan->type) {
case IIO_VOLTAGE:
if ((!state) && (chip->c_mask & (1 << (15 -
IIO_EVENT_CODE_EXTRACT_CHAN(event_code)))))
chip->c_mask &= ~(1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN
(event_code)));
else if (state && (!(chip->c_mask & (1 << (15 -
IIO_EVENT_CODE_EXTRACT_CHAN(event_code))))))
chip->c_mask |= (1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN
(event_code)));
if ((!state) && (chip->c_mask & mask))
chip->c_mask &= ~mask;
else if (state && (!(chip->c_mask & mask)))
chip->c_mask |= mask;
else
break;
......@@ -473,6 +400,24 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
}
}
static const struct iio_event_spec ad7291_events[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
}, {
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_EITHER,
.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
},
};
#define AD7291_VOLTAGE_CHAN(_chan) \
{ \
.type = IIO_VOLTAGE, \
......@@ -480,8 +425,8 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.indexed = 1, \
.channel = _chan, \
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) \
.event_spec = ad7291_events, \
.num_event_specs = ARRAY_SIZE(ad7291_events), \
}
static const struct iio_chan_spec ad7291_channels[] = {
......@@ -500,23 +445,17 @@ static const struct iio_chan_spec ad7291_channels[] = {
BIT(IIO_CHAN_INFO_SCALE),
.indexed = 1,
.channel = 0,
.event_mask =
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)
.event_spec = ad7291_events,
.num_event_specs = ARRAY_SIZE(ad7291_events),
}
};
static struct attribute_group ad7291_event_attribute_group = {
.attrs = ad7291_event_attributes,
};
static const struct iio_info ad7291_info = {
.read_raw = &ad7291_read_raw,
.read_event_config = &ad7291_read_event_config,
.write_event_config = &ad7291_write_event_config,
.read_event_value = &ad7291_read_event_value,
.write_event_value = &ad7291_write_event_value,
.event_attrs = &ad7291_event_attribute_group,
.read_event_config_new = &ad7291_read_event_config,
.write_event_config_new = &ad7291_write_event_config,
.read_event_value_new = &ad7291_read_event_value,
.write_event_value_new = &ad7291_write_event_value,
.driver_module = THIS_MODULE,
};
......
......@@ -36,18 +36,10 @@
#define AD7998_ALERT_STAT_REG 0x1
#define AD7998_CONF_REG 0x2
#define AD7998_CYCLE_TMR_REG 0x3
#define AD7998_DATALOW_CH1_REG 0x4
#define AD7998_DATAHIGH_CH1_REG 0x5
#define AD7998_HYST_CH1_REG 0x6
#define AD7998_DATALOW_CH2_REG 0x7
#define AD7998_DATAHIGH_CH2_REG 0x8
#define AD7998_HYST_CH2_REG 0x9
#define AD7998_DATALOW_CH3_REG 0xA
#define AD7998_DATAHIGH_CH3_REG 0xB
#define AD7998_HYST_CH3_REG 0xC
#define AD7998_DATALOW_CH4_REG 0xD
#define AD7998_DATAHIGH_CH4_REG 0xE
#define AD7998_HYST_CH4_REG 0xF
#define AD7998_DATALOW_REG(x) ((x) * 3 + 0x4)
#define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5)
#define AD7998_HYST_REG(x) ((x) * 3 + 0x6)
#define AD7998_CYC_MASK 0x7
#define AD7998_CYC_DIS 0x0
......
This diff is collapsed.
......@@ -160,7 +160,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if ((irq < 0) || (irq >= NR_IRQS)) {
if (irq <= 0) {
dev_err(&pdev->dev, "failed getting interrupt resource\n");
return -EINVAL;
}
......
......@@ -1041,10 +1041,6 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
goto err_mem;
}
ret = iio_sw_buffer_preenable(iio);
if (ret < 0)
goto err_buf;
if (lradc->soc == IMX28_LRADC)
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
LRADC_CTRL1);
......@@ -1069,8 +1065,6 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
return 0;
err_buf:
kfree(lradc->buffer);
err_mem:
mutex_unlock(&lradc->lock);
return ret;
......
......@@ -146,7 +146,6 @@ static int spear_read_raw(struct iio_dev *indio_dev,
long mask)
{
struct spear_adc_info *info = iio_priv(indio_dev);
u32 scale_mv;
u32 status;
switch (mask) {
......@@ -319,7 +318,7 @@ static int spear_adc_probe(struct platform_device *pdev)
return -ENOMEM;
}
info->adc_base_spear3xx =
(struct adc_regs_spear3xx *)info->adc_base_spear6xx;
(struct adc_regs_spear3xx __iomem *)info->adc_base_spear6xx;
info->clk = clk_get(dev, NULL);
if (IS_ERR(info->clk)) {
......@@ -334,7 +333,7 @@ static int spear_adc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if ((irq < 0) || (irq >= NR_IRQS)) {
if (irq <= 0) {
dev_err(dev, "failed getting interrupt resource\n");
ret = -EINVAL;
goto errout3;
......
This diff is collapsed.
......@@ -57,6 +57,20 @@ static const struct iio_dummy_accel_calibscale dummy_scales[] = {
{ 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),
};
#endif
/*
* iio_dummy_channels - Description of available channels
*
......@@ -104,12 +118,8 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
.shift = 0, /* zero shift */
},
#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
/*
* simple event - triggered when value rises above
* a threshold
*/
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
.event_spec = &iio_dummy_event,
.num_event_specs = 1,
#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
},
/* Differential ADC channel in_voltage1-voltage2_raw etc*/
......@@ -360,10 +370,10 @@ static const struct iio_info iio_dummy_info = {
.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,
.read_event_config_new = &iio_simple_dummy_read_event_config,
.write_event_config_new = &iio_simple_dummy_write_event_config,
.read_event_value_new = &iio_simple_dummy_read_event_value,
.write_event_value_new = &iio_simple_dummy_write_event_value,
#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
};
......
......@@ -45,19 +45,29 @@ struct iio_dummy_state {
struct iio_dev;
int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
u64 event_code);
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,
u64 event_code,
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,
u64 event_code,
int *val);
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,
u64 event_code,
int val);
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);
int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev);
......
......@@ -98,14 +98,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
}
static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = {
/*
* iio_sw_buffer_preenable:
* Generic function for equal sized ring elements + 64 bit timestamp
* Assumes that any combination of channels can be enabled.
* Typically replaced to implement restrictions on what combinations
* can be captured (hardware scan modes).
*/
.preenable = &iio_sw_buffer_preenable,
/*
* iio_triggered_buffer_postenable:
* Generic function that simply attaches the pollfunc to the trigger.
......@@ -135,7 +127,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
goto error_ret;
}
indio_dev->buffer = buffer;
iio_device_attach_buffer(indio_dev, buffer);
/* Enable timestamps by default */
buffer->scan_timestamp = true;
......
......@@ -574,10 +574,6 @@ static int ad5933_ring_preenable(struct iio_dev *indio_dev)
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
ret = iio_sw_buffer_preenable(indio_dev);
if (ret < 0)
return ret;
ret = ad5933_reset(st);
if (ret < 0)
return ret;
......@@ -630,10 +626,14 @@ static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = {
static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer)
struct iio_buffer *buffer;
buffer = iio_kfifo_allocate(indio_dev);
if (buffer)
return -ENOMEM;
iio_device_attach_buffer(indio_dev, buffer);
/* Ring buffer functions - here trigger setup related */
indio_dev->setup_ops = &ad5933_ring_setup_ops;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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