diff options
Diffstat (limited to 'drivers/iio/dac')
-rw-r--r-- | drivers/iio/dac/Kconfig | 12 | ||||
-rw-r--r-- | drivers/iio/dac/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/dac/ad5064.c | 18 | ||||
-rw-r--r-- | drivers/iio/dac/ad5360.c | 8 | ||||
-rw-r--r-- | drivers/iio/dac/ad5380.c | 28 | ||||
-rw-r--r-- | drivers/iio/dac/ad5421.c | 6 | ||||
-rw-r--r-- | drivers/iio/dac/ad5446.c | 24 | ||||
-rw-r--r-- | drivers/iio/dac/ad5449.c | 376 | ||||
-rw-r--r-- | drivers/iio/dac/ad5504.c | 12 | ||||
-rw-r--r-- | drivers/iio/dac/ad5624r_spi.c | 12 | ||||
-rw-r--r-- | drivers/iio/dac/ad5686.c | 14 | ||||
-rw-r--r-- | drivers/iio/dac/ad5755.c | 16 | ||||
-rw-r--r-- | drivers/iio/dac/ad5764.c | 6 | ||||
-rw-r--r-- | drivers/iio/dac/ad5791.c | 19 | ||||
-rw-r--r-- | drivers/iio/dac/max517.c | 6 | ||||
-rw-r--r-- | drivers/iio/dac/mcp4725.c | 8 |
16 files changed, 491 insertions, 75 deletions
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index b1c0ee5294ca..f4a6f0838327 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -67,6 +67,16 @@ config AD5446 To compile this driver as a module, choose M here: the module will be called ad5446. +config AD5449 + tristate "Analog Device AD5449 and similar DACs driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5415, AD5426, AD5429, + AD5432, AD5439, AD5443, AD5449 Digital to Analog Converters. + + To compile this driver as a module, choose M here: the + module will be called ad5449. + config AD5504 tristate "Analog Devices AD5504/AD5501 DAC SPI driver" depends on SPI @@ -122,7 +132,7 @@ config AD5686 config MAX517 tristate "Maxim MAX517/518/519 DAC driver" - depends on I2C && EXPERIMENTAL + depends on I2C 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). diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index c0d333b23ba3..5b528ebb3343 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o obj-$(CONFIG_AD5064) += ad5064.o obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o +obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index eb281a2c295b..2fe1d4edcb2f 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -424,8 +424,8 @@ 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 device *dev, enum ad5064_type type, - const char *name, ad5064_write_func write) +static int ad5064_probe(struct device *dev, enum ad5064_type type, + const char *name, ad5064_write_func write) { struct iio_dev *indio_dev; struct ad5064_state *st; @@ -495,7 +495,7 @@ error_free: return ret; } -static int __devexit ad5064_remove(struct device *dev) +static int ad5064_remove(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5064_state *st = iio_priv(indio_dev); @@ -523,7 +523,7 @@ static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, return spi_write(spi, &st->data.spi, sizeof(st->data.spi)); } -static int __devinit ad5064_spi_probe(struct spi_device *spi) +static int ad5064_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -531,7 +531,7 @@ static int __devinit ad5064_spi_probe(struct spi_device *spi) ad5064_spi_write); } -static int __devexit ad5064_spi_remove(struct spi_device *spi) +static int ad5064_spi_remove(struct spi_device *spi) { return ad5064_remove(&spi->dev); } @@ -563,7 +563,7 @@ static struct spi_driver ad5064_spi_driver = { .owner = THIS_MODULE, }, .probe = ad5064_spi_probe, - .remove = __devexit_p(ad5064_spi_remove), + .remove = ad5064_spi_remove, .id_table = ad5064_spi_ids, }; @@ -596,14 +596,14 @@ static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, return i2c_master_send(i2c, st->data.i2c, 3); } -static int __devinit ad5064_i2c_probe(struct i2c_client *i2c, +static int 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) +static int ad5064_i2c_remove(struct i2c_client *i2c) { return ad5064_remove(&i2c->dev); } @@ -625,7 +625,7 @@ static struct i2c_driver ad5064_i2c_driver = { .owner = THIS_MODULE, }, .probe = ad5064_i2c_probe, - .remove = __devexit_p(ad5064_i2c_remove), + .remove = ad5064_i2c_remove, .id_table = ad5064_i2c_ids, }; diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index 8fce84fe70b1..54b46fd3aede 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -433,7 +433,7 @@ static const char * const ad5360_vref_name[] = { "vref0", "vref1", "vref2" }; -static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) +static int ad5360_alloc_channels(struct iio_dev *indio_dev) { struct ad5360_state *st = iio_priv(indio_dev); struct iio_chan_spec *channels; @@ -456,7 +456,7 @@ static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) return 0; } -static int __devinit ad5360_probe(struct spi_device *spi) +static int ad5360_probe(struct spi_device *spi) { enum ad5360_type type = spi_get_device_id(spi)->driver_data; struct iio_dev *indio_dev; @@ -524,7 +524,7 @@ error_free: return ret; } -static int __devexit ad5360_remove(struct spi_device *spi) +static int ad5360_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5360_state *st = iio_priv(indio_dev); @@ -560,7 +560,7 @@ static struct spi_driver ad5360_driver = { .owner = THIS_MODULE, }, .probe = ad5360_probe, - .remove = __devexit_p(ad5360_remove), + .remove = ad5360_remove, .id_table = ad5360_ids, }; module_spi_driver(ad5360_driver); diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 14991ac55f26..483fc379a2da 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -338,7 +338,7 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { }, }; -static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev) +static int ad5380_alloc_channels(struct iio_dev *indio_dev) { struct ad5380_state *st = iio_priv(indio_dev); struct iio_chan_spec *channels; @@ -361,8 +361,8 @@ static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev) return 0; } -static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap, - enum ad5380_type type, const char *name) +static int ad5380_probe(struct device *dev, struct regmap *regmap, + enum ad5380_type type, const char *name) { struct iio_dev *indio_dev; struct ad5380_state *st; @@ -406,7 +406,11 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap, goto error_free_reg; } - st->vref = regulator_get_voltage(st->vref_reg); + ret = regulator_get_voltage(st->vref_reg); + if (ret < 0) + goto error_disable_reg; + + st->vref = ret; } else { st->vref = st->chip_info->int_vref; ctrl |= AD5380_CTRL_INT_VREF_EN; @@ -441,7 +445,7 @@ error_out: return ret; } -static int __devexit ad5380_remove(struct device *dev) +static int ad5380_remove(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5380_state *st = iio_priv(indio_dev); @@ -478,7 +482,7 @@ static const struct regmap_config ad5380_regmap_config = { #if IS_ENABLED(CONFIG_SPI_MASTER) -static int __devinit ad5380_spi_probe(struct spi_device *spi) +static int ad5380_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct regmap *regmap; @@ -491,7 +495,7 @@ static int __devinit ad5380_spi_probe(struct spi_device *spi) return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name); } -static int __devexit ad5380_spi_remove(struct spi_device *spi) +static int ad5380_spi_remove(struct spi_device *spi) { return ad5380_remove(&spi->dev); } @@ -523,7 +527,7 @@ static struct spi_driver ad5380_spi_driver = { .owner = THIS_MODULE, }, .probe = ad5380_spi_probe, - .remove = __devexit_p(ad5380_spi_remove), + .remove = ad5380_spi_remove, .id_table = ad5380_spi_ids, }; @@ -552,8 +556,8 @@ static inline void ad5380_spi_unregister_driver(void) #if IS_ENABLED(CONFIG_I2C) -static int __devinit ad5380_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int ad5380_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct regmap *regmap; @@ -565,7 +569,7 @@ static int __devinit ad5380_i2c_probe(struct i2c_client *i2c, return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name); } -static int __devexit ad5380_i2c_remove(struct i2c_client *i2c) +static int ad5380_i2c_remove(struct i2c_client *i2c) { return ad5380_remove(&i2c->dev); } @@ -597,7 +601,7 @@ static struct i2c_driver ad5380_i2c_driver = { .owner = THIS_MODULE, }, .probe = ad5380_i2c_probe, - .remove = __devexit_p(ad5380_i2c_remove), + .remove = ad5380_i2c_remove, .id_table = ad5380_i2c_ids, }; diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index cdbc5bf25c31..43be948db83e 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -449,7 +449,7 @@ static const struct iio_info ad5421_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad5421_probe(struct spi_device *spi) +static int ad5421_probe(struct spi_device *spi) { struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev); struct iio_dev *indio_dev; @@ -516,7 +516,7 @@ error_free: return ret; } -static int __devexit ad5421_remove(struct spi_device *spi) +static int ad5421_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); @@ -534,7 +534,7 @@ static struct spi_driver ad5421_driver = { .owner = THIS_MODULE, }, .probe = ad5421_probe, - .remove = __devexit_p(ad5421_remove), + .remove = ad5421_remove, }; module_spi_driver(ad5421_driver); diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 3310cbbd41e7..f5583aedfb59 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -212,8 +212,8 @@ static const struct iio_info ad5446_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad5446_probe(struct device *dev, const char *name, - const struct ad5446_chip_info *chip_info) +static int ad5446_probe(struct device *dev, const char *name, + const struct ad5446_chip_info *chip_info) { struct ad5446_state *st; struct iio_dev *indio_dev; @@ -226,7 +226,11 @@ static int __devinit ad5446_probe(struct device *dev, const char *name, if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(reg); + ret = regulator_get_voltage(reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } indio_dev = iio_device_alloc(sizeof(*st)); @@ -461,7 +465,7 @@ static const struct spi_device_id ad5446_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, ad5446_spi_ids); -static int __devinit ad5446_spi_probe(struct spi_device *spi) +static int ad5446_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -469,7 +473,7 @@ static int __devinit ad5446_spi_probe(struct spi_device *spi) &ad5446_spi_chip_info[id->driver_data]); } -static int __devexit ad5446_spi_remove(struct spi_device *spi) +static int ad5446_spi_remove(struct spi_device *spi) { return ad5446_remove(&spi->dev); } @@ -480,7 +484,7 @@ static struct spi_driver ad5446_spi_driver = { .owner = THIS_MODULE, }, .probe = ad5446_spi_probe, - .remove = __devexit_p(ad5446_spi_remove), + .remove = ad5446_spi_remove, .id_table = ad5446_spi_ids, }; @@ -539,14 +543,14 @@ static const struct ad5446_chip_info ad5446_i2c_chip_info[] = { }, }; -static int __devinit ad5446_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int ad5446_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { return ad5446_probe(&i2c->dev, id->name, &ad5446_i2c_chip_info[id->driver_data]); } -static int __devexit ad5446_i2c_remove(struct i2c_client *i2c) +static int ad5446_i2c_remove(struct i2c_client *i2c) { return ad5446_remove(&i2c->dev); } @@ -568,7 +572,7 @@ static struct i2c_driver ad5446_i2c_driver = { .owner = THIS_MODULE, }, .probe = ad5446_i2c_probe, - .remove = __devexit_p(ad5446_i2c_remove), + .remove = ad5446_i2c_remove, .id_table = ad5446_i2c_ids, }; diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c new file mode 100644 index 000000000000..c4731b7b577b --- /dev/null +++ b/drivers/iio/dac/ad5449.c @@ -0,0 +1,376 @@ +/* + * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog + * Converter driver. + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * 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/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> + +#include <linux/platform_data/ad5449.h> + +#define AD5449_MAX_CHANNELS 2 +#define AD5449_MAX_VREFS 2 + +#define AD5449_CMD_NOOP 0x0 +#define AD5449_CMD_LOAD_AND_UPDATE(x) (0x1 + (x) * 3) +#define AD5449_CMD_READ(x) (0x2 + (x) * 3) +#define AD5449_CMD_LOAD(x) (0x3 + (x) * 3) +#define AD5449_CMD_CTRL 13 + +#define AD5449_CTRL_SDO_OFFSET 10 +#define AD5449_CTRL_DAISY_CHAIN BIT(9) +#define AD5449_CTRL_HCLR_TO_MIDSCALE BIT(8) +#define AD5449_CTRL_SAMPLE_RISING BIT(7) + +/** + * struct ad5449_chip_info - chip specific information + * @channels: Channel specification + * @num_channels: Number of channels + * @has_ctrl: Chip has a control register + */ +struct ad5449_chip_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; + bool has_ctrl; +}; + +/** + * struct ad5449 - driver instance specific data + * @spi: the SPI device for this driver instance + * @chip_info: chip model specific constants, available modes etc + * @vref_reg: vref supply regulators + * @has_sdo: whether the SDO line is connected + * @dac_cache: Cache for the DAC values + * @data: spi transfer buffers + */ +struct ad5449 { + struct spi_device *spi; + const struct ad5449_chip_info *chip_info; + struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS]; + + bool has_sdo; + uint16_t dac_cache[AD5449_MAX_CHANNELS]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be16 data[2] ____cacheline_aligned; +}; + +enum ad5449_type { + ID_AD5426, + ID_AD5429, + ID_AD5432, + ID_AD5439, + ID_AD5443, + ID_AD5449, +}; + +static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr, + unsigned int val) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + st->data[0] = cpu_to_be16((addr << 12) | val); + ret = spi_write(st->spi, st->data, 2); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, + unsigned int *val) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + struct spi_message msg; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0], + .len = 2, + .cs_change = 1, + }, { + .tx_buf = &st->data[1], + .rx_buf = &st->data[1], + .len = 2, + }, + }; + + spi_message_init(&msg); + spi_message_add_tail(&t[0], &msg); + spi_message_add_tail(&t[1], &msg); + + mutex_lock(&indio_dev->mlock); + st->data[0] = cpu_to_be16(addr << 12); + st->data[1] = cpu_to_be16(AD5449_CMD_NOOP); + + ret = spi_sync(st->spi, &msg); + if (ret < 0) + goto out_unlock; + + *val = be16_to_cpu(st->data[1]); + +out_unlock: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad5449_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad5449 *st = iio_priv(indio_dev); + struct regulator_bulk_data *reg; + int scale_uv; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (st->has_sdo) { + ret = ad5449_read(indio_dev, + AD5449_CMD_READ(chan->address), val); + if (ret) + return ret; + *val &= 0xfff; + } else { + *val = st->dac_cache[chan->address]; + } + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + reg = &st->vref_reg[chan->channel]; + scale_uv = regulator_get_voltage(reg->consumer); + if (scale_uv < 0) + return scale_uv; + + *val = scale_uv / 1000; + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + + return -EINVAL; +} + +static int ad5449_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long info) +{ + struct ad5449 *st = iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (val < 0 || val >= (1 << chan->scan_type.realbits)) + return -EINVAL; + + ret = ad5449_write(indio_dev, + AD5449_CMD_LOAD_AND_UPDATE(chan->address), + val << chan->scan_type.shift); + if (ret == 0) + st->dac_cache[chan->address] = val; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info ad5449_info = { + .read_raw = ad5449_read_raw, + .write_raw = ad5449_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD5449_CHANNEL(chan, bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = (chan), \ + .scan_type = IIO_ST('u', (bits), 16, 12 - (bits)), \ +} + +#define DECLARE_AD5449_CHANNELS(name, bits) \ +const struct iio_chan_spec name[] = { \ + AD5449_CHANNEL(0, bits), \ + AD5449_CHANNEL(1, bits), \ +} + +static DECLARE_AD5449_CHANNELS(ad5429_channels, 8); +static DECLARE_AD5449_CHANNELS(ad5439_channels, 10); +static DECLARE_AD5449_CHANNELS(ad5449_channels, 12); + +static const struct ad5449_chip_info ad5449_chip_info[] = { + [ID_AD5426] = { + .channels = ad5429_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5429] = { + .channels = ad5429_channels, + .num_channels = 2, + .has_ctrl = true, + }, + [ID_AD5432] = { + .channels = ad5439_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5439] = { + .channels = ad5439_channels, + .num_channels = 2, + .has_ctrl = true, + }, + [ID_AD5443] = { + .channels = ad5449_channels, + .num_channels = 1, + .has_ctrl = false, + }, + [ID_AD5449] = { + .channels = ad5449_channels, + .num_channels = 2, + .has_ctrl = true, + }, +}; + +static const char *ad5449_vref_name(struct ad5449 *st, int n) +{ + if (st->chip_info->num_channels == 1) + return "VREF"; + + if (n == 0) + return "VREFA"; + else + return "VREFB"; +} + +static int ad5449_spi_probe(struct spi_device *spi) +{ + struct ad5449_platform_data *pdata = spi->dev.platform_data; + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct ad5449 *st; + unsigned int i; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->chip_info = &ad5449_chip_info[id->driver_data]; + st->spi = spi; + + for (i = 0; i < st->chip_info->num_channels; ++i) + st->vref_reg[i].supply = ad5449_vref_name(st, i); + + ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels, + st->vref_reg); + if (ret) + goto error_free; + + ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg); + if (ret) + goto error_free_reg; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = id->name; + indio_dev->info = &ad5449_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + if (st->chip_info->has_ctrl) { + unsigned int ctrl = 0x00; + if (pdata) { + if (pdata->hardware_clear_to_midscale) + ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; + ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; + st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; + } else { + st->has_sdo = true; + } + ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); +error_free_reg: + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int ad5449_spi_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5449 *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5449_spi_ids[] = { + { "ad5415", ID_AD5449 }, + { "ad5426", ID_AD5426 }, + { "ad5429", ID_AD5429 }, + { "ad5432", ID_AD5432 }, + { "ad5439", ID_AD5439 }, + { "ad5443", ID_AD5443 }, + { "ad5449", ID_AD5449 }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5449_spi_ids); + +static struct spi_driver ad5449_spi_driver = { + .driver = { + .name = "ad5449", + .owner = THIS_MODULE, + }, + .probe = ad5449_spi_probe, + .remove = ad5449_spi_remove, + .id_table = ad5449_spi_ids, +}; +module_spi_driver(ad5449_spi_driver); + +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); +MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index 242bdc7d0044..0661829f2773 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -277,7 +277,7 @@ static const struct iio_chan_spec ad5504_channels[] = { AD5504_CHANNEL(3), }; -static int __devinit ad5504_probe(struct spi_device *spi) +static int ad5504_probe(struct spi_device *spi) { struct ad5504_platform_data *pdata = spi->dev.platform_data; struct iio_dev *indio_dev; @@ -296,7 +296,11 @@ static int __devinit ad5504_probe(struct spi_device *spi) if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(reg); + ret = regulator_get_voltage(reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } spi_set_drvdata(spi, indio_dev); @@ -352,7 +356,7 @@ error_ret: return ret; } -static int __devexit ad5504_remove(struct spi_device *spi) +static int ad5504_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5504_state *st = iio_priv(indio_dev); @@ -383,7 +387,7 @@ static struct spi_driver ad5504_driver = { .owner = THIS_MODULE, }, .probe = ad5504_probe, - .remove = __devexit_p(ad5504_remove), + .remove = ad5504_remove, .id_table = ad5504_id, }; module_spi_driver(ad5504_driver); diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 6a7d6a48cc6d..f6e116627b71 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -220,7 +220,7 @@ static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { }, }; -static int __devinit ad5624r_probe(struct spi_device *spi) +static int ad5624r_probe(struct spi_device *spi) { struct ad5624r_state *st; struct iio_dev *indio_dev; @@ -238,7 +238,11 @@ static int __devinit ad5624r_probe(struct spi_device *spi) if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_get_voltage(st->reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } spi_set_drvdata(spi, indio_dev); @@ -282,7 +286,7 @@ error_ret: return ret; } -static int __devexit ad5624r_remove(struct spi_device *spi) +static int ad5624r_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5624r_state *st = iio_priv(indio_dev); @@ -314,7 +318,7 @@ static struct spi_driver ad5624r_driver = { .owner = THIS_MODULE, }, .probe = ad5624r_probe, - .remove = __devexit_p(ad5624r_remove), + .remove = ad5624r_remove, .id_table = ad5624r_id, }; module_spi_driver(ad5624r_driver); diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 6948d75e1036..ca9609d7a15c 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -188,7 +188,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, if (ret) return ret; - if (readin == true) + if (readin) st->pwr_down_mask |= (0x3 << (chan->channel * 2)); else st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); @@ -313,7 +313,7 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { }; -static int __devinit ad5686_probe(struct spi_device *spi) +static int ad5686_probe(struct spi_device *spi) { struct ad5686_state *st; struct iio_dev *indio_dev; @@ -332,7 +332,11 @@ static int __devinit ad5686_probe(struct spi_device *spi) if (ret) goto error_put_reg; - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_get_voltage(st->reg); + if (ret < 0) + goto error_disable_reg; + + voltage_uv = ret; } st->chip_info = @@ -379,7 +383,7 @@ error_put_reg: return ret; } -static int __devexit ad5686_remove(struct spi_device *spi) +static int ad5686_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5686_state *st = iio_priv(indio_dev); @@ -408,7 +412,7 @@ static struct spi_driver ad5686_driver = { .owner = THIS_MODULE, }, .probe = ad5686_probe, - .remove = __devexit_p(ad5686_remove), + .remove = ad5686_remove, .id_table = ad5686_id, }; module_spi_driver(ad5686_driver); diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 5db3506034c5..0869bbd27d30 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -447,8 +447,8 @@ static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode) } } -static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev, - const struct ad5755_platform_data *pdata) +static int ad5755_setup_pdata(struct iio_dev *indio_dev, + const struct ad5755_platform_data *pdata) { struct ad5755_state *st = iio_priv(indio_dev); unsigned int val; @@ -503,7 +503,7 @@ static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev, return 0; } -static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode) +static bool ad5755_is_voltage_mode(enum ad5755_mode mode) { switch (mode) { case AD5755_MODE_VOLTAGE_0V_5V: @@ -516,8 +516,8 @@ static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode) } } -static int __devinit ad5755_init_channels(struct iio_dev *indio_dev, - const struct ad5755_platform_data *pdata) +static int ad5755_init_channels(struct iio_dev *indio_dev, + const struct ad5755_platform_data *pdata) { struct ad5755_state *st = iio_priv(indio_dev); struct iio_chan_spec *channels = st->channels; @@ -562,7 +562,7 @@ static const struct ad5755_platform_data ad5755_default_pdata = { }, }; -static int __devinit ad5755_probe(struct spi_device *spi) +static int ad5755_probe(struct spi_device *spi) { enum ad5755_type type = spi_get_device_id(spi)->driver_data; const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev); @@ -614,7 +614,7 @@ error_free: return ret; } -static int __devexit ad5755_remove(struct spi_device *spi) +static int ad5755_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); @@ -640,7 +640,7 @@ static struct spi_driver ad5755_driver = { .owner = THIS_MODULE, }, .probe = ad5755_probe, - .remove = __devexit_p(ad5755_remove), + .remove = ad5755_remove, .id_table = ad5755_id, }; module_spi_driver(ad5755_driver); diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index ffce30447445..7f9045e6daa4 100644 --- a/drivers/iio/dac/ad5764.c +++ b/drivers/iio/dac/ad5764.c @@ -273,7 +273,7 @@ static const struct iio_info ad5764_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad5764_probe(struct spi_device *spi) +static int ad5764_probe(struct spi_device *spi) { enum ad5764_type type = spi_get_device_id(spi)->driver_data; struct iio_dev *indio_dev; @@ -340,7 +340,7 @@ error_free: return ret; } -static int __devexit ad5764_remove(struct spi_device *spi) +static int ad5764_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5764_state *st = iio_priv(indio_dev); @@ -372,7 +372,7 @@ static struct spi_driver ad5764_driver = { .owner = THIS_MODULE, }, .probe = ad5764_probe, - .remove = __devexit_p(ad5764_remove), + .remove = ad5764_remove, .id_table = ad5764_ids, }; module_spi_driver(ad5764_driver); diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 2bd2e37280ff..6407b5407ddd 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -346,7 +346,7 @@ static const struct iio_info ad5791_info = { .driver_module = THIS_MODULE, }; -static int __devinit ad5791_probe(struct spi_device *spi) +static int ad5791_probe(struct spi_device *spi) { struct ad5791_platform_data *pdata = spi->dev.platform_data; struct iio_dev *indio_dev; @@ -365,7 +365,11 @@ static int __devinit ad5791_probe(struct spi_device *spi) if (ret) goto error_put_reg_pos; - pos_voltage_uv = regulator_get_voltage(st->reg_vdd); + ret = regulator_get_voltage(st->reg_vdd); + if (ret < 0) + goto error_disable_reg_pos; + + pos_voltage_uv = ret; } st->reg_vss = regulator_get(&spi->dev, "vss"); @@ -374,7 +378,11 @@ static int __devinit ad5791_probe(struct spi_device *spi) if (ret) goto error_put_reg_neg; - neg_voltage_uv = regulator_get_voltage(st->reg_vss); + ret = regulator_get_voltage(st->reg_vss); + if (ret < 0) + goto error_disable_reg_neg; + + neg_voltage_uv = ret; } st->pwr_down = true; @@ -428,6 +436,7 @@ error_put_reg_neg: if (!IS_ERR(st->reg_vss)) regulator_put(st->reg_vss); +error_disable_reg_pos: if (!IS_ERR(st->reg_vdd)) regulator_disable(st->reg_vdd); error_put_reg_pos: @@ -439,7 +448,7 @@ error_ret: return ret; } -static int __devexit ad5791_remove(struct spi_device *spi) +static int ad5791_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5791_state *st = iio_priv(indio_dev); @@ -475,7 +484,7 @@ static struct spi_driver ad5791_driver = { .owner = THIS_MODULE, }, .probe = ad5791_probe, - .remove = __devexit_p(ad5791_remove), + .remove = ad5791_remove, .id_table = ad5791_id, }; module_spi_driver(ad5791_driver); diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index c3d748c25939..352abe2004a4 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -156,7 +156,7 @@ static const struct iio_chan_spec max517_channels[] = { MAX517_CHANNEL(1) }; -static int __devinit max517_probe(struct i2c_client *client, +static int max517_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max517_data *data; @@ -210,7 +210,7 @@ exit: return err; } -static int __devexit max517_remove(struct i2c_client *client) +static int max517_remove(struct i2c_client *client) { iio_device_unregister(i2c_get_clientdata(client)); iio_device_free(i2c_get_clientdata(client)); @@ -232,7 +232,7 @@ static struct i2c_driver max517_driver = { .pm = MAX517_PM_OPS, }, .probe = max517_probe, - .remove = __devexit_p(max517_remove), + .remove = max517_remove, .id_table = max517_id, }; module_i2c_driver(max517_driver); diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index e0e168bd5b45..8f88cc4059a2 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -141,8 +141,8 @@ static const struct iio_info mcp4725_info = { .driver_module = THIS_MODULE, }; -static int __devinit mcp4725_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mcp4725_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct mcp4725_data *data; struct iio_dev *indio_dev; @@ -195,7 +195,7 @@ exit: return err; } -static int __devexit mcp4725_remove(struct i2c_client *client) +static int mcp4725_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); @@ -217,7 +217,7 @@ static struct i2c_driver mcp4725_driver = { .pm = MCP4725_PM_OPS, }, .probe = mcp4725_probe, - .remove = __devexit_p(mcp4725_remove), + .remove = mcp4725_remove, .id_table = mcp4725_id, }; module_i2c_driver(mcp4725_driver); |