linux/drivers/iio/dac/ltc2632.c
<<
>>
Prefs
   1/*
   2 * LTC2632 Digital to analog convertors spi driver
   3 *
   4 * Copyright 2017 Maxime Roussin-BĂ©langer
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8
   9#include <linux/device.h>
  10#include <linux/spi/spi.h>
  11#include <linux/module.h>
  12#include <linux/iio/iio.h>
  13
  14#define LTC2632_DAC_CHANNELS                    2
  15
  16#define LTC2632_ADDR_DAC0                       0x0
  17#define LTC2632_ADDR_DAC1                       0x1
  18
  19#define LTC2632_CMD_WRITE_INPUT_N               0x0
  20#define LTC2632_CMD_UPDATE_DAC_N                0x1
  21#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL    0x2
  22#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N      0x3
  23#define LTC2632_CMD_POWERDOWN_DAC_N             0x4
  24#define LTC2632_CMD_POWERDOWN_CHIP              0x5
  25#define LTC2632_CMD_INTERNAL_REFER              0x6
  26#define LTC2632_CMD_EXTERNAL_REFER              0x7
  27
  28/**
  29 * struct ltc2632_chip_info - chip specific information
  30 * @channels:           channel spec for the DAC
  31 * @vref_mv:            reference voltage
  32 */
  33struct ltc2632_chip_info {
  34        const struct iio_chan_spec *channels;
  35        const int vref_mv;
  36};
  37
  38/**
  39 * struct ltc2632_state - driver instance specific data
  40 * @spi_dev:                    pointer to the spi_device struct
  41 * @powerdown_cache_mask        used to show current channel powerdown state
  42 */
  43struct ltc2632_state {
  44        struct spi_device *spi_dev;
  45        unsigned int powerdown_cache_mask;
  46};
  47
  48enum ltc2632_supported_device_ids {
  49        ID_LTC2632L12,
  50        ID_LTC2632L10,
  51        ID_LTC2632L8,
  52        ID_LTC2632H12,
  53        ID_LTC2632H10,
  54        ID_LTC2632H8,
  55};
  56
  57static int ltc2632_spi_write(struct spi_device *spi,
  58                             u8 cmd, u8 addr, u16 val, u8 shift)
  59{
  60        u32 data;
  61        u8 msg[3];
  62
  63        /*
  64         * The input shift register is 24 bits wide.
  65         * The next four are the command bits, C3 to C0,
  66         * followed by the 4-bit DAC address, A3 to A0, and then the
  67         * 12-, 10-, 8-bit data-word. The data-word comprises the 12-,
  68         * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
  69         */
  70        data = (cmd << 20) | (addr << 16) | (val << shift);
  71        msg[0] = data >> 16;
  72        msg[1] = data >> 8;
  73        msg[2] = data;
  74
  75        return spi_write(spi, msg, sizeof(msg));
  76}
  77
  78static int ltc2632_read_raw(struct iio_dev *indio_dev,
  79                            struct iio_chan_spec const *chan,
  80                            int *val,
  81                            int *val2,
  82                            long m)
  83{
  84        struct ltc2632_chip_info *chip_info;
  85
  86        const struct ltc2632_state *st = iio_priv(indio_dev);
  87        const struct spi_device_id *spi_dev_id = spi_get_device_id(st->spi_dev);
  88
  89        chip_info = (struct ltc2632_chip_info *)spi_dev_id->driver_data;
  90
  91        switch (m) {
  92        case IIO_CHAN_INFO_SCALE:
  93                *val = chip_info->vref_mv;
  94                *val2 = chan->scan_type.realbits;
  95                return IIO_VAL_FRACTIONAL_LOG2;
  96        }
  97        return -EINVAL;
  98}
  99
 100static int ltc2632_write_raw(struct iio_dev *indio_dev,
 101                             struct iio_chan_spec const *chan,
 102                             int val,
 103                             int val2,
 104                             long mask)
 105{
 106        struct ltc2632_state *st = iio_priv(indio_dev);
 107
 108        switch (mask) {
 109        case IIO_CHAN_INFO_RAW:
 110                if (val >= (1 << chan->scan_type.realbits) || val < 0)
 111                        return -EINVAL;
 112
 113                return ltc2632_spi_write(st->spi_dev,
 114                                         LTC2632_CMD_WRITE_INPUT_N_UPDATE_N,
 115                                         chan->address, val,
 116                                         chan->scan_type.shift);
 117        default:
 118                return -EINVAL;
 119        }
 120}
 121
 122static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev,
 123                                          uintptr_t private,
 124                                          const struct iio_chan_spec *chan,
 125                                          char *buf)
 126{
 127        struct ltc2632_state *st = iio_priv(indio_dev);
 128
 129        return sprintf(buf, "%d\n",
 130                       !!(st->powerdown_cache_mask & (1 << chan->channel)));
 131}
 132
 133static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev,
 134                                           uintptr_t private,
 135                                           const struct iio_chan_spec *chan,
 136                                           const char *buf,
 137                                           size_t len)
 138{
 139        bool pwr_down;
 140        int ret;
 141        struct ltc2632_state *st = iio_priv(indio_dev);
 142
 143        ret = strtobool(buf, &pwr_down);
 144        if (ret)
 145                return ret;
 146
 147        if (pwr_down)
 148                st->powerdown_cache_mask |= (1 << chan->channel);
 149        else
 150                st->powerdown_cache_mask &= ~(1 << chan->channel);
 151
 152        ret = ltc2632_spi_write(st->spi_dev,
 153                                LTC2632_CMD_POWERDOWN_DAC_N,
 154                                chan->channel, 0, 0);
 155
 156        return ret ? ret : len;
 157}
 158
 159static const struct iio_info ltc2632_info = {
 160        .write_raw      = ltc2632_write_raw,
 161        .read_raw       = ltc2632_read_raw,
 162        .driver_module  = THIS_MODULE,
 163};
 164
 165static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
 166        {
 167                .name = "powerdown",
 168                .read = ltc2632_read_dac_powerdown,
 169                .write = ltc2632_write_dac_powerdown,
 170                .shared = IIO_SEPARATE,
 171        },
 172        { },
 173};
 174
 175#define LTC2632_CHANNEL(_chan, _bits) { \
 176                .type = IIO_VOLTAGE, \
 177                .indexed = 1, \
 178                .output = 1, \
 179                .channel = (_chan), \
 180                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 181                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 182                .address = (_chan), \
 183                .scan_type = { \
 184                        .realbits       = (_bits), \
 185                        .shift          = 16 - (_bits), \
 186                }, \
 187                .ext_info = ltc2632_ext_info, \
 188}
 189
 190#define DECLARE_LTC2632_CHANNELS(_name, _bits) \
 191        const struct iio_chan_spec _name ## _channels[] = { \
 192                LTC2632_CHANNEL(0, _bits), \
 193                LTC2632_CHANNEL(1, _bits), \
 194        }
 195
 196static DECLARE_LTC2632_CHANNELS(ltc2632l12, 12);
 197static DECLARE_LTC2632_CHANNELS(ltc2632l10, 10);
 198static DECLARE_LTC2632_CHANNELS(ltc2632l8, 8);
 199
 200static DECLARE_LTC2632_CHANNELS(ltc2632h12, 12);
 201static DECLARE_LTC2632_CHANNELS(ltc2632h10, 10);
 202static DECLARE_LTC2632_CHANNELS(ltc2632h8, 8);
 203
 204static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
 205        [ID_LTC2632L12] = {
 206                .channels       = ltc2632l12_channels,
 207                .vref_mv        = 2500,
 208        },
 209        [ID_LTC2632L10] = {
 210                .channels       = ltc2632l10_channels,
 211                .vref_mv        = 2500,
 212        },
 213        [ID_LTC2632L8] =  {
 214                .channels       = ltc2632l8_channels,
 215                .vref_mv        = 2500,
 216        },
 217        [ID_LTC2632H12] = {
 218                .channels       = ltc2632h12_channels,
 219                .vref_mv        = 4096,
 220        },
 221        [ID_LTC2632H10] = {
 222                .channels       = ltc2632h10_channels,
 223                .vref_mv        = 4096,
 224        },
 225        [ID_LTC2632H8] =  {
 226                .channels       = ltc2632h8_channels,
 227                .vref_mv        = 4096,
 228        },
 229};
 230
 231static int ltc2632_probe(struct spi_device *spi)
 232{
 233        struct ltc2632_state *st;
 234        struct iio_dev *indio_dev;
 235        struct ltc2632_chip_info *chip_info;
 236        int ret;
 237
 238        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 239        if (!indio_dev)
 240                return -ENOMEM;
 241
 242        st = iio_priv(indio_dev);
 243
 244        spi_set_drvdata(spi, indio_dev);
 245        st->spi_dev = spi;
 246
 247        chip_info = (struct ltc2632_chip_info *)
 248                        spi_get_device_id(spi)->driver_data;
 249
 250        indio_dev->dev.parent = &spi->dev;
 251        indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name
 252                                                 : spi_get_device_id(spi)->name;
 253        indio_dev->info = &ltc2632_info;
 254        indio_dev->modes = INDIO_DIRECT_MODE;
 255        indio_dev->channels = chip_info->channels;
 256        indio_dev->num_channels = LTC2632_DAC_CHANNELS;
 257
 258        ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 0, 0, 0);
 259        if (ret) {
 260                dev_err(&spi->dev,
 261                        "Set internal reference command failed, %d\n", ret);
 262                return ret;
 263        }
 264
 265        return devm_iio_device_register(&spi->dev, indio_dev);
 266}
 267
 268static const struct spi_device_id ltc2632_id[] = {
 269        { "ltc2632-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L12] },
 270        { "ltc2632-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L10] },
 271        { "ltc2632-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L8] },
 272        { "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
 273        { "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
 274        { "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
 275        {}
 276};
 277MODULE_DEVICE_TABLE(spi, ltc2632_id);
 278
 279static struct spi_driver ltc2632_driver = {
 280        .driver         = {
 281                .name   = "ltc2632",
 282        },
 283        .probe          = ltc2632_probe,
 284        .id_table       = ltc2632_id,
 285};
 286module_spi_driver(ltc2632_driver);
 287
 288static const struct of_device_id ltc2632_of_match[] = {
 289        {
 290                .compatible = "lltc,ltc2632-l12",
 291                .data = &ltc2632_chip_info_tbl[ID_LTC2632L12]
 292        }, {
 293                .compatible = "lltc,ltc2632-l10",
 294                .data = &ltc2632_chip_info_tbl[ID_LTC2632L10]
 295        }, {
 296                .compatible = "lltc,ltc2632-l8",
 297                .data = &ltc2632_chip_info_tbl[ID_LTC2632L8]
 298        }, {
 299                .compatible = "lltc,ltc2632-h12",
 300                .data = &ltc2632_chip_info_tbl[ID_LTC2632H12]
 301        }, {
 302                .compatible = "lltc,ltc2632-h10",
 303                .data = &ltc2632_chip_info_tbl[ID_LTC2632H10]
 304        }, {
 305                .compatible = "lltc,ltc2632-h8",
 306                .data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
 307        },
 308        {}
 309};
 310MODULE_DEVICE_TABLE(of, ltc2632_of_match);
 311
 312MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
 313MODULE_DESCRIPTION("LTC2632 DAC SPI driver");
 314MODULE_LICENSE("GPL v2");
 315