root/drivers/iio/dac/ti-dac082s085.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ti_dac_cmd
  2. ti_dac_get_powerdown_mode
  3. ti_dac_set_powerdown_mode
  4. ti_dac_read_powerdown
  5. ti_dac_write_powerdown
  6. ti_dac_read_raw
  7. ti_dac_write_raw
  8. ti_dac_write_raw_get_fmt
  9. ti_dac_probe
  10. ti_dac_remove

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

/* [<][>][^][v][top][bottom][index][help] */