aboutsummaryrefslogtreecommitdiff
path: root/drivers/iio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/Kconfig10
-rw-r--r--drivers/iio/Makefile4
-rw-r--r--drivers/iio/adc/Kconfig13
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad7266.c536
-rw-r--r--drivers/iio/adc/at91_adc.c57
-rw-r--r--drivers/iio/dac/Kconfig132
-rw-r--r--drivers/iio/dac/Makefile16
-rw-r--r--drivers/iio/dac/ad5064.c676
-rw-r--r--drivers/iio/dac/ad5360.c570
-rw-r--r--drivers/iio/dac/ad5380.c655
-rw-r--r--drivers/iio/dac/ad5421.c544
-rw-r--r--drivers/iio/dac/ad5446.c393
-rw-r--r--drivers/iio/dac/ad5446.h91
-rw-r--r--drivers/iio/dac/ad5504.c393
-rw-r--r--drivers/iio/dac/ad5624r.h79
-rw-r--r--drivers/iio/dac/ad5624r_spi.c324
-rw-r--r--drivers/iio/dac/ad5686.c418
-rw-r--r--drivers/iio/dac/ad5764.c382
-rw-r--r--drivers/iio/dac/ad5791.c485
-rw-r--r--drivers/iio/dac/max517.c242
-rw-r--r--drivers/iio/dac/mcp4725.c227
-rw-r--r--drivers/iio/frequency/Kconfig41
-rw-r--r--drivers/iio/frequency/Makefile6
-rw-r--r--drivers/iio/frequency/ad9523.c1059
-rw-r--r--drivers/iio/frequency/adf4350.c486
-rw-r--r--drivers/iio/industrialio-buffer.c52
-rw-r--r--drivers/iio/industrialio-core.c70
-rw-r--r--drivers/iio/industrialio-event.c3
-rw-r--r--drivers/iio/industrialio-trigger.c45
-rw-r--r--drivers/iio/industrialio-triggered-buffer.c110
-rw-r--r--drivers/iio/inkern.c48
-rw-r--r--drivers/iio/light/Kconfig45
-rw-r--r--drivers/iio/light/Makefile7
-rw-r--r--drivers/iio/light/adjd_s311.c365
-rw-r--r--drivers/iio/light/lm3533-als.c932
-rw-r--r--drivers/iio/light/vcnl4000.c217
37 files changed, 9619 insertions, 115 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 2ec93da41e2..d4984c8be97 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -29,6 +29,13 @@ config IIO_KFIFO_BUF
no buffer events so it is up to userspace to work out how
often to read from the buffer.
+config IIO_TRIGGERED_BUFFER
+ tristate
+ select IIO_TRIGGER
+ select IIO_KFIFO_BUF
+ help
+ Provides helper functions for setting up triggered buffers.
+
endif # IIO_BUFFER
config IIO_TRIGGER
@@ -49,5 +56,8 @@ config IIO_CONSUMERS_PER_TRIGGER
source "drivers/iio/adc/Kconfig"
source "drivers/iio/amplifiers/Kconfig"
+source "drivers/iio/light/Kconfig"
+source "drivers/iio/frequency/Kconfig"
+source "drivers/iio/dac/Kconfig"
endif # IIO
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index e425afd1480..34309abb797 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -7,7 +7,11 @@ industrialio-y := industrialio-core.o industrialio-event.o inkern.o
industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
+obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
obj-y += adc/
obj-y += amplifiers/
+obj-y += light/
+obj-y += frequency/
+obj-y += dac/
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9a0df8123cc..8a78b4f3ef5 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -3,12 +3,21 @@
#
menu "Analog to digital converters"
+config AD7266
+ tristate "Analog Devices AD7265/AD7266 ADC driver"
+ depends on SPI_MASTER
+ select IIO_BUFFER
+ select IIO_TRIGGER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Analog Devices AD7265 and AD7266
+ ADCs.
+
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
select IIO_BUFFER
- select IIO_KFIFO_BUF
- select IIO_TRIGGER
+ select IIO_TRIGGERED_BUFFER
select SYSFS
help
Say yes here to build support for Atmel AT91 ADC.
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 175c8d41ea9..52eec254c38 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -2,4 +2,5 @@
# Makefile for IIO ADC drivers
#
+obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
new file mode 100644
index 00000000000..5c3f1ba5a06
--- /dev/null
+++ b/drivers/iio/adc/ad7266.c
@@ -0,0 +1,536 @@
+/*
+ * AD7266/65 SPI ADC driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include <linux/interrupt.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/platform_data/ad7266.h>
+
+struct ad7266_state {
+ struct spi_device *spi;
+ struct regulator *reg;
+ unsigned long vref_uv;
+
+ struct spi_transfer single_xfer[3];
+ struct spi_message single_msg;
+
+ enum ad7266_range range;
+ enum ad7266_mode mode;
+ bool fixed_addr;
+ struct gpio gpios[3];
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ * The buffer needs to be large enough to hold two samples (4 bytes) and
+ * the naturally aligned timestamp (8 bytes).
+ */
+ uint8_t data[ALIGN(4, sizeof(s64)) + sizeof(s64)] ____cacheline_aligned;
+};
+
+static int ad7266_wakeup(struct ad7266_state *st)
+{
+ /* Any read with >= 2 bytes will wake the device */
+ return spi_read(st->spi, st->data, 2);
+}
+
+static int ad7266_powerdown(struct ad7266_state *st)
+{
+ /* Any read with < 2 bytes will powerdown the device */
+ return spi_read(st->spi, st->data, 1);
+}
+
+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;
+}
+
+static int ad7266_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7266_state *st = iio_priv(indio_dev);
+ return ad7266_powerdown(st);
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .preenable = &ad7266_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
+ .postdisable = &ad7266_postdisable,
+};
+
+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;
+
+ ret = spi_read(st->spi, st->data, 4);
+ if (ret == 0) {
+ if (indio_dev->scan_timestamp)
+ ((s64 *)st->data)[1] = pf->timestamp;
+ iio_push_to_buffer(buffer, (u8 *)st->data, pf->timestamp);
+ }
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
+{
+ unsigned int i;
+
+ if (st->fixed_addr)
+ return;
+
+ switch (st->mode) {
+ case AD7266_MODE_SINGLE_ENDED:
+ nr >>= 1;
+ break;
+ case AD7266_MODE_PSEUDO_DIFF:
+ nr |= 1;
+ break;
+ case AD7266_MODE_DIFF:
+ nr &= ~1;
+ break;
+ }
+
+ for (i = 0; i < 3; ++i)
+ gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i)));
+}
+
+static int ad7266_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad7266_state *st = iio_priv(indio_dev);
+ unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength);
+
+ ad7266_select_input(st, nr);
+
+ return 0;
+}
+
+static int ad7266_read_single(struct ad7266_state *st, int *val,
+ unsigned int address)
+{
+ int ret;
+
+ ad7266_select_input(st, address);
+
+ ret = spi_sync(st->spi, &st->single_msg);
+ *val = be16_to_cpu(st->data[address % 2]);
+
+ return ret;
+}
+
+static int ad7266_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long m)
+{
+ struct ad7266_state *st = iio_priv(indio_dev);
+ unsigned long scale_uv;
+ int ret;
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
+
+ ret = ad7266_read_single(st, val, chan->address);
+ if (ret)
+ return ret;
+
+ *val = (*val >> 2) & 0xfff;
+ if (chan->scan_type.sign == 's')
+ *val = sign_extend32(*val, 11);
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ scale_uv = (st->vref_uv * 100);
+ if (st->mode == AD7266_MODE_DIFF)
+ scale_uv *= 2;
+ if (st->range == AD7266_RANGE_2VREF)
+ scale_uv *= 2;
+
+ scale_uv >>= chan->scan_type.realbits;
+ *val = scale_uv / 100000;
+ *val2 = (scale_uv % 100000) * 10;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ if (st->range == AD7266_RANGE_2VREF &&
+ st->mode != AD7266_MODE_DIFF)
+ *val = 2048;
+ else
+ *val = 0;
+ return IIO_VAL_INT;
+ }
+ return -EINVAL;
+}
+
+#define AD7266_CHAN(_chan, _sign) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_chan), \
+ .address = (_chan), \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \
+ | IIO_CHAN_INFO_SCALE_SHARED_BIT \
+ | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
+ .scan_index = (_chan), \
+ .scan_type = { \
+ .sign = (_sign), \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .shift = 2, \
+ .endianness = IIO_BE, \
+ }, \
+}
+
+#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \
+const struct iio_chan_spec ad7266_channels_##_name[] = { \
+ AD7266_CHAN(0, (_sign)), \
+ AD7266_CHAN(1, (_sign)), \
+ AD7266_CHAN(2, (_sign)), \
+ AD7266_CHAN(3, (_sign)), \
+ AD7266_CHAN(4, (_sign)), \
+ AD7266_CHAN(5, (_sign)), \
+ AD7266_CHAN(6, (_sign)), \
+ AD7266_CHAN(7, (_sign)), \
+ AD7266_CHAN(8, (_sign)), \
+ AD7266_CHAN(9, (_sign)), \
+ AD7266_CHAN(10, (_sign)), \
+ AD7266_CHAN(11, (_sign)), \
+ IIO_CHAN_SOFT_TIMESTAMP(13), \
+}
+
+#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \
+const struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \
+ AD7266_CHAN(0, (_sign)), \
+ AD7266_CHAN(1, (_sign)), \
+ IIO_CHAN_SOFT_TIMESTAMP(2), \
+}
+
+static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u');
+static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's');
+static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u');
+static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
+
+#define AD7266_CHAN_DIFF(_chan, _sign) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_chan) * 2, \
+ .channel2 = (_chan) * 2 + 1, \
+ .address = (_chan), \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \
+ | IIO_CHAN_INFO_SCALE_SHARED_BIT \
+ | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
+ .scan_index = (_chan), \
+ .scan_type = { \
+ .sign = _sign, \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .shift = 2, \
+ .endianness = IIO_BE, \
+ }, \
+ .differential = 1, \
+}
+
+#define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \
+const struct iio_chan_spec ad7266_channels_diff_##_name[] = { \
+ AD7266_CHAN_DIFF(0, (_sign)), \
+ AD7266_CHAN_DIFF(1, (_sign)), \
+ AD7266_CHAN_DIFF(2, (_sign)), \
+ AD7266_CHAN_DIFF(3, (_sign)), \
+ AD7266_CHAN_DIFF(4, (_sign)), \
+ AD7266_CHAN_DIFF(5, (_sign)), \
+ IIO_CHAN_SOFT_TIMESTAMP(6), \
+}
+
+static AD7266_DECLARE_DIFF_CHANNELS(s, 's');
+static AD7266_DECLARE_DIFF_CHANNELS(u, 'u');
+
+#define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \
+const struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \
+ AD7266_CHAN_DIFF(0, (_sign)), \
+ AD7266_CHAN_DIFF(1, (_sign)), \
+ IIO_CHAN_SOFT_TIMESTAMP(2), \
+}
+
+static AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's');
+static AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u');
+
+static const struct iio_info ad7266_info = {
+ .read_raw = &ad7266_read_raw,
+ .update_scan_mode = &ad7266_update_scan_mode,
+ .driver_module = THIS_MODULE,
+};
+
+static unsigned long ad7266_available_scan_masks[] = {
+ 0x003,
+ 0x00c,
+ 0x030,
+ 0x0c0,
+ 0x300,
+ 0xc00,
+ 0x000,
+};
+
+static unsigned long ad7266_available_scan_masks_diff[] = {
+ 0x003,
+ 0x00c,
+ 0x030,
+ 0x000,
+};
+
+static unsigned long ad7266_available_scan_masks_fixed[] = {
+ 0x003,
+ 0x000,
+};
+
+struct ad7266_chan_info {
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ unsigned long *scan_masks;
+};
+
+#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
+ (((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0))
+
+static const struct ad7266_chan_info ad7266_chan_infos[] = {
+ [AD7266_CHAN_INFO_INDEX(0, 0, 0)] = {
+ .channels = ad7266_channels_u,
+ .num_channels = ARRAY_SIZE(ad7266_channels_u),
+ .scan_masks = ad7266_available_scan_masks,
+ },
+ [AD7266_CHAN_INFO_INDEX(0, 0, 1)] = {
+ .channels = ad7266_channels_u_fixed,
+ .num_channels = ARRAY_SIZE(ad7266_channels_u_fixed),
+ .scan_masks = ad7266_available_scan_masks_fixed,
+ },
+ [AD7266_CHAN_INFO_INDEX(0, 1, 0)] = {
+ .channels = ad7266_channels_s,
+ .num_channels = ARRAY_SIZE(ad7266_channels_s),
+ .scan_masks = ad7266_available_scan_masks,
+ },
+ [AD7266_CHAN_INFO_INDEX(0, 1, 1)] = {
+ .channels = ad7266_channels_s_fixed,
+ .num_channels = ARRAY_SIZE(ad7266_channels_s_fixed),
+ .scan_masks = ad7266_available_scan_masks_fixed,
+ },
+ [AD7266_CHAN_INFO_INDEX(1, 0, 0)] = {
+ .channels = ad7266_channels_diff_u,
+ .num_channels = ARRAY_SIZE(ad7266_channels_diff_u),
+ .scan_masks = ad7266_available_scan_masks_diff,
+ },
+ [AD7266_CHAN_INFO_INDEX(1, 0, 1)] = {
+ .channels = ad7266_channels_diff_fixed_u,
+ .num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u),
+ .scan_masks = ad7266_available_scan_masks_fixed,
+ },
+ [AD7266_CHAN_INFO_INDEX(1, 1, 0)] = {
+ .channels = ad7266_channels_diff_s,
+ .num_channels = ARRAY_SIZE(ad7266_channels_diff_s),
+ .scan_masks = ad7266_available_scan_masks_diff,
+ },
+ [AD7266_CHAN_INFO_INDEX(1, 1, 1)] = {
+ .channels = ad7266_channels_diff_fixed_s,
+ .num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s),
+ .scan_masks = ad7266_available_scan_masks_fixed,
+ },
+};
+
+static void __devinit ad7266_init_channels(struct iio_dev *indio_dev)
+{
+ struct ad7266_state *st = iio_priv(indio_dev);
+ bool is_differential, is_signed;
+ const struct ad7266_chan_info *chan_info;
+ int i;
+
+ is_differential = st->mode != AD7266_MODE_SINGLE_ENDED;
+ is_signed = (st->range == AD7266_RANGE_2VREF) |
+ (st->mode == AD7266_MODE_DIFF);
+
+ i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr);
+ chan_info = &ad7266_chan_infos[i];
+
+ indio_dev->channels = chan_info->channels;
+ indio_dev->num_channels = chan_info->num_channels;
+ indio_dev->available_scan_masks = chan_info->scan_masks;
+ indio_dev->masklength = chan_info->num_channels - 1;
+}
+
+static const char * const ad7266_gpio_labels[] = {
+ "AD0", "AD1", "AD2",
+};
+
+static int __devinit ad7266_probe(struct spi_device *spi)
+{
+ struct ad7266_platform_data *pdata = spi->dev.platform_data;
+ struct iio_dev *indio_dev;
+ struct ad7266_state *st;
+ unsigned int i;
+ int ret;
+
+ indio_dev = iio_device_alloc(sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->reg = regulator_get(&spi->dev, "vref");
+ if (!IS_ERR_OR_NULL(st->reg)) {
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+
+ st->vref_uv = regulator_get_voltage(st->reg);
+ } else {
+ /* Use internal reference */
+ st->vref_uv = 2500000;
+ }
+
+ if (pdata) {
+ st->fixed_addr = pdata->fixed_addr;
+ st->mode = pdata->mode;
+ st->range = pdata->range;
+
+ if (!st->fixed_addr) {
+ for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
+ st->gpios[i].gpio = pdata->addr_gpios[i];
+ st->gpios[i].flags = GPIOF_OUT_INIT_LOW;
+ st->gpios[i].label = ad7266_gpio_labels[i];
+ }
+ ret = gpio_request_array(st->gpios,
+ ARRAY_SIZE(st->gpios));
+ if (ret)
+ goto error_disable_reg;
+ }
+ } else {
+ st->fixed_addr = true;
+ st->range = AD7266_RANGE_VREF;
+ st->mode = AD7266_MODE_DIFF;
+ }
+
+ spi_set_drvdata(spi, indio_dev);
+ st->spi = spi;
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ad7266_info;
+
+ ad7266_init_channels(indio_dev);
+
+ /* wakeup */
+ st->single_xfer[0].rx_buf = &st->data;
+ st->single_xfer[0].len = 2;
+ st->single_xfer[0].cs_change = 1;
+ /* conversion */
+ st->single_xfer[1].rx_buf = &st->data;
+ st->single_xfer[1].len = 4;
+ st->single_xfer[1].cs_change = 1;
+ /* powerdown */
+ st->single_xfer[2].tx_buf = &st->data;
+ st->single_xfer[2].len = 1;
+
+ spi_message_init(&st->single_msg);
+ spi_message_add_tail(&st->single_xfer[0], &st->single_msg);
+ spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
+ spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
+
+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ &ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
+ if (ret)
+ goto error_free_gpios;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_buffer_cleanup;
+
+ return 0;
+
+error_buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+error_free_gpios:
+ if (!st->fixed_addr)
+ gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
+error_disable_reg:
+ if (!IS_ERR_OR_NULL(st->reg))
+ regulator_disable(st->reg);
+error_put_reg:
+ if (!IS_ERR_OR_NULL(st->reg))
+ regulator_put(st->reg);
+
+ iio_device_free(indio_dev);
+
+ return ret;
+}
+
+static int __devexit ad7266_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7266_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ if (!st->fixed_addr)
+ gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
+ if (!IS_ERR_OR_NULL(st->reg)) {
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+ }
+ iio_device_free(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad7266_id[] = {
+ {"ad7265", 0},
+ {"ad7266", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad7266_id);
+
+static struct spi_driver ad7266_driver = {
+ .driver = {
+ .name = "ad7266",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7266_probe,
+ .remove = __devexit_p(ad7266_remove),
+ .id_table = ad7266_id,
+};
+module_spi_driver(ad7266_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD7266/65 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index f18a95d8025..f61780a0237 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -26,9 +26,9 @@
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <mach/at91_adc.h>
@@ -318,58 +318,15 @@ static void at91_adc_trigger_remove(struct iio_dev *idev)
}
}
-static const struct iio_buffer_setup_ops at91_adc_buffer_ops = {
- .preenable = &iio_sw_buffer_preenable,
- .postenable = &iio_triggered_buffer_postenable,
- .predisable = &iio_triggered_buffer_predisable,
-};
-
static int at91_adc_buffer_init(struct iio_dev *idev)
{
- int ret;
-
- idev->buffer = iio_kfifo_allocate(idev);
- if (!idev->buffer) {
- ret = -ENOMEM;
- goto error_ret;
- }
-
- idev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
- &at91_adc_trigger_handler,
- IRQF_ONESHOT,
- idev,
- "%s-consumer%d",
- idev->name,
- idev->id);
- if (idev->pollfunc == NULL) {
- ret = -ENOMEM;
- goto error_pollfunc;
- }
-
- idev->setup_ops = &at91_adc_buffer_ops;
- idev->modes |= INDIO_BUFFER_TRIGGERED;
-
- ret = iio_buffer_register(idev,
- idev->channels,
- idev->num_channels);
- if (ret)
- goto error_register;
-
- return 0;
-
-error_register:
- iio_dealloc_pollfunc(idev->pollfunc);
-error_pollfunc:
- iio_kfifo_free(idev->buffer);
-error_ret:
- return ret;
+ return iio_triggered_buffer_setup(idev, &iio_pollfunc_store_time,
+ &at91_adc_trigger_handler, NULL);
}
static void at91_adc_buffer_remove(struct iio_dev *idev)
{
- iio_buffer_unregister(idev);
- iio_dealloc_pollfunc(idev->pollfunc);
- iio_kfifo_free(idev->buffer);
+ iio_triggered_buffer_cleanup(idev);
}
static int at91_adc_read_raw(struct iio_dev *idev,
@@ -392,9 +349,11 @@ static int at91_adc_read_raw(struct iio_dev *idev,
st->done,
msecs_to_jiffies(1000));
if (ret == 0)
- return -ETIMEDOUT;
- else if (ret < 0)
+ ret = -ETIMEDOUT;
+ if (ret < 0) {
+ mutex_unlock(&st->lock);
return ret;
+ }
*val = st->last_value;
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
new file mode 100644
index 00000000000..1be15fa9d61
--- /dev/null
+++ b/drivers/iio/dac/Kconfig
@@ -0,0 +1,132 @@
+#
+# DAC drivers
+#
+menu "Digital to analog converters"
+
+config AD5064
+ tristate "Analog Devices AD5064 and similar multi-channel DAC driver"
+ depends on (SPI_MASTER || I2C)
+ help
+ Say yes here to build support for Analog Devices AD5024, AD5025, AD5044,
+ AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668,
+ AD5669R Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5064.
+
+config AD5360
+ tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5360, AD5361,
+ AD5362, AD5363, AD5370, AD5371, AD5373 multi-channel
+ Digital to Analog Converters (DAC).
+
+ To compile this driver as module choose M here: the module will be called
+ ad5360.
+
+config AD5380
+ tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver"
+ depends on (SPI_MASTER || I2C)
+ select REGMAP_I2C if I2C
+ select REGMAP_SPI if SPI_MASTER
+ help
+ Say yes here to build support for Analog Devices AD5380, AD5381,
+ AD5382, AD5383, AD5384, AD5390, AD5391, AD5392 multi-channel
+ Digital to Analog Converters (DAC).
+
+ To compile this driver as module choose M here: the module will be called
+ ad5380.
+
+config AD5421
+ tristate "Analog Devices AD5421 DAC driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5421 loop-powered
+ digital-to-analog convertors (DAC).
+
+ To compile this driver as module choose M here: the module will be called
+ ad5421.
+
+config AD5624R_SPI
+ tristate "Analog Devices AD5624/44/64R DAC spi driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5624R, AD5644R and
+ AD5664R converters (DAC). This driver uses the common SPI interface.
+
+config AD5446
+ tristate "Analog Devices AD5446 and similar single channel DACs driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5444, AD5446, AD5450,
+ AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601,
+ AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5446.
+
+config AD5504
+ tristate "Analog Devices AD5504/AD5501 DAC SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5504, AD5501,
+ High Voltage Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5504.
+
+config AD5764
+ tristate "Analog Devices AD5764/64R/44/44R DAC driver"
+ depends on SPI_MASTER
+ help
+ Say yes here to build support for Analog Devices AD5764, AD5764R, AD5744,
+ AD5744R Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5764.
+
+config AD5791
+ tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5760, AD5780,
+ AD5781, AD5790, AD5791 High Resolution Voltage Output Digital to
+ Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5791.
+
+config AD5686
+ tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5686R, AD5685R,
+ AD5684R, AD5791 Voltage Output Digital to
+ Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5686.
+
+config MAX517
+ tristate "Maxim MAX517/518/519 DAC driver"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Maxim chips MAX517,
+ MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs).
+
+ This driver can also be built as a module. If so, the module
+ will be called max517.
+
+config MCP4725
+ tristate "MCP4725 DAC driver"
+ depends on I2C
+ ---help---
+ Say Y here if you want to build a driver for the Microchip
+ MCP 4725 12-bit digital-to-analog converter (DAC) with I2C
+ interface.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mcp4725.
+
+endmenu
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
new file mode 100644
index 00000000000..9ea3ceeefc0
--- /dev/null
+++ b/drivers/iio/dac/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for industrial I/O DAC drivers
+#
+
+obj-$(CONFIG_AD5360) += ad5360.o
+obj-$(CONFIG_AD5380) += ad5380.o
+obj-$(CONFIG_AD5421) += ad5421.o
+obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
+obj-$(CONFIG_AD5064) += ad5064.o
+obj-$(CONFIG_AD5504) += ad5504.o
+obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_AD5764) += ad5764.o
+obj-$(CONFIG_AD5791) += ad5791.o
+obj-$(CONFIG_AD5686) += ad5686.o
+obj-$(CONFIG_MAX517) += max517.o
+obj-$(CONFIG_MCP4725) += mcp4725.o
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
new file mode 100644
index 00000000000..eb281a2c295
--- /dev/null
+++ b/drivers/iio/dac/ad5064.c
@@ -0,0 +1,676 @@
+/*
+ * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R,
+ * AD5648, AD5666, AD5668, AD5669R Digital to analog converters driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>