summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/iio/Kconfig6
-rw-r--r--drivers/iio/Makefile1
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c15
-rw-r--r--drivers/iio/adc/Kconfig31
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ad7266.c3
-rw-r--r--drivers/iio/adc/ad7476.c2
-rw-r--r--drivers/iio/adc/ad7887.c (renamed from drivers/staging/iio/adc/ad7887_core.c)217
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c2
-rw-r--r--drivers/iio/adc/at91_adc.c3
-rw-r--r--drivers/iio/adc/max1363.c (renamed from drivers/staging/iio/adc/max1363_core.c)330
-rw-r--r--drivers/iio/buffer_cb.c113
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c15
-rw-r--r--drivers/iio/industrialio-buffer.c380
-rw-r--r--drivers/iio/industrialio-core.c1
-rw-r--r--drivers/iio/inkern.c1
-rw-r--r--drivers/iio/light/adjd_s311.c3
-rw-r--r--drivers/iio/light/hid-sensor-als.c15
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c15
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c2
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c2
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c2
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c2
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c2
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c2
-rw-r--r--drivers/staging/iio/adc/Kconfig37
-rw-r--r--drivers/staging/iio/adc/Makefile9
-rw-r--r--drivers/staging/iio/adc/ad7298_ring.c2
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c2
-rw-r--r--drivers/staging/iio/adc/ad7887.h99
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c122
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c2
-rw-r--r--drivers/staging/iio/adc/max1363.h177
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c139
-rw-r--r--drivers/staging/iio/adc/mxs-lradc.c3
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c2
-rw-r--r--drivers/staging/iio/iio_simple_dummy_buffer.c5
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c4
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c5
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c2
-rw-r--r--include/linux/iio/buffer.h24
-rw-r--r--include/linux/iio/consumer.h48
-rw-r--r--include/linux/iio/iio.h2
-rw-r--r--include/linux/iio/machine.h2
-rw-r--r--include/linux/platform_data/ad7887.h26
45 files changed, 1003 insertions, 876 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index fc937aca71fb..65ae734c607d 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -20,6 +20,12 @@ config IIO_BUFFER
if IIO_BUFFER
+config IIO_BUFFER_CB
+boolean "IIO callback buffer used for push in-kernel interfaces"
+ help
+ Should be selected by any drivers that do-inkernel push
+ usage. That is, those where the data is pushed to the consumer.
+
config IIO_KFIFO_BUF
select IIO_TRIGGER
tristate "Industrial I/O buffering based on kfifo"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 761f2b65ac52..31d76a07ec65 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_IIO) += industrialio.o
industrialio-y := industrialio-core.o industrialio-event.o inkern.o
industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
+industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o
obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 314a4057879e..a95cda0e387f 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = {
/* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
{
- struct iio_buffer *buffer = indio_dev->buffer;
- int datum_sz;
-
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- if (!buffer) {
- dev_err(&indio_dev->dev, "Buffer == NULL\n");
- return;
- }
- datum_sz = buffer->access->get_bytes_per_datum(buffer);
- if (len > datum_sz) {
- dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
- datum_sz);
- return;
- }
- iio_push_to_buffer(buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
}
/* Callback handler to send event after all samples are received and captured */
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 492758120338..ef5200a6850e 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -45,6 +45,19 @@ config AD7476
To compile this driver as a module, choose M here: the
module will be called ad7476.
+config AD7887
+ tristate "Analog Devices AD7887 ADC driver"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Analog Devices
+ AD7887 SPI analog to digital converter (ADC).
+ If unsure, say N (but it's safe to say "Y").
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7887.
+
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
@@ -60,4 +73,22 @@ config LP8788_ADC
help
Say yes here to build support for TI LP8788 ADC.
+config MAX1363
+ tristate "Maxim max1363 ADC driver"
+ depends on I2C
+ select IIO_TRIGGER
+ select MAX1363_RING_BUFFER
+ select IIO_BUFFER
+ select IIO_KFIFO_BUF
+ help
+ Say yes here to build support for many Maxim i2c analog to digital
+ converters (ADC). (max1361, max1362, max1363, max1364, max1036,
+ max1037, max1038, max1039, max1136, max1136, max1137, max1138,
+ max1139, max1236, max1237, max11238, max1239, max11600, max11601,
+ max11602, max11603, max11604, max11605, max11606, max11607,
+ max11608, max11609, max11610, max11611, max11612, max11613,
+ max11614, max11615, max11616, max11617, max11644, max11645,
+ max11646, max11647) Provides direct access via sysfs and buffered
+ data via the iio dev interface.
+
endmenu
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 900995d5e179..54ac7bbcd01b 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -6,5 +6,7 @@ obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7791) += ad7791.o
+obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index b11f214779a2..a6f4fc5f8201 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
- struct iio_buffer *buffer = indio_dev->buffer;
struct ad7266_state *st = iio_priv(indio_dev);
int ret;
@@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
if (ret == 0) {
if (indio_dev->scan_timestamp)
((s64 *)st->data)[1] = pf->timestamp;
- iio_push_to_buffer(buffer, (u8 *)st->data);
+ iio_push_to_buffers(indio_dev, (u8 *)st->data);
}
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 7f2f45a0a48d..330248bfebae 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
((s64 *)st->data)[1] = time_ns;
- iio_push_to_buffer(indio_dev->buffer, st->data);
+ iio_push_to_buffers(indio_dev, st->data);
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/iio/adc/ad7887.c
index 551790584a12..81153fafac7a 100644
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ b/drivers/iio/adc/ad7887.c
@@ -14,13 +14,139 @@
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/interrupt.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
-#include "ad7887.h"
+#include <linux/platform_data/ad7887.h>
+
+#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */
+#define AD7887_DUAL (1 << 4) /* dual-channel mode */
+#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */
+#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */
+#define AD7887_PM_MODE1 (0) /* CS based shutdown */
+#define AD7887_PM_MODE2 (1) /* full on */
+#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */
+#define AD7887_PM_MODE4 (3) /* standby mode */
+
+enum ad7887_channels {
+ AD7887_CH0,
+ AD7887_CH0_CH1,
+ AD7887_CH1,
+};
+
+#define RES_MASK(bits) ((1 << (bits)) - 1)
+
+/**
+ * struct ad7887_chip_info - chip specifc information
+ * @int_vref_mv: the internal reference voltage
+ * @channel: channel specification
+ */
+struct ad7887_chip_info {
+ u16 int_vref_mv;
+ struct iio_chan_spec channel[3];
+};
+
+struct ad7887_state {
+ struct spi_device *spi;
+ const struct ad7887_chip_info *chip_info;
+ struct regulator *reg;
+ struct spi_transfer xfer[4];
+ struct spi_message msg[3];
+ struct spi_message *ring_msg;
+ unsigned char tx_cmd_buf[4];
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ * Buffer needs to be large enough to hold two 16 bit samples and a
+ * 64 bit aligned 64 bit timestamp.
+ */
+ unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)]
+ ____cacheline_aligned;
+};
+
+enum ad7887_supported_device_ids {
+ ID_AD7887
+};
+
+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) {
+ case (1 << 0):
+ st->ring_msg = &st->msg[AD7887_CH0];
+ break;
+ case (1 << 1):
+ st->ring_msg = &st->msg[AD7887_CH1];
+ /* Dummy read: push CH1 setting down to hardware */
+ spi_sync(st->spi, st->ring_msg);
+ break;
+ case ((1 << 1) | (1 << 0)):
+ st->ring_msg = &st->msg[AD7887_CH0_CH1];
+ break;
+ }
+
+ return 0;
+}
+
+static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7887_state *st = iio_priv(indio_dev);
+
+ /* dummy read: restore default CH0 settin */
+ return spi_sync(st->spi, &st->msg[AD7887_CH0]);
+}
+
+/**
+ * ad7887_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad7887_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7887_state *st = iio_priv(indio_dev);
+ s64 time_ns;
+ int b_sent;
+
+ b_sent = spi_sync(st->spi, st->ring_msg);
+ if (b_sent)
+ goto done;
+
+ time_ns = iio_get_time_ns();
+
+ if (indio_dev->scan_timestamp)
+ memcpy(st->data + indio_dev->scan_bytes - sizeof(s64),
+ &time_ns, sizeof(time_ns));
+
+ iio_push_to_buffers(indio_dev, st->data);
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
+ .preenable = &ad7887_ring_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
+ .postdisable = &ad7887_ring_postdisable,
+};
static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch)
{
@@ -39,7 +165,6 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
{
int ret;
struct ad7887_state *st = iio_priv(indio_dev);
- unsigned int scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
@@ -52,15 +177,22 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
- *val = (ret >> st->chip_info->channel[0].scan_type.shift) &
- RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+ *val = ret >> chan->scan_type.shift;
+ *val &= RES_MASK(chan->scan_type.realbits);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- scale_uv = (st->int_vref_mv * 1000)
- >> st->chip_info->channel[0].scan_type.realbits;
- *val = scale_uv/1000;
- *val2 = (scale_uv%1000)*1000;
- return IIO_VAL_INT_PLUS_MICRO;
+ if (st->reg) {
+ *val = regulator_get_voltage(st->reg);
+ if (*val < 0)
+ return *val;
+ *val /= 1000;
+ } else {
+ *val = st->chip_info->int_vref_mv;
+ }
+
+ *val2 = chan->scan_type.realbits;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
@@ -105,21 +237,25 @@ static int __devinit ad7887_probe(struct spi_device *spi)
{
struct ad7887_platform_data *pdata = spi->dev.platform_data;
struct ad7887_state *st;
- int ret, voltage_uv = 0;
struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ uint8_t mode;
+ int ret;
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
+ if (!pdata || !pdata->use_onchip_ref) {
+ st->reg = regulator_get(&spi->dev, "vref");
+ if (IS_ERR(st->reg)) {
+ ret = PTR_ERR(st->reg);
+ goto error_free;
+ }
+
ret = regulator_enable(st->reg);
if (ret)
goto error_put_reg;
-
- voltage_uv = regulator_get_voltage(st->reg);
}
st->chip_info =
@@ -136,9 +272,13 @@ static int __devinit ad7887_probe(struct spi_device *spi)
/* Setup default message */
- st->tx_cmd_buf[0] = AD7887_CH_AIN0 | AD7887_PM_MODE4 |
- ((pdata && pdata->use_onchip_ref) ?
- 0 : AD7887_REF_DIS);
+ mode = AD7887_PM_MODE4;
+ if (!pdata || !pdata->use_onchip_ref)
+ mode |= AD7887_REF_DIS;
+ if (pdata && pdata->en_dual)
+ mode |= AD7887_DUAL;
+
+ st->tx_cmd_buf[0] = AD7887_CH_AIN0 | mode;
st->xfer[0].rx_buf = &st->data[0];
st->xfer[0].tx_buf = &st->tx_cmd_buf[0];
@@ -148,56 +288,36 @@ static int __devinit ad7887_probe(struct spi_device *spi)
spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]);
if (pdata && pdata->en_dual) {
- st->tx_cmd_buf[0] |= AD7887_DUAL | AD7887_REF_DIS;
-
- st->tx_cmd_buf[2] = AD7887_CH_AIN1 | AD7887_DUAL |
- AD7887_REF_DIS | AD7887_PM_MODE4;
- st->tx_cmd_buf[4] = AD7887_CH_AIN0 | AD7887_DUAL |
- AD7887_REF_DIS | AD7887_PM_MODE4;
- st->tx_cmd_buf[6] = AD7887_CH_AIN1 | AD7887_DUAL |
- AD7887_REF_DIS | AD7887_PM_MODE4;
+ st->tx_cmd_buf[2] = AD7887_CH_AIN1 | mode;
st->xfer[1].rx_buf = &st->data[0];
st->xfer[1].tx_buf = &st->tx_cmd_buf[2];
st->xfer[1].len = 2;
st->xfer[2].rx_buf = &st->data[2];
- st->xfer[2].tx_buf = &st->tx_cmd_buf[4];
+ st->xfer[2].tx_buf = &st->tx_cmd_buf[0];
st->xfer[2].len = 2;
spi_message_init(&st->msg[AD7887_CH0_CH1]);
spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]);
spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]);
- st->xfer[3].rx_buf = &st->data[0];
- st->xfer[3].tx_buf = &st->tx_cmd_buf[6];
+ st->xfer[3].rx_buf = &st->data[2];
+ st->xfer[3].tx_buf = &st->tx_cmd_buf[2];
st->xfer[3].len = 2;
spi_message_init(&st->msg[AD7887_CH1]);
spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]);
- if (pdata && pdata->vref_mv)
- st->int_vref_mv = pdata->vref_mv;
- else if (voltage_uv)
- st->int_vref_mv = voltage_uv / 1000;
- else
- dev_warn(&spi->dev, "reference voltage unspecified\n");
-
indio_dev->channels = st->chip_info->channel;
indio_dev->num_channels = 3;
} else {
- if (pdata && pdata->vref_mv)
- st->int_vref_mv = pdata->vref_mv;
- else if (pdata && pdata->use_onchip_ref)
- st->int_vref_mv = st->chip_info->int_vref_mv;
- else
- dev_warn(&spi->dev, "reference voltage unspecified\n");
-
indio_dev->channels = &st->chip_info->channel[1];
indio_dev->num_channels = 2;
}
- ret = ad7887_register_ring_funcs_and_init(indio_dev);
+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ &ad7887_trigger_handler, &ad7887_ring_setup_ops);
if (ret)
goto error_disable_reg;
@@ -207,13 +327,14 @@ static int __devinit ad7887_probe(struct spi_device *spi)
return 0;
error_unregister_ring:
- ad7887_ring_cleanup(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
error_disable_reg:
- if (!IS_ERR(st->reg))
+ if (st->reg)
regulator_disable(st->reg);
error_put_reg:
- if (!IS_ERR(st->reg))
+ if (st->reg)
regulator_put(st->reg);
+error_free:
iio_device_free(indio_dev);
return ret;
@@ -225,8 +346,8 @@ static int __devexit ad7887_remove(struct spi_device *spi)
struct ad7887_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- ad7887_ring_cleanup(indio_dev);
- if (!IS_ERR(st->reg)) {
+ iio_triggered_buffer_cleanup(indio_dev);
+ if (st->reg) {
regulator_disable(st->reg);
regulator_put(st->reg);
}
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 67baa1363d7a..afe6d78c8ff0 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
break;
}
- iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data);
+ iio_push_to_buffers(indio_dev, (uint8_t *)data);
iio_trigger_notify_done(indio_dev->trig);
sigma_delta->irq_dis = false;
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 2e2c9a80aa37..03b85940f4ba 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -65,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *idev = pf->indio_dev;
struct at91_adc_state *st = iio_priv(idev);
- struct iio_buffer *buffer = idev->buffer;
int i, j = 0;
for (i = 0; i < idev->masklength; i++) {
@@ -81,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
*timestamp = pf->timestamp;
}
- iio_push_to_buffer(buffer, st->buffer);
+ iio_push_to_buffers(indio_dev, (u8 *)st->buffer);
iio_trigger_notify_done(idev->trig);
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/iio/adc/max1363.c
index d7b4ffcfa052..1e84b5b55093 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/iio/adc/max1363.c
@@ -37,8 +37,151 @@
#include <linux/iio/events.h>
#include <linux/iio/buffer.h>
#include <linux/iio/driver.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define MAX1363_SETUP_BYTE(a) ((a) | 0x80)
+
+/* There is a fair bit more defined here than currently
+ * used, but the intention is to support everything these
+ * chips do in the long run */
+
+/* see data sheets */
+/* max1363 and max1236, max1237, max1238, max1239 */
+#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00
+#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20
+#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40
+#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60
+#define MAX1363_SETUP_POWER_UP_INT_REF 0x10
+#define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00
+
+/* think about includeing max11600 etc - more settings */
+#define MAX1363_SETUP_EXT_CLOCK 0x08
+#define MAX1363_SETUP_INT_CLOCK 0x00
+#define MAX1363_SETUP_UNIPOLAR 0x00
+#define MAX1363_SETUP_BIPOLAR 0x04
+#define MAX1363_SETUP_RESET 0x00
+#define MAX1363_SETUP_NORESET 0x02
+/* max1363 only - though don't care on others.
+ * For now monitor modes are not implemented as the relevant
+ * line is not connected on my test board.
+ * The definitions are here as I intend to add this soon.
+ */
+#define MAX1363_SETUP_MONITOR_SETUP 0x01
+
+/* Specific to the max1363 */
+#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4))
+#define MAX1363_MON_INT_ENABLE 0x01
+
+/* defined for readability reasons */
+/* All chips */
+#define MAX1363_CONFIG_BYTE(a) ((a))
+
+#define MAX1363_CONFIG_SE 0x01
+#define MAX1363_CONFIG_DE 0x00
+#define MAX1363_CONFIG_SCAN_TO_CS 0x00
+#define MAX1363_CONFIG_SCAN_SINGLE_8 0x20
+#define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40
+#define MAX1363_CONFIG_SCAN_SINGLE_1 0x60
+/* max123{6-9} only */
+#define MAX1236_SCAN_MID_TO_CHANNEL 0x40
+
+/* max1363 only - merely part of channel selects or don't care for others*/
+#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18
+
+#define MAX1363_CHANNEL_SEL(a) ((a) << 1)
+
+/* max1363 strictly 0x06 - but doesn't matter */
+#define MAX1363_CHANNEL_SEL_MASK 0x1E
+#define MAX1363_SCAN_MASK 0x60
+#define MAX1363_SE_DE_MASK 0x01
+
+#define MAX1363_MAX_CHANNELS 25
+/**
+ * struct max1363_mode - scan mode information
+ * @conf: The corresponding value of the configuration register
+ * @modemask: Bit mask corresponding to channels enabled in this mode
+ */
+struct max1363_mode {
+ int8_t conf;
+ DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS);
+};
-#include "max1363.h"
+/* This must be maintained along side the max1363_mode_table in max1363_core */
+enum max1363_modes {
+ /* Single read of a single channel */
+ _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
+ /* Differential single read */
+ d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
+ d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
+ /* Scan to channel and mid to channel where overlapping */
+ s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6,
+ s6to7, s0to7, s6to8, s0to8, s6to9,
+ s0to9, s6to10, s0to10, s6to11, s0to11,
+ /* Differential scan to channel and mid to channel where overlapping */
+ d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9,
+ d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2,
+ d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8,
+ d7m6to11m10, d1m0to11m10,
+};
+
+/**
+ * struct max1363_chip_info - chip specifc information
+ * @info: iio core function callbacks structure
+ * @channels: channel specification
+ * @num_channels: number of channels
+ * @mode_list: array of available scan modes
+ * @default_mode: the scan mode in which the chip starts up
+ * @int_vref_mv: the internal reference voltage
+ * @num_channels: number of channels
+ * @bits: accuracy of the adc in bits
+ */
+struct max1363_chip_info {
+ const struct iio_info *info;
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ const enum max1363_modes *mode_list;
+ enum max1363_modes default_mode;
+ u16 int_vref_mv;
+ u8 num_modes;
+ u8 bits;
+};
+
+/**
+ * struct max1363_state - driver instance specific data
+ * @client: i2c_client
+ * @setupbyte: cache of current device setup byte
+ * @configbyte: cache of current device config byte
+ * @chip_info: chip model specific constants, available modes etc
+ * @current_mode: the scan mode of this chip
+ * @requestedmask: a valid requested set of channels
+ * @reg: supply regulator
+ * @monitor_on: whether monitor mode is enabled
+ * @monitor_speed: parameter corresponding to device monitor speed setting
+ * @mask_high: bitmask for enabled high thresholds
+ * @mask_low: bitmask for enabled low thresholds
+ * @thresh_high: high threshold values
+ * @thresh_low: low threshold values
+ */
+struct max1363_state {
+ struct i2c_client *client;
+ u8 setupbyte;
+ u8 configbyte;
+ const struct max1363_chip_info *chip_info;
+ const struct max1363_mode *current_mode;
+ u32 requestedmask;
+ struct regulator *reg;
+
+ /* Using monitor modes and buffer at the same time is
+ currently not supported */
+ bool monitor_on;
+ unsigned int monitor_speed:3;
+ u8 mask_high;
+ u8 mask_low;
+ /* 4x unipolar first then the fours bipolar ones */
+ s16 thresh_high[8];
+ s16 thresh_low[8];
+};
#define MAX1363_MODE_SINGLE(_num, _mask) { \
.conf = MAX1363_CHANNEL_SEL(_num) \
@@ -148,7 +291,7 @@ static const struct max1363_mode max1363_mode_table[] = {
MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000),
};
-const struct max1363_mode
+static const struct max1363_mode
*max1363_match_mode(const unsigned long *mask,
const struct max1363_chip_info *ci)
{
@@ -172,7 +315,7 @@ static int max1363_write_basic_config(struct i2c_client *client,
return i2c_master_send(client, tx_buf, 2);
}
-int max1363_set_scan_mode(struct max1363_state *st)
+static int max1363_set_scan_mode(struct max1363_state *st)
{
st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
| MAX1363_SCAN_MASK
@@ -622,9 +765,9 @@ static int max1363_read_event_config(struct iio_dev *indio_dev,
u64 event_code)
{
struct max1363_state *st = iio_priv(indio_dev);
-
int val;
int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
+
mutex_lock(&indio_dev->mlock);
if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
val = (1 << number) & st->mask_low;
@@ -644,7 +787,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
const long *modemask;
if (!enabled) {
- /* transition to ring capture is not currently supported */
+ /* transition to buffered capture is not currently supported */
st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP;
st->configbyte &= ~MAX1363_SCAN_MASK;
st->monitor_on = false;
@@ -826,8 +969,21 @@ static struct attribute_group max1363_event_attribute_group = {
.name = "events",
};
-#define MAX1363_EVENT_FUNCS \
+static int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct max1363_state *st = iio_priv(indio_dev);
+ /*
+ * Need to figure out the current mode based upon the requested
+ * scan mask in iio_dev
+ */
+ st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
+ if (!st->current_mode)
+ return -EINVAL;
+ max1363_set_scan_mode(st);
+ return 0;
+}
static const struct iio_info max1238_info = {
.read_raw = &max1363_read_raw,
@@ -1230,8 +1386,6 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
},
};
-
-
static int max1363_initial_setup(struct max1363_state *st)
{
st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
@@ -1269,34 +1423,137 @@ static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev)
return 0;
}
+
+static irqreturn_t max1363_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct max1363_state *st = iio_priv(indio_dev);
+ s64 time_ns;
+ __u8 *rxbuf;
+ int b_sent;
+ size_t d_size;
+ unsigned long numvals = bitmap_weight(st->current_mode->modemask,
+ MAX1363_MAX_CHANNELS);
+
+ /* Ensure the timestamp is 8 byte aligned */
+ if (st->chip_info->bits != 8)
+ d_size = numvals*2;
+ else
+ d_size = numvals;
+ if (indio_dev->scan_timestamp) {
+ d_size += sizeof(s64);
+ if (d_size % sizeof(s64))
+ d_size += sizeof(s64) - (d_size % sizeof(s64));
+ }
+ /* Monitor mode prevents reading. Whilst not currently implemented
+ * might as well have this test in here in the meantime as it does
+ * no harm.
+ */
+ if (numvals == 0)
+ goto done;
+
+ rxbuf = kmalloc(d_size, GFP_KERNEL);
+ if (rxbuf == NULL)
+ goto done;
+ if (st->chip_info->bits != 8)
+ b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
+ else
+ b_sent = i2c_master_recv(st->client, rxbuf, numvals);
+ if (b_sent < 0)
+ goto done_free;
+
+ time_ns = iio_get_time_ns();
+
+ if (indio_dev->scan_timestamp)
+ memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+ iio_push_to_buffers(indio_dev, rxbuf);
+
+done_free:
+ kfree(rxbuf);
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_buffer_setup_ops max1363_buffered_setup_ops = {
+ .postenable = &iio_triggered_buffer_postenable,
+ .preenable = &iio_sw_buffer_preenable,
+ .predisable = &iio_triggered_buffer_predisable,
+};
+
+static int max1363_register_buffered_funcs_and_init(struct iio_dev *indio_dev)
+{
+ struct max1363_state *st = iio_priv(indio_dev);
+ int ret = 0;
+
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
+ if (!indio_dev->buffer) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
+ &max1363_trigger_handler,
+ IRQF_ONESHOT,
+ indio_dev,
+ "%s_consumer%d",
+ st->client->name,
+ indio_dev->id);
+ if (indio_dev->pollfunc == NULL) {
+ ret = -ENOMEM;
+ goto error_deallocate_sw_rb;
+ }
+ /* Buffer functions - here trigger setup related */
+ indio_dev->setup_ops = &max1363_buffered_setup_ops;
+
+ /* Flag that polled buffering is possible */
+ indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
+
+ return 0;
+
+error_deallocate_sw_rb:
+ iio_kfifo_free(indio_dev->buffer);
+error_ret:
+ return ret;
+}
+
+static void max1363_buffer_cleanup(struct iio_dev *indio_dev)
+{
+ /* ensure that the trigger has been detached */
+ iio_dealloc_pollfunc(indio_dev->pollfunc);
+ iio_kfifo_free(indio_dev->buffer);
+}
+
static int __devinit max1363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct max1363_state *st;
struct iio_dev *indio_dev;
- struct regulator *reg;
-
- reg = regulator_get(&client->dev, "vcc");
- if (IS_ERR(reg)) {
- ret = PTR_ERR(reg);
- goto error_out;
- }
-
- ret = regulator_enable(reg);
- if (ret)
- goto error_put_reg;
indio_dev = iio_device_alloc(sizeof(struct max1363_state));
if (indio_dev == NULL) {
ret = -ENOMEM;
- goto error_disable_reg;
+ goto error_out;
}
+
ret = iio_map_array_register(indio_dev, client->dev.platform_data);
if (ret < 0)
goto error_free_device;
+
st = iio_priv(indio_dev);
- st->reg = reg;
+
+ st->reg = regulator_get(&client->dev, "vcc");
+ if (IS_ERR(st->reg)) {
+ ret = PTR_ERR(st->reg);
+ goto error_unregister_map;
+ }
+
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+
/* this is only used for device removal purposes */
i2c_set_clientdata(client, indio_dev);
@@ -1305,7 +1562,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
ret = max1363_alloc_scan_masks(indio_dev);
if (ret)
- goto error_unregister_map;
+ goto error_disable_reg;
/* Estabilish that the iio_dev is a child of the i2c device */
indio_dev->dev.parent = &client->dev;
@@ -1320,7 +1577,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
if (ret < 0)
goto error_free_available_scan_masks;
- ret = max1363_register_ring_funcs_and_init(indio_dev);
+ ret = max1363_register_buffered_funcs_and_init(indio_dev);
if (ret)
goto error_free_available_scan_masks;
@@ -1328,7 +1585,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
st->chip_info->channels,
st->chip_info->num_channels);
if (ret)
- goto error_cleanup_ring;
+ goto error_cleanup_buffer;
if (client->irq) {
ret = request_threaded_irq(st->client->irq,
@@ -1339,7 +1596,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
indio_dev);
if (ret)
- goto error_uninit_ring;
+ goto error_uninit_buffer;
}
ret = iio_device_register(indio_dev);
@@ -1349,20 +1606,20 @@ static int __devinit max1363_probe(struct i2c_client *client,
return 0;
error_free_irq:
free_irq(st->client->irq, indio_dev);
-error_uninit_ring:
+error_uninit_buffer:
iio_buffer_unregister(indio_dev);
-error_cleanup_ring:
- max1363_ring_cleanup(indio_dev);
+error_cleanup_buffer:
+ max1363_buffer_cleanup(indio_dev);
error_free_available_scan_masks:
kfree(indio_dev->available_scan_masks);
error_unregister_map:
iio_map_array_unregister(indio_dev, client->dev.platform_data);
-error_free_device:
- iio_device_free(indio_dev);
error_disable_reg:
- regulator_disable(reg);
+ regulator_disable(st->reg);
error_put_reg:
- regulator_put(reg);
+ regulator_put(st->reg);
+error_free_device:
+ iio_device_free(indio_dev);
error_out:
return ret;
}
@@ -1371,17 +1628,16 @@ static int __devexit max1363_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct max1363_state *st = iio_priv(indio_dev);
- struct regulator *reg = st->reg;
iio_device_unregister(indio_dev);
if (client->irq)
free_irq(st->client->irq, indio_dev);
iio_buffer_unregister(indio_dev);
- max1363_ring_cleanup(indio_dev);
+ max1363_buffer_cleanup(indio_dev);
kfree(indio_dev->available_scan_masks);
- if (!IS_ERR(reg)) {
- regulator_disable(reg);
- regulator_put(reg);
+ if (!IS_ERR(st->reg)) {
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
}
iio_map_array_unregister(indio_dev, client->dev.platform_data);
iio_device_free(indio_dev);
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c
new file mode 100644
index 000000000000..4d40e24f3721
--- /dev/null
+++ b/drivers/iio/buffer_cb.c
@@ -0,0 +1,113 @@
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/consumer.h>
+
+struct iio_cb_buffer {
+ struct iio_buffer buffer;
+ int (*cb)(u8 *data, void *private);
+ void *private;
+ struct iio_channel *channels;
+};
+
+static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data)
+{
+ struct iio_cb_buffer *cb_buff = container_of(buffer,
+ struct iio_cb_buffer,
+ buffer);
+
+ return cb_buff->cb(data, cb_buff->private);
+}
+
+static struct iio_buffer_access_funcs iio_cb_access = {
+ .store_to = &iio_buffer_cb_store_to,
+};
+
+struct iio_cb_buffer *iio_channel_get_all_cb(const char *name,
+ int (*cb)(u8 *data,
+ void *private),
+ void *private)
+{
+ int ret;
+ struct iio_cb_buffer *cb_buff;
+ struct iio_dev *indio_dev;
+ struct iio_channel *chan;
+
+ cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL);
+ if (cb_buff == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ cb_buff->private = private;
+ cb_buff->cb = cb;
+ cb_buff->buffer.access = &iio_cb_access;
+ INIT_LIST_HEAD(&cb_buff->buffer.demux_list);
+
+ cb_buff->channels = iio_channel_get_all(name);
+ if (IS_ERR(cb_buff->channels)) {
+ ret = PTR_ERR(cb_buff->channels);
+ goto error_free_cb_buff;
+ }
+
+ indio_dev = cb_buff->channels[0].indio_dev;
+ cb_buff->buffer.scan_mask
+ = kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long),
+ GFP_KERNEL);
+ if (cb_buff->buffer.scan_mask == NULL) {
+ ret = -ENOMEM;
+ goto error_release_channels;
+ }
+ chan = &cb_buff->channels[0];
+ while (chan->indio_dev) {
+ if (chan->indio_dev != indio_dev) {
+ ret = -EINVAL;
+ goto error_release_channels;
+ }
+ set_bit(chan->channel->scan_index,
+ cb_buff->buffer.scan_mask);
+ chan++;
+ }
+
+ return cb_buff;
+
+error_release_channels:
+ 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);
+
+int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff)
+{
+ return iio_update_buffers(cb_buff->channels[0].indio_dev,
+ &cb_buff->buffer,
+ NULL);
+}
+EXPORT_SYMBOL_GPL(iio_channel_start_all_cb);
+
+void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff)
+{
+ iio_update_buffers(cb_buff->channels[0].indio_dev,
+ NULL,
+ &cb_buff->buffer);
+}
+EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb);
+
+void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)
+{
+ iio_channel_release_all(cb_buff->channels);
+ kfree(cb_buff);
+}
+EXPORT_SYMBOL_GPL(iio_channel_release_all_cb);
+
+struct iio_channel
+*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer)
+{
+ return cb_buffer->channels;
+}
+EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels);
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 4c56ada51c39..02ef989b830d 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = {
/* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
{
- struct iio_buffer *buffer = indio_dev->buffer;
- int datum_sz;
-
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- if (!buffer) {
- dev_err(&indio_dev->dev, "Buffer == NULL\n");
- return;
- }
- datum_sz = buffer->access->get_bytes_per_datum(buffer);
- if (len > datum_sz) {
- dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
- datum_sz);
- return;
- }
- iio_push_to_buffer(buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
}
/* Callback handler to send event after all samples are received and captured */
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 722a83fd8d85..aaadd32f9f0d 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = {
[IIO_LE] = "le",
};
+static bool iio_buffer_is_active(struct iio_dev *indio_dev,
+ struct iio_buffer *buf)
+{
+ struct list_head *p;
+
+ list_for_each(p, &indio_dev->buffer_list)
+ if (p == &buf->buffer_list)
+ return true;
+
+ return false;
+}
+
/**
* iio_buffer_read_first_n_outer() - chrdev read for buffer access
*
@@ -134,7 +146,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
if (ret < 0)
return ret;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_enabled(indio_dev)) {
+ if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
ret = -EBUSY;
goto error_ret;
}
@@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
return ret;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_enabled(indio_dev)) {
+ if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
ret = -EBUSY;
goto error_ret;
}
indio_dev->buffer->scan_timestamp = state;
- indio_dev->scan_timestamp = state;
error_ret:
mutex_unlock(&indio_dev->mlock);
@@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
return len;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_enabled(indio_dev)) {
+ if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
ret = -EBUSY;
} else {
if (buffer->access->set_length)
@@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev,
}
EXPORT_SYMBOL(iio_buffer_write_length);
-ssize_t iio_buffer_store_enable(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- int ret;
- bool requested_state, current_state;
- int previous_mode;
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
-
- mutex_lock(&indio_dev->mlock);
- previous_mode = indio_dev->currentmode;
- requested_state = !(buf[0] == '0');
- current_state = iio_buffer_enabled(indio_dev);
- if (current_state == requested_state) {
- printk(KERN_INFO "iio-buffer, current state requested again\n");
- goto done;
- }
- if (requested_state) {
- if (indio_dev->setup_ops->preenable) {
- ret = indio_dev->setup_ops->preenable(indio_dev);
- if (ret) {
- printk(KERN_ERR
- "Buffer not started: "
- "buffer preenable failed\n");
- goto error_ret;
- }
- }
- if (buffer->access->request_update) {
- ret = buffer->access->request_update(buffer);
- if (ret) {
- printk(KERN_INFO
- "Buffer not started: "
- "buffer parameter update failed\n");
- goto error_ret;
- }
- }
- /* Definitely possible for devices to support both of these. */
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
- if (!indio_dev->trig) {
- printk(KERN_INFO
- "Buffer not started: no trigger\n");
- ret = -EINVAL;
- goto error_ret;
- }
- indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
- } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE)
- indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
- else { /* should never be reached */
- ret = -EINVAL;
- goto error_ret;
- }
-
- if (indio_dev->setup_ops->postenable) {
- ret = indio_dev->setup_ops->postenable(indio_dev);
- if (ret) {
- printk(KERN_INFO
- "Buffer not started: "
- "postenable failed\n");
- indio_dev->currentmode = previous_mode;
- if (indio_dev->setup_ops->postdisable)
- indio_dev->setup_ops->
- postdisable(indio_dev);
- goto error_ret;
- }
- }
- } else {
- if (indio_dev->setup_ops->predisable) {
- ret = indio_dev->setup_ops->predisable(indio_dev);
- if (ret)
- goto error_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;
- }
- }
-done:
- mutex_unlock(&indio_dev->mlock);
- return len;
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-EXPORT_SYMBOL(iio_buffer_store_enable);
-
ssize_t iio_buffer_show_enable(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
+ return sprintf(buf, "%d\n",
+ iio_buffer_is_active(indio_dev,
+ indio_dev->buffer));
}
EXPORT_SYMBOL(iio_buffer_show_enable);
@@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
return bytes;
}
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+int iio_update_buffers(struct iio_dev *indio_dev,
+ struct iio_buffer *insert_buffer,
+ struct iio_buffer *remove_buffer)
{
- struct iio_buffer *buffer = indio_dev->buffer;
- dev_dbg(&indio_dev->dev, "%s\n", __func__);
+ int ret;
+ int success = 0;
+ struct iio_buffer *buffer;
+ unsigned long *compound_mask;
+ const unsigned long *old_mask;
- /* How much space will the demuxed element take? */
- indio_dev->scan_bytes =
- iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
- buffer->scan_timestamp);
- buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes);
+ /* Wind down existing buffers - iff there are any */
+ if (!list_empty(&indio_dev->buffer_list)) {
+ if (indio_dev->setup_ops->predisable) {
+ ret = indio_dev->setup_ops->predisable(indio_dev);
+ if (ret)
+ goto error_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;
+ }
+ }
+ /* Keep a copy of current setup to allow roll back */
+ old_mask = indio_dev->active_scan_mask;
+ if (!indio_dev->available_scan_masks)
+ indio_dev->active_scan_mask = NULL;
+
+ if (remove_buffer)
+ list_del(&remove_buffer->buffer_list);
+ if (insert_buffer)
+ list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list);
+
+ /* If no buffers in list, we are done */
+ if (list_empty(&indio_dev->buffer_list)) {
+ indio_dev->currentmode = INDIO_DIRECT_MODE;
+ if (indio_dev->available_scan_masks == NULL)
+ kfree(old_mask);
+ return 0;
+ }
/* What scan mask do we actually have ?*/
- if (indio_dev->available_scan_masks)
+ compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
+ sizeof(long), GFP_KERNEL);
+ if (compound_mask == NULL) {
+ if (indio_dev->available_scan_masks == NULL)
+ kfree(old_mask);
+ return -ENOMEM;
+ }
+ indio_dev->scan_timestamp = 0;
+
+ list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+ bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
+ indio_dev->masklength);
+ indio_dev->scan_timestamp |= buffer->scan_timestamp;
+ }
+ if (indio_dev->available_scan_masks) {
indio_dev->active_scan_mask =
iio_scan_mask_match(indio_dev->available_scan_masks,
indio_dev->masklength,
- buffer->scan_mask);
- else
- indio_dev->active_scan_mask = buffer->scan_mask;
-
- if (indio_dev->active_scan_mask == NULL)
- return -EINVAL;
+ compound_mask);
+ if (indio_dev->active_scan_mask == NULL) {
+ /*
+ * Roll back.
+ * Note can only occur when adding a buffer.
+ */
+ list_del(&insert_buffer->buffer_list);
+ indio_dev->active_scan_mask = old_mask;
+ success = -EINVAL;
+ }
+ } else {
+ indio_dev->active_scan_mask = compound_mask;
+ }
iio_update_demux(indio_dev);
- if (indio_dev->info->update_scan_mode)
- return indio_dev->info
+ /* Wind up again */
+ if (indio_dev->setup_ops->preenable) {
+ ret = indio_dev->setup_ops->preenable(indio_dev);
+ if (ret) {
+ printk(KERN_ERR
+ "Buffer not started:"
+ "buffer preenable failed\n");
+ goto error_remove_inserted;
+ }
+ }
+ indio_dev->scan_bytes =
+ 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)
+ if (buffer->access->request_update) {
+ ret = buffer->access->request_update(buffer);
+ if (ret) {
+ printk(KERN_INFO
+ "Buffer not started:"
+ "buffer parameter update failed\n");
+ goto error_run_postdisable;
+ }
+ }
+ if (indio_dev->info->update_scan_mode) {
+ ret = indio_dev->info
->update_scan_mode(indio_dev,
indio_dev->active_scan_mask);
+ if (ret < 0) {
+ printk(KERN_INFO "update scan mode failed\n");
+ goto error_run_postdisable;
+ }
+ }
+ /* Definitely possible for devices to support both of these.*/
+ if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
+ if (!indio_dev->trig) {
+ printk(KERN_INFO "Buffer not started: no trigger\n");
+ ret = -EINVAL;
+ /* Can only occur on first buffer */
+ goto error_run_postdisable;
+ }
+ indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
+ } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) {
+ indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
+ } else { /* should never be reached */
+ ret = -EINVAL;
+ goto error_run_postdisable;
+ }
+
+ if (indio_dev->setup_ops->postenable) {
+ ret = indio_dev->setup_ops->postenable(indio_dev);
+ if (ret) {
+ printk(KERN_INFO
+ "Buffer not started: postenable failed\n");
+ indio_dev->currentmode = INDIO_DIRECT_MODE;
+ if (indio_dev->setup_ops->postdisable)
+ indio_dev->setup_ops->postdisable(indio_dev);
+ goto error_disable_all_buffers;
+ }
+ }
+
+ if (indio_dev->available_scan_masks)
+ kfree(compound_mask);
+ else
+ kfree(old_mask);
+
+ return success;
+
+error_disable_all_buffers:
+ indio_dev->currentmode = INDIO_DIRECT_MODE;
+error_run_postdisable:
+ if (indio_dev->setup_ops->postdisable)
+ indio_dev->setup_ops->postdisable(indio_dev);
+error_remove_inserted:
+
+ if (insert_buffer)
+ list_del(&insert_buffer->buffer_list);
+ indio_dev->active_scan_mask = old_mask;
+ kfree(compound_mask);
+error_ret:
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iio_update_buffers);
+
+ssize_t iio_buffer_store_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ int ret;
+ bool requested_state;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *pbuf = indio_dev->buffer;
+ bool inlist;
+
+ ret = strtobool(buf, &requested_state);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&indio_dev->mlock);
+
+ /* Find out if it is in the list */
+ inlist = iio_buffer_is_active(indio_dev, pbuf);
+ /* Already in desired state */
+ if (inlist == requested_state)
+ goto done;
+
+ if (requested_state)
+ ret = iio_update_buffers(indio_dev,
+ indio_dev->buffer, NULL);
+ else
+ ret = iio_update_buffers(indio_dev,
+ NULL, indio_dev->buffer);
+
+ if (ret < 0)
+ goto done;
+done:
+ mutex_unlock(&indio_dev->mlock);
+ return (ret < 0) ? ret : len;
+}
+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);
@@ -599,7 +707,11 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
* iio_scan_mask_set() - set particular bit in the scan mask
* @buffer: the buffer whose scan mask we are interested in
* @bit: the bit to be set.
- **/
+ *
+ * Note that at this point we have no way of knowing what other
+ * buffers might request, hence this code only verifies that the
+ * individual buffers request is plausible.
+ */
int iio_scan_mask_set(struct iio_dev *indio_dev,
struct iio_buffer *buffer, int bit)
{
@@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer,
return buffer->demux_bounce;
}
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
+static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
{
unsigned char *dataout = iio_demux(buffer, data);
return buffer->access->store_to(buffer, dataout);
}
-EXPORT_SYMBOL_GPL(iio_push_to_buffer);
static void iio_buffer_demux_free(struct iio_buffer *buffer)
{
@@ -699,10 +810,26 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
}
}
-int iio_update_demux(struct iio_dev *indio_dev)
+
+int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data)
+{
+ int ret;
+ struct iio_buffer *buf;
+
+ list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) {
+ ret = iio_push_to_buffer(buf, data);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iio_push_to_buffers);
+
+static int iio_buffer_update_demux(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer)
{
const struct iio_chan_spec *ch;
- struct iio_buffer *buffer = indio_dev->buffer;
int ret, in_ind = -1, out_ind, length;
unsigned in_loc = 0, out_loc = 0;
struct iio_demux_table *p;
@@ -787,4 +914,23 @@ error_clear_mux_table:
return ret;
}
+
+int iio_update_demux(struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer;
+ int ret;
+
+ list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+ ret = iio_buffer_update_demux(indio_dev, buffer);
+ if (ret < 0)
+ goto error_clear_mux_table;
+ }
+ return 0;
+
+error_clear_mux_table:
+ list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+ iio_buffer_demux_free(buffer);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(iio_update_demux);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index cd700368eed0..060a4045be85 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -856,6 +856,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
return NULL;
}
dev_set_name(&dev->dev, "iio:device%d", dev->id);
+ INIT_LIST_HEAD(&dev->buffer_list);
}
return dev;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index b394621d362c..d55e98fb300e 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -203,6 +203,7 @@ struct iio_channel *iio_channel_get_all(const char *name)
if (name && strcmp(name, c->map->consumer_dev_name) != 0)
continue;
chans[mapind].indio_dev = c->indio_dev;
+ chans[mapind].data = c->map->consumer_data;
chans[mapind].channel =
iio_chan_spec_from_name(chans[mapind].indio_dev,
c->map->adc_channel_label);
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 164b62b91a4b..36d210a06b28 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adjd_s311_data *data = iio_priv(indio_dev);
- struct iio_buffer *buffer = indio_dev->buffer;
s64 time_ns = iio_get_time_ns();
int len = 0;
int i, j = 0;
@@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
= time_ns;
- iio_push_to_buffer(buffer, (u8 *)data->buffer);
+ iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 96e3691e42c4..8e1f69844eea 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -176,21 +176,8 @@ static const struct iio_info als_info = {
/* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
{
- struct iio_buffer *buffer = indio_dev->buffer;
- int datum_sz;
-
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- if (!buffer) {
- dev_err(&indio_dev->dev, "Buffer == NULL\n");
- return;
- }
- datum_sz = buffer->access->get_bytes_per_datum(buffer);
- if (len > datum_sz) {
- dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
- datum_sz);
- return;
- }
- iio_push_to_buffer(buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
}
/* Callback handler to send event after all samples are received and captured */
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index c4f0d274f577..d1b5fb74b9bf 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = {
/* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
{
- struct iio_buffer *buffer = indio_dev->buffer;
- int datum_sz;
-
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- if (!buffer) {
- dev_err(&indio_dev->dev, "Buffer == NULL\n");
- return;
- }
- datum_sz = buffer->access->get_bytes_per_datum(buffer);
- if (len > datum_sz) {
- dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
- datum_sz);
- return;
- }
- iio_push_to_buffer(buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
}
/* Callback handler to send event after all samples are received and captured */
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
index 97c09f0c26ae..e14ca60092a2 100644
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ b/drivers/staging/iio/accel/adis16201_ring.c
@@ -82,7 +82,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
index 7507e1a04591..eba2e285c84a 100644
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ b/drivers/staging/iio/accel/adis16203_ring.c
@@ -81,7 +81,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
index 4c976bec986b..3611a13836c9 100644
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ b/drivers/staging/iio/accel/adis16204_ring.c
@@ -78,7 +78,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index f939e29d6c82..6af9a5dbc709 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -78,7 +78,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index caff8e25e0a2..e2ac8a8c8107 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -76,7 +76,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 246352716537..bc38651c315e 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -154,7 +154,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
= pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 71a515d0a6de..0177f1e02300 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -68,19 +68,6 @@ config AD799X_RING_BUFFER
Say yes here to include ring buffer support in the AD799X
ADC driver.
-config AD7887
- tristate "Analog Devices AD7887 ADC driver"
- depends on SPI
- select IIO_BUFFER
- select IIO_TRIGGERED_BUFFER
- help
- Say yes here to build support for Analog Devices
- AD7887 SPI analog to digital converter (ADC).
- If unsure, say N (but it's safe to say "Y").
-
- To compile this driver as a module, choose M here: the
- module will be called ad7887.
-
config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
@@ -143,30 +130,6 @@ config AD7280
To compile this driver as a module, choose M here: the
module will be called ad7280a
-config MAX1363
- tristate "Maxim max1363 ADC driver"
- depends on I2C
- select IIO_TRIGGER if IIO_BUFFER
- select MAX1363_RING_BUFFER
- help
- Say yes here to build support for many Maxim i2c analog to digital
- converters (ADC). (max1361, max1362, max1363, max1364, max1036,
- max1037, max1038, max1039, max1136, max1136, max1137, max1138,
- max1139, max1236, max1237, max11238, max1239, max11600, max11601,
- max11602, max11603, max11604, max11605, max11606, max11607,
- max11608, max11609, max11610, max11611, max11612, max11613,
- max11614, max11615, max11616, max11617, max11644, max11645,
- max11646, max11647) Provides direct access via sysfs.
-
-config MAX1363_RING_BUFFER
- bool "Maxim max1363: use ring buffer"
- depends on MAX1363
- select IIO_BUFFER
- select IIO_SW_RING
- help
- Say yes here to include ring buffer support in the MAX1363
- ADC driver.
-
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index ff561c591d66..12b4bd32437f 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -2,11 +2,6 @@
# Makefile for industrial I/O ADC drivers
#
-max1363-y := max1363_core.o
-max1363-y += max1363_ring.o
-
-obj-$(CONFIG_MAX1363) += max1363.o
-
ad7606-y := ad7606_core.o
ad7606-$(CONFIG_IIO_BUFFER) += ad7606_ring.o
ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
@@ -17,10 +12,6 @@ ad799x-y := ad799x_core.o
ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
obj-$(CONFIG_AD799X) += ad799x.o
-ad7887-y := ad7887_core.o
-ad7887-$(CONFIG_IIO_BUFFER) += ad7887_ring.o
-obj-$(CONFIG_AD7887) += ad7887.o
-
ad7298-y := ad7298_core.o
ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o
obj-$(CONFIG_AD7298) += ad7298.o
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
index c2906a85fedb..b3dd514b9627 100644
--- a/drivers/staging/iio/adc/ad7298_ring.c
+++ b/drivers/staging/iio/adc/ad7298_ring.c
@@ -93,7 +93,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
indio_dev->masklength); i++)
buf[i] = be16_to_cpu(st->rx_buf[i]);
- iio_push_to_buffer(indio_dev->buffer, (u8 *)buf);
+ iio_push_to_buffers(indio_dev, (u8 *)buf);
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index ba04d0ffd4f4..2b25cb07fe41 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -83,7 +83,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
if (indio_dev->scan_timestamp)
*((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns;
- iio_push_to_buffer(indio_dev->buffer, buf);
+ iio_push_to_buffers(indio_dev, buf);
done:
gpio_set_value(st->pdata->gpio_convst, 0);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h
deleted file mode 100644
index 2e09e54fc9c5..000000000000
--- a/drivers/staging/iio/adc/ad7887.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * AD7887 SPI ADC driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-#ifndef IIO_ADC_AD7887_H_
-#define IIO_ADC_AD7887_H_
-
-#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */
-#define AD7887_DUAL (1 << 4) /* dual-channel mode */
-#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */
-#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */
-#define AD7887_PM_MODE1 (0) /* CS based shutdown */
-#define AD7887_PM_MODE2 (1) /* full on */
-#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */
-#define AD7887_PM_MODE4 (3) /* standby mode */
-
-enum ad7887_channels {
- AD7887_CH0,
- AD7887_CH0_CH1,
- AD7887_CH1,
-};
-
-#define RES_MASK(bits) ((1 << (bits)) - 1) /* TODO: move this into a common header */
-
-/*
- * TODO: struct ad7887_platform_data needs to go into include/linux/iio
- */
-
-struct ad7887_platform_data {
- /* External Vref voltage applied */
- u16 vref_mv;
- /*
- * AD7887:
- * In single channel mode en_dual = flase, AIN1/Vref pins assumes its
- * Vref function. In dual channel mode en_dual = true, AIN1 becomes the
- * second input channel, and Vref is internally connected to Vdd.
- */
- bool en_dual;
- /*
- * AD7887:
- * use_onchip_ref = true, the Vref is internally connected to the 2.500V
- * Voltage reference. If use_onchip_ref = false, the reference voltage
- * is supplied by AIN1/Vref
- */
- bool use_onchip_ref;
-};
-
-/**
- * struct ad7887_chip_info - chip specifc information
- * @int_vref_mv: the internal reference voltage
- * @channel: channel specification
- */
-
-struct ad7887_chip_info {
- u16 int_vref_mv;
- struct iio_chan_spec channel[3];
-};
-
-struct ad7887_state {
- struct spi_device *spi;
- const struct ad7887_chip_info *chip_info;
- struct regulator *reg;
- u16 int_vref_mv;
- struct spi_transfer xfer[4];
- struct spi_message msg[3];
- struct spi_message *ring_msg;
- unsigned char tx_cmd_buf[8];
-
- /*
- * DMA (thus cache coherency maintenance) requires the
- * transfer buffers to live in their own cache lines.
- */
-
- unsigned char data[4] ____cacheline_aligned;
-};
-
-enum ad7887_supported_device_ids {
- ID_AD7887
-};
-
-#ifdef CONFIG_IIO_BUFFER
-int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void ad7887_ring_cleanup(struct iio_dev *indio_dev);
-#else /* CONFIG_IIO_BUFFER */
-
-static inline int
-ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline void ad7887_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_IIO_BUFFER */
-#endif /* IIO_ADC_AD7887_H_ */
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
deleted file mode 100644
index b39923bbeedc..000000000000
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2010-2012 Analog Devices Inc.
- * Copyright (C) 2008 Jonathan Cameron
- *
- * Licensed under the GPL-2.
- *
- * ad7887_ring.c
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
-
-#include "ad7887.h"
-
-/**
- * ad7887_ring_preenable() setup the parameters of the ring before enabling
- *
- * The complex nature of the setting of the nuber of bytes per datum is due
- * to this driver currently ensuring that the timestamp is stored at an 8
- * byte boundary.
- **/
-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) {
- case (1 << 0):
- st->ring_msg = &st->msg[AD7887_CH0];
- break;
- case (1 << 1):
- st->ring_msg = &st->msg[AD7887_CH1];
- /* Dummy read: push CH1 setting down to hardware */
- spi_sync(st->spi, st->ring_msg);
- break;
- case ((1 << 1) | (1 << 0)):
- st->ring_msg = &st->msg[AD7887_CH0_CH1];
- break;
- }
-
- return 0;
-}
-
-static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
-{
- struct ad7887_state *st = iio_priv(indio_dev);
-
- /* dummy read: restore default CH0 settin */
- return spi_sync(st->spi, &st->msg[AD7887_CH0]);
-}
-
-/**
- * ad7887_trigger_handler() bh of trigger launched polling to ring buffer
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- **/
-static irqreturn_t ad7887_trigger_handler(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- struct ad7887_state *st = iio_priv(indio_dev);
- s64 time_ns;
- __u8 *buf;
- int b_sent;
-
- unsigned int bytes = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) *
- st->chip_info->channel[0].scan_type.storagebits / 8;
-
- buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
- if (buf == NULL)
- goto done;
-
- b_sent = spi_sync(st->spi, st->ring_msg);
- if (b_sent)
- goto done;
-
- time_ns = iio_get_time_ns();
-
- memcpy(buf, st->data, bytes);
- if (indio_dev->scan_timestamp)
- memcpy(buf + indio_dev->scan_bytes - sizeof(s64),
- &time_ns, sizeof(time_ns));
-
- iio_push_to_buffer(indio_dev->buffer, buf);
-done:
- kfree(buf);
- iio_trigger_notify_done(indio_dev->trig);
-
- return IRQ_HANDLED;
-}
-
-static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
- .preenable = &ad7887_ring_preenable,
- .postenable = &iio_triggered_buffer_postenable,
- .predisable = &iio_triggered_buffer_predisable,
- .postdisable = &ad7887_ring_postdisable,
-};
-
-int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
- return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- &ad7887_trigger_handler, &ad7887_ring_setup_ops);
-}
-
-void ad7887_ring_cleanup(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
-}
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 86026d9b20bc..2c5f38475a8e 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -77,7 +77,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns));
- iio_push_to_buffer(indio_dev->buffer, rxbuf);
+ iio_push_to_buffers(indio_dev, rxbuf);
done:
kfree(rxbuf);
out:
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
deleted file mode 100644
index c746918683f1..000000000000
--- a/drivers/staging/iio/adc/max1363.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef _MAX1363_H_
-#define _MAX1363_H_
-
-#define MAX1363_SETUP_BYTE(a) ((a) | 0x80)
-
-/* There is a fair bit more defined here than currently
- * used, but the intention is to support everything these
- * chips do in the long run */
-
-/* see data sheets */
-/* max1363 and max1236, max1237, max1238, max1239 */
-#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00
-#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20
-#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40
-#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60
-#define MAX1363_SETUP_POWER_UP_INT_REF 0x10
-#define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00
-
-/* think about includeing max11600 etc - more settings */
-#define MAX1363_SETUP_EXT_CLOCK 0x08
-#define MAX1363_SETUP_INT_CLOCK 0x00
-#define MAX1363_SETUP_UNIPOLAR 0x00
-#define MAX1363_SETUP_BIPOLAR 0x04
-#define MAX1363_SETUP_RESET 0x00
-#define MAX1363_SETUP_NORESET 0x02
-/* max1363 only - though don't care on others.
- * For now monitor modes are not implemented as the relevant
- * line is not connected on my test board.
- * The definitions are here as I intend to add this soon.
- */
-#define MAX1363_SETUP_MONITOR_SETUP 0x01
-
-/* Specific to the max1363 */
-#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4))
-#define MAX1363_MON_INT_ENABLE 0x01
-
-/* defined for readability reasons */
-/* All chips */
-#define MAX1363_CONFIG_BYTE(a) ((a))
-
-#define MAX1363_CONFIG_SE 0x01
-#define MAX1363_CONFIG_DE 0x00
-#define MAX1363_CONFIG_SCAN_TO_CS 0x00
-#define MAX1363_CONFIG_SCAN_SINGLE_8 0x20
-#define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40
-#define MAX1363_CONFIG_SCAN_SINGLE_1 0x60
-/* max123{6-9} only */
-#define MAX1236_SCAN_MID_TO_CHANNEL 0x40
-
-/* max1363 only - merely part of channel selects or don't care for others*/
-#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18
-
-#define MAX1363_CHANNEL_SEL(a) ((a) << 1)
-
-/* max1363 strictly 0x06 - but doesn't matter */
-#define MAX1363_CHANNEL_SEL_MASK 0x1E
-#define MAX1363_SCAN_MASK 0x60
-#define MAX1363_SE_DE_MASK 0x01
-
-#define MAX1363_MAX_CHANNELS 25
-/**
- * struct max1363_mode - scan mode information
- * @conf: The corresponding value of the configuration register
- * @modemask: Bit mask corresponding to channels enabled in this mode
- */
-struct max1363_mode {
- int8_t conf;
- DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS);
-};
-
-/* This must be maintained along side the max1363_mode_table in max1363_core */
-enum max1363_modes {
- /* Single read of a single channel */
- _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
- /* Differential single read */
- d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
- d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
- /* Scan to channel and mid to channel where overlapping */
- s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6,
- s6to7, s0to7, s6to8, s0to8, s6to9,
- s0to9, s6to10, s0to10, s6to11, s0to11,
- /* Differential scan to channel and mid to channel where overlapping */
- d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9,
- d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2,
- d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8,
- d7m6to11m10, d1m0to11m10,
-};
-
-/**
- * struct max1363_chip_info - chip specifc information
- * @name: indentification string for chip
- * @bits: accuracy of the adc in bits
- * @int_vref_mv: the internal reference voltage
- * @info: iio core function callbacks structure
- * @mode_list: array of available scan modes
- * @num_modes: the number of scan modes available
- * @default_mode: the scan mode in which the chip starts up
- * @channel: channel specification
- * @num_channels: number of channels
- */
-struct max1363_chip_info {
- const struct iio_info *info;
- const struct iio_chan_spec *channels;
- int num_channels;
- const enum max1363_modes *mode_list;
- enum max1363_modes default_mode;
- u16 int_vref_mv;
- u8 num_modes;
- u8 bits;
-};
-
-/**
- * struct max1363_state - driver instance specific data
- * @client: i2c_client
- * @setupbyte: cache of current device setup byte
- * @configbyte: cache of current device config byte
- * @chip_info: chip model specific constants, available modes etc
- * @current_mode: the scan mode of this chip
- * @requestedmask: a valid requested set of channels
- * @reg: supply regulator
- * @monitor_on: whether monitor mode is enabled
- * @monitor_speed: parameter corresponding to device monitor speed setting
- * @mask_high: bitmask for enabled high thresholds
- * @mask_low: bitmask for enabled low thresholds
- * @thresh_high: high threshold values
- * @thresh_low: low threshold values
- */
-struct max1363_state {
- struct i2c_client *client;
- u8 setupbyte;
- u8 configbyte;
- const struct max1363_chip_info *chip_info;
- const struct max1363_mode *current_mode;
- u32 requestedmask;
- struct regulator *reg;
-
- /* Using monitor modes and buffer at the same time is
- currently not supported */
- bool monitor_on;
- unsigned int monitor_speed:3;
- u8 mask_high;
- u8 mask_low;
- /* 4x unipolar first then the fours bipolar ones */
- s16 thresh_high[8];
- s16 thresh_low[8];
-};
-
-const struct max1363_mode
-*max1363_match_mode(const unsigned long *mask,
- const struct max1363_chip_info *ci);
-
-int max1363_set_scan_mode(struct max1363_state *st);
-
-#ifdef CONFIG_MAX1363_RING_BUFFER
-int max1363_update_scan_mode(struct iio_dev *indio_dev,
- const unsigned long *scan_mask);
-int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void max1363_ring_cleanup(struct iio_dev *indio_dev);
-
-#else /* CONFIG_MAX1363_RING_BUFFER */
-int max1363_update_scan_mode(struct iio_dev *indio_dev,
- const long *scan_mask)
-{
- return 0;
-}
-
-static inline int
-max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline void max1363_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_MAX1363_RING_BUFFER */
-#endif /* _MAX1363_H_ */
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
deleted file mode 100644
index 5f74f3b7671a..000000000000
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2008 Jonathan Cameron
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * max1363_ring.c
- */
-
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/bitops.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-
-#include "max1363.h"
-
-int max1363_update_scan_mode(struct iio_dev *indio_dev,
- const unsigned long *scan_mask)
-{
- struct max1363_state *st = iio_priv(indio_dev);
-
- /*
- * Need to figure out the current mode based upon the requested
- * scan mask in iio_dev
- */
- st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
- if (!st->current_mode)
- return -EINVAL;
- max1363_set_scan_mode(st);
- return 0;
-}
-
-static irqreturn_t max1363_trigger_handler(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- struct max1363_state *st = iio_priv(indio_dev);
- s64 time_ns;
- __u8 *rxbuf;
- int b_sent;
- size_t d_size;
- unsigned long numvals = bitmap_weight(st->current_mode->modemask,
- MAX1363_MAX_CHANNELS);
-
- /* Ensure the timestamp is 8 byte aligned */
- if (st->chip_info->bits != 8)
- d_size = numvals*2;
- else
- d_size = numvals;
- if (indio_dev->scan_timestamp) {
- d_size += sizeof(s64);
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
- }
- /* Monitor mode prevents reading. Whilst not currently implemented
- * might as well have this test in here in the meantime as it does
- * no harm.
- */
- if (numvals == 0)
- goto done;
-
- rxbuf = kmalloc(d_size, GFP_KERNEL);
- if (rxbuf == NULL)
- goto done;
- if (st->chip_info->bits != 8)
- b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
- else
- b_sent = i2c_master_recv(st->client, rxbuf, numvals);
- if (b_sent < 0)
- goto done_free;
-
- time_ns = iio_get_time_ns();
-
- if (indio_dev->scan_timestamp)
- memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
- iio_push_to_buffer(indio_dev->buffer, rxbuf);
-
-done_free:
- kfree(rxbuf);
-done:
- iio_trigger_notify_done(indio_dev->trig);
-
- return IRQ_HANDLED;
-}
-
-static const struct iio_buffer_setup_ops max1363_ring_setup_ops = {
- .postenable = &iio_triggered_buffer_postenable,
- .preenable = &iio_sw_buffer_preenable,
- .predisable = &iio_triggered_buffer_predisable,
-};
-
-int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
- struct max1363_state *st = iio_priv(indio_dev);
- int ret = 0;
-
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
- if (!indio_dev->buffer) {
- ret = -ENOMEM;
- goto error_ret;
- }
- indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
- &max1363_trigger_handler,
- IRQF_ONESHOT,
- indio_dev,
- "%s_consumer%d",
- st->client->name,
- indio_dev->id);
- if (indio_dev->pollfunc == NULL) {
- ret = -ENOMEM;
- goto error_deallocate_sw_rb;
- }
- /* Ring buffer functions - here trigger setup related */
- indio_dev->setup_ops = &max1363_ring_setup_ops;
-
- /* Flag that polled ring buffering is possible */
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-
- return 0;
-
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
-error_ret:
- return ret;
-}
-
-void max1363_ring_cleanup(struct iio_dev *indio_dev)
-{
- /* ensure that the trigger has been detached */
- iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
-}
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index df5bba284b73..3b467d8c5882 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -237,7 +237,6 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *iio = pf->indio_dev;
struct mxs_lradc *lradc = iio_priv(iio);
- struct iio_buffer *buffer = iio->buffer;
const uint32_t chan_value = LRADC_CH_ACCUMULATE |
((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
int i, j = 0;
@@ -256,7 +255,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
*timestamp = pf->timestamp;
}
- iio_push_to_buffer(buffer, (u8 *)lradc->buffer);
+ iio_push_to_buffers(iio, (u8 *)lradc->buffer);
iio_trigger_notify_done(iio->trig);
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index e294cb49736d..d6c48f850a9e 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -81,7 +81,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
done:
diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c
index 697d9700db2f..dee16f0e7570 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -46,7 +46,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
- struct iio_buffer *buffer = indio_dev->buffer;
int len = 0;
u16 *data;
@@ -76,7 +75,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength);
i++, j++) {
- j = find_next_bit(buffer->scan_mask,
+ j = find_next_bit(indio_dev->active_scan_mask,
indio_dev->masklength, j);
/* random access read from the 'device' */
data[i] = fakedata[j];
@@ -87,7 +86,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
if (indio_dev->scan_timestamp)
*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
= iio_get_time_ns();
- iio_push_to_buffer(buffer, (u8 *)data);
+ iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data);
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index de21d47f33e9..b1fef147d5b5 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -647,7 +647,6 @@ static void ad5933_work(struct work_struct *work)
struct ad5933_state *st = container_of(work,
struct ad5933_state, work.work);
struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
- struct iio_buffer *ring = indio_dev->buffer;
signed short buf[2];
unsigned char status;
@@ -677,8 +676,7 @@ static void ad5933_work(struct work_struct *work)
} else {
buf[0] = be16_to_cpu(buf[0]);
}
- /* save datum to the ring */
- iio_push_to_buffer(ring, (u8 *)buf);
+ iio_push_to_buffers(indio_dev, (u8 *)buf);
} else {
/* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies);
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index 260bdd1a4681..d46c1e38cf7b 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -114,7 +114,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16400_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
int i = 0, j, ret = 0;
s16 *data;
@@ -148,9 +147,9 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
}
}
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
- iio_push_to_buffer(ring, (u8 *) data);
+ iio_push_to_buffers(indio_dev, (u8 *) data);
done:
kfree(data);
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index 9e49baccf660..4552a4c7fe33 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -73,7 +73,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp)
dat64[1] = pf->timestamp;
- iio_push_to_buffer(indio_dev->buffer, (u8 *)dat64);
+ iio_push_to_buffers(indio_dev, (u8 *)dat64);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index c629b3a1d9a9..027040569180 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -66,7 +66,8 @@ struct iio_buffer_access_funcs {
* @stufftoread: [INTERN] flag to indicate new data.
* @demux_list: [INTERN] list of operations required to demux the scan.
* @demux_bounce: [INTERN] buffer for doing gather from incoming scan.
- **/
+ * @buffer_list: [INTERN] entry in the devices list of current buffers.
+ */
struct iio_buffer {
int length;
int bytes_per_datum;
@@ -81,9 +82,22 @@ struct iio_buffer {
const struct attribute_group *attrs;
struct list_head demux_list;
unsigned char *demux_bounce;
+ struct list_head buffer_list;
};
/**
+ * iio_update_buffers() - add or remove buffer from active list
+ * @indio_dev: device to add buffer to
+ * @insert_buffer: buffer to insert
+ * @remove_buffer: buffer_to_remove
+ *
+ * Note this will tear down the all buffering and build it up again
+ */
+int iio_update_buffers(struct iio_dev *indio_dev,
+ struct iio_buffer *insert_buffer,
+ struct iio_buffer *remove_buffer);
+
+/**
* iio_buffer_init() - Initialize the buffer structure
* @buffer: buffer to be initialized
**/
@@ -115,11 +129,11 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
struct iio_buffer *buffer, int bit);
/**
- * iio_push_to_buffer() - push to a registered buffer.
- * @buffer: IIO buffer structure for device
- * @data: the data to push to the buffer
+ * iio_push_to_buffers() - push to a registered buffer.
+ * @indio_dev: iio_dev structure for device.
+ * @data: Full scan.
*/
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data);
+int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data);
int iio_update_demux(struct iio_dev *indio_dev);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index e875bcf0478f..126c0a9375f2 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -18,10 +18,12 @@ struct iio_chan_spec;
* struct iio_channel - everything needed for a consumer to use a channel
* @indio_dev: Device on which the channel exists.
* @channel: Full description of the channel.
+ * @data: Data about the channel used by consumer.
*/
struct iio_channel {
struct iio_dev *indio_dev;
const struct iio_chan_spec *channel;
+ void *data;
};
/**
@@ -59,6 +61,52 @@ struct iio_channel *iio_channel_get_all(const char *name);
*/
void iio_channel_release_all(struct iio_channel *chan);
+struct iio_cb_buffer;
+/**
+ * iio_channel_get_all_cb() - register callback for triggered capture
+ * @name: Name of client device.
+ * @cb: Callback function.
+ * @private: Private data passed to callback.
+ *
+ * NB right now we have no ability to mux data from multiple devices.
+ * So if the channels requested come from different devices this will
+ * fail.
+ */
+struct iio_cb_buffer *iio_channel_get_all_cb(const char *name,
+ int (*cb)(u8 *data,
+ void *private),
+ void *private);
+/**
+ * iio_channel_release_all_cb() - release and unregister the callback.
+ * @cb_buffer: The callback buffer that was allocated.
+ */
+void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buffer);
+
+/**
+ * iio_channel_start_all_cb() - start the flow of data through callback.
+ * @cb_buff: The callback buffer we are starting.
+ */
+int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff);
+
+/**
+ * iio_channel_stop_all_cb() - stop the flow of data through the callback.
+ * @cb_buff: The callback buffer we are stopping.
+ */
+void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff);
+
+/**
+ * iio_channel_cb_get_channels() - get access to the underlying channels.
+ * @cb_buff: The callback buffer from whom we want the channel
+ * information.
+ *
+ * This function allows one to obtain information about the channels.
+ * Whilst this may allow direct reading if all buffers are disabled, the
+ * primary aim is to allow drivers that are consuming a channel to query
+ * things like scaling of the channel.
+ */
+struct iio_channel
+*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer);
+
/**
* iio_read_channel_raw() - read from a given channel
* @chan: The channel being queried.
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 7806c24e5bc8..adca93a999a7 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -410,6 +410,7 @@ struct iio_buffer_setup_ops {
* and owner
* @event_interface: [INTERN] event chrdevs associated with interrupt lines
* @buffer: [DRIVER] any buffer present
+ * @buffer_list: [INTERN] list of all buffers currently attached
* @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux
* @mlock: [INTERN] lock used to prevent simultaneous device state
* changes
@@ -448,6 +449,7 @@ struct iio_dev {
struct iio_event_interface *event_interface;
struct iio_buffer *buffer;
+ struct list_head buffer_list;
int scan_bytes;
struct mutex mlock;
diff --git a/include/linux/iio/machine.h b/include/linux/iio/machine.h
index 809a3f08d5a5..1601a2a63a72 100644
--- a/include/linux/iio/machine.h
+++ b/include/linux/iio/machine.h
@@ -19,11 +19,13 @@
* @consumer_dev_name: Name to uniquely identify the consumer device.
* @consumer_channel: Unique name used to identify the channel on the
* consumer side.
+ * @consumer_data: Data about the channel for use by the consumer driver.
*/
struct iio_map {
const char *adc_channel_label;
const char *consumer_dev_name;
const char *consumer_channel;
+ void *consumer_data;
};
#endif
diff --git a/include/linux/platform_data/ad7887.h b/include/linux/platform_data/ad7887.h
new file mode 100644
index 000000000000..1e06eac3174d
--- /dev/null
+++ b/include/linux/platform_data/ad7887.h
@@ -0,0 +1,26 @@
+/*
+ * AD7887 SPI ADC driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#ifndef IIO_ADC_AD7887_H_
+#define IIO_ADC_AD7887_H_
+
+/**
+ * struct ad7887_platform_data - AD7887 ADC driver platform data
+ * @en_dual: Whether to use dual channel mode. If set to true AIN1 becomes the
+ * second input channel, and Vref is internally connected to Vdd. If set to
+ * false the device is used in single channel mode and AIN1/Vref is used as
+ * VREF input.
+ * @use_onchip_ref: Whether to use the onchip reference. If set to true the
+ * internal 2.5V reference is used. If set to false a external reference is
+ * used.
+ */
+struct ad7887_platform_data {
+ bool en_dual;
+ bool use_onchip_ref;
+};
+
+#endif /* IIO_ADC_AD7887_H_ */