linux/drivers/iio/dac/ad5624r_spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver
   4 *
   5 * Copyright 2010-2011 Analog Devices Inc.
   6 */
   7
   8#include <linux/interrupt.h>
   9#include <linux/fs.h>
  10#include <linux/device.h>
  11#include <linux/kernel.h>
  12#include <linux/spi/spi.h>
  13#include <linux/slab.h>
  14#include <linux/sysfs.h>
  15#include <linux/regulator/consumer.h>
  16#include <linux/module.h>
  17
  18#include <linux/iio/iio.h>
  19#include <linux/iio/sysfs.h>
  20
  21#include <asm/unaligned.h>
  22
  23#include "ad5624r.h"
  24
  25static int ad5624r_spi_write(struct spi_device *spi,
  26                             u8 cmd, u8 addr, u16 val, u8 shift)
  27{
  28        u32 data;
  29        u8 msg[3];
  30
  31        /*
  32         * The input shift register is 24 bits wide. The first two bits are
  33         * don't care bits. The next three are the command bits, C2 to C0,
  34         * followed by the 3-bit DAC address, A2 to A0, and then the
  35         * 16-, 14-, 12-bit data-word. The data-word comprises the 16-,
  36         * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits,
  37         * for the AD5664R, AD5644R, and AD5624R, respectively.
  38         */
  39        data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift);
  40        put_unaligned_be24(data, &msg[0]);
  41
  42        return spi_write(spi, msg, sizeof(msg));
  43}
  44
  45static int ad5624r_read_raw(struct iio_dev *indio_dev,
  46                           struct iio_chan_spec const *chan,
  47                           int *val,
  48                           int *val2,
  49                           long m)
  50{
  51        struct ad5624r_state *st = iio_priv(indio_dev);
  52
  53        switch (m) {
  54        case IIO_CHAN_INFO_SCALE:
  55                *val = st->vref_mv;
  56                *val2 = chan->scan_type.realbits;
  57                return IIO_VAL_FRACTIONAL_LOG2;
  58        }
  59        return -EINVAL;
  60}
  61
  62static int ad5624r_write_raw(struct iio_dev *indio_dev,
  63                               struct iio_chan_spec const *chan,
  64                               int val,
  65                               int val2,
  66                               long mask)
  67{
  68        struct ad5624r_state *st = iio_priv(indio_dev);
  69
  70        switch (mask) {
  71        case IIO_CHAN_INFO_RAW:
  72                if (val >= (1 << chan->scan_type.realbits) || val < 0)
  73                        return -EINVAL;
  74
  75                return ad5624r_spi_write(st->us,
  76                                AD5624R_CMD_WRITE_INPUT_N_UPDATE_N,
  77                                chan->address, val,
  78                                chan->scan_type.shift);
  79        default:
  80                return -EINVAL;
  81        }
  82}
  83
  84static const char * const ad5624r_powerdown_modes[] = {
  85        "1kohm_to_gnd",
  86        "100kohm_to_gnd",
  87        "three_state"
  88};
  89
  90static int ad5624r_get_powerdown_mode(struct iio_dev *indio_dev,
  91        const struct iio_chan_spec *chan)
  92{
  93        struct ad5624r_state *st = iio_priv(indio_dev);
  94
  95        return st->pwr_down_mode;
  96}
  97
  98static int ad5624r_set_powerdown_mode(struct iio_dev *indio_dev,
  99        const struct iio_chan_spec *chan, unsigned int mode)
 100{
 101        struct ad5624r_state *st = iio_priv(indio_dev);
 102
 103        st->pwr_down_mode = mode;
 104
 105        return 0;
 106}
 107
 108static const struct iio_enum ad5624r_powerdown_mode_enum = {
 109        .items = ad5624r_powerdown_modes,
 110        .num_items = ARRAY_SIZE(ad5624r_powerdown_modes),
 111        .get = ad5624r_get_powerdown_mode,
 112        .set = ad5624r_set_powerdown_mode,
 113};
 114
 115static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev,
 116        uintptr_t private, const struct iio_chan_spec *chan, char *buf)
 117{
 118        struct ad5624r_state *st = iio_priv(indio_dev);
 119
 120        return sysfs_emit(buf, "%d\n",
 121                          !!(st->pwr_down_mask & (1 << chan->channel)));
 122}
 123
 124static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev,
 125        uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
 126        size_t len)
 127{
 128        bool pwr_down;
 129        int ret;
 130        struct ad5624r_state *st = iio_priv(indio_dev);
 131
 132        ret = strtobool(buf, &pwr_down);
 133        if (ret)
 134                return ret;
 135
 136        if (pwr_down)
 137                st->pwr_down_mask |= (1 << chan->channel);
 138        else
 139                st->pwr_down_mask &= ~(1 << chan->channel);
 140
 141        ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0,
 142                                (st->pwr_down_mode << 4) |
 143                                st->pwr_down_mask, 16);
 144
 145        return ret ? ret : len;
 146}
 147
 148static const struct iio_info ad5624r_info = {
 149        .write_raw = ad5624r_write_raw,
 150        .read_raw = ad5624r_read_raw,
 151};
 152
 153static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
 154        {
 155                .name = "powerdown",
 156                .read = ad5624r_read_dac_powerdown,
 157                .write = ad5624r_write_dac_powerdown,
 158                .shared = IIO_SEPARATE,
 159        },
 160        IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
 161                 &ad5624r_powerdown_mode_enum),
 162        IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
 163        { },
 164};
 165
 166#define AD5624R_CHANNEL(_chan, _bits) { \
 167        .type = IIO_VOLTAGE, \
 168        .indexed = 1, \
 169        .output = 1, \
 170        .channel = (_chan), \
 171        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 172        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 173        .address = (_chan), \
 174        .scan_type = { \
 175                .sign = 'u', \
 176                .realbits = (_bits), \
 177                .storagebits = 16, \
 178                .shift = 16 - (_bits), \
 179        }, \
 180        .ext_info = ad5624r_ext_info, \
 181}
 182
 183#define DECLARE_AD5624R_CHANNELS(_name, _bits) \
 184        const struct iio_chan_spec _name##_channels[] = { \
 185                AD5624R_CHANNEL(0, _bits), \
 186                AD5624R_CHANNEL(1, _bits), \
 187                AD5624R_CHANNEL(2, _bits), \
 188                AD5624R_CHANNEL(3, _bits), \
 189}
 190
 191static DECLARE_AD5624R_CHANNELS(ad5624r, 12);
 192static DECLARE_AD5624R_CHANNELS(ad5644r, 14);
 193static DECLARE_AD5624R_CHANNELS(ad5664r, 16);
 194
 195static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
 196        [ID_AD5624R3] = {
 197                .channels = ad5624r_channels,
 198                .int_vref_mv = 1250,
 199        },
 200        [ID_AD5624R5] = {
 201                .channels = ad5624r_channels,
 202                .int_vref_mv = 2500,
 203        },
 204        [ID_AD5644R3] = {
 205                .channels = ad5644r_channels,
 206                .int_vref_mv = 1250,
 207        },
 208        [ID_AD5644R5] = {
 209                .channels = ad5644r_channels,
 210                .int_vref_mv = 2500,
 211        },
 212        [ID_AD5664R3] = {
 213                .channels = ad5664r_channels,
 214                .int_vref_mv = 1250,
 215        },
 216        [ID_AD5664R5] = {
 217                .channels = ad5664r_channels,
 218                .int_vref_mv = 2500,
 219        },
 220};
 221
 222static int ad5624r_probe(struct spi_device *spi)
 223{
 224        struct ad5624r_state *st;
 225        struct iio_dev *indio_dev;
 226        int ret, voltage_uv = 0;
 227
 228        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 229        if (!indio_dev)
 230                return -ENOMEM;
 231        st = iio_priv(indio_dev);
 232        st->reg = devm_regulator_get(&spi->dev, "vcc");
 233        if (!IS_ERR(st->reg)) {
 234                ret = regulator_enable(st->reg);
 235                if (ret)
 236                        return ret;
 237
 238                ret = regulator_get_voltage(st->reg);
 239                if (ret < 0)
 240                        goto error_disable_reg;
 241
 242                voltage_uv = ret;
 243        }
 244
 245        spi_set_drvdata(spi, indio_dev);
 246        st->chip_info =
 247                &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 248
 249        if (voltage_uv)
 250                st->vref_mv = voltage_uv / 1000;
 251        else
 252                st->vref_mv = st->chip_info->int_vref_mv;
 253
 254        st->us = spi;
 255
 256        indio_dev->name = spi_get_device_id(spi)->name;
 257        indio_dev->info = &ad5624r_info;
 258        indio_dev->modes = INDIO_DIRECT_MODE;
 259        indio_dev->channels = st->chip_info->channels;
 260        indio_dev->num_channels = AD5624R_DAC_CHANNELS;
 261
 262        ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
 263                                !!voltage_uv, 16);
 264        if (ret)
 265                goto error_disable_reg;
 266
 267        ret = iio_device_register(indio_dev);
 268        if (ret)
 269                goto error_disable_reg;
 270
 271        return 0;
 272
 273error_disable_reg:
 274        if (!IS_ERR(st->reg))
 275                regulator_disable(st->reg);
 276
 277        return ret;
 278}
 279
 280static int ad5624r_remove(struct spi_device *spi)
 281{
 282        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 283        struct ad5624r_state *st = iio_priv(indio_dev);
 284
 285        iio_device_unregister(indio_dev);
 286        if (!IS_ERR(st->reg))
 287                regulator_disable(st->reg);
 288
 289        return 0;
 290}
 291
 292static const struct spi_device_id ad5624r_id[] = {
 293        {"ad5624r3", ID_AD5624R3},
 294        {"ad5644r3", ID_AD5644R3},
 295        {"ad5664r3", ID_AD5664R3},
 296        {"ad5624r5", ID_AD5624R5},
 297        {"ad5644r5", ID_AD5644R5},
 298        {"ad5664r5", ID_AD5664R5},
 299        {}
 300};
 301MODULE_DEVICE_TABLE(spi, ad5624r_id);
 302
 303static struct spi_driver ad5624r_driver = {
 304        .driver = {
 305                   .name = "ad5624r",
 306                   },
 307        .probe = ad5624r_probe,
 308        .remove = ad5624r_remove,
 309        .id_table = ad5624r_id,
 310};
 311module_spi_driver(ad5624r_driver);
 312
 313MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 314MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver");
 315MODULE_LICENSE("GPL v2");
 316