linux/drivers/iio/dac/ad5624r_spi.c
<<
>>
Prefs
   1/*
   2 * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver
   3 *
   4 * Copyright 2010-2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/fs.h>
  11#include <linux/device.h>
  12#include <linux/kernel.h>
  13#include <linux/spi/spi.h>
  14#include <linux/slab.h>
  15#include <linux/sysfs.h>
  16#include <linux/regulator/consumer.h>
  17#include <linux/module.h>
  18
  19#include <linux/iio/iio.h>
  20#include <linux/iio/sysfs.h>
  21
  22#include "ad5624r.h"
  23
  24static int ad5624r_spi_write(struct spi_device *spi,
  25                             u8 cmd, u8 addr, u16 val, u8 len)
  26{
  27        u32 data;
  28        u8 msg[3];
  29
  30        /*
  31         * The input shift register is 24 bits wide. The first two bits are
  32         * don't care bits. The next three are the command bits, C2 to C0,
  33         * followed by the 3-bit DAC address, A2 to A0, and then the
  34         * 16-, 14-, 12-bit data-word. The data-word comprises the 16-,
  35         * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits,
  36         * for the AD5664R, AD5644R, and AD5624R, respectively.
  37         */
  38        data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len));
  39        msg[0] = data >> 16;
  40        msg[1] = data >> 8;
  41        msg[2] = data;
  42
  43        return spi_write(spi, msg, 3);
  44}
  45
  46static int ad5624r_read_raw(struct iio_dev *indio_dev,
  47                           struct iio_chan_spec const *chan,
  48                           int *val,
  49                           int *val2,
  50                           long m)
  51{
  52        struct ad5624r_state *st = iio_priv(indio_dev);
  53        unsigned long scale_uv;
  54
  55        switch (m) {
  56        case IIO_CHAN_INFO_SCALE:
  57                scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
  58                *val =  scale_uv / 1000;
  59                *val2 = (scale_uv % 1000) * 1000;
  60                return IIO_VAL_INT_PLUS_MICRO;
  61
  62        }
  63        return -EINVAL;
  64}
  65
  66static int ad5624r_write_raw(struct iio_dev *indio_dev,
  67                               struct iio_chan_spec const *chan,
  68                               int val,
  69                               int val2,
  70                               long mask)
  71{
  72        struct ad5624r_state *st = iio_priv(indio_dev);
  73        int ret;
  74
  75        switch (mask) {
  76        case IIO_CHAN_INFO_RAW:
  77                if (val >= (1 << chan->scan_type.realbits) || val < 0)
  78                        return -EINVAL;
  79
  80                return ad5624r_spi_write(st->us,
  81                                AD5624R_CMD_WRITE_INPUT_N_UPDATE_N,
  82                                chan->address, val,
  83                                chan->scan_type.shift);
  84        default:
  85                ret = -EINVAL;
  86        }
  87
  88        return -EINVAL;
  89}
  90
  91static const char * const ad5624r_powerdown_modes[] = {
  92        "1kohm_to_gnd",
  93        "100kohm_to_gnd",
  94        "three_state"
  95};
  96
  97static int ad5624r_get_powerdown_mode(struct iio_dev *indio_dev,
  98        const struct iio_chan_spec *chan)
  99{
 100        struct ad5624r_state *st = iio_priv(indio_dev);
 101
 102        return st->pwr_down_mode;
 103}
 104
 105static int ad5624r_set_powerdown_mode(struct iio_dev *indio_dev,
 106        const struct iio_chan_spec *chan, unsigned int mode)
 107{
 108        struct ad5624r_state *st = iio_priv(indio_dev);
 109
 110        st->pwr_down_mode = mode;
 111
 112        return 0;
 113}
 114
 115static const struct iio_enum ad5624r_powerdown_mode_enum = {
 116        .items = ad5624r_powerdown_modes,
 117        .num_items = ARRAY_SIZE(ad5624r_powerdown_modes),
 118        .get = ad5624r_get_powerdown_mode,
 119        .set = ad5624r_set_powerdown_mode,
 120};
 121
 122static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev,
 123        uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 124{
 125        struct ad5624r_state *st = iio_priv(indio_dev);
 126
 127        return sprintf(buf, "%d\n",
 128                        !!(st->pwr_down_mask & (1 << chan->channel)));
 129}
 130
 131static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev,
 132        uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
 133        size_t len)
 134{
 135        bool pwr_down;
 136        int ret;
 137        struct ad5624r_state *st = iio_priv(indio_dev);
 138
 139        ret = strtobool(buf, &pwr_down);
 140        if (ret)
 141                return ret;
 142
 143        if (pwr_down)
 144                st->pwr_down_mask |= (1 << chan->channel);
 145        else
 146                st->pwr_down_mask &= ~(1 << chan->channel);
 147
 148        ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0,
 149                                (st->pwr_down_mode << 4) |
 150                                st->pwr_down_mask, 16);
 151
 152        return ret ? ret : len;
 153}
 154
 155static const struct iio_info ad5624r_info = {
 156        .write_raw = ad5624r_write_raw,
 157        .read_raw = ad5624r_read_raw,
 158        .driver_module = THIS_MODULE,
 159};
 160
 161static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
 162        {
 163                .name = "powerdown",
 164                .read = ad5624r_read_dac_powerdown,
 165                .write = ad5624r_write_dac_powerdown,
 166        },
 167        IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum),
 168        IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
 169        { },
 170};
 171
 172#define AD5624R_CHANNEL(_chan, _bits) { \
 173        .type = IIO_VOLTAGE, \
 174        .indexed = 1, \
 175        .output = 1, \
 176        .channel = (_chan), \
 177        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 178        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 179        .address = (_chan), \
 180        .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
 181        .ext_info = ad5624r_ext_info, \
 182}
 183
 184#define DECLARE_AD5624R_CHANNELS(_name, _bits) \
 185        const struct iio_chan_spec _name##_channels[] = { \
 186                AD5624R_CHANNEL(0, _bits), \
 187                AD5624R_CHANNEL(1, _bits), \
 188                AD5624R_CHANNEL(2, _bits), \
 189                AD5624R_CHANNEL(3, _bits), \
 190}
 191
 192static DECLARE_AD5624R_CHANNELS(ad5624r, 12);
 193static DECLARE_AD5624R_CHANNELS(ad5644r, 14);
 194static DECLARE_AD5624R_CHANNELS(ad5664r, 16);
 195
 196static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
 197        [ID_AD5624R3] = {
 198                .channels = ad5624r_channels,
 199                .int_vref_mv = 1250,
 200        },
 201        [ID_AD5624R5] = {
 202                .channels = ad5624r_channels,
 203                .int_vref_mv = 2500,
 204        },
 205        [ID_AD5644R3] = {
 206                .channels = ad5644r_channels,
 207                .int_vref_mv = 1250,
 208        },
 209        [ID_AD5644R5] = {
 210                .channels = ad5644r_channels,
 211                .int_vref_mv = 2500,
 212        },
 213        [ID_AD5664R3] = {
 214                .channels = ad5664r_channels,
 215                .int_vref_mv = 1250,
 216        },
 217        [ID_AD5664R5] = {
 218                .channels = ad5664r_channels,
 219                .int_vref_mv = 2500,
 220        },
 221};
 222
 223static int ad5624r_probe(struct spi_device *spi)
 224{
 225        struct ad5624r_state *st;
 226        struct iio_dev *indio_dev;
 227        int ret, voltage_uv = 0;
 228
 229        indio_dev = iio_device_alloc(sizeof(*st));
 230        if (indio_dev == NULL) {
 231                ret = -ENOMEM;
 232                goto error_ret;
 233        }
 234        st = iio_priv(indio_dev);
 235        st->reg = regulator_get(&spi->dev, "vcc");
 236        if (!IS_ERR(st->reg)) {
 237                ret = regulator_enable(st->reg);
 238                if (ret)
 239                        goto error_put_reg;
 240
 241                ret = regulator_get_voltage(st->reg);
 242                if (ret < 0)
 243                        goto error_disable_reg;
 244
 245                voltage_uv = ret;
 246        }
 247
 248        spi_set_drvdata(spi, indio_dev);
 249        st->chip_info =
 250                &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 251
 252        if (voltage_uv)
 253                st->vref_mv = voltage_uv / 1000;
 254        else
 255                st->vref_mv = st->chip_info->int_vref_mv;
 256
 257        st->us = spi;
 258
 259        indio_dev->dev.parent = &spi->dev;
 260        indio_dev->name = spi_get_device_id(spi)->name;
 261        indio_dev->info = &ad5624r_info;
 262        indio_dev->modes = INDIO_DIRECT_MODE;
 263        indio_dev->channels = st->chip_info->channels;
 264        indio_dev->num_channels = AD5624R_DAC_CHANNELS;
 265
 266        ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
 267                                !!voltage_uv, 16);
 268        if (ret)
 269                goto error_disable_reg;
 270
 271        ret = iio_device_register(indio_dev);
 272        if (ret)
 273                goto error_disable_reg;
 274
 275        return 0;
 276
 277error_disable_reg:
 278        if (!IS_ERR(st->reg))
 279                regulator_disable(st->reg);
 280error_put_reg:
 281        if (!IS_ERR(st->reg))
 282                regulator_put(st->reg);
 283        iio_device_free(indio_dev);
 284error_ret:
 285
 286        return ret;
 287}
 288
 289static int ad5624r_remove(struct spi_device *spi)
 290{
 291        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 292        struct ad5624r_state *st = iio_priv(indio_dev);
 293
 294        iio_device_unregister(indio_dev);
 295        if (!IS_ERR(st->reg)) {
 296                regulator_disable(st->reg);
 297                regulator_put(st->reg);
 298        }
 299        iio_device_free(indio_dev);
 300
 301        return 0;
 302}
 303
 304static const struct spi_device_id ad5624r_id[] = {
 305        {"ad5624r3", ID_AD5624R3},
 306        {"ad5644r3", ID_AD5644R3},
 307        {"ad5664r3", ID_AD5664R3},
 308        {"ad5624r5", ID_AD5624R5},
 309        {"ad5644r5", ID_AD5644R5},
 310        {"ad5664r5", ID_AD5664R5},
 311        {}
 312};
 313MODULE_DEVICE_TABLE(spi, ad5624r_id);
 314
 315static struct spi_driver ad5624r_driver = {
 316        .driver = {
 317                   .name = "ad5624r",
 318                   .owner = THIS_MODULE,
 319                   },
 320        .probe = ad5624r_probe,
 321        .remove = ad5624r_remove,
 322        .id_table = ad5624r_id,
 323};
 324module_spi_driver(ad5624r_driver);
 325
 326MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 327MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver");
 328MODULE_LICENSE("GPL v2");
 329