linux/drivers/staging/iio/adc/ad7780.c
<<
>>
Prefs
   1/*
   2 * AD7170/AD7171 and AD7780/AD7781 SPI ADC driver
   3 *
   4 * Copyright 2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/device.h>
  11#include <linux/kernel.h>
  12#include <linux/slab.h>
  13#include <linux/sysfs.h>
  14#include <linux/spi/spi.h>
  15#include <linux/regulator/consumer.h>
  16#include <linux/err.h>
  17#include <linux/sched.h>
  18#include <linux/gpio/consumer.h>
  19#include <linux/module.h>
  20
  21#include <linux/iio/iio.h>
  22#include <linux/iio/sysfs.h>
  23#include <linux/iio/adc/ad_sigma_delta.h>
  24
  25#define AD7780_RDY      BIT(7)
  26#define AD7780_FILTER   BIT(6)
  27#define AD7780_ERR      BIT(5)
  28#define AD7780_ID1      BIT(4)
  29#define AD7780_ID0      BIT(3)
  30#define AD7780_GAIN     BIT(2)
  31#define AD7780_PAT1     BIT(1)
  32#define AD7780_PAT0     BIT(0)
  33
  34struct ad7780_chip_info {
  35        struct iio_chan_spec    channel;
  36        unsigned int            pattern_mask;
  37        unsigned int            pattern;
  38};
  39
  40struct ad7780_state {
  41        const struct ad7780_chip_info   *chip_info;
  42        struct regulator                *reg;
  43        struct gpio_desc                *powerdown_gpio;
  44        unsigned int    gain;
  45        u16                             int_vref_mv;
  46
  47        struct ad_sigma_delta sd;
  48};
  49
  50enum ad7780_supported_device_ids {
  51        ID_AD7170,
  52        ID_AD7171,
  53        ID_AD7780,
  54        ID_AD7781,
  55};
  56
  57static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd)
  58{
  59        return container_of(sd, struct ad7780_state, sd);
  60}
  61
  62static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
  63                           enum ad_sigma_delta_mode mode)
  64{
  65        struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
  66        unsigned int val;
  67
  68        switch (mode) {
  69        case AD_SD_MODE_SINGLE:
  70        case AD_SD_MODE_CONTINUOUS:
  71                val = 1;
  72                break;
  73        default:
  74                val = 0;
  75                break;
  76        }
  77
  78        gpiod_set_value(st->powerdown_gpio, val);
  79
  80        return 0;
  81}
  82
  83static int ad7780_read_raw(struct iio_dev *indio_dev,
  84                           struct iio_chan_spec const *chan,
  85                           int *val,
  86                           int *val2,
  87                           long m)
  88{
  89        struct ad7780_state *st = iio_priv(indio_dev);
  90
  91        switch (m) {
  92        case IIO_CHAN_INFO_RAW:
  93                return ad_sigma_delta_single_conversion(indio_dev, chan, val);
  94        case IIO_CHAN_INFO_SCALE:
  95                *val = st->int_vref_mv * st->gain;
  96                *val2 = chan->scan_type.realbits - 1;
  97                return IIO_VAL_FRACTIONAL_LOG2;
  98        case IIO_CHAN_INFO_OFFSET:
  99                *val -= (1 << (chan->scan_type.realbits - 1));
 100                return IIO_VAL_INT;
 101        }
 102
 103        return -EINVAL;
 104}
 105
 106static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
 107                                     unsigned int raw_sample)
 108{
 109        struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
 110        const struct ad7780_chip_info *chip_info = st->chip_info;
 111
 112        if ((raw_sample & AD7780_ERR) ||
 113            ((raw_sample & chip_info->pattern_mask) != chip_info->pattern))
 114                return -EIO;
 115
 116        if (raw_sample & AD7780_GAIN)
 117                st->gain = 1;
 118        else
 119                st->gain = 128;
 120
 121        return 0;
 122}
 123
 124static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
 125        .set_mode = ad7780_set_mode,
 126        .postprocess_sample = ad7780_postprocess_sample,
 127        .has_registers = false,
 128};
 129
 130#define AD7780_CHANNEL(bits, wordsize) \
 131        AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, wordsize - bits)
 132
 133static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
 134        [ID_AD7170] = {
 135                .channel = AD7780_CHANNEL(12, 24),
 136                .pattern = 0x5,
 137                .pattern_mask = 0x7,
 138        },
 139        [ID_AD7171] = {
 140                .channel = AD7780_CHANNEL(16, 24),
 141                .pattern = 0x5,
 142                .pattern_mask = 0x7,
 143        },
 144        [ID_AD7780] = {
 145                .channel = AD7780_CHANNEL(24, 32),
 146                .pattern = 0x1,
 147                .pattern_mask = 0x3,
 148        },
 149        [ID_AD7781] = {
 150                .channel = AD7780_CHANNEL(20, 32),
 151                .pattern = 0x1,
 152                .pattern_mask = 0x3,
 153        },
 154};
 155
 156static const struct iio_info ad7780_info = {
 157        .read_raw = ad7780_read_raw,
 158};
 159
 160static int ad7780_probe(struct spi_device *spi)
 161{
 162        struct ad7780_state *st;
 163        struct iio_dev *indio_dev;
 164        int ret, voltage_uv = 0;
 165
 166        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 167        if (!indio_dev)
 168                return -ENOMEM;
 169
 170        st = iio_priv(indio_dev);
 171        st->gain = 1;
 172
 173        ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
 174
 175        st->reg = devm_regulator_get(&spi->dev, "avdd");
 176        if (IS_ERR(st->reg))
 177                return PTR_ERR(st->reg);
 178
 179        ret = regulator_enable(st->reg);
 180        if (ret) {
 181                dev_err(&spi->dev, "Failed to enable specified AVdd supply\n");
 182                return ret;
 183        }
 184        voltage_uv = regulator_get_voltage(st->reg);
 185
 186        st->chip_info =
 187                &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 188
 189        if (voltage_uv)
 190                st->int_vref_mv = voltage_uv / 1000;
 191        else
 192                dev_warn(&spi->dev, "Reference voltage unspecified\n");
 193
 194        spi_set_drvdata(spi, indio_dev);
 195
 196        indio_dev->dev.parent = &spi->dev;
 197        indio_dev->name = spi_get_device_id(spi)->name;
 198        indio_dev->modes = INDIO_DIRECT_MODE;
 199        indio_dev->channels = &st->chip_info->channel;
 200        indio_dev->num_channels = 1;
 201        indio_dev->info = &ad7780_info;
 202
 203        st->powerdown_gpio = devm_gpiod_get_optional(&spi->dev,
 204                                                     "powerdown",
 205                                                     GPIOD_OUT_LOW);
 206        if (IS_ERR(st->powerdown_gpio)) {
 207                ret = PTR_ERR(st->powerdown_gpio);
 208                dev_err(&spi->dev, "Failed to request powerdown GPIO: %d\n",
 209                        ret);
 210                goto error_disable_reg;
 211        }
 212
 213        ret = ad_sd_setup_buffer_and_trigger(indio_dev);
 214        if (ret)
 215                goto error_disable_reg;
 216
 217        ret = iio_device_register(indio_dev);
 218        if (ret)
 219                goto error_cleanup_buffer_and_trigger;
 220
 221        return 0;
 222
 223error_cleanup_buffer_and_trigger:
 224        ad_sd_cleanup_buffer_and_trigger(indio_dev);
 225error_disable_reg:
 226        regulator_disable(st->reg);
 227
 228        return ret;
 229}
 230
 231static int ad7780_remove(struct spi_device *spi)
 232{
 233        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 234        struct ad7780_state *st = iio_priv(indio_dev);
 235
 236        iio_device_unregister(indio_dev);
 237        ad_sd_cleanup_buffer_and_trigger(indio_dev);
 238
 239        regulator_disable(st->reg);
 240
 241        return 0;
 242}
 243
 244static const struct spi_device_id ad7780_id[] = {
 245        {"ad7170", ID_AD7170},
 246        {"ad7171", ID_AD7171},
 247        {"ad7780", ID_AD7780},
 248        {"ad7781", ID_AD7781},
 249        {}
 250};
 251MODULE_DEVICE_TABLE(spi, ad7780_id);
 252
 253static struct spi_driver ad7780_driver = {
 254        .driver = {
 255                .name   = "ad7780",
 256        },
 257        .probe          = ad7780_probe,
 258        .remove         = ad7780_remove,
 259        .id_table       = ad7780_id,
 260};
 261module_spi_driver(ad7780_driver);
 262
 263MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 264MODULE_DESCRIPTION("Analog Devices AD7780 and similar ADCs");
 265MODULE_LICENSE("GPL v2");
 266