summaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/dac/ad5380.c
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-09-12 11:14:33 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-09-12 11:14:33 -0400
commit25a765b7f05cb8460fa01b54568894b20e184862 (patch)
tree0b56db57b4d9f912393ab303c269e0fe6cdf8635 /drivers/staging/iio/dac/ad5380.c
parent9d2be9287107695708e6aae5105a8a518a6cb4d0 (diff)
parent64282278989d5b0398dcb3ba7904cb00c621dc35 (diff)
downloadlinux-stable-25a765b7f05cb8460fa01b54568894b20e184862.tar.gz
linux-stable-25a765b7f05cb8460fa01b54568894b20e184862.tar.bz2
linux-stable-25a765b7f05cb8460fa01b54568894b20e184862.zip
Merge branch 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into stable/for-linus-3.7
* 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (9690 commits) x86: Document x86_init.paging.pagetable_init() x86: xen: Cleanup and remove x86_init.paging.pagetable_setup_done() x86: Move paging_init() call to x86_init.paging.pagetable_init() x86: Rename pagetable_setup_start() to pagetable_init() x86: Remove base argument from x86_init.paging.pagetable_setup_start Linux 3.6-rc5 HID: tpkbd: work even if the new Lenovo Keyboard driver is not configured Remove user-triggerable BUG from mpol_to_str xen/pciback: Fix proper FLR steps. uml: fix compile error in deliver_alarm() dj: memory scribble in logi_dj Fix order of arguments to compat_put_time[spec|val] xen: Use correct masking in xen_swiotlb_alloc_coherent. xen: fix logical error in tlb flushing xen/p2m: Fix one-off error in checking the P2M tree directory. powerpc: Don't use __put_user() in patch_instruction powerpc: Make sure IPI handlers see data written by IPI senders powerpc: Restore correct DSCR in context switch powerpc: Fix DSCR inheritance in copy_thread() powerpc: Keep thread.dscr and thread.dscr_inherit in sync ...
Diffstat (limited to 'drivers/staging/iio/dac/ad5380.c')
-rw-r--r--drivers/staging/iio/dac/ad5380.c677
1 files changed, 0 insertions, 677 deletions
diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c
deleted file mode 100644
index 370d2842190e..000000000000
--- a/drivers/staging/iio/dac/ad5380.c
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * Analog devices AD5380, AD5381, AD5382, AD5383, AD5390, AD5391, AD5392
- * multi-channel 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/i2c.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include "dac.h"
-
-
-#define AD5380_REG_DATA(x) (((x) << 2) | 3)
-#define AD5380_REG_OFFSET(x) (((x) << 2) | 2)
-#define AD5380_REG_GAIN(x) (((x) << 2) | 1)
-#define AD5380_REG_SF_PWR_DOWN (8 << 2)
-#define AD5380_REG_SF_PWR_UP (9 << 2)
-#define AD5380_REG_SF_CTRL (12 << 2)
-
-#define AD5380_CTRL_PWR_DOWN_MODE_OFFSET 13
-#define AD5380_CTRL_INT_VREF_2V5 BIT(12)
-#define AD5380_CTRL_INT_VREF_EN BIT(10)
-
-/**
- * struct ad5380_chip_info - chip specific information
- * @channel_template: channel specification template
- * @num_channels: number of channels
- * @int_vref: internal vref in uV
-*/
-
-struct ad5380_chip_info {
- struct iio_chan_spec channel_template;
- unsigned int num_channels;
- unsigned int int_vref;
-};
-
-/**
- * struct ad5380_state - driver instance specific data
- * @regmap: regmap instance used by the device
- * @chip_info: chip model specific constants, available modes etc
- * @vref_reg: vref supply regulator
- * @vref: actual reference voltage used in uA
- * @pwr_down: whether the chip is currently in power down mode
- */
-
-struct ad5380_state {
- struct regmap *regmap;
- const struct ad5380_chip_info *chip_info;
- struct regulator *vref_reg;
- int vref;
- bool pwr_down;
-};
-
-enum ad5380_type {
- ID_AD5380_3,
- ID_AD5380_5,
- ID_AD5381_3,
- ID_AD5381_5,
- ID_AD5382_3,
- ID_AD5382_5,
- ID_AD5383_3,
- ID_AD5383_5,
- ID_AD5390_3,
- ID_AD5390_5,
- ID_AD5391_3,
- ID_AD5391_5,
- ID_AD5392_3,
- ID_AD5392_5,
-};
-
-#define AD5380_CHANNEL(_bits) { \
- .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .output = 1, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
- .scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)) \
-}
-
-static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
- [ID_AD5380_3] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 40,
- .int_vref = 1250000,
- },
- [ID_AD5380_5] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 40,
- .int_vref = 2500000,
- },
- [ID_AD5381_3] = {
- .channel_template = AD5380_CHANNEL(12),
- .num_channels = 16,
- .int_vref = 1250000,
- },
- [ID_AD5381_5] = {
- .channel_template = AD5380_CHANNEL(12),
- .num_channels = 16,
- .int_vref = 2500000,
- },
- [ID_AD5382_3] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 32,
- .int_vref = 1250000,
- },
- [ID_AD5382_5] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 32,
- .int_vref = 2500000,
- },
- [ID_AD5383_3] = {
- .channel_template = AD5380_CHANNEL(12),
- .num_channels = 32,
- .int_vref = 1250000,
- },
- [ID_AD5383_5] = {
- .channel_template = AD5380_CHANNEL(12),
- .num_channels = 32,
- .int_vref = 2500000,
- },
- [ID_AD5390_3] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 16,
- .int_vref = 1250000,
- },
- [ID_AD5390_5] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 16,
- .int_vref = 2500000,
- },
- [ID_AD5391_3] = {
- .channel_template = AD5380_CHANNEL(12),
- .num_channels = 16,
- .int_vref = 1250000,
- },
- [ID_AD5391_5] = {
- .channel_template = AD5380_CHANNEL(12),
- .num_channels = 16,
- .int_vref = 2500000,
- },
- [ID_AD5392_3] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 8,
- .int_vref = 1250000,
- },
- [ID_AD5392_5] = {
- .channel_template = AD5380_CHANNEL(14),
- .num_channels = 8,
- .int_vref = 2500000,
- },
-};
-
-static ssize_t ad5380_read_dac_powerdown(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
-
- return sprintf(buf, "%d\n", st->pwr_down);
-}
-
-static ssize_t ad5380_write_dac_powerdown(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
- bool pwr_down;
- int ret;
-
- ret = strtobool(buf, &pwr_down);
- if (ret)
- return ret;
-
- mutex_lock(&indio_dev->mlock);
-
- if (pwr_down)
- ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0);
- else
- ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_UP, 0);
-
- st->pwr_down = pwr_down;
-
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
-static IIO_DEVICE_ATTR(out_voltage_powerdown,
- S_IRUGO | S_IWUSR,
- ad5380_read_dac_powerdown,
- ad5380_write_dac_powerdown, 0);
-
-static const char ad5380_powerdown_modes[][15] = {
- [0] = "100kohm_to_gnd",
- [1] = "three_state",
-};
-
-static ssize_t ad5380_read_powerdown_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
- unsigned int mode;
- int ret;
-
- ret = regmap_read(st->regmap, AD5380_REG_SF_CTRL, &mode);
- if (ret)
- return ret;
-
- mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1;
-
- return sprintf(buf, "%s\n", ad5380_powerdown_modes[mode]);
-}
-
-static ssize_t ad5380_write_powerdown_mode(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
- unsigned int i;
- int ret;
-
- for (i = 0; i < ARRAY_SIZE(ad5380_powerdown_modes); ++i) {
- if (sysfs_streq(buf, ad5380_powerdown_modes[i]))
- break;
- }
-
- if (i == ARRAY_SIZE(ad5380_powerdown_modes))
- return -EINVAL;
-
- ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL,
- 1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET,
- i << AD5380_CTRL_PWR_DOWN_MODE_OFFSET);
-
- return ret ? ret : len;
-}
-
-static IIO_DEVICE_ATTR(out_voltage_powerdown_mode,
- S_IRUGO | S_IWUSR,
- ad5380_read_powerdown_mode,
- ad5380_write_powerdown_mode, 0);
-
-static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
- "100kohm_to_gnd three_state");
-
-static struct attribute *ad5380_attributes[] = {
- &iio_dev_attr_out_voltage_powerdown.dev_attr.attr,
- &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ad5380_attribute_group = {
- .attrs = ad5380_attributes,
-};
-
-static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan,
- long info)
-{
- switch (info) {
- case 0:
- return AD5380_REG_DATA(chan->address);
- case IIO_CHAN_INFO_CALIBBIAS:
- return AD5380_REG_OFFSET(chan->address);
- case IIO_CHAN_INFO_CALIBSCALE:
- return AD5380_REG_GAIN(chan->address);
- default:
- break;
- }
-
- return 0;
-}
-
-static int ad5380_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan, int val, int val2, long info)
-{
- const unsigned int max_val = (1 << chan->scan_type.realbits);
- struct ad5380_state *st = iio_priv(indio_dev);
-
- switch (info) {
- case IIO_CHAN_INFO_RAW:
- case IIO_CHAN_INFO_CALIBSCALE:
- if (val >= max_val || val < 0)
- return -EINVAL;
-
- return regmap_write(st->regmap,
- ad5380_info_to_reg(chan, info),
- val << chan->scan_type.shift);
- case IIO_CHAN_INFO_CALIBBIAS:
- val += (1 << chan->scan_type.realbits) / 2;
- if (val >= max_val || val < 0)
- return -EINVAL;
-
- return regmap_write(st->regmap,
- AD5380_REG_OFFSET(chan->address),
- val << chan->scan_type.shift);
- default:
- break;
- }
- return -EINVAL;
-}
-
-static int ad5380_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan, int *val, int *val2, long info)
-{
- struct ad5380_state *st = iio_priv(indio_dev);
- unsigned long scale_uv;
- int ret;
-
- switch (info) {
- case IIO_CHAN_INFO_RAW:
- case IIO_CHAN_INFO_CALIBSCALE:
- ret = regmap_read(st->regmap, ad5380_info_to_reg(chan, info),
- val);
- if (ret)
- return ret;
- *val >>= chan->scan_type.shift;
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_CALIBBIAS:
- ret = regmap_read(st->regmap, AD5380_REG_OFFSET(chan->address),
- val);
- if (ret)
- return ret;
- *val >>= chan->scan_type.shift;
- val -= (1 << chan->scan_type.realbits) / 2;
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_SCALE:
- scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100;
- *val = scale_uv / 100000;
- *val2 = (scale_uv % 100000) * 10;
- return IIO_VAL_INT_PLUS_MICRO;
- default:
- break;
- }
-
- return -EINVAL;
-}
-
-static const struct iio_info ad5380_info = {
- .read_raw = ad5380_read_raw,
- .write_raw = ad5380_write_raw,
- .attrs = &ad5380_attribute_group,
- .driver_module = THIS_MODULE,
-};
-
-static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev)
-{
- struct ad5380_state *st = iio_priv(indio_dev);
- struct iio_chan_spec *channels;
- unsigned int i;
-
- channels = kcalloc(st->chip_info->num_channels,
- sizeof(struct iio_chan_spec), GFP_KERNEL);
-
- if (!channels)
- return -ENOMEM;
-
- for (i = 0; i < st->chip_info->num_channels; ++i) {
- channels[i] = st->chip_info->channel_template;
- channels[i].channel = i;
- channels[i].address = i;
- }
-
- indio_dev->channels = channels;
-
- return 0;
-}
-
-static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
- enum ad5380_type type, const char *name)
-{
- struct iio_dev *indio_dev;
- struct ad5380_state *st;
- unsigned int ctrl = 0;
- int ret;
-
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- dev_err(dev, "Failed to allocate iio device\n");
- ret = -ENOMEM;
- goto error_regmap_exit;
- }
-
- st = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
-
- st->chip_info = &ad5380_chip_info_tbl[type];
- st->regmap = regmap;
-
- indio_dev->dev.parent = dev;
- indio_dev->name = name;
- indio_dev->info = &ad5380_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->num_channels = st->chip_info->num_channels;
-
- ret = ad5380_alloc_channels(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
- goto error_free;
- }
-
- if (st->chip_info->int_vref == 2500000)
- ctrl |= AD5380_CTRL_INT_VREF_2V5;
-
- st->vref_reg = regulator_get(dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(dev, "Failed to enable vref regulators: %d\n",
- ret);
- goto error_free_reg;
- }
-
- st->vref = regulator_get_voltage(st->vref_reg);
- } else {
- st->vref = st->chip_info->int_vref;
- ctrl |= AD5380_CTRL_INT_VREF_EN;
- }
-
- ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl);
- if (ret) {
- dev_err(dev, "Failed to write to device: %d\n", ret);
- goto error_disable_reg;
- }
-
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to register iio device: %d\n", ret);
- goto error_disable_reg;
- }
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
-error_free_reg:
- if (!IS_ERR(st->vref_reg))
- regulator_put(st->vref_reg);
-
- kfree(indio_dev->channels);
-error_free:
- iio_device_free(indio_dev);
-error_regmap_exit:
- regmap_exit(regmap);
-
- return ret;
-}
-
-static int __devexit ad5380_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- kfree(indio_dev->channels);
-
- if (!IS_ERR(st->vref_reg)) {
- regulator_disable(st->vref_reg);
- regulator_put(st->vref_reg);
- }
-
- regmap_exit(st->regmap);
- iio_device_free(indio_dev);
-
- return 0;
-}
-
-static bool ad5380_reg_false(struct device *dev, unsigned int reg)
-{
- return false;
-}
-
-static const struct regmap_config ad5380_regmap_config = {
- .reg_bits = 10,
- .val_bits = 14,
-
- .max_register = AD5380_REG_DATA(40),
- .cache_type = REGCACHE_RBTREE,
-
- .volatile_reg = ad5380_reg_false,
- .readable_reg = ad5380_reg_false,
-};
-
-#if IS_ENABLED(CONFIG_SPI_MASTER)
-
-static int __devinit ad5380_spi_probe(struct spi_device *spi)
-{
- const struct spi_device_id *id = spi_get_device_id(spi);
- struct regmap *regmap;
-
- regmap = regmap_init_spi(spi, &ad5380_regmap_config);
-
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
- return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
-}
-
-static int __devexit ad5380_spi_remove(struct spi_device *spi)
-{
- return ad5380_remove(&spi->dev);
-}
-
-static const struct spi_device_id ad5380_spi_ids[] = {
- { "ad5380-3", ID_AD5380_3 },
- { "ad5380-5", ID_AD5380_5 },
- { "ad5381-3", ID_AD5381_3 },
- { "ad5381-5", ID_AD5381_5 },
- { "ad5382-3", ID_AD5382_3 },
- { "ad5382-5", ID_AD5382_5 },
- { "ad5383-3", ID_AD5383_3 },
- { "ad5383-5", ID_AD5383_5 },
- { "ad5384-3", ID_AD5380_3 },
- { "ad5384-5", ID_AD5380_5 },
- { "ad5390-3", ID_AD5390_3 },
- { "ad5390-5", ID_AD5390_5 },
- { "ad5391-3", ID_AD5391_3 },
- { "ad5391-5", ID_AD5391_5 },
- { "ad5392-3", ID_AD5392_3 },
- { "ad5392-5", ID_AD5392_5 },
- { }
-};
-MODULE_DEVICE_TABLE(spi, ad5380_spi_ids);
-
-static struct spi_driver ad5380_spi_driver = {
- .driver = {
- .name = "ad5380",
- .owner = THIS_MODULE,
- },
- .probe = ad5380_spi_probe,
- .remove = __devexit_p(ad5380_spi_remove),
- .id_table = ad5380_spi_ids,
-};
-
-static inline int ad5380_spi_register_driver(void)
-{
- return spi_register_driver(&ad5380_spi_driver);
-}
-
-static inline void ad5380_spi_unregister_driver(void)
-{
- spi_unregister_driver(&ad5380_spi_driver);
-}
-
-#else
-
-static inline int ad5380_spi_register_driver(void)
-{
- return 0;
-}
-
-static inline void ad5380_spi_unregister_driver(void)
-{
-}
-
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
-
-static int __devinit ad5380_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct regmap *regmap;
-
- regmap = regmap_init_i2c(i2c, &ad5380_regmap_config);
-
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
- return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);
-}
-
-static int __devexit ad5380_i2c_remove(struct i2c_client *i2c)
-{
- return ad5380_remove(&i2c->dev);
-}
-
-static const struct i2c_device_id ad5380_i2c_ids[] = {
- { "ad5380-3", ID_AD5380_3 },
- { "ad5380-5", ID_AD5380_5 },
- { "ad5381-3", ID_AD5381_3 },
- { "ad5381-5", ID_AD5381_5 },
- { "ad5382-3", ID_AD5382_3 },
- { "ad5382-5", ID_AD5382_5 },
- { "ad5383-3", ID_AD5383_3 },
- { "ad5383-5", ID_AD5383_5 },
- { "ad5384-3", ID_AD5380_3 },
- { "ad5384-5", ID_AD5380_5 },
- { "ad5390-3", ID_AD5390_3 },
- { "ad5390-5", ID_AD5390_5 },
- { "ad5391-3", ID_AD5391_3 },
- { "ad5391-5", ID_AD5391_5 },
- { "ad5392-3", ID_AD5392_3 },
- { "ad5392-5", ID_AD5392_5 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids);
-
-static struct i2c_driver ad5380_i2c_driver = {
- .driver = {
- .name = "ad5380",
- .owner = THIS_MODULE,
- },
- .probe = ad5380_i2c_probe,
- .remove = __devexit_p(ad5380_i2c_remove),
- .id_table = ad5380_i2c_ids,
-};
-
-static inline int ad5380_i2c_register_driver(void)
-{
- return i2c_add_driver(&ad5380_i2c_driver);
-}
-
-static inline void ad5380_i2c_unregister_driver(void)
-{
- i2c_del_driver(&ad5380_i2c_driver);
-}
-
-#else
-
-static inline int ad5380_i2c_register_driver(void)
-{
- return 0;
-}
-
-static inline void ad5380_i2c_unregister_driver(void)
-{
-}
-
-#endif
-
-static int __init ad5380_spi_init(void)
-{
- int ret;
-
- ret = ad5380_spi_register_driver();
- if (ret)
- return ret;
-
- ret = ad5380_i2c_register_driver();
- if (ret) {
- ad5380_spi_unregister_driver();
- return ret;
- }
-
- return 0;
-}
-module_init(ad5380_spi_init);
-
-static void __exit ad5380_spi_exit(void)
-{
- ad5380_i2c_unregister_driver();
- ad5380_spi_unregister_driver();
-
-}
-module_exit(ad5380_spi_exit);
-
-MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("Analog Devices AD5380/81/82/83/84/90/91/92 DAC");
-MODULE_LICENSE("GPL v2");