linux/drivers/iio/dac/ltc2632.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * LTC2632 Digital to analog convertors spi driver
   4 *
   5 * Copyright 2017 Maxime Roussin-BĂ©langer
   6 * expanded by Silvan Murer <silvan.murer@gmail.com>
   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#include <linux/regulator/consumer.h>
  14
  15#define LTC2632_DAC_CHANNELS                    2
  16
  17#define LTC2632_ADDR_DAC0                       0x0
  18#define LTC2632_ADDR_DAC1                       0x1
  19
  20#define LTC2632_CMD_WRITE_INPUT_N               0x0
  21#define LTC2632_CMD_UPDATE_DAC_N                0x1
  22#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL    0x2
  23#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N      0x3
  24#define LTC2632_CMD_POWERDOWN_DAC_N             0x4
  25#define LTC2632_CMD_POWERDOWN_CHIP              0x5
  26#define LTC2632_CMD_INTERNAL_REFER              0x6
  27#define LTC2632_CMD_EXTERNAL_REFER              0x7
  28
  29/**
  30 * struct ltc2632_chip_info - chip specific information
  31 * @channels:           channel spec for the DAC
  32 * @vref_mv:            internal reference voltage
  33 */
  34struct ltc2632_chip_info {
  35        const struct iio_chan_spec *channels;
  36        const int vref_mv;
  37};
  38
  39/**
  40 * struct ltc2632_state - driver instance specific data
  41 * @spi_dev:                    pointer to the spi_device struct
  42 * @powerdown_cache_mask        used to show current channel powerdown state
  43 * @vref_mv                     used reference voltage (internal or external)
  44 * @vref_reg            regulator for the reference voltage
  45 */
  46struct ltc2632_state {
  47        struct spi_device *spi_dev;
  48        unsigned int powerdown_cache_mask;
  49        int vref_mv;
  50        struct regulator *vref_reg;
  51};
  52
  53enum ltc2632_supported_device_ids {
  54        ID_LTC2632L12,
  55        ID_LTC2632L10,
  56        ID_LTC2632L8,
  57        ID_LTC2632H12,
  58        ID_LTC2632H10,
  59        ID_LTC2632H8,
  60};
  61
  62static int ltc2632_spi_write(struct spi_device *spi,
  63                             u8 cmd, u8 addr, u16 val, u8 shift)
  64{
  65        u32 data;
  66        u8 msg[3];
  67
  68        /*
  69         * The input shift register is 24 bits wide.
  70         * The next four are the command bits, C3 to C0,
  71         * followed by the 4-bit DAC address, A3 to A0, and then the
  72         * 12-, 10-, 8-bit data-word. The data-word comprises the 12-,
  73         * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
  74         */
  75        data = (cmd << 20) | (addr << 16) | (val << shift);
  76        msg[0] = data >> 16;
  77        msg[1] = data >> 8;
  78        msg[2] = data;
  79
  80        return spi_write(spi, msg, sizeof(msg));
  81}
  82
  83static int ltc2632_read_raw(struct iio_dev *indio_dev,
  84                            struct iio_chan_spec const *chan,
  85                            int *val,
  86                            int *val2,
  87                            long m)
  88{
  89        const struct ltc2632_state *st = iio_priv(indio_dev);
  90
  91        switch (m) {
  92        case IIO_CHAN_INFO_SCALE:
  93                *val = st->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};
 163
 164static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
 165        {
 166                .name = "powerdown",
 167                .read = ltc2632_read_dac_powerdown,
 168                .write = ltc2632_write_dac_powerdown,
 169                .shared = IIO_SEPARATE,
 170        },
 171        { },
 172};
 173
 174#define LTC2632_CHANNEL(_chan, _bits) { \
 175                .type = IIO_VOLTAGE, \
 176                .indexed = 1, \
 177                .output = 1, \
 178                .channel = (_chan), \
 179                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 180                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 181                .address = (_chan), \
 182                .scan_type = { \
 183                        .realbits       = (_bits), \
 184                        .shift          = 16 - (_bits), \
 185                }, \
 186                .ext_info = ltc2632_ext_info, \
 187}
 188
 189#define DECLARE_LTC2632_CHANNELS(_name, _bits) \
 190        const struct iio_chan_spec _name ## _channels[] = { \
 191                LTC2632_CHANNEL(0, _bits), \
 192                LTC2632_CHANNEL(1, _bits), \
 193        }
 194
 195static DECLARE_LTC2632_CHANNELS(ltc2632l12, 12);
 196static DECLARE_LTC2632_CHANNELS(ltc2632l10, 10);
 197static DECLARE_LTC2632_CHANNELS(ltc2632l8, 8);
 198
 199static DECLARE_LTC2632_CHANNELS(ltc2632h12, 12);
 200static DECLARE_LTC2632_CHANNELS(ltc2632h10, 10);
 201static DECLARE_LTC2632_CHANNELS(ltc2632h8, 8);
 202
 203static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
 204        [ID_LTC2632L12] = {
 205                .channels       = ltc2632l12_channels,
 206                .vref_mv        = 2500,
 207        },
 208        [ID_LTC2632L10] = {
 209                .channels       = ltc2632l10_channels,
 210                .vref_mv        = 2500,
 211        },
 212        [ID_LTC2632L8] =  {
 213                .channels       = ltc2632l8_channels,
 214                .vref_mv        = 2500,
 215        },
 216        [ID_LTC2632H12] = {
 217                .channels       = ltc2632h12_channels,
 218                .vref_mv        = 4096,
 219        },
 220        [ID_LTC2632H10] = {
 221                .channels       = ltc2632h10_channels,
 222                .vref_mv        = 4096,
 223        },
 224        [ID_LTC2632H8] =  {
 225                .channels       = ltc2632h8_channels,
 226                .vref_mv        = 4096,
 227        },
 228};
 229
 230static int ltc2632_probe(struct spi_device *spi)
 231{
 232        struct ltc2632_state *st;
 233        struct iio_dev *indio_dev;
 234        struct ltc2632_chip_info *chip_info;
 235        int ret;
 236
 237        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 238        if (!indio_dev)
 239                return -ENOMEM;
 240
 241        st = iio_priv(indio_dev);
 242
 243        spi_set_drvdata(spi, indio_dev);
 244        st->spi_dev = spi;
 245
 246        chip_info = (struct ltc2632_chip_info *)
 247                        spi_get_device_id(spi)->driver_data;
 248
 249        st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
 250        if (PTR_ERR(st->vref_reg) == -ENODEV) {
 251                /* use internal reference voltage */
 252                st->vref_reg = NULL;
 253                st->vref_mv = chip_info->vref_mv;
 254
 255                ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER,
 256                                0, 0, 0);
 257                if (ret) {
 258                        dev_err(&spi->dev,
 259                                "Set internal reference command failed, %d\n",
 260                                ret);
 261                        return ret;
 262                }
 263        } else if (IS_ERR(st->vref_reg)) {
 264                dev_err(&spi->dev,
 265                                "Error getting voltage reference regulator\n");
 266                return PTR_ERR(st->vref_reg);
 267        } else {
 268                /* use external reference voltage */
 269                ret = regulator_enable(st->vref_reg);
 270                if (ret) {
 271                        dev_err(&spi->dev,
 272                                "enable reference regulator failed, %d\n",
 273                                ret);
 274                        return ret;
 275                }
 276                st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000;
 277
 278                ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER,
 279                                0, 0, 0);
 280                if (ret) {
 281                        dev_err(&spi->dev,
 282                                "Set external reference command failed, %d\n",
 283                                ret);
 284                        return ret;
 285                }
 286        }
 287
 288        indio_dev->dev.parent = &spi->dev;
 289        indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name
 290                                                 : spi_get_device_id(spi)->name;
 291        indio_dev->info = &ltc2632_info;
 292        indio_dev->modes = INDIO_DIRECT_MODE;
 293        indio_dev->channels = chip_info->channels;
 294        indio_dev->num_channels = LTC2632_DAC_CHANNELS;
 295
 296        return iio_device_register(indio_dev);
 297}
 298
 299static int ltc2632_remove(struct spi_device *spi)
 300{
 301        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 302        struct ltc2632_state *st = iio_priv(indio_dev);
 303
 304        iio_device_unregister(indio_dev);
 305
 306        if (st->vref_reg)
 307                regulator_disable(st->vref_reg);
 308
 309        return 0;
 310}
 311
 312static const struct spi_device_id ltc2632_id[] = {
 313        { "ltc2632-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L12] },
 314        { "ltc2632-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L10] },
 315        { "ltc2632-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L8] },
 316        { "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
 317        { "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
 318        { "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
 319        {}
 320};
 321MODULE_DEVICE_TABLE(spi, ltc2632_id);
 322
 323static const struct of_device_id ltc2632_of_match[] = {
 324        {
 325                .compatible = "lltc,ltc2632-l12",
 326                .data = &ltc2632_chip_info_tbl[ID_LTC2632L12]
 327        }, {
 328                .compatible = "lltc,ltc2632-l10",
 329                .data = &ltc2632_chip_info_tbl[ID_LTC2632L10]
 330        }, {
 331                .compatible = "lltc,ltc2632-l8",
 332                .data = &ltc2632_chip_info_tbl[ID_LTC2632L8]
 333        }, {
 334                .compatible = "lltc,ltc2632-h12",
 335                .data = &ltc2632_chip_info_tbl[ID_LTC2632H12]
 336        }, {
 337                .compatible = "lltc,ltc2632-h10",
 338                .data = &ltc2632_chip_info_tbl[ID_LTC2632H10]
 339        }, {
 340                .compatible = "lltc,ltc2632-h8",
 341                .data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
 342        },
 343        {}
 344};
 345MODULE_DEVICE_TABLE(of, ltc2632_of_match);
 346
 347static struct spi_driver ltc2632_driver = {
 348        .driver         = {
 349                .name   = "ltc2632",
 350                .of_match_table = of_match_ptr(ltc2632_of_match),
 351        },
 352        .probe          = ltc2632_probe,
 353        .remove         = ltc2632_remove,
 354        .id_table       = ltc2632_id,
 355};
 356module_spi_driver(ltc2632_driver);
 357
 358MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
 359MODULE_DESCRIPTION("LTC2632 DAC SPI driver");
 360MODULE_LICENSE("GPL v2");
 361