linux/drivers/iio/dac/ad5504.c
<<
>>
Prefs
   1/*
   2 * AD5504, AD5501 High Voltage Digital to Analog Converter
   3 *
   4 * Copyright 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#include <linux/iio/events.h>
  22#include <linux/iio/dac/ad5504.h>
  23
  24#define AD5505_BITS                     12
  25#define AD5504_RES_MASK                 ((1 << (AD5505_BITS)) - 1)
  26
  27#define AD5504_CMD_READ                 (1 << 15)
  28#define AD5504_CMD_WRITE                (0 << 15)
  29#define AD5504_ADDR(addr)               ((addr) << 12)
  30
  31/* Registers */
  32#define AD5504_ADDR_NOOP                0
  33#define AD5504_ADDR_DAC(x)              ((x) + 1)
  34#define AD5504_ADDR_ALL_DAC             5
  35#define AD5504_ADDR_CTRL                7
  36
  37/* Control Register */
  38#define AD5504_DAC_PWR(ch)              ((ch) << 2)
  39#define AD5504_DAC_PWRDWN_MODE(mode)    ((mode) << 6)
  40#define AD5504_DAC_PWRDN_20K            0
  41#define AD5504_DAC_PWRDN_3STATE         1
  42
  43/**
  44 * struct ad5446_state - driver instance specific data
  45 * @us:                 spi_device
  46 * @reg:                supply regulator
  47 * @vref_mv:            actual reference voltage used
  48 * @pwr_down_mask       power down mask
  49 * @pwr_down_mode       current power down mode
  50 */
  51
  52struct ad5504_state {
  53        struct spi_device               *spi;
  54        struct regulator                *reg;
  55        unsigned short                  vref_mv;
  56        unsigned                        pwr_down_mask;
  57        unsigned                        pwr_down_mode;
  58};
  59
  60/**
  61 * ad5504_supported_device_ids:
  62 */
  63
  64enum ad5504_supported_device_ids {
  65        ID_AD5504,
  66        ID_AD5501,
  67};
  68
  69static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val)
  70{
  71        u16 tmp = cpu_to_be16(AD5504_CMD_WRITE |
  72                              AD5504_ADDR(addr) |
  73                              (val & AD5504_RES_MASK));
  74
  75        return spi_write(spi, (u8 *)&tmp, 2);
  76}
  77
  78static int ad5504_spi_read(struct spi_device *spi, u8 addr)
  79{
  80        u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr));
  81        u16 val;
  82        int ret;
  83        struct spi_transfer     t = {
  84                        .tx_buf         = &tmp,
  85                        .rx_buf         = &val,
  86                        .len            = 2,
  87                };
  88        ret = spi_sync_transfer(spi, &t, 1);
  89
  90        if (ret < 0)
  91                return ret;
  92
  93        return be16_to_cpu(val) & AD5504_RES_MASK;
  94}
  95
  96static int ad5504_read_raw(struct iio_dev *indio_dev,
  97                           struct iio_chan_spec const *chan,
  98                           int *val,
  99                           int *val2,
 100                           long m)
 101{
 102        struct ad5504_state *st = iio_priv(indio_dev);
 103        unsigned long scale_uv;
 104        int ret;
 105
 106        switch (m) {
 107        case IIO_CHAN_INFO_RAW:
 108                ret = ad5504_spi_read(st->spi, chan->address);
 109                if (ret < 0)
 110                        return ret;
 111
 112                *val = ret;
 113
 114                return IIO_VAL_INT;
 115        case IIO_CHAN_INFO_SCALE:
 116                scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
 117                *val =  scale_uv / 1000;
 118                *val2 = (scale_uv % 1000) * 1000;
 119                return IIO_VAL_INT_PLUS_MICRO;
 120
 121        }
 122        return -EINVAL;
 123}
 124
 125static int ad5504_write_raw(struct iio_dev *indio_dev,
 126                               struct iio_chan_spec const *chan,
 127                               int val,
 128                               int val2,
 129                               long mask)
 130{
 131        struct ad5504_state *st = iio_priv(indio_dev);
 132        int ret;
 133
 134        switch (mask) {
 135        case IIO_CHAN_INFO_RAW:
 136                if (val >= (1 << chan->scan_type.realbits) || val < 0)
 137                        return -EINVAL;
 138
 139                return ad5504_spi_write(st->spi, chan->address, val);
 140        default:
 141                ret = -EINVAL;
 142        }
 143
 144        return -EINVAL;
 145}
 146
 147static const char * const ad5504_powerdown_modes[] = {
 148        "20kohm_to_gnd",
 149        "three_state",
 150};
 151
 152static int ad5504_get_powerdown_mode(struct iio_dev *indio_dev,
 153        const struct iio_chan_spec *chan)
 154{
 155        struct ad5504_state *st = iio_priv(indio_dev);
 156
 157        return st->pwr_down_mode;
 158}
 159
 160static int ad5504_set_powerdown_mode(struct iio_dev *indio_dev,
 161        const struct iio_chan_spec *chan, unsigned int mode)
 162{
 163        struct ad5504_state *st = iio_priv(indio_dev);
 164
 165        st->pwr_down_mode = mode;
 166
 167        return 0;
 168}
 169
 170static const struct iio_enum ad5504_powerdown_mode_enum = {
 171        .items = ad5504_powerdown_modes,
 172        .num_items = ARRAY_SIZE(ad5504_powerdown_modes),
 173        .get = ad5504_get_powerdown_mode,
 174        .set = ad5504_set_powerdown_mode,
 175};
 176
 177static ssize_t ad5504_read_dac_powerdown(struct iio_dev *indio_dev,
 178        uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 179{
 180        struct ad5504_state *st = iio_priv(indio_dev);
 181
 182        return sprintf(buf, "%d\n",
 183                        !(st->pwr_down_mask & (1 << chan->channel)));
 184}
 185
 186static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev,
 187        uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
 188        size_t len)
 189{
 190        bool pwr_down;
 191        int ret;
 192        struct ad5504_state *st = iio_priv(indio_dev);
 193
 194        ret = strtobool(buf, &pwr_down);
 195        if (ret)
 196                return ret;
 197
 198        if (pwr_down)
 199                st->pwr_down_mask |= (1 << chan->channel);
 200        else
 201                st->pwr_down_mask &= ~(1 << chan->channel);
 202
 203        ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL,
 204                                AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) |
 205                                AD5504_DAC_PWR(st->pwr_down_mask));
 206
 207        /* writes to the CTRL register must be followed by a NOOP */
 208        ad5504_spi_write(st->spi, AD5504_ADDR_NOOP, 0);
 209
 210        return ret ? ret : len;
 211}
 212
 213static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000");
 214static IIO_CONST_ATTR(temp0_thresh_rising_en, "1");
 215
 216static struct attribute *ad5504_ev_attributes[] = {
 217        &iio_const_attr_temp0_thresh_rising_value.dev_attr.attr,
 218        &iio_const_attr_temp0_thresh_rising_en.dev_attr.attr,
 219        NULL,
 220};
 221
 222static struct attribute_group ad5504_ev_attribute_group = {
 223        .attrs = ad5504_ev_attributes,
 224        .name = "events",
 225};
 226
 227static irqreturn_t ad5504_event_handler(int irq, void *private)
 228{
 229        iio_push_event(private,
 230                       IIO_UNMOD_EVENT_CODE(IIO_TEMP,
 231                                            0,
 232                                            IIO_EV_TYPE_THRESH,
 233                                            IIO_EV_DIR_RISING),
 234                       iio_get_time_ns());
 235
 236        return IRQ_HANDLED;
 237}
 238
 239static const struct iio_info ad5504_info = {
 240        .write_raw = ad5504_write_raw,
 241        .read_raw = ad5504_read_raw,
 242        .event_attrs = &ad5504_ev_attribute_group,
 243        .driver_module = THIS_MODULE,
 244};
 245
 246static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
 247        {
 248                .name = "powerdown",
 249                .read = ad5504_read_dac_powerdown,
 250                .write = ad5504_write_dac_powerdown,
 251        },
 252        IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum),
 253        IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum),
 254        { },
 255};
 256
 257#define AD5504_CHANNEL(_chan) { \
 258        .type = IIO_VOLTAGE, \
 259        .indexed = 1, \
 260        .output = 1, \
 261        .channel = (_chan), \
 262        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 263        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 264        .address = AD5504_ADDR_DAC(_chan), \
 265        .scan_type = IIO_ST('u', 12, 16, 0), \
 266        .ext_info = ad5504_ext_info, \
 267}
 268
 269static const struct iio_chan_spec ad5504_channels[] = {
 270        AD5504_CHANNEL(0),
 271        AD5504_CHANNEL(1),
 272        AD5504_CHANNEL(2),
 273        AD5504_CHANNEL(3),
 274};
 275
 276static int ad5504_probe(struct spi_device *spi)
 277{
 278        struct ad5504_platform_data *pdata = spi->dev.platform_data;
 279        struct iio_dev *indio_dev;
 280        struct ad5504_state *st;
 281        struct regulator *reg;
 282        int ret, voltage_uv = 0;
 283
 284        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 285        if (!indio_dev)
 286                return -ENOMEM;
 287        reg = devm_regulator_get(&spi->dev, "vcc");
 288        if (!IS_ERR(reg)) {
 289                ret = regulator_enable(reg);
 290                if (ret)
 291                        return ret;
 292
 293                ret = regulator_get_voltage(reg);
 294                if (ret < 0)
 295                        goto error_disable_reg;
 296
 297                voltage_uv = ret;
 298        }
 299
 300        spi_set_drvdata(spi, indio_dev);
 301        st = iio_priv(indio_dev);
 302        if (voltage_uv)
 303                st->vref_mv = voltage_uv / 1000;
 304        else if (pdata)
 305                st->vref_mv = pdata->vref_mv;
 306        else
 307                dev_warn(&spi->dev, "reference voltage unspecified\n");
 308
 309        st->reg = reg;
 310        st->spi = spi;
 311        indio_dev->dev.parent = &spi->dev;
 312        indio_dev->name = spi_get_device_id(st->spi)->name;
 313        indio_dev->info = &ad5504_info;
 314        if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
 315                indio_dev->num_channels = 1;
 316        else
 317                indio_dev->num_channels = 4;
 318        indio_dev->channels = ad5504_channels;
 319        indio_dev->modes = INDIO_DIRECT_MODE;
 320
 321        if (spi->irq) {
 322                ret = devm_request_threaded_irq(&spi->dev, spi->irq,
 323                                           NULL,
 324                                           &ad5504_event_handler,
 325                                           IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 326                                           spi_get_device_id(st->spi)->name,
 327                                           indio_dev);
 328                if (ret)
 329                        goto error_disable_reg;
 330        }
 331
 332        ret = iio_device_register(indio_dev);
 333        if (ret)
 334                goto error_disable_reg;
 335
 336        return 0;
 337
 338error_disable_reg:
 339        if (!IS_ERR(reg))
 340                regulator_disable(reg);
 341
 342        return ret;
 343}
 344
 345static int ad5504_remove(struct spi_device *spi)
 346{
 347        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 348        struct ad5504_state *st = iio_priv(indio_dev);
 349
 350        iio_device_unregister(indio_dev);
 351
 352        if (!IS_ERR(st->reg))
 353                regulator_disable(st->reg);
 354
 355        return 0;
 356}
 357
 358static const struct spi_device_id ad5504_id[] = {
 359        {"ad5504", ID_AD5504},
 360        {"ad5501", ID_AD5501},
 361        {}
 362};
 363MODULE_DEVICE_TABLE(spi, ad5504_id);
 364
 365static struct spi_driver ad5504_driver = {
 366        .driver = {
 367                   .name = "ad5504",
 368                   .owner = THIS_MODULE,
 369                   },
 370        .probe = ad5504_probe,
 371        .remove = ad5504_remove,
 372        .id_table = ad5504_id,
 373};
 374module_spi_driver(ad5504_driver);
 375
 376MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 377MODULE_DESCRIPTION("Analog Devices AD5501/AD5501 DAC");
 378MODULE_LICENSE("GPL v2");
 379