linux/drivers/iio/dac/ti-dac082s085.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ti-dac082s085.c - Texas Instruments 8/10/12-bit 2/4-channel DAC driver
   4 *
   5 * Copyright (C) 2017 KUNBUS GmbH
   6 *
   7 * https://www.ti.com/lit/ds/symlink/dac082s085.pdf
   8 * https://www.ti.com/lit/ds/symlink/dac102s085.pdf
   9 * https://www.ti.com/lit/ds/symlink/dac122s085.pdf
  10 * https://www.ti.com/lit/ds/symlink/dac084s085.pdf
  11 * https://www.ti.com/lit/ds/symlink/dac104s085.pdf
  12 * https://www.ti.com/lit/ds/symlink/dac124s085.pdf
  13 */
  14
  15#include <linux/iio/iio.h>
  16#include <linux/module.h>
  17#include <linux/mod_devicetable.h>
  18#include <linux/regulator/consumer.h>
  19#include <linux/spi/spi.h>
  20
  21enum { dual_8bit, dual_10bit, dual_12bit, quad_8bit, quad_10bit, quad_12bit };
  22
  23struct ti_dac_spec {
  24        u8 num_channels;
  25        u8 resolution;
  26};
  27
  28static const struct ti_dac_spec ti_dac_spec[] = {
  29        [dual_8bit]  = { .num_channels = 2, .resolution = 8  },
  30        [dual_10bit] = { .num_channels = 2, .resolution = 10 },
  31        [dual_12bit] = { .num_channels = 2, .resolution = 12 },
  32        [quad_8bit]  = { .num_channels = 4, .resolution = 8  },
  33        [quad_10bit] = { .num_channels = 4, .resolution = 10 },
  34        [quad_12bit] = { .num_channels = 4, .resolution = 12 },
  35};
  36
  37/**
  38 * struct ti_dac_chip - TI DAC chip
  39 * @lock: protects write sequences
  40 * @vref: regulator generating Vref
  41 * @mesg: SPI message to perform a write
  42 * @xfer: SPI transfer used by @mesg
  43 * @val: cached value of each output
  44 * @powerdown: whether the chip is powered down
  45 * @powerdown_mode: selected by the user
  46 * @resolution: resolution of the chip
  47 * @buf: buffer for @xfer
  48 */
  49struct ti_dac_chip {
  50        struct mutex lock;
  51        struct regulator *vref;
  52        struct spi_message mesg;
  53        struct spi_transfer xfer;
  54        u16 val[4];
  55        bool powerdown;
  56        u8 powerdown_mode;
  57        u8 resolution;
  58        u8 buf[2] ____cacheline_aligned;
  59};
  60
  61#define WRITE_NOT_UPDATE(chan)  (0x00 | (chan) << 6)
  62#define WRITE_AND_UPDATE(chan)  (0x10 | (chan) << 6)
  63#define WRITE_ALL_UPDATE         0x20
  64#define POWERDOWN(mode)         (0x30 | ((mode) + 1) << 6)
  65
  66static int ti_dac_cmd(struct ti_dac_chip *ti_dac, u8 cmd, u16 val)
  67{
  68        u8 shift = 12 - ti_dac->resolution;
  69
  70        ti_dac->buf[0] = cmd | (val >> (8 - shift));
  71        ti_dac->buf[1] = (val << shift) & 0xff;
  72        return spi_sync(ti_dac->mesg.spi, &ti_dac->mesg);
  73}
  74
  75static const char * const ti_dac_powerdown_modes[] = {
  76        "2.5kohm_to_gnd", "100kohm_to_gnd", "three_state",
  77};
  78
  79static int ti_dac_get_powerdown_mode(struct iio_dev *indio_dev,
  80                                     const struct iio_chan_spec *chan)
  81{
  82        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
  83
  84        return ti_dac->powerdown_mode;
  85}
  86
  87static int ti_dac_set_powerdown_mode(struct iio_dev *indio_dev,
  88                                     const struct iio_chan_spec *chan,
  89                                     unsigned int mode)
  90{
  91        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
  92        int ret = 0;
  93
  94        if (ti_dac->powerdown_mode == mode)
  95                return 0;
  96
  97        mutex_lock(&ti_dac->lock);
  98        if (ti_dac->powerdown) {
  99                ret = ti_dac_cmd(ti_dac, POWERDOWN(mode), 0);
 100                if (ret)
 101                        goto out;
 102        }
 103        ti_dac->powerdown_mode = mode;
 104
 105out:
 106        mutex_unlock(&ti_dac->lock);
 107        return ret;
 108}
 109
 110static const struct iio_enum ti_dac_powerdown_mode = {
 111        .items = ti_dac_powerdown_modes,
 112        .num_items = ARRAY_SIZE(ti_dac_powerdown_modes),
 113        .get = ti_dac_get_powerdown_mode,
 114        .set = ti_dac_set_powerdown_mode,
 115};
 116
 117static ssize_t ti_dac_read_powerdown(struct iio_dev *indio_dev,
 118                                     uintptr_t private,
 119                                     const struct iio_chan_spec *chan,
 120                                     char *buf)
 121{
 122        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
 123
 124        return sysfs_emit(buf, "%d\n", ti_dac->powerdown);
 125}
 126
 127static ssize_t ti_dac_write_powerdown(struct iio_dev *indio_dev,
 128                                      uintptr_t private,
 129                                      const struct iio_chan_spec *chan,
 130                                      const char *buf, size_t len)
 131{
 132        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
 133        bool powerdown;
 134        int ret;
 135
 136        ret = strtobool(buf, &powerdown);
 137        if (ret)
 138                return ret;
 139
 140        if (ti_dac->powerdown == powerdown)
 141                return len;
 142
 143        mutex_lock(&ti_dac->lock);
 144        if (powerdown)
 145                ret = ti_dac_cmd(ti_dac, POWERDOWN(ti_dac->powerdown_mode), 0);
 146        else
 147                ret = ti_dac_cmd(ti_dac, WRITE_AND_UPDATE(0), ti_dac->val[0]);
 148        if (!ret)
 149                ti_dac->powerdown = powerdown;
 150        mutex_unlock(&ti_dac->lock);
 151
 152        return ret ? ret : len;
 153}
 154
 155static const struct iio_chan_spec_ext_info ti_dac_ext_info[] = {
 156        {
 157                .name      = "powerdown",
 158                .read      = ti_dac_read_powerdown,
 159                .write     = ti_dac_write_powerdown,
 160                .shared    = IIO_SHARED_BY_TYPE,
 161        },
 162        IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode),
 163        IIO_ENUM_AVAILABLE("powerdown_mode", &ti_dac_powerdown_mode),
 164        { },
 165};
 166
 167#define TI_DAC_CHANNEL(chan) {                                  \
 168        .type = IIO_VOLTAGE,                                    \
 169        .channel = (chan),                                      \
 170        .address = (chan),                                      \
 171        .indexed = true,                                        \
 172        .output = true,                                         \
 173        .datasheet_name = (const char[]){ 'A' + (chan), 0 },    \
 174        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
 175        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
 176        .ext_info = ti_dac_ext_info,                            \
 177}
 178
 179static const struct iio_chan_spec ti_dac_channels[] = {
 180        TI_DAC_CHANNEL(0),
 181        TI_DAC_CHANNEL(1),
 182        TI_DAC_CHANNEL(2),
 183        TI_DAC_CHANNEL(3),
 184};
 185
 186static int ti_dac_read_raw(struct iio_dev *indio_dev,
 187                           struct iio_chan_spec const *chan,
 188                           int *val, int *val2, long mask)
 189{
 190        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
 191        int ret;
 192
 193        switch (mask) {
 194        case IIO_CHAN_INFO_RAW:
 195                *val = ti_dac->val[chan->channel];
 196                ret = IIO_VAL_INT;
 197                break;
 198
 199        case IIO_CHAN_INFO_SCALE:
 200                ret = regulator_get_voltage(ti_dac->vref);
 201                if (ret < 0)
 202                        return ret;
 203
 204                *val = ret / 1000;
 205                *val2 = ti_dac->resolution;
 206                ret = IIO_VAL_FRACTIONAL_LOG2;
 207                break;
 208
 209        default:
 210                ret = -EINVAL;
 211        }
 212
 213        return ret;
 214}
 215
 216static int ti_dac_write_raw(struct iio_dev *indio_dev,
 217                            struct iio_chan_spec const *chan,
 218                            int val, int val2, long mask)
 219{
 220        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
 221        int ret;
 222
 223        switch (mask) {
 224        case IIO_CHAN_INFO_RAW:
 225                if (ti_dac->val[chan->channel] == val)
 226                        return 0;
 227
 228                if (val >= (1 << ti_dac->resolution) || val < 0)
 229                        return -EINVAL;
 230
 231                if (ti_dac->powerdown)
 232                        return -EBUSY;
 233
 234                mutex_lock(&ti_dac->lock);
 235                ret = ti_dac_cmd(ti_dac, WRITE_AND_UPDATE(chan->channel), val);
 236                if (!ret)
 237                        ti_dac->val[chan->channel] = val;
 238                mutex_unlock(&ti_dac->lock);
 239                break;
 240
 241        default:
 242                ret = -EINVAL;
 243        }
 244
 245        return ret;
 246}
 247
 248static int ti_dac_write_raw_get_fmt(struct iio_dev *indio_dev,
 249                                    struct iio_chan_spec const *chan, long mask)
 250{
 251        return IIO_VAL_INT;
 252}
 253
 254static const struct iio_info ti_dac_info = {
 255        .read_raw          = ti_dac_read_raw,
 256        .write_raw         = ti_dac_write_raw,
 257        .write_raw_get_fmt = ti_dac_write_raw_get_fmt,
 258};
 259
 260static int ti_dac_probe(struct spi_device *spi)
 261{
 262        struct device *dev = &spi->dev;
 263        const struct ti_dac_spec *spec;
 264        struct ti_dac_chip *ti_dac;
 265        struct iio_dev *indio_dev;
 266        int ret;
 267
 268        indio_dev = devm_iio_device_alloc(dev, sizeof(*ti_dac));
 269        if (!indio_dev)
 270                return -ENOMEM;
 271
 272        indio_dev->info = &ti_dac_info;
 273        indio_dev->name = spi->modalias;
 274        indio_dev->modes = INDIO_DIRECT_MODE;
 275        indio_dev->channels = ti_dac_channels;
 276        spi_set_drvdata(spi, indio_dev);
 277
 278        ti_dac = iio_priv(indio_dev);
 279        ti_dac->xfer.tx_buf = &ti_dac->buf;
 280        ti_dac->xfer.len = sizeof(ti_dac->buf);
 281        spi_message_init_with_transfers(&ti_dac->mesg, &ti_dac->xfer, 1);
 282        ti_dac->mesg.spi = spi;
 283
 284        spec = &ti_dac_spec[spi_get_device_id(spi)->driver_data];
 285        indio_dev->num_channels = spec->num_channels;
 286        ti_dac->resolution = spec->resolution;
 287
 288        ti_dac->vref = devm_regulator_get(dev, "vref");
 289        if (IS_ERR(ti_dac->vref))
 290                return PTR_ERR(ti_dac->vref);
 291
 292        ret = regulator_enable(ti_dac->vref);
 293        if (ret < 0)
 294                return ret;
 295
 296        mutex_init(&ti_dac->lock);
 297
 298        ret = ti_dac_cmd(ti_dac, WRITE_ALL_UPDATE, 0);
 299        if (ret) {
 300                dev_err(dev, "failed to initialize outputs to 0\n");
 301                goto err;
 302        }
 303
 304        ret = iio_device_register(indio_dev);
 305        if (ret)
 306                goto err;
 307
 308        return 0;
 309
 310err:
 311        mutex_destroy(&ti_dac->lock);
 312        regulator_disable(ti_dac->vref);
 313        return ret;
 314}
 315
 316static int ti_dac_remove(struct spi_device *spi)
 317{
 318        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 319        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
 320
 321        iio_device_unregister(indio_dev);
 322        mutex_destroy(&ti_dac->lock);
 323        regulator_disable(ti_dac->vref);
 324
 325        return 0;
 326}
 327
 328static const struct of_device_id ti_dac_of_id[] = {
 329        { .compatible = "ti,dac082s085" },
 330        { .compatible = "ti,dac102s085" },
 331        { .compatible = "ti,dac122s085" },
 332        { .compatible = "ti,dac084s085" },
 333        { .compatible = "ti,dac104s085" },
 334        { .compatible = "ti,dac124s085" },
 335        { }
 336};
 337MODULE_DEVICE_TABLE(of, ti_dac_of_id);
 338
 339static const struct spi_device_id ti_dac_spi_id[] = {
 340        { "dac082s085", dual_8bit  },
 341        { "dac102s085", dual_10bit },
 342        { "dac122s085", dual_12bit },
 343        { "dac084s085", quad_8bit  },
 344        { "dac104s085", quad_10bit },
 345        { "dac124s085", quad_12bit },
 346        { }
 347};
 348MODULE_DEVICE_TABLE(spi, ti_dac_spi_id);
 349
 350static struct spi_driver ti_dac_driver = {
 351        .driver = {
 352                .name           = "ti-dac082s085",
 353                .of_match_table = ti_dac_of_id,
 354        },
 355        .probe    = ti_dac_probe,
 356        .remove   = ti_dac_remove,
 357        .id_table = ti_dac_spi_id,
 358};
 359module_spi_driver(ti_dac_driver);
 360
 361MODULE_AUTHOR("Lukas Wunner <lukas@wunner.de>");
 362MODULE_DESCRIPTION("Texas Instruments 8/10/12-bit 2/4-channel DAC driver");
 363MODULE_LICENSE("GPL v2");
 364