linux/drivers/iio/dac/ltc1660.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Driver for Linear Technology LTC1665/LTC1660, 8 channels DAC
   4 *
   5 * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
   6 */
   7#include <linux/bitops.h>
   8#include <linux/iio/iio.h>
   9#include <linux/iio/sysfs.h>
  10#include <linux/init.h>
  11#include <linux/module.h>
  12#include <linux/regulator/consumer.h>
  13#include <linux/regmap.h>
  14#include <linux/spi/spi.h>
  15
  16#define LTC1660_REG_WAKE        0x0
  17#define LTC1660_REG_DAC_A       0x1
  18#define LTC1660_REG_DAC_B       0x2
  19#define LTC1660_REG_DAC_C       0x3
  20#define LTC1660_REG_DAC_D       0x4
  21#define LTC1660_REG_DAC_E       0x5
  22#define LTC1660_REG_DAC_F       0x6
  23#define LTC1660_REG_DAC_G       0x7
  24#define LTC1660_REG_DAC_H       0x8
  25#define LTC1660_REG_SLEEP       0xe
  26
  27#define LTC1660_NUM_CHANNELS    8
  28
  29static const struct regmap_config ltc1660_regmap_config = {
  30        .reg_bits = 4,
  31        .val_bits = 12,
  32};
  33
  34enum ltc1660_supported_device_ids {
  35        ID_LTC1660,
  36        ID_LTC1665,
  37};
  38
  39struct ltc1660_priv {
  40        struct spi_device *spi;
  41        struct regmap *regmap;
  42        struct regulator *vref_reg;
  43        unsigned int value[LTC1660_NUM_CHANNELS];
  44        unsigned int vref_mv;
  45};
  46
  47static int ltc1660_read_raw(struct iio_dev *indio_dev,
  48                struct iio_chan_spec const *chan,
  49                int *val,
  50                int *val2,
  51                long mask)
  52{
  53        struct ltc1660_priv *priv = iio_priv(indio_dev);
  54
  55        switch (mask) {
  56        case IIO_CHAN_INFO_RAW:
  57                *val = priv->value[chan->channel];
  58                return IIO_VAL_INT;
  59        case IIO_CHAN_INFO_SCALE:
  60                *val = regulator_get_voltage(priv->vref_reg);
  61                if (*val < 0) {
  62                        dev_err(&priv->spi->dev, "failed to read vref regulator: %d\n",
  63                                        *val);
  64                        return *val;
  65                }
  66
  67                /* Convert to mV */
  68                *val /= 1000;
  69                *val2 = chan->scan_type.realbits;
  70                return IIO_VAL_FRACTIONAL_LOG2;
  71        default:
  72                return -EINVAL;
  73        }
  74}
  75
  76static int ltc1660_write_raw(struct iio_dev *indio_dev,
  77                struct iio_chan_spec const *chan,
  78                int val,
  79                int val2,
  80                long mask)
  81{
  82        struct ltc1660_priv *priv = iio_priv(indio_dev);
  83        int ret;
  84
  85        switch (mask) {
  86        case IIO_CHAN_INFO_RAW:
  87                if (val2 != 0)
  88                        return -EINVAL;
  89
  90                if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0))
  91                        return -EINVAL;
  92
  93                ret = regmap_write(priv->regmap, chan->channel,
  94                                        (val << chan->scan_type.shift));
  95                if (!ret)
  96                        priv->value[chan->channel] = val;
  97
  98                return ret;
  99        default:
 100                return -EINVAL;
 101        }
 102}
 103
 104#define LTC1660_CHAN(chan, bits) {                      \
 105        .type = IIO_VOLTAGE,                            \
 106        .indexed = 1,                                   \
 107        .output = 1,                                    \
 108        .channel = chan,                                \
 109        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
 110        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
 111        .scan_type = {                                  \
 112                .sign = 'u',                            \
 113                .realbits = (bits),                     \
 114                .storagebits = 16,                      \
 115                .shift = 12 - (bits),                   \
 116        },                                              \
 117}
 118
 119#define  LTC1660_OCTAL_CHANNELS(bits) {                 \
 120                LTC1660_CHAN(LTC1660_REG_DAC_A, bits),  \
 121                LTC1660_CHAN(LTC1660_REG_DAC_B, bits),  \
 122                LTC1660_CHAN(LTC1660_REG_DAC_C, bits),  \
 123                LTC1660_CHAN(LTC1660_REG_DAC_D, bits),  \
 124                LTC1660_CHAN(LTC1660_REG_DAC_E, bits),  \
 125                LTC1660_CHAN(LTC1660_REG_DAC_F, bits),  \
 126                LTC1660_CHAN(LTC1660_REG_DAC_G, bits),  \
 127                LTC1660_CHAN(LTC1660_REG_DAC_H, bits),  \
 128}
 129
 130static const struct iio_chan_spec ltc1660_channels[][LTC1660_NUM_CHANNELS] = {
 131        [ID_LTC1660] = LTC1660_OCTAL_CHANNELS(10),
 132        [ID_LTC1665] = LTC1660_OCTAL_CHANNELS(8),
 133};
 134
 135static const struct iio_info ltc1660_info = {
 136        .read_raw = &ltc1660_read_raw,
 137        .write_raw = &ltc1660_write_raw,
 138};
 139
 140static int __maybe_unused ltc1660_suspend(struct device *dev)
 141{
 142        struct ltc1660_priv *priv = iio_priv(spi_get_drvdata(
 143                                                to_spi_device(dev)));
 144        return regmap_write(priv->regmap, LTC1660_REG_SLEEP, 0x00);
 145}
 146
 147static int __maybe_unused ltc1660_resume(struct device *dev)
 148{
 149        struct ltc1660_priv *priv = iio_priv(spi_get_drvdata(
 150                                                to_spi_device(dev)));
 151        return regmap_write(priv->regmap, LTC1660_REG_WAKE, 0x00);
 152}
 153static SIMPLE_DEV_PM_OPS(ltc1660_pm_ops, ltc1660_suspend, ltc1660_resume);
 154
 155static int ltc1660_probe(struct spi_device *spi)
 156{
 157        struct iio_dev *indio_dev;
 158        struct ltc1660_priv *priv;
 159        const struct spi_device_id *id = spi_get_device_id(spi);
 160        int ret;
 161
 162        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*priv));
 163        if (indio_dev == NULL)
 164                return -ENOMEM;
 165
 166        priv = iio_priv(indio_dev);
 167        priv->regmap = devm_regmap_init_spi(spi, &ltc1660_regmap_config);
 168        if (IS_ERR(priv->regmap)) {
 169                dev_err(&spi->dev, "failed to register spi regmap %ld\n",
 170                        PTR_ERR(priv->regmap));
 171                return PTR_ERR(priv->regmap);
 172        }
 173
 174        priv->vref_reg = devm_regulator_get(&spi->dev, "vref");
 175        if (IS_ERR(priv->vref_reg)) {
 176                dev_err(&spi->dev, "vref regulator not specified\n");
 177                return PTR_ERR(priv->vref_reg);
 178        }
 179
 180        ret = regulator_enable(priv->vref_reg);
 181        if (ret) {
 182                dev_err(&spi->dev, "failed to enable vref regulator: %d\n",
 183                                ret);
 184                return ret;
 185        }
 186
 187        priv->spi = spi;
 188        spi_set_drvdata(spi, indio_dev);
 189        indio_dev->info = &ltc1660_info;
 190        indio_dev->modes = INDIO_DIRECT_MODE;
 191        indio_dev->channels = ltc1660_channels[id->driver_data];
 192        indio_dev->num_channels = LTC1660_NUM_CHANNELS;
 193        indio_dev->name = id->name;
 194
 195        ret = iio_device_register(indio_dev);
 196        if (ret) {
 197                dev_err(&spi->dev, "failed to register iio device: %d\n",
 198                                ret);
 199                goto error_disable_reg;
 200        }
 201
 202        return 0;
 203
 204error_disable_reg:
 205        regulator_disable(priv->vref_reg);
 206
 207        return ret;
 208}
 209
 210static int ltc1660_remove(struct spi_device *spi)
 211{
 212        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 213        struct ltc1660_priv *priv = iio_priv(indio_dev);
 214
 215        iio_device_unregister(indio_dev);
 216        regulator_disable(priv->vref_reg);
 217
 218        return 0;
 219}
 220
 221static const struct of_device_id ltc1660_dt_ids[] = {
 222        { .compatible = "lltc,ltc1660", .data = (void *)ID_LTC1660 },
 223        { .compatible = "lltc,ltc1665", .data = (void *)ID_LTC1665 },
 224        { /* sentinel */ }
 225};
 226MODULE_DEVICE_TABLE(of, ltc1660_dt_ids);
 227
 228static const struct spi_device_id ltc1660_id[] = {
 229        {"ltc1660", ID_LTC1660},
 230        {"ltc1665", ID_LTC1665},
 231        { /* sentinel */ }
 232};
 233MODULE_DEVICE_TABLE(spi, ltc1660_id);
 234
 235static struct spi_driver ltc1660_driver = {
 236        .driver = {
 237                .name = "ltc1660",
 238                .of_match_table = ltc1660_dt_ids,
 239                .pm = &ltc1660_pm_ops,
 240        },
 241        .probe  = ltc1660_probe,
 242        .remove = ltc1660_remove,
 243        .id_table = ltc1660_id,
 244};
 245module_spi_driver(ltc1660_driver);
 246
 247MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
 248MODULE_DESCRIPTION("Linear Technology LTC1660/LTC1665 DAC");
 249MODULE_LICENSE("GPL v2");
 250