linux/drivers/iio/dac/ad5761.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter
   4 *
   5 * Copyright 2016 Qtechnology A/S
   6 * 2016 Ricardo Ribalda <ribalda@kernel.org>
   7 */
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/spi/spi.h>
  11#include <linux/bitops.h>
  12#include <linux/iio/iio.h>
  13#include <linux/iio/sysfs.h>
  14#include <linux/regulator/consumer.h>
  15#include <linux/platform_data/ad5761.h>
  16
  17#define AD5761_ADDR(addr)               ((addr & 0xf) << 16)
  18#define AD5761_ADDR_NOOP                0x0
  19#define AD5761_ADDR_DAC_WRITE           0x3
  20#define AD5761_ADDR_CTRL_WRITE_REG      0x4
  21#define AD5761_ADDR_SW_DATA_RESET       0x7
  22#define AD5761_ADDR_DAC_READ            0xb
  23#define AD5761_ADDR_CTRL_READ_REG       0xc
  24#define AD5761_ADDR_SW_FULL_RESET       0xf
  25
  26#define AD5761_CTRL_USE_INTVREF         BIT(5)
  27#define AD5761_CTRL_ETS                 BIT(6)
  28
  29/**
  30 * struct ad5761_chip_info - chip specific information
  31 * @int_vref:   Value of the internal reference voltage in mV - 0 if external
  32 *              reference voltage is used
  33 * @channel:    channel specification
  34*/
  35
  36struct ad5761_chip_info {
  37        unsigned long int_vref;
  38        const struct iio_chan_spec channel;
  39};
  40
  41struct ad5761_range_params {
  42        int m;
  43        int c;
  44};
  45
  46enum ad5761_supported_device_ids {
  47        ID_AD5721,
  48        ID_AD5721R,
  49        ID_AD5761,
  50        ID_AD5761R,
  51};
  52
  53/**
  54 * struct ad5761_state - driver instance specific data
  55 * @spi:                spi_device
  56 * @vref_reg:           reference voltage regulator
  57 * @use_intref:         true when the internal voltage reference is used
  58 * @vref:               actual voltage reference in mVolts
  59 * @range:              output range mode used
  60 * @lock:               lock to protect the data buffer during SPI ops
  61 * @data:               cache aligned spi buffer
  62 */
  63struct ad5761_state {
  64        struct spi_device               *spi;
  65        struct regulator                *vref_reg;
  66        struct mutex                    lock;
  67
  68        bool use_intref;
  69        int vref;
  70        enum ad5761_voltage_range range;
  71
  72        /*
  73         * DMA (thus cache coherency maintenance) requires the
  74         * transfer buffers to live in their own cache lines.
  75         */
  76        union {
  77                __be32 d32;
  78                u8 d8[4];
  79        } data[3] ____cacheline_aligned;
  80};
  81
  82static const struct ad5761_range_params ad5761_range_params[] = {
  83        [AD5761_VOLTAGE_RANGE_M10V_10V] = {
  84                .m = 80,
  85                .c = 40,
  86        },
  87        [AD5761_VOLTAGE_RANGE_0V_10V] = {
  88                .m = 40,
  89                .c = 0,
  90        },
  91        [AD5761_VOLTAGE_RANGE_M5V_5V] = {
  92                .m = 40,
  93                .c = 20,
  94        },
  95        [AD5761_VOLTAGE_RANGE_0V_5V] = {
  96                .m = 20,
  97                .c = 0,
  98        },
  99        [AD5761_VOLTAGE_RANGE_M2V5_7V5] = {
 100                .m = 40,
 101                .c = 10,
 102        },
 103        [AD5761_VOLTAGE_RANGE_M3V_3V] = {
 104                .m = 24,
 105                .c = 12,
 106        },
 107        [AD5761_VOLTAGE_RANGE_0V_16V] = {
 108                .m = 64,
 109                .c = 0,
 110        },
 111        [AD5761_VOLTAGE_RANGE_0V_20V] = {
 112                .m = 80,
 113                .c = 0,
 114        },
 115};
 116
 117static int _ad5761_spi_write(struct ad5761_state *st, u8 addr, u16 val)
 118{
 119        st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr) | val);
 120
 121        return spi_write(st->spi, &st->data[0].d8[1], 3);
 122}
 123
 124static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val)
 125{
 126        struct ad5761_state *st = iio_priv(indio_dev);
 127        int ret;
 128
 129        mutex_lock(&st->lock);
 130        ret = _ad5761_spi_write(st, addr, val);
 131        mutex_unlock(&st->lock);
 132
 133        return ret;
 134}
 135
 136static int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val)
 137{
 138        int ret;
 139        struct spi_transfer xfers[] = {
 140                {
 141                        .tx_buf = &st->data[0].d8[1],
 142                        .bits_per_word = 8,
 143                        .len = 3,
 144                        .cs_change = true,
 145                }, {
 146                        .tx_buf = &st->data[1].d8[1],
 147                        .rx_buf = &st->data[2].d8[1],
 148                        .bits_per_word = 8,
 149                        .len = 3,
 150                },
 151        };
 152
 153        st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr));
 154        st->data[1].d32 = cpu_to_be32(AD5761_ADDR(AD5761_ADDR_NOOP));
 155
 156        ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
 157
 158        *val = be32_to_cpu(st->data[2].d32);
 159
 160        return ret;
 161}
 162
 163static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val)
 164{
 165        struct ad5761_state *st = iio_priv(indio_dev);
 166        int ret;
 167
 168        mutex_lock(&st->lock);
 169        ret = _ad5761_spi_read(st, addr, val);
 170        mutex_unlock(&st->lock);
 171
 172        return ret;
 173}
 174
 175static int ad5761_spi_set_range(struct ad5761_state *st,
 176                                enum ad5761_voltage_range range)
 177{
 178        u16 aux;
 179        int ret;
 180
 181        aux = (range & 0x7) | AD5761_CTRL_ETS;
 182
 183        if (st->use_intref)
 184                aux |= AD5761_CTRL_USE_INTVREF;
 185
 186        ret = _ad5761_spi_write(st, AD5761_ADDR_SW_FULL_RESET, 0);
 187        if (ret)
 188                return ret;
 189
 190        ret = _ad5761_spi_write(st, AD5761_ADDR_CTRL_WRITE_REG, aux);
 191        if (ret)
 192                return ret;
 193
 194        st->range = range;
 195
 196        return 0;
 197}
 198
 199static int ad5761_read_raw(struct iio_dev *indio_dev,
 200                           struct iio_chan_spec const *chan,
 201                           int *val,
 202                           int *val2,
 203                           long mask)
 204{
 205        struct ad5761_state *st;
 206        int ret;
 207        u16 aux;
 208
 209        switch (mask) {
 210        case IIO_CHAN_INFO_RAW:
 211                ret = ad5761_spi_read(indio_dev, AD5761_ADDR_DAC_READ, &aux);
 212                if (ret)
 213                        return ret;
 214                *val = aux >> chan->scan_type.shift;
 215                return IIO_VAL_INT;
 216        case IIO_CHAN_INFO_SCALE:
 217                st = iio_priv(indio_dev);
 218                *val = st->vref * ad5761_range_params[st->range].m;
 219                *val /= 10;
 220                *val2 = chan->scan_type.realbits;
 221                return IIO_VAL_FRACTIONAL_LOG2;
 222        case IIO_CHAN_INFO_OFFSET:
 223                st = iio_priv(indio_dev);
 224                *val = -(1 << chan->scan_type.realbits);
 225                *val *= ad5761_range_params[st->range].c;
 226                *val /= ad5761_range_params[st->range].m;
 227                return IIO_VAL_INT;
 228        default:
 229                return -EINVAL;
 230        }
 231}
 232
 233static int ad5761_write_raw(struct iio_dev *indio_dev,
 234                            struct iio_chan_spec const *chan,
 235                            int val,
 236                            int val2,
 237                            long mask)
 238{
 239        u16 aux;
 240
 241        if (mask != IIO_CHAN_INFO_RAW)
 242                return -EINVAL;
 243
 244        if (val2 || (val << chan->scan_type.shift) > 0xffff || val < 0)
 245                return -EINVAL;
 246
 247        aux = val << chan->scan_type.shift;
 248
 249        return ad5761_spi_write(indio_dev, AD5761_ADDR_DAC_WRITE, aux);
 250}
 251
 252static const struct iio_info ad5761_info = {
 253        .read_raw = &ad5761_read_raw,
 254        .write_raw = &ad5761_write_raw,
 255};
 256
 257#define AD5761_CHAN(_bits) {                            \
 258        .type = IIO_VOLTAGE,                            \
 259        .output = 1,                                    \
 260        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
 261        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
 262                BIT(IIO_CHAN_INFO_OFFSET),              \
 263        .scan_type = {                                  \
 264                .sign = 'u',                            \
 265                .realbits = (_bits),                    \
 266                .storagebits = 16,                      \
 267                .shift = 16 - (_bits),                  \
 268        },                                              \
 269}
 270
 271static const struct ad5761_chip_info ad5761_chip_infos[] = {
 272        [ID_AD5721] = {
 273                .int_vref = 0,
 274                .channel = AD5761_CHAN(12),
 275        },
 276        [ID_AD5721R] = {
 277                .int_vref = 2500,
 278                .channel = AD5761_CHAN(12),
 279        },
 280        [ID_AD5761] = {
 281                .int_vref = 0,
 282                .channel = AD5761_CHAN(16),
 283        },
 284        [ID_AD5761R] = {
 285                .int_vref = 2500,
 286                .channel = AD5761_CHAN(16),
 287        },
 288};
 289
 290static int ad5761_get_vref(struct ad5761_state *st,
 291                           const struct ad5761_chip_info *chip_info)
 292{
 293        int ret;
 294
 295        st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref");
 296        if (PTR_ERR(st->vref_reg) == -ENODEV) {
 297                /* Use Internal regulator */
 298                if (!chip_info->int_vref) {
 299                        dev_err(&st->spi->dev,
 300                                "Voltage reference not found\n");
 301                        return -EIO;
 302                }
 303
 304                st->use_intref = true;
 305                st->vref = chip_info->int_vref;
 306                return 0;
 307        }
 308
 309        if (IS_ERR(st->vref_reg)) {
 310                dev_err(&st->spi->dev,
 311                        "Error getting voltage reference regulator\n");
 312                return PTR_ERR(st->vref_reg);
 313        }
 314
 315        ret = regulator_enable(st->vref_reg);
 316        if (ret) {
 317                dev_err(&st->spi->dev,
 318                         "Failed to enable voltage reference\n");
 319                return ret;
 320        }
 321
 322        ret = regulator_get_voltage(st->vref_reg);
 323        if (ret < 0) {
 324                dev_err(&st->spi->dev,
 325                         "Failed to get voltage reference value\n");
 326                goto disable_regulator_vref;
 327        }
 328
 329        if (ret < 2000000 || ret > 3000000) {
 330                dev_warn(&st->spi->dev,
 331                         "Invalid external voltage ref. value %d uV\n", ret);
 332                ret = -EIO;
 333                goto disable_regulator_vref;
 334        }
 335
 336        st->vref = ret / 1000;
 337        st->use_intref = false;
 338
 339        return 0;
 340
 341disable_regulator_vref:
 342        regulator_disable(st->vref_reg);
 343        st->vref_reg = NULL;
 344        return ret;
 345}
 346
 347static int ad5761_probe(struct spi_device *spi)
 348{
 349        struct iio_dev *iio_dev;
 350        struct ad5761_state *st;
 351        int ret;
 352        const struct ad5761_chip_info *chip_info =
 353                &ad5761_chip_infos[spi_get_device_id(spi)->driver_data];
 354        enum ad5761_voltage_range voltage_range = AD5761_VOLTAGE_RANGE_0V_5V;
 355        struct ad5761_platform_data *pdata = dev_get_platdata(&spi->dev);
 356
 357        iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 358        if (!iio_dev)
 359                return -ENOMEM;
 360
 361        st = iio_priv(iio_dev);
 362
 363        st->spi = spi;
 364        spi_set_drvdata(spi, iio_dev);
 365
 366        ret = ad5761_get_vref(st, chip_info);
 367        if (ret)
 368                return ret;
 369
 370        if (pdata)
 371                voltage_range = pdata->voltage_range;
 372
 373        mutex_init(&st->lock);
 374
 375        ret = ad5761_spi_set_range(st, voltage_range);
 376        if (ret)
 377                goto disable_regulator_err;
 378
 379        iio_dev->info = &ad5761_info;
 380        iio_dev->modes = INDIO_DIRECT_MODE;
 381        iio_dev->channels = &chip_info->channel;
 382        iio_dev->num_channels = 1;
 383        iio_dev->name = spi_get_device_id(st->spi)->name;
 384        ret = iio_device_register(iio_dev);
 385        if (ret)
 386                goto disable_regulator_err;
 387
 388        return 0;
 389
 390disable_regulator_err:
 391        if (!IS_ERR_OR_NULL(st->vref_reg))
 392                regulator_disable(st->vref_reg);
 393
 394        return ret;
 395}
 396
 397static int ad5761_remove(struct spi_device *spi)
 398{
 399        struct iio_dev *iio_dev = spi_get_drvdata(spi);
 400        struct ad5761_state *st = iio_priv(iio_dev);
 401
 402        iio_device_unregister(iio_dev);
 403
 404        if (!IS_ERR_OR_NULL(st->vref_reg))
 405                regulator_disable(st->vref_reg);
 406
 407        return 0;
 408}
 409
 410static const struct spi_device_id ad5761_id[] = {
 411        {"ad5721", ID_AD5721},
 412        {"ad5721r", ID_AD5721R},
 413        {"ad5761", ID_AD5761},
 414        {"ad5761r", ID_AD5761R},
 415        {}
 416};
 417MODULE_DEVICE_TABLE(spi, ad5761_id);
 418
 419static struct spi_driver ad5761_driver = {
 420        .driver = {
 421                   .name = "ad5761",
 422                   },
 423        .probe = ad5761_probe,
 424        .remove = ad5761_remove,
 425        .id_table = ad5761_id,
 426};
 427module_spi_driver(ad5761_driver);
 428
 429MODULE_AUTHOR("Ricardo Ribalda <ribalda@kernel.org>");
 430MODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver");
 431MODULE_LICENSE("GPL v2");
 432