linux/drivers/iio/dac/ad5791.c
<<
>>
Prefs
   1/*
   2 * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog
   3 * Converter
   4 *
   5 * Copyright 2011 Analog Devices Inc.
   6 *
   7 * Licensed under the GPL-2.
   8 */
   9
  10#include <linux/interrupt.h>
  11#include <linux/fs.h>
  12#include <linux/device.h>
  13#include <linux/kernel.h>
  14#include <linux/spi/spi.h>
  15#include <linux/slab.h>
  16#include <linux/sysfs.h>
  17#include <linux/regulator/consumer.h>
  18#include <linux/module.h>
  19
  20#include <linux/iio/iio.h>
  21#include <linux/iio/sysfs.h>
  22#include <linux/iio/dac/ad5791.h>
  23
  24#define AD5791_RES_MASK(x)              ((1 << (x)) - 1)
  25#define AD5791_DAC_MASK                 AD5791_RES_MASK(20)
  26#define AD5791_DAC_MSB                  (1 << 19)
  27
  28#define AD5791_CMD_READ                 (1 << 23)
  29#define AD5791_CMD_WRITE                (0 << 23)
  30#define AD5791_ADDR(addr)               ((addr) << 20)
  31
  32/* Registers */
  33#define AD5791_ADDR_NOOP                0
  34#define AD5791_ADDR_DAC0                1
  35#define AD5791_ADDR_CTRL                2
  36#define AD5791_ADDR_CLRCODE             3
  37#define AD5791_ADDR_SW_CTRL             4
  38
  39/* Control Register */
  40#define AD5791_CTRL_RBUF                (1 << 1)
  41#define AD5791_CTRL_OPGND               (1 << 2)
  42#define AD5791_CTRL_DACTRI              (1 << 3)
  43#define AD5791_CTRL_BIN2SC              (1 << 4)
  44#define AD5791_CTRL_SDODIS              (1 << 5)
  45#define AD5761_CTRL_LINCOMP(x)          ((x) << 6)
  46
  47#define AD5791_LINCOMP_0_10             0
  48#define AD5791_LINCOMP_10_12            1
  49#define AD5791_LINCOMP_12_16            2
  50#define AD5791_LINCOMP_16_19            3
  51#define AD5791_LINCOMP_19_20            12
  52
  53#define AD5780_LINCOMP_0_10             0
  54#define AD5780_LINCOMP_10_20            12
  55
  56/* Software Control Register */
  57#define AD5791_SWCTRL_LDAC              (1 << 0)
  58#define AD5791_SWCTRL_CLR               (1 << 1)
  59#define AD5791_SWCTRL_RESET             (1 << 2)
  60
  61#define AD5791_DAC_PWRDN_6K             0
  62#define AD5791_DAC_PWRDN_3STATE         1
  63
  64/**
  65 * struct ad5791_chip_info - chip specific information
  66 * @get_lin_comp:       function pointer to the device specific function
  67 */
  68
  69struct ad5791_chip_info {
  70        int (*get_lin_comp)     (unsigned int span);
  71};
  72
  73/**
  74 * struct ad5791_state - driver instance specific data
  75 * @us:                 spi_device
  76 * @reg_vdd:            positive supply regulator
  77 * @reg_vss:            negative supply regulator
  78 * @chip_info:          chip model specific constants
  79 * @vref_mv:            actual reference voltage used
  80 * @vref_neg_mv:        voltage of the negative supply
  81 * @pwr_down_mode       current power down mode
  82 */
  83
  84struct ad5791_state {
  85        struct spi_device               *spi;
  86        struct regulator                *reg_vdd;
  87        struct regulator                *reg_vss;
  88        const struct ad5791_chip_info   *chip_info;
  89        unsigned short                  vref_mv;
  90        unsigned int                    vref_neg_mv;
  91        unsigned                        ctrl;
  92        unsigned                        pwr_down_mode;
  93        bool                            pwr_down;
  94};
  95
  96/**
  97 * ad5791_supported_device_ids:
  98 */
  99
 100enum ad5791_supported_device_ids {
 101        ID_AD5760,
 102        ID_AD5780,
 103        ID_AD5781,
 104        ID_AD5791,
 105};
 106
 107static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val)
 108{
 109        union {
 110                u32 d32;
 111                u8 d8[4];
 112        } data;
 113
 114        data.d32 = cpu_to_be32(AD5791_CMD_WRITE |
 115                              AD5791_ADDR(addr) |
 116                              (val & AD5791_DAC_MASK));
 117
 118        return spi_write(spi, &data.d8[1], 3);
 119}
 120
 121static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
 122{
 123        union {
 124                u32 d32;
 125                u8 d8[4];
 126        } data[3];
 127        int ret;
 128        struct spi_transfer xfers[] = {
 129                {
 130                        .tx_buf = &data[0].d8[1],
 131                        .bits_per_word = 8,
 132                        .len = 3,
 133                        .cs_change = 1,
 134                }, {
 135                        .tx_buf = &data[1].d8[1],
 136                        .rx_buf = &data[2].d8[1],
 137                        .bits_per_word = 8,
 138                        .len = 3,
 139                },
 140        };
 141
 142        data[0].d32 = cpu_to_be32(AD5791_CMD_READ |
 143                              AD5791_ADDR(addr));
 144        data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP));
 145
 146        ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
 147
 148        *val = be32_to_cpu(data[2].d32);
 149
 150        return ret;
 151}
 152
 153static const char * const ad5791_powerdown_modes[] = {
 154        "6kohm_to_gnd",
 155        "three_state",
 156};
 157
 158static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev,
 159        const struct iio_chan_spec *chan)
 160{
 161        struct ad5791_state *st = iio_priv(indio_dev);
 162
 163        return st->pwr_down_mode;
 164}
 165
 166static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev,
 167        const struct iio_chan_spec *chan, unsigned int mode)
 168{
 169        struct ad5791_state *st = iio_priv(indio_dev);
 170
 171        st->pwr_down_mode = mode;
 172
 173        return 0;
 174}
 175
 176static const struct iio_enum ad5791_powerdown_mode_enum = {
 177        .items = ad5791_powerdown_modes,
 178        .num_items = ARRAY_SIZE(ad5791_powerdown_modes),
 179        .get = ad5791_get_powerdown_mode,
 180        .set = ad5791_set_powerdown_mode,
 181};
 182
 183static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev,
 184        uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 185{
 186        struct ad5791_state *st = iio_priv(indio_dev);
 187
 188        return sprintf(buf, "%d\n", st->pwr_down);
 189}
 190
 191static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev,
 192         uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
 193         size_t len)
 194{
 195        bool pwr_down;
 196        int ret;
 197        struct ad5791_state *st = iio_priv(indio_dev);
 198
 199        ret = strtobool(buf, &pwr_down);
 200        if (ret)
 201                return ret;
 202
 203        if (!pwr_down) {
 204                st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
 205        } else {
 206                if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K)
 207                        st->ctrl |= AD5791_CTRL_OPGND;
 208                else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE)
 209                        st->ctrl |= AD5791_CTRL_DACTRI;
 210        }
 211        st->pwr_down = pwr_down;
 212
 213        ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl);
 214
 215        return ret ? ret : len;
 216}
 217
 218static int ad5791_get_lin_comp(unsigned int span)
 219{
 220        if (span <= 10000)
 221                return AD5791_LINCOMP_0_10;
 222        else if (span <= 12000)
 223                return AD5791_LINCOMP_10_12;
 224        else if (span <= 16000)
 225                return AD5791_LINCOMP_12_16;
 226        else if (span <= 19000)
 227                return AD5791_LINCOMP_16_19;
 228        else
 229                return AD5791_LINCOMP_19_20;
 230}
 231
 232static int ad5780_get_lin_comp(unsigned int span)
 233{
 234        if (span <= 10000)
 235                return AD5780_LINCOMP_0_10;
 236        else
 237                return AD5780_LINCOMP_10_20;
 238}
 239static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
 240        [ID_AD5760] = {
 241                .get_lin_comp = ad5780_get_lin_comp,
 242        },
 243        [ID_AD5780] = {
 244                .get_lin_comp = ad5780_get_lin_comp,
 245        },
 246        [ID_AD5781] = {
 247                .get_lin_comp = ad5791_get_lin_comp,
 248        },
 249        [ID_AD5791] = {
 250                .get_lin_comp = ad5791_get_lin_comp,
 251        },
 252};
 253
 254static int ad5791_read_raw(struct iio_dev *indio_dev,
 255                           struct iio_chan_spec const *chan,
 256                           int *val,
 257                           int *val2,
 258                           long m)
 259{
 260        struct ad5791_state *st = iio_priv(indio_dev);
 261        u64 val64;
 262        int ret;
 263
 264        switch (m) {
 265        case IIO_CHAN_INFO_RAW:
 266                ret = ad5791_spi_read(st->spi, chan->address, val);
 267                if (ret)
 268                        return ret;
 269                *val &= AD5791_DAC_MASK;
 270                *val >>= chan->scan_type.shift;
 271                return IIO_VAL_INT;
 272        case IIO_CHAN_INFO_SCALE:
 273                *val = 0;
 274                *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
 275                return IIO_VAL_INT_PLUS_MICRO;
 276        case IIO_CHAN_INFO_OFFSET:
 277                val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
 278                do_div(val64, st->vref_mv);
 279                *val = -val64;
 280                return IIO_VAL_INT;
 281        default:
 282                return -EINVAL;
 283        }
 284
 285};
 286
 287static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
 288        {
 289                .name = "powerdown",
 290                .shared = true,
 291                .read = ad5791_read_dac_powerdown,
 292                .write = ad5791_write_dac_powerdown,
 293        },
 294        IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum),
 295        IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
 296        { },
 297};
 298
 299#define AD5791_CHAN(bits, shift) {                      \
 300        .type = IIO_VOLTAGE,                            \
 301        .output = 1,                                    \
 302        .indexed = 1,                                   \
 303        .address = AD5791_ADDR_DAC0,                    \
 304        .channel = 0,                                   \
 305        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
 306        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
 307                BIT(IIO_CHAN_INFO_OFFSET),              \
 308        .scan_type = IIO_ST('u', bits, 24, shift),      \
 309        .ext_info = ad5791_ext_info,                    \
 310}
 311
 312static const struct iio_chan_spec ad5791_channels[] = {
 313        [ID_AD5760] = AD5791_CHAN(16, 4),
 314        [ID_AD5780] = AD5791_CHAN(18, 2),
 315        [ID_AD5781] = AD5791_CHAN(18, 2),
 316        [ID_AD5791] = AD5791_CHAN(20, 0)
 317};
 318
 319static int ad5791_write_raw(struct iio_dev *indio_dev,
 320                            struct iio_chan_spec const *chan,
 321                            int val,
 322                            int val2,
 323                            long mask)
 324{
 325        struct ad5791_state *st = iio_priv(indio_dev);
 326
 327        switch (mask) {
 328        case IIO_CHAN_INFO_RAW:
 329                val &= AD5791_RES_MASK(chan->scan_type.realbits);
 330                val <<= chan->scan_type.shift;
 331
 332                return ad5791_spi_write(st->spi, chan->address, val);
 333
 334        default:
 335                return -EINVAL;
 336        }
 337}
 338
 339static const struct iio_info ad5791_info = {
 340        .read_raw = &ad5791_read_raw,
 341        .write_raw = &ad5791_write_raw,
 342        .driver_module = THIS_MODULE,
 343};
 344
 345static int ad5791_probe(struct spi_device *spi)
 346{
 347        struct ad5791_platform_data *pdata = spi->dev.platform_data;
 348        struct iio_dev *indio_dev;
 349        struct ad5791_state *st;
 350        int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
 351
 352        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 353        if (!indio_dev)
 354                return -ENOMEM;
 355        st = iio_priv(indio_dev);
 356        st->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
 357        if (!IS_ERR(st->reg_vdd)) {
 358                ret = regulator_enable(st->reg_vdd);
 359                if (ret)
 360                        return ret;
 361
 362                ret = regulator_get_voltage(st->reg_vdd);
 363                if (ret < 0)
 364                        goto error_disable_reg_pos;
 365
 366                pos_voltage_uv = ret;
 367        }
 368
 369        st->reg_vss = devm_regulator_get(&spi->dev, "vss");
 370        if (!IS_ERR(st->reg_vss)) {
 371                ret = regulator_enable(st->reg_vss);
 372                if (ret)
 373                        goto error_disable_reg_pos;
 374
 375                ret = regulator_get_voltage(st->reg_vss);
 376                if (ret < 0)
 377                        goto error_disable_reg_neg;
 378
 379                neg_voltage_uv = ret;
 380        }
 381
 382        st->pwr_down = true;
 383        st->spi = spi;
 384
 385        if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
 386                st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
 387                st->vref_neg_mv = neg_voltage_uv / 1000;
 388        } else if (pdata) {
 389                st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv;
 390                st->vref_neg_mv = pdata->vref_neg_mv;
 391        } else {
 392                dev_warn(&spi->dev, "reference voltage unspecified\n");
 393        }
 394
 395        ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
 396        if (ret)
 397                goto error_disable_reg_neg;
 398
 399        st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi)
 400                                              ->driver_data];
 401
 402
 403        st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
 404                  | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) |
 405                  AD5791_CTRL_BIN2SC;
 406
 407        ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl |
 408                AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
 409        if (ret)
 410                goto error_disable_reg_neg;
 411
 412        spi_set_drvdata(spi, indio_dev);
 413        indio_dev->dev.parent = &spi->dev;
 414        indio_dev->info = &ad5791_info;
 415        indio_dev->modes = INDIO_DIRECT_MODE;
 416        indio_dev->channels
 417                = &ad5791_channels[spi_get_device_id(spi)->driver_data];
 418        indio_dev->num_channels = 1;
 419        indio_dev->name = spi_get_device_id(st->spi)->name;
 420        ret = iio_device_register(indio_dev);
 421        if (ret)
 422                goto error_disable_reg_neg;
 423
 424        return 0;
 425
 426error_disable_reg_neg:
 427        if (!IS_ERR(st->reg_vss))
 428                regulator_disable(st->reg_vss);
 429error_disable_reg_pos:
 430        if (!IS_ERR(st->reg_vdd))
 431                regulator_disable(st->reg_vdd);
 432        return ret;
 433}
 434
 435static int ad5791_remove(struct spi_device *spi)
 436{
 437        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 438        struct ad5791_state *st = iio_priv(indio_dev);
 439
 440        iio_device_unregister(indio_dev);
 441        if (!IS_ERR(st->reg_vdd))
 442                regulator_disable(st->reg_vdd);
 443
 444        if (!IS_ERR(st->reg_vss))
 445                regulator_disable(st->reg_vss);
 446
 447        return 0;
 448}
 449
 450static const struct spi_device_id ad5791_id[] = {
 451        {"ad5760", ID_AD5760},
 452        {"ad5780", ID_AD5780},
 453        {"ad5781", ID_AD5781},
 454        {"ad5790", ID_AD5791},
 455        {"ad5791", ID_AD5791},
 456        {}
 457};
 458MODULE_DEVICE_TABLE(spi, ad5791_id);
 459
 460static struct spi_driver ad5791_driver = {
 461        .driver = {
 462                   .name = "ad5791",
 463                   .owner = THIS_MODULE,
 464                   },
 465        .probe = ad5791_probe,
 466        .remove = ad5791_remove,
 467        .id_table = ad5791_id,
 468};
 469module_spi_driver(ad5791_driver);
 470
 471MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 472MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC");
 473MODULE_LICENSE("GPL v2");
 474