diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-06 16:03:44 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-06 16:03:44 -0700 |
commit | c01ef023ec1d2af185e55f7600405dcce1813d5d (patch) | |
tree | 8414fab21c640d6112eef0df0fce8e0718b87a83 | |
parent | b600c5b569c2f62eacf8d71dd9975d7a996073f3 (diff) | |
parent | cf82cb8128496955a38fa62e1819ceb1d596e2eb (diff) | |
download | blackbird-op-linux-c01ef023ec1d2af185e55f7600405dcce1813d5d.tar.gz blackbird-op-linux-c01ef023ec1d2af185e55f7600405dcce1813d5d.zip |
Merge branch 'togreg' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
-rw-r--r-- | drivers/iio/adc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/adc/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/adc/ad7266.c | 536 | ||||
-rw-r--r-- | drivers/iio/dac/Kconfig | 8 | ||||
-rw-r--r-- | drivers/iio/dac/ad5064.c | 200 | ||||
-rw-r--r-- | drivers/iio/industrialio-core.c | 2 | ||||
-rw-r--r-- | drivers/iio/inkern.c | 33 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16201_core.c | 27 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16203_core.c | 28 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16204_core.c | 99 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16209_core.c | 29 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16220_core.c | 24 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16240_core.c | 20 | ||||
-rw-r--r-- | drivers/staging/iio/gyro/adis16260_core.c | 19 | ||||
-rw-r--r-- | drivers/staging/iio/iio_hwmon.c | 12 | ||||
-rw-r--r-- | drivers/staging/iio/imu/adis16400_core.c | 22 | ||||
-rw-r--r-- | include/linux/iio/consumer.h | 34 | ||||
-rw-r--r-- | include/linux/iio/types.h | 2 | ||||
-rw-r--r-- | include/linux/platform_data/ad7266.h | 54 |
19 files changed, 843 insertions, 317 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 4f7f584cfd61..8a78b4f3ef58 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -3,6 +3,16 @@ # 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 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 175c8d41ea99..52eec254c38c 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 000000000000..5c3f1ba5a06d --- /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/dac/Kconfig b/drivers/iio/dac/Kconfig index afd207e171cf..1be15fa9d618 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -4,12 +4,12 @@ menu "Digital to analog converters" config AD5064 - tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/66/68 DAC driver" - depends on SPI + 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, AD5648, AD5666, AD5668 Digital - to Analog Converter. + 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. diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 276af02520af..aa739c497f2b 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -1,6 +1,6 @@ /* - * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, - * AD5666, AD5668 Digital to analog converters driver + * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, + * AD5648, AD5666, AD5668, AD5669R Digital to analog converters driver * * Copyright 2011 Analog Devices Inc. * @@ -12,9 +12,11 @@ #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> +#include <asm/unaligned.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -62,9 +64,14 @@ struct ad5064_chip_info { unsigned int num_channels; }; +struct ad5064_state; + +typedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val); + /** * struct ad5064_state - driver instance specific data - * @spi: spi_device + * @dev: the device for this driver instance * @chip_info: chip model specific constants, available modes etc * @vref_reg: vref supply regulators * @pwr_down: whether channel is powered down @@ -72,11 +79,12 @@ struct ad5064_chip_info { * @dac_cache: current DAC raw value (chip does not support readback) * @use_internal_vref: set to true if the internal reference voltage should be * used. - * @data: spi transfer buffers + * @write: register write callback + * @data: i2c/spi transfer buffers */ struct ad5064_state { - struct spi_device *spi; + struct device *dev; const struct ad5064_chip_info *chip_info; struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; bool pwr_down[AD5064_MAX_DAC_CHANNELS]; @@ -84,11 +92,16 @@ struct ad5064_state { unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; bool use_internal_vref; + ad5064_write_func write; + /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. */ - __be32 data ____cacheline_aligned; + union { + u8 i2c[3]; + __be32 spi; + } data ____cacheline_aligned; }; enum ad5064_type { @@ -109,14 +122,31 @@ enum ad5064_type { ID_AD5668_2, }; +static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + + st->data.i2c[0] = (cmd << 4) | addr; + put_unaligned_be16(val, &st->data.i2c[1]); + return i2c_master_send(i2c, st->data.i2c, 3); +} + static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val) +{ + struct spi_device *spi = to_spi_device(st->dev); + + st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); + return spi_write(spi, &st->data.spi, sizeof(st->data.spi)); +} + +static int ad5064_write(struct ad5064_state *st, unsigned int cmd, unsigned int addr, unsigned int val, unsigned int shift) { val <<= shift; - st->data = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); - - return spi_write(st->spi, &st->data, sizeof(st->data)); + return st->write(st, cmd, addr, val); } static int ad5064_sync_powerdown_mode(struct ad5064_state *st, @@ -130,7 +160,7 @@ static int ad5064_sync_powerdown_mode(struct ad5064_state *st, if (st->pwr_down[channel]) val |= st->pwr_down_mode[channel] << 8; - ret = ad5064_spi_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); + ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); return ret; } @@ -251,7 +281,7 @@ static int ad5064_write_raw(struct iio_dev *indio_dev, return -EINVAL; mutex_lock(&indio_dev->mlock); - ret = ad5064_spi_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, + ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, chan->address, val, chan->scan_type.shift); if (ret == 0) st->dac_cache[chan->channel] = val; @@ -413,9 +443,9 @@ static const char * const ad5064_vref_name(struct ad5064_state *st, return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; } -static int __devinit ad5064_probe(struct spi_device *spi) +static int __devinit ad5064_probe(struct device *dev, enum ad5064_type type, + const char *name, ad5064_write_func write) { - enum ad5064_type type = spi_get_device_id(spi)->driver_data; struct iio_dev *indio_dev; struct ad5064_state *st; unsigned int i; @@ -426,24 +456,25 @@ static int __devinit ad5064_probe(struct spi_device *spi) return -ENOMEM; st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); + dev_set_drvdata(dev, indio_dev); st->chip_info = &ad5064_chip_info_tbl[type]; - st->spi = spi; + st->dev = dev; + st->write = write; for (i = 0; i < ad5064_num_vref(st); ++i) st->vref_reg[i].supply = ad5064_vref_name(st, i); - ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), + ret = regulator_bulk_get(dev, ad5064_num_vref(st), st->vref_reg); if (ret) { if (!st->chip_info->internal_vref) goto error_free; st->use_internal_vref = true; - ret = ad5064_spi_write(st, AD5064_CMD_CONFIG, 0, + ret = ad5064_write(st, AD5064_CMD_CONFIG, 0, AD5064_CONFIG_INT_VREF_ENABLE, 0); if (ret) { - dev_err(&spi->dev, "Failed to enable internal vref: %d\n", + dev_err(dev, "Failed to enable internal vref: %d\n", ret); goto error_free; } @@ -458,8 +489,8 @@ static int __devinit ad5064_probe(struct spi_device *spi) st->dac_cache[i] = 0x8000; } - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = dev; + indio_dev->name = name; indio_dev->info = &ad5064_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channels; @@ -483,10 +514,9 @@ error_free: return ret; } - -static int __devexit ad5064_remove(struct spi_device *spi) +static int __devexit ad5064_remove(struct device *dev) { - struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5064_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); @@ -501,7 +531,22 @@ static int __devexit ad5064_remove(struct spi_device *spi) return 0; } -static const struct spi_device_id ad5064_id[] = { +#if IS_ENABLED(CONFIG_SPI_MASTER) + +static int __devinit ad5064_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + + return ad5064_probe(&spi->dev, id->driver_data, id->name, + ad5064_spi_write); +} + +static int __devexit ad5064_spi_remove(struct spi_device *spi) +{ + return ad5064_remove(&spi->dev); +} + +static const struct spi_device_id ad5064_spi_ids[] = { {"ad5024", ID_AD5024}, {"ad5025", ID_AD5025}, {"ad5044", ID_AD5044}, @@ -520,19 +565,112 @@ static const struct spi_device_id ad5064_id[] = { {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ {} }; -MODULE_DEVICE_TABLE(spi, ad5064_id); +MODULE_DEVICE_TABLE(spi, ad5064_spi_ids); -static struct spi_driver ad5064_driver = { +static struct spi_driver ad5064_spi_driver = { .driver = { .name = "ad5064", .owner = THIS_MODULE, }, - .probe = ad5064_probe, - .remove = __devexit_p(ad5064_remove), - .id_table = ad5064_id, + .probe = ad5064_spi_probe, + .remove = __devexit_p(ad5064_spi_remove), + .id_table = ad5064_spi_ids, }; -module_spi_driver(ad5064_driver); + +static int __init ad5064_spi_register_driver(void) +{ + return spi_register_driver(&ad5064_spi_driver); +} + +static void __exit ad5064_spi_unregister_driver(void) +{ + spi_unregister_driver(&ad5064_spi_driver); +} + +#else + +static inline int ad5064_spi_register_driver(void) { return 0; } +static inline void ad5064_spi_unregister_driver(void) { } + +#endif + +#if IS_ENABLED(CONFIG_I2C) + +static int __devinit ad5064_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + return ad5064_probe(&i2c->dev, id->driver_data, id->name, + ad5064_i2c_write); +} + +static int __devexit ad5064_i2c_remove(struct i2c_client *i2c) +{ + return ad5064_remove(&i2c->dev); +} + +static const struct i2c_device_id ad5064_i2c_ids[] = { + {"ad5629-1", ID_AD5628_1}, + {"ad5629-2", ID_AD5628_2}, + {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */ + {"ad5669-1", ID_AD5668_1}, + {"ad5669-2", ID_AD5668_2}, + {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */ + {} +}; +MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); + +static struct i2c_driver ad5064_i2c_driver = { + .driver = { + .name = "ad5064", + .owner = THIS_MODULE, + }, + .probe = ad5064_i2c_probe, + .remove = __devexit_p(ad5064_i2c_remove), + .id_table = ad5064_i2c_ids, +}; + +static int __init ad5064_i2c_register_driver(void) +{ + return i2c_add_driver(&ad5064_i2c_driver); +} + +static void __exit ad5064_i2c_unregister_driver(void) +{ + i2c_del_driver(&ad5064_i2c_driver); +} + +#else + +static inline int ad5064_i2c_register_driver(void) { return 0; } +static inline void ad5064_i2c_unregister_driver(void) { } + +#endif + +static int __init ad5064_init(void) +{ + int ret; + + ret = ad5064_spi_register_driver(); + if (ret) + return ret; + + ret = ad5064_i2c_register_driver(); + if (ret) { + ad5064_spi_unregister_driver(); + return ret; + } + + return 0; +} +module_init(ad5064_init); + +static void __exit ad5064_exit(void) +{ + ad5064_i2c_unregister_driver(); + ad5064_spi_unregister_driver(); +} +module_exit(ad5064_exit); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/66/68 DAC"); +MODULE_DESCRIPTION("Analog Devices AD5024 and similar multi-channel DACs"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index a5a446beb2fa..bb3c692e49b8 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -70,6 +70,8 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_X] = "x", [IIO_MOD_Y] = "y", [IIO_MOD_Z] = "z", + [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", + [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", [IIO_MOD_LIGHT_BOTH] = "both", [IIO_MOD_LIGHT_IR] = "ir", }; diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index d4760bd1e9b1..9a46ca61ef02 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -92,8 +92,7 @@ error_ret: EXPORT_SYMBOL_GPL(iio_map_array_unregister); static const struct iio_chan_spec -*iio_chan_spec_from_name(const struct iio_dev *indio_dev, - const char *name) +*iio_chan_spec_from_name(const struct iio_dev *indio_dev, const char *name) { int i; const struct iio_chan_spec *chan = NULL; @@ -108,8 +107,7 @@ static const struct iio_chan_spec } -struct iio_channel *iio_st_channel_get(const char *name, - const char *channel_name) +struct iio_channel *iio_channel_get(const char *name, const char *channel_name) { struct iio_map_internal *c_i = NULL, *c = NULL; struct iio_channel *channel; @@ -145,16 +143,16 @@ struct iio_channel *iio_st_channel_get(const char *name, return channel; } -EXPORT_SYMBOL_GPL(iio_st_channel_get); +EXPORT_SYMBOL_GPL(iio_channel_get); -void iio_st_channel_release(struct iio_channel *channel) +void iio_channel_release(struct iio_channel *channel) { iio_device_put(channel->indio_dev); kfree(channel); } -EXPORT_SYMBOL_GPL(iio_st_channel_release); +EXPORT_SYMBOL_GPL(iio_channel_release); -struct iio_channel *iio_st_channel_get_all(const char *name) +struct iio_channel *iio_channel_get_all(const char *name) { struct iio_channel *chans; struct iio_map_internal *c = NULL; @@ -217,9 +215,9 @@ error_ret: return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(iio_st_channel_get_all); +EXPORT_SYMBOL_GPL(iio_channel_get_all); -void iio_st_channel_release_all(struct iio_channel *channels) +void iio_channel_release_all(struct iio_channel *channels) { struct iio_channel *chan = &channels[0]; @@ -229,9 +227,9 @@ void iio_st_channel_release_all(struct iio_channel *channels) } kfree(channels); } -EXPORT_SYMBOL_GPL(iio_st_channel_release_all); +EXPORT_SYMBOL_GPL(iio_channel_release_all); -int iio_st_read_channel_raw(struct iio_channel *chan, int *val) +int iio_read_channel_raw(struct iio_channel *chan, int *val) { int val2, ret; @@ -248,9 +246,9 @@ err_unlock: return ret; } -EXPORT_SYMBOL_GPL(iio_st_read_channel_raw); +EXPORT_SYMBOL_GPL(iio_read_channel_raw); -int iio_st_read_channel_scale(struct iio_channel *chan, int *val, int *val2) +int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) { int ret; @@ -269,10 +267,9 @@ err_unlock: return ret; } -EXPORT_SYMBOL_GPL(iio_st_read_channel_scale); +EXPORT_SYMBOL_GPL(iio_read_channel_scale); -int iio_st_get_channel_type(struct iio_channel *chan, - enum iio_chan_type *type) +int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) { int ret = 0; /* Need to verify underlying driver has not gone away */ @@ -289,4 +286,4 @@ err_unlock: return ret; } -EXPORT_SYMBOL_GPL(iio_st_get_channel_type); +EXPORT_SYMBOL_GPL(iio_get_channel_type); diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 02b340919c0e..204106b72d24 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -159,21 +159,6 @@ static int adis16201_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16201_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - int ret; - bool res; - - if (len < 1) - return -EINVAL; - ret = strtobool(buf, &res); - if (ret || !res) - return ret; - return adis16201_reset(dev_to_iio_dev(dev)); -} - int adis16201_set_irq(struct iio_dev *indio_dev, bool enable) { int ret = 0; @@ -507,19 +492,7 @@ static struct iio_chan_spec adis16201_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(7) }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16201_write_reset, 0); - -static struct attribute *adis16201_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16201_attribute_group = { - .attrs = adis16201_attributes, -}; - static const struct iio_info adis16201_info = { - .attrs = &adis16201_attribute_group, .read_raw = &adis16201_read_raw, .write_raw = &adis16201_write_raw, .driver_module = THIS_MODULE, diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 15d46bfd1b42..22085e9dfd16 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -178,22 +178,6 @@ static int adis16203_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16203_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16203_reset(indio_dev); - } - return -EINVAL; -} - int adis16203_set_irq(struct iio_dev *indio_dev, bool enable) { int ret = 0; @@ -444,19 +428,7 @@ static struct iio_chan_spec adis16203_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(5), }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16203_write_reset, 0); - -static struct attribute *adis16203_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16203_attribute_group = { - .attrs = adis16203_attributes, -}; - static const struct iio_info adis16203_info = { - .attrs = &adis16203_attribute_group, .read_raw = &adis16203_read_raw, .write_raw = &adis16203_write_raw, .driver_module = THIS_MODULE, diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 457982bf7eac..5f2e5f11c543 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -169,32 +169,6 @@ error_ret: return ret; } -static ssize_t adis16204_read_14bit_signed(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - s16 val = 0; - ssize_t ret; - - mutex_lock(&indio_dev->mlock); - - ret = adis16204_spi_read_reg_16(indio_dev, - this_attr->address, (u16 *)&val); - if (!ret) { - if (val & ADIS16204_ERROR_ACTIVE) - adis16204_check_status(indio_dev); - - val = ((s16)(val << 2) >> 2); - ret = sprintf(buf, "%d\n", val); - } - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - static int adis16204_reset(struct iio_dev *indio_dev) { int ret; @@ -207,23 +181,6 @@ static int adis16204_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16204_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16204_reset(indio_dev); - } - return -EINVAL; -} - int adis16204_set_irq(struct iio_dev *indio_dev, bool enable) { int ret = 0; @@ -299,18 +256,6 @@ err_ret: } /* Unique to this driver currently */ -#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ - IIO_DEVICE_ATTR(in_accel_xy, S_IRUGO, _show, NULL, _addr) -#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(in_accel_xypeak, S_IRUGO, _show, NULL, _addr) - -static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed, - ADIS16204_XY_RSS_OUT); -static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed, - ADIS16204_XY_PEAK_OUT); -static IIO_CONST_ATTR(in_accel_xy_scale, "0.017125"); - -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0); enum adis16204_channel { in_supply, @@ -318,9 +263,10 @@ enum adis16204_channel { temp, accel_x, accel_y, + accel_xy, }; -static u8 adis16204_addresses[5][3] = { +static u8 adis16204_addresses[6][3] = { [in_supply] = { ADIS16204_SUPPLY_OUT }, [in_aux] = { ADIS16204_AUX_ADC }, [temp] = { ADIS16204_TEMP_OUT }, @@ -328,6 +274,8 @@ static u8 adis16204_addresses[5][3] = { ADIS16204_X_PEAK_OUT }, [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT }, + [accel_xy] = { ADIS16204_XY_RSS_OUT, 0, + ADIS16204_XY_PEAK_OUT }, }; static int adis16204_read_raw(struct iio_dev *indio_dev, @@ -381,10 +329,16 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - if (chan->channel2 == IIO_MOD_X) + switch (chan->channel2) { + case IIO_MOD_X: + case IIO_MOD_ROOT_SUM_SQUARED_X_Y: *val2 = 17125; - else + break; + case IIO_MOD_Y: + case IIO_MOD_Z: *val2 = 8407; + break; + } return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -517,22 +471,23 @@ static struct iio_chan_spec adis16204_channels[] = { }, }, IIO_CHAN_SOFT_TIMESTAMP(5), -}; - -static struct attribute *adis16204_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - &iio_dev_attr_in_accel_xy.dev_attr.attr, - &iio_dev_attr_in_accel_xypeak.dev_attr.attr, - &iio_const_attr_in_accel_xy_scale.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16204_attribute_group = { - .attrs = adis16204_attributes, + { + .type = IIO_ACCEL, + .modified = 1, + .channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_PEAK_SEPARATE_BIT, + .address = accel_xy, + .scan_type = { + .sign = 'u', + .realbits = 14, + .storagebits = 16, + }, + } }; static const struct iio_info adis16204_info = { - .attrs = &adis16204_attribute_group, .read_raw = &adis16204_read_raw, .write_raw = &adis16204_write_raw, .driver_module = THIS_MODULE, @@ -569,7 +524,7 @@ static int __devinit adis16204_probe(struct spi_device *spi) ret = iio_buffer_register(indio_dev, adis16204_channels, - ARRAY_SIZE(adis16204_channels)); + 6); if (ret) { printk(KERN_ERR "failed to initialize the ring\n"); goto error_unreg_ring_funcs; diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 6fc426e27e4e..494570508c36 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -153,23 +153,6 @@ static int adis16209_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16209_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16209_reset(indio_dev); - } - return -EINVAL; -} - int adis16209_set_irq(struct iio_dev *indio_dev, bool enable) { int ret = 0; @@ -519,19 +502,7 @@ static struct iio_chan_spec adis16209_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(8) }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16209_write_reset, 0); - -static struct attribute *adis16209_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16209_attribute_group = { - .attrs = adis16209_attributes, -}; - static const struct iio_info adis16209_info = { - .attrs = &adis16209_attribute_group, .read_raw = &adis16209_read_raw, .write_raw = &adis16209_write_raw, .driver_module = THIS_MODULE, diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index af5c57637166..575f1af25d5d 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -204,26 +204,6 @@ static int adis16220_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16220_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - - ret = adis16220_reset(indio_dev); - if (ret) - return ret; - return len; -} - static ssize_t adis16220_write_capture(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -454,9 +434,6 @@ static struct bin_attribute adc2_bin = { .size = ADIS16220_CAPTURE_SIZE, }; -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, - adis16220_write_reset, 0); - #define IIO_DEV_ATTR_CAPTURE(_store) \ IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) @@ -611,7 +588,6 @@ static const struct iio_chan_spec adis16220_channels[] = { }; static struct attribute *adis16220_attributes[] = { - &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_capture.dev_attr.attr, &iio_dev_attr_capture_count.dev_attr.attr, NULL diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 1a51f03d3d76..b30b7874ffb0 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -199,23 +199,6 @@ static int adis16240_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16240_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16240_reset(indio_dev); - } - return -EINVAL; -} - int adis16240_set_irq(struct iio_dev *indio_dev, bool enable) { int ret = 0; @@ -329,8 +312,6 @@ static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, adis16240_read_12bit_signed, NULL, ADIS16240_XYZPEAK_OUT); -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16240_write_reset, 0); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096"); enum adis16240_chan { @@ -559,7 +540,6 @@ static struct iio_chan_spec adis16240_channels[] = { static struct attribute *adis16240_attributes[] = { &iio_dev_attr_in_accel_xyz_squared_peak_raw.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, NULL }; diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index fdb84cc3d7c9..f16b3938928f 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -233,22 +233,6 @@ static int adis16260_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16260_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - if (len < 1) - return -EINVAL; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16260_reset(indio_dev); - } - return -EINVAL; -} - int adis16260_set_irq(struct iio_dev *indio_dev, bool enable) { int ret; @@ -375,8 +359,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, adis16260_read_frequency, adis16260_write_frequency); -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16260_write_reset, 0); - static IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, adis16260_read_frequency_available, NULL, 0); @@ -604,7 +586,6 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, static struct attribute *adis16260_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, NULL }; diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c index b03554fee443..27d27ec9521f 100644 --- a/drivers/staging/iio/iio_hwmon.c +++ b/drivers/staging/iio/iio_hwmon.c @@ -51,12 +51,12 @@ static ssize_t iio_hwmon_read_val(struct device *dev, * No locking between this pair, so theoretically possible * the scale has changed. */ - ret = iio_st_read_channel_raw(&state->channels[sattr->index], + ret = iio_read_channel_raw(&state->channels[sattr->index], &val); if (ret < 0) return ret; - ret = iio_st_read_channel_scale(&state->channels[sattr->index], + ret = iio_read_channel_scale(&state->channels[sattr->index], &scaleint, &scalepart); if (ret < 0) return ret; @@ -106,7 +106,7 @@ static int __devinit iio_hwmon_probe(struct platform_device *pdev) goto error_ret; } - st->channels = iio_st_channel_get_all(dev_name(&pdev->dev)); + st->channels = iio_channel_get_all(dev_name(&pdev->dev)); if (IS_ERR(st->channels)) { ret = PTR_ERR(st->channels); goto error_free_state; @@ -130,7 +130,7 @@ static int __devinit iio_hwmon_probe(struct platform_device *pdev) } sysfs_attr_init(&a->dev_attr.attr); - ret = iio_st_get_channel_type(&st->channels[i], &type); + ret = iio_get_channel_type(&st->channels[i], &type); if (ret < 0) { kfree(a); goto error_free_attrs; @@ -186,7 +186,7 @@ error_free_attrs: iio_hwmon_free_attrs(st); kfree(st->attrs); error_release_channels: - iio_st_channel_release_all(st->channels); + iio_channel_release_all(st->channels); error_free_state: kfree(st); error_ret: @@ -201,7 +201,7 @@ static int __devexit iio_hwmon_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); iio_hwmon_free_attrs(st); kfree(st->attrs); - iio_st_channel_release_all(st->channels); + iio_channel_release_all(st->channels); return 0; } diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 387301437cf5..1f4c17779b5a 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -268,25 +268,6 @@ static int adis16400_reset(struct iio_dev *indio_dev) return ret; } -static ssize_t adis16400_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - if (val) { - ret = adis16400_reset(dev_to_iio_dev(dev)); - if (ret < 0) - return ret; - } - - return len; -} - int adis16400_set_irq(struct iio_dev *indio_dev, bool enable) { int ret; @@ -454,8 +435,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, adis16400_read_frequency, adis16400_write_frequency); -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); enum adis16400_chan { @@ -1066,7 +1045,6 @@ static const struct iio_chan_spec adis16334_channels[] = { static struct attribute *adis16400_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, NULL }; diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 1a15e560a5a1..e2657e6d4d26 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -33,17 +33,17 @@ struct iio_channel { * side. This typically describes the channels use within * the consumer. E.g. 'battery_voltage' */ -struct iio_channel *iio_st_channel_get(const char *name, - const char *consumer_channel); +struct iio_channel *iio_channel_get(const char *name, + const char *consumer_channel); /** - * iio_st_channel_release() - release channels obtained via iio_st_channel_get + * iio_channel_release() - release channels obtained via iio_channel_get * @chan: The channel to be released. */ -void iio_st_channel_release(struct iio_channel *chan); +void iio_channel_release(struct iio_channel *chan); /** - * iio_st_channel_get_all() - get all channels associated with a client + * iio_channel_get_all() - get all channels associated with a client * @name: name of consumer device. * * Returns an array of iio_channel structures terminated with one with @@ -51,37 +51,37 @@ void iio_st_channel_release(struct iio_channel *chan); * This function is used by fairly generic consumers to get all the * channels registered as having this consumer. */ -struct iio_channel *iio_st_channel_get_all(const char *name); +struct iio_channel *iio_channel_get_all(const char *name); /** - * iio_st_channel_release_all() - reverse iio_st_get_all + * iio_channel_release_all() - reverse iio_channel_get_all * @chan: Array of channels to be released. */ -void iio_st_channel_release_all(struct iio_channel *chan); +void iio_channel_release_all(struct iio_channel *chan); /** - * iio_st_read_channel_raw() - read from a given channel + * iio_read_channel_raw() - read from a given channel * @channel: The channel being queried. * @val: Value read back. * * Note raw reads from iio channels are in adc counts and hence * scale will need to be applied if standard units required. */ -int iio_st_read_channel_raw(struct iio_channel *chan, - int *val); +int iio_read_channel_raw(struct iio_channel *chan, + int *val); /** - * iio_st_get_channel_type() - get the type of a channel + * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. * @type: The type of the channel. * * returns the enum iio_chan_type of the channel */ -int iio_st_get_channel_type(struct iio_channel *channel, - enum iio_chan_type *type); +int iio_get_channel_type(struct iio_channel *channel, + enum iio_chan_type *type); /** - * iio_st_read_channel_scale() - read the scale value for a channel + * iio_read_channel_scale() - read the scale value for a channel * @channel: The channel being queried. * @val: First part of value read back. * @val2: Second part of value read back. @@ -90,7 +90,7 @@ int iio_st_get_channel_type(struct iio_channel *channel, * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val * + val2/1e6 */ -int iio_st_read_channel_scale(struct iio_channel *chan, int *val, - int *val2); +int iio_read_channel_scale(struct iio_channel *chan, int *val, + int *val2); #endif diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index d086736a9033..e25040173346 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -44,6 +44,8 @@ enum iio_modifier { IIO_MOD_X_OR_Y_OR_Z, IIO_MOD_LIGHT_BOTH, IIO_MOD_LIGHT_IR, + IIO_MOD_ROOT_SUM_SQUARED_X_Y, + IIO_MOD_SUM_SQUARED_X_Y_Z, }; #define IIO_VAL_INT 1 diff --git a/include/linux/platform_data/ad7266.h b/include/linux/platform_data/ad7266.h new file mode 100644 index 000000000000..eabfdcb26992 --- /dev/null +++ b/include/linux/platform_data/ad7266.h @@ -0,0 +1,54 @@ +/* + * AD7266/65 SPI ADC driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef __IIO_ADC_AD7266_H__ +#define __IIO_ADC_AD7266_H__ + +/** + * enum ad7266_range - AD7266 reference voltage range + * @AD7266_RANGE_VREF: Device is configured for input range 0V - VREF + * (RANGE pin set to low) + * @AD7266_RANGE_2VREF: Device is configured for input range 0V - 2VREF + * (RANGE pin set to high) + */ +enum ad7266_range { + AD7266_RANGE_VREF, + AD7266_RANGE_2VREF, +}; + +/** + * enum ad7266_mode - AD7266 sample mode + * @AD7266_MODE_DIFF: Device is configured for full differential mode + * (SGL/DIFF pin set to low, AD0 pin set to low) + * @AD7266_MODE_PSEUDO_DIFF: Device is configured for pseudo differential mode + * (SGL/DIFF pin set to low, AD0 pin set to high) + * @AD7266_MODE_SINGLE_ENDED: Device is configured for single-ended mode + * (SGL/DIFF pin set to high) + */ +enum ad7266_mode { + AD7266_MODE_DIFF, + AD7266_MODE_PSEUDO_DIFF, + AD7266_MODE_SINGLE_ENDED, +}; + +/** + * struct ad7266_platform_data - Platform data for the AD7266 driver + * @range: Reference voltage range the device is configured for + * @mode: Sample mode the device is configured for + * @fixed_addr: Whether the address pins are hard-wired + * @addr_gpios: GPIOs used for controlling the address pins, only used if + * fixed_addr is set to false. + */ +struct ad7266_platform_data { + enum ad7266_range range; + enum ad7266_mode mode; + bool fixed_addr; + unsigned int addr_gpios[3]; +}; + +#endif |