root/drivers/iio/dac/ad5360.c
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Analog devices AD5360, AD5361, AD5362, AD5363, AD5370, AD5371, AD5373
 * multi-channel Digital to Analog Converters driver
 *
 * Copyright 2011 Analog Devices Inc.
 */

#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>

#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>

#define AD5360_CMD(x)                           ((x) << 22)
#define AD5360_ADDR(x)                          ((x) << 16)

#define AD5360_READBACK_TYPE(x)                 ((x) << 13)
#define AD5360_READBACK_ADDR(x)                 ((x) << 7)

#define AD5360_CHAN_ADDR(chan)                  ((chan) + 0x8)

#define AD5360_CMD_WRITE_DATA                   0x3
#define AD5360_CMD_WRITE_OFFSET                 0x2
#define AD5360_CMD_WRITE_GAIN                   0x1
#define AD5360_CMD_SPECIAL_FUNCTION             0x0

/* Special function register addresses */
#define AD5360_REG_SF_NOP                       0x0
#define AD5360_REG_SF_CTRL                      0x1
#define AD5360_REG_SF_OFS(x)                    (0x2 + (x))
#define AD5360_REG_SF_READBACK                  0x5

#define AD5360_SF_CTRL_PWR_DOWN                 BIT(0)

#define AD5360_READBACK_X1A                     0x0
#define AD5360_READBACK_X1B                     0x1
#define AD5360_READBACK_OFFSET                  0x2
#define AD5360_READBACK_GAIN                    0x3
#define AD5360_READBACK_SF                      0x4


/**
 * struct ad5360_chip_info - chip specific information
 * @channel_template:   channel specification template
 * @num_channels:       number of channels
 * @channels_per_group: number of channels per group
 * @num_vrefs:          number of vref supplies for the chip
*/

struct ad5360_chip_info {
        struct iio_chan_spec    channel_template;
        unsigned int            num_channels;
        unsigned int            channels_per_group;
        unsigned int            num_vrefs;
};

/**
 * struct ad5360_state - driver instance specific data
 * @spi:                spi_device
 * @chip_info:          chip model specific constants, available modes etc
 * @vref_reg:           vref supply regulators
 * @ctrl:               control register cache
 * @lock:               lock to protect the data buffer during SPI ops
 * @data:               spi transfer buffers
 */

struct ad5360_state {
        struct spi_device               *spi;
        const struct ad5360_chip_info   *chip_info;
        struct regulator_bulk_data      vref_reg[3];
        unsigned int                    ctrl;
        struct mutex                    lock;

        /*
         * DMA (thus cache coherency maintenance) may require the
         * transfer buffers to live in their own cache lines.
         */
        union {
                __be32 d32;
                u8 d8[4];
        } data[2] __aligned(IIO_DMA_MINALIGN);
};

enum ad5360_type {
        ID_AD5360,
        ID_AD5361,
        ID_AD5362,
        ID_AD5363,
        ID_AD5370,
        ID_AD5371,
        ID_AD5372,
        ID_AD5373,
};

#define AD5360_CHANNEL(bits) {                                  \
        .type = IIO_VOLTAGE,                                    \
        .indexed = 1,                                           \
        .output = 1,                                            \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |          \
                BIT(IIO_CHAN_INFO_SCALE) |                              \
                BIT(IIO_CHAN_INFO_OFFSET) |                             \
                BIT(IIO_CHAN_INFO_CALIBSCALE) |                 \
                BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
        .scan_type = {                                          \
                .sign = 'u',                                    \
                .realbits = (bits),                             \
                .storagebits = 16,                              \
                .shift = 16 - (bits),                           \
        },                                                      \
}

static const struct ad5360_chip_info ad5360_chip_info_tbl[] = {
        [ID_AD5360] = {
                .channel_template = AD5360_CHANNEL(16),
                .num_channels = 16,
                .channels_per_group = 8,
                .num_vrefs = 2,
        },
        [ID_AD5361] = {
                .channel_template = AD5360_CHANNEL(14),
                .num_channels = 16,
                .channels_per_group = 8,
                .num_vrefs = 2,
        },
        [ID_AD5362] = {
                .channel_template = AD5360_CHANNEL(16),
                .num_channels = 8,
                .channels_per_group = 4,
                .num_vrefs = 2,
        },
        [ID_AD5363] = {
                .channel_template = AD5360_CHANNEL(14),
                .num_channels = 8,
                .channels_per_group = 4,
                .num_vrefs = 2,
        },
        [ID_AD5370] = {
                .channel_template = AD5360_CHANNEL(16),
                .num_channels = 40,
                .channels_per_group = 8,
                .num_vrefs = 2,
        },
        [ID_AD5371] = {
                .channel_template = AD5360_CHANNEL(14),
                .num_channels = 40,
                .channels_per_group = 8,
                .num_vrefs = 3,
        },
        [ID_AD5372] = {
                .channel_template = AD5360_CHANNEL(16),
                .num_channels = 32,
                .channels_per_group = 8,
                .num_vrefs = 2,
        },
        [ID_AD5373] = {
                .channel_template = AD5360_CHANNEL(14),
                .num_channels = 32,
                .channels_per_group = 8,
                .num_vrefs = 2,
        },
};

static unsigned int ad5360_get_channel_vref_index(struct ad5360_state *st,
        unsigned int channel)
{
        unsigned int i;

        /* The first groups have their own vref, while the remaining groups
         * share the last vref */
        i = channel / st->chip_info->channels_per_group;
        if (i >= st->chip_info->num_vrefs)
                i = st->chip_info->num_vrefs - 1;

        return i;
}

static int ad5360_get_channel_vref(struct ad5360_state *st,
        unsigned int channel)
{
        unsigned int i = ad5360_get_channel_vref_index(st, channel);

        return regulator_get_voltage(st->vref_reg[i].consumer);
}


static int ad5360_write_unlocked(struct iio_dev *indio_dev,
        unsigned int cmd, unsigned int addr, unsigned int val,
        unsigned int shift)
{
        struct ad5360_state *st = iio_priv(indio_dev);

        val <<= shift;
        val |= AD5360_CMD(cmd) | AD5360_ADDR(addr);
        st->data[0].d32 = cpu_to_be32(val);

        return spi_write(st->spi, &st->data[0].d8[1], 3);
}

static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd,
        unsigned int addr, unsigned int val, unsigned int shift)
{
        int ret;
        struct ad5360_state *st = iio_priv(indio_dev);

        mutex_lock(&st->lock);
        ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift);
        mutex_unlock(&st->lock);

        return ret;
}

static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
        unsigned int addr)
{
        struct ad5360_state *st = iio_priv(indio_dev);
        int ret;
        struct spi_transfer t[] = {
                {
                        .tx_buf = &st->data[0].d8[1],
                        .len = 3,
                        .cs_change = 1,
                }, {
                        .rx_buf = &st->data[1].d8[1],
                        .len = 3,
                },
        };

        mutex_lock(&st->lock);

        st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) |
                AD5360_ADDR(AD5360_REG_SF_READBACK) |
                AD5360_READBACK_TYPE(type) |
                AD5360_READBACK_ADDR(addr));

        ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
        if (ret >= 0)
                ret = be32_to_cpu(st->data[1].d32) & 0xffff;

        mutex_unlock(&st->lock);

        return ret;
}

static ssize_t ad5360_read_dac_powerdown(struct device *dev,
                                           struct device_attribute *attr,
                                           char *buf)
{
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad5360_state *st = iio_priv(indio_dev);

        return sysfs_emit(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN));
}

static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
        unsigned int clr)
{
        struct ad5360_state *st = iio_priv(indio_dev);
        int ret;

        mutex_lock(&st->lock);

        st->ctrl |= set;
        st->ctrl &= ~clr;

        ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION,
                        AD5360_REG_SF_CTRL, st->ctrl, 0);

        mutex_unlock(&st->lock);

        return ret;
}

static ssize_t ad5360_write_dac_powerdown(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t len)
{
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        bool pwr_down;
        int ret;

        ret = kstrtobool(buf, &pwr_down);
        if (ret)
                return ret;

        if (pwr_down)
                ret = ad5360_update_ctrl(indio_dev, AD5360_SF_CTRL_PWR_DOWN, 0);
        else
                ret = ad5360_update_ctrl(indio_dev, 0, AD5360_SF_CTRL_PWR_DOWN);

        return ret ? ret : len;
}

static IIO_DEVICE_ATTR(out_voltage_powerdown,
                        S_IRUGO | S_IWUSR,
                        ad5360_read_dac_powerdown,
                        ad5360_write_dac_powerdown, 0);

static struct attribute *ad5360_attributes[] = {
        &iio_dev_attr_out_voltage_powerdown.dev_attr.attr,
        NULL,
};

static const struct attribute_group ad5360_attribute_group = {
        .attrs = ad5360_attributes,
};

static int ad5360_write_raw(struct iio_dev *indio_dev,
                               struct iio_chan_spec const *chan,
                               int val,
                               int val2,
                               long mask)
{
        struct ad5360_state *st = iio_priv(indio_dev);
        int max_val = (1 << chan->scan_type.realbits);
        unsigned int ofs_index;

        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                if (val >= max_val || val < 0)
                        return -EINVAL;

                return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA,
                                 chan->address, val, chan->scan_type.shift);

        case IIO_CHAN_INFO_CALIBBIAS:
                if (val >= max_val || val < 0)
                        return -EINVAL;

                return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET,
                                 chan->address, val, chan->scan_type.shift);

        case IIO_CHAN_INFO_CALIBSCALE:
                if (val >= max_val || val < 0)
                        return -EINVAL;

                return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN,
                                 chan->address, val, chan->scan_type.shift);

        case IIO_CHAN_INFO_OFFSET:
                if (val <= -max_val || val > 0)
                        return -EINVAL;

                val = -val;

                /* offset is supposed to have the same scale as raw, but it
                 * is always 14bits wide, so on a chip where the raw value has
                 * more bits, we need to shift offset. */
                val >>= (chan->scan_type.realbits - 14);

                /* There is one DAC offset register per vref. Changing one
                 * channels offset will also change the offset for all other
                 * channels which share the same vref supply. */
                ofs_index = ad5360_get_channel_vref_index(st, chan->channel);
                return ad5360_write(indio_dev, AD5360_CMD_SPECIAL_FUNCTION,
                                 AD5360_REG_SF_OFS(ofs_index), val, 0);
        default:
                break;
        }

        return -EINVAL;
}

static int ad5360_read_raw(struct iio_dev *indio_dev,
                           struct iio_chan_spec const *chan,
                           int *val,
                           int *val2,
                           long m)
{
        struct ad5360_state *st = iio_priv(indio_dev);
        unsigned int ofs_index;
        int scale_uv;
        int ret;

        switch (m) {
        case IIO_CHAN_INFO_RAW:
                ret = ad5360_read(indio_dev, AD5360_READBACK_X1A,
                        chan->address);
                if (ret < 0)
                        return ret;
                *val = ret >> chan->scan_type.shift;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
                scale_uv = ad5360_get_channel_vref(st, chan->channel);
                if (scale_uv < 0)
                        return scale_uv;

                /* vout = 4 * vref * dac_code */
                *val = scale_uv * 4 / 1000;
                *val2 = chan->scan_type.realbits;
                return IIO_VAL_FRACTIONAL_LOG2;
        case IIO_CHAN_INFO_CALIBBIAS:
                ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET,
                        chan->address);
                if (ret < 0)
                        return ret;
                *val = ret;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBSCALE:
                ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN,
                        chan->address);
                if (ret < 0)
                        return ret;
                *val = ret;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
                ofs_index = ad5360_get_channel_vref_index(st, chan->channel);
                ret = ad5360_read(indio_dev, AD5360_READBACK_SF,
                        AD5360_REG_SF_OFS(ofs_index));
                if (ret < 0)
                        return ret;

                ret <<= (chan->scan_type.realbits - 14);
                *val = -ret;
                return IIO_VAL_INT;
        }

        return -EINVAL;
}

static const struct iio_info ad5360_info = {
        .read_raw = ad5360_read_raw,
        .write_raw = ad5360_write_raw,
        .attrs = &ad5360_attribute_group,
};

static const char * const ad5360_vref_name[] = {
         "vref0", "vref1", "vref2"
};

static int ad5360_alloc_channels(struct iio_dev *indio_dev)
{
        struct ad5360_state *st = iio_priv(indio_dev);
        struct iio_chan_spec *channels;
        unsigned int i;

        channels = kzalloc_objs(struct iio_chan_spec,
                                st->chip_info->num_channels);

        if (!channels)
                return -ENOMEM;

        for (i = 0; i < st->chip_info->num_channels; ++i) {
                channels[i] = st->chip_info->channel_template;
                channels[i].channel = i;
                channels[i].address = AD5360_CHAN_ADDR(i);
        }

        indio_dev->channels = channels;

        return 0;
}

static int ad5360_probe(struct spi_device *spi)
{
        enum ad5360_type type = spi_get_device_id(spi)->driver_data;
        struct iio_dev *indio_dev;
        struct ad5360_state *st;
        unsigned int i;
        int ret;

        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
        if (indio_dev == NULL) {
                dev_err(&spi->dev, "Failed to allocate iio device\n");
                return  -ENOMEM;
        }

        st = iio_priv(indio_dev);
        spi_set_drvdata(spi, indio_dev);

        st->chip_info = &ad5360_chip_info_tbl[type];
        st->spi = spi;

        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5360_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->num_channels = st->chip_info->num_channels;

        mutex_init(&st->lock);

        ret = ad5360_alloc_channels(indio_dev);
        if (ret) {
                dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret);
                return ret;
        }

        for (i = 0; i < st->chip_info->num_vrefs; ++i)
                st->vref_reg[i].supply = ad5360_vref_name[i];

        ret = devm_regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs,
                st->vref_reg);
        if (ret) {
                dev_err(&spi->dev, "Failed to request vref regulators: %d\n", ret);
                goto error_free_channels;
        }

        ret = regulator_bulk_enable(st->chip_info->num_vrefs, st->vref_reg);
        if (ret) {
                dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", ret);
                goto error_free_channels;
        }

        ret = iio_device_register(indio_dev);
        if (ret) {
                dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
                goto error_disable_reg;
        }

        return 0;

error_disable_reg:
        regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg);
error_free_channels:
        kfree(indio_dev->channels);

        return ret;
}

static void ad5360_remove(struct spi_device *spi)
{
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5360_state *st = iio_priv(indio_dev);

        iio_device_unregister(indio_dev);

        kfree(indio_dev->channels);

        regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg);
}

static const struct spi_device_id ad5360_ids[] = {
        { "ad5360", ID_AD5360 },
        { "ad5361", ID_AD5361 },
        { "ad5362", ID_AD5362 },
        { "ad5363", ID_AD5363 },
        { "ad5370", ID_AD5370 },
        { "ad5371", ID_AD5371 },
        { "ad5372", ID_AD5372 },
        { "ad5373", ID_AD5373 },
        { }
};
MODULE_DEVICE_TABLE(spi, ad5360_ids);

static struct spi_driver ad5360_driver = {
        .driver = {
                   .name = "ad5360",
        },
        .probe = ad5360_probe,
        .remove = ad5360_remove,
        .id_table = ad5360_ids,
};
module_spi_driver(ad5360_driver);

MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices AD5360/61/62/63/70/71/72/73 DAC");
MODULE_LICENSE("GPL v2");