linux/drivers/iio/adc/ti-ads8344.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * ADS8344 16-bit 8-Channel ADC driver
   4 *
   5 * Author: Gregory CLEMENT <gregory.clement@bootlin.com>
   6 *
   7 * Datasheet: https://www.ti.com/lit/ds/symlink/ads8344.pdf
   8 */
   9
  10#include <linux/delay.h>
  11#include <linux/iio/buffer.h>
  12#include <linux/iio/iio.h>
  13#include <linux/module.h>
  14#include <linux/regulator/consumer.h>
  15#include <linux/spi/spi.h>
  16
  17#define ADS8344_START BIT(7)
  18#define ADS8344_SINGLE_END BIT(2)
  19#define ADS8344_CHANNEL(channel) ((channel) << 4)
  20#define ADS8344_CLOCK_INTERNAL 0x2 /* PD1 = 1 and PD0 = 0 */
  21
  22struct ads8344 {
  23        struct spi_device *spi;
  24        struct regulator *reg;
  25        /*
  26         * Lock protecting access to adc->tx_buff and rx_buff,
  27         * especially from concurrent read on sysfs file.
  28         */
  29        struct mutex lock;
  30
  31        u8 tx_buf ____cacheline_aligned;
  32        u8 rx_buf[3];
  33};
  34
  35#define ADS8344_VOLTAGE_CHANNEL(chan, addr)                             \
  36        {                                                               \
  37                .type = IIO_VOLTAGE,                                    \
  38                .indexed = 1,                                           \
  39                .channel = chan,                                        \
  40                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
  41                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
  42                .address = addr,                                        \
  43        }
  44
  45#define ADS8344_VOLTAGE_CHANNEL_DIFF(chan1, chan2, addr)                \
  46        {                                                               \
  47                .type = IIO_VOLTAGE,                                    \
  48                .indexed = 1,                                           \
  49                .channel = (chan1),                                     \
  50                .channel2 = (chan2),                                    \
  51                .differential = 1,                                      \
  52                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
  53                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
  54                .address = addr,                                        \
  55        }
  56
  57static const struct iio_chan_spec ads8344_channels[] = {
  58        ADS8344_VOLTAGE_CHANNEL(0, 0),
  59        ADS8344_VOLTAGE_CHANNEL(1, 4),
  60        ADS8344_VOLTAGE_CHANNEL(2, 1),
  61        ADS8344_VOLTAGE_CHANNEL(3, 5),
  62        ADS8344_VOLTAGE_CHANNEL(4, 2),
  63        ADS8344_VOLTAGE_CHANNEL(5, 6),
  64        ADS8344_VOLTAGE_CHANNEL(6, 3),
  65        ADS8344_VOLTAGE_CHANNEL(7, 7),
  66        ADS8344_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
  67        ADS8344_VOLTAGE_CHANNEL_DIFF(2, 3, 9),
  68        ADS8344_VOLTAGE_CHANNEL_DIFF(4, 5, 10),
  69        ADS8344_VOLTAGE_CHANNEL_DIFF(6, 7, 11),
  70        ADS8344_VOLTAGE_CHANNEL_DIFF(1, 0, 12),
  71        ADS8344_VOLTAGE_CHANNEL_DIFF(3, 2, 13),
  72        ADS8344_VOLTAGE_CHANNEL_DIFF(5, 4, 14),
  73        ADS8344_VOLTAGE_CHANNEL_DIFF(7, 6, 15),
  74};
  75
  76static int ads8344_adc_conversion(struct ads8344 *adc, int channel,
  77                                  bool differential)
  78{
  79        struct spi_device *spi = adc->spi;
  80        int ret;
  81
  82        adc->tx_buf = ADS8344_START;
  83        if (!differential)
  84                adc->tx_buf |= ADS8344_SINGLE_END;
  85        adc->tx_buf |= ADS8344_CHANNEL(channel);
  86        adc->tx_buf |= ADS8344_CLOCK_INTERNAL;
  87
  88        ret = spi_write(spi, &adc->tx_buf, 1);
  89        if (ret)
  90                return ret;
  91
  92        udelay(9);
  93
  94        ret = spi_read(spi, adc->rx_buf, sizeof(adc->rx_buf));
  95        if (ret)
  96                return ret;
  97
  98        return adc->rx_buf[0] << 9 | adc->rx_buf[1] << 1 | adc->rx_buf[2] >> 7;
  99}
 100
 101static int ads8344_read_raw(struct iio_dev *iio,
 102                            struct iio_chan_spec const *channel, int *value,
 103                            int *shift, long mask)
 104{
 105        struct ads8344 *adc = iio_priv(iio);
 106
 107        switch (mask) {
 108        case IIO_CHAN_INFO_RAW:
 109                mutex_lock(&adc->lock);
 110                *value = ads8344_adc_conversion(adc, channel->address,
 111                                                channel->differential);
 112                mutex_unlock(&adc->lock);
 113                if (*value < 0)
 114                        return *value;
 115
 116                return IIO_VAL_INT;
 117        case IIO_CHAN_INFO_SCALE:
 118                *value = regulator_get_voltage(adc->reg);
 119                if (*value < 0)
 120                        return *value;
 121
 122                /* convert regulator output voltage to mV */
 123                *value /= 1000;
 124                *shift = 16;
 125
 126                return IIO_VAL_FRACTIONAL_LOG2;
 127        default:
 128                return -EINVAL;
 129        }
 130}
 131
 132static const struct iio_info ads8344_info = {
 133        .read_raw = ads8344_read_raw,
 134};
 135
 136static int ads8344_probe(struct spi_device *spi)
 137{
 138        struct iio_dev *indio_dev;
 139        struct ads8344 *adc;
 140        int ret;
 141
 142        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
 143        if (!indio_dev)
 144                return -ENOMEM;
 145
 146        adc = iio_priv(indio_dev);
 147        adc->spi = spi;
 148        mutex_init(&adc->lock);
 149
 150        indio_dev->name = dev_name(&spi->dev);
 151        indio_dev->info = &ads8344_info;
 152        indio_dev->modes = INDIO_DIRECT_MODE;
 153        indio_dev->channels = ads8344_channels;
 154        indio_dev->num_channels = ARRAY_SIZE(ads8344_channels);
 155
 156        adc->reg = devm_regulator_get(&spi->dev, "vref");
 157        if (IS_ERR(adc->reg))
 158                return PTR_ERR(adc->reg);
 159
 160        ret = regulator_enable(adc->reg);
 161        if (ret)
 162                return ret;
 163
 164        spi_set_drvdata(spi, indio_dev);
 165
 166        ret = iio_device_register(indio_dev);
 167        if (ret) {
 168                regulator_disable(adc->reg);
 169                return ret;
 170        }
 171
 172        return 0;
 173}
 174
 175static int ads8344_remove(struct spi_device *spi)
 176{
 177        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 178        struct ads8344 *adc = iio_priv(indio_dev);
 179
 180        iio_device_unregister(indio_dev);
 181        regulator_disable(adc->reg);
 182
 183        return 0;
 184}
 185
 186static const struct of_device_id ads8344_of_match[] = {
 187        { .compatible = "ti,ads8344", },
 188        {}
 189};
 190MODULE_DEVICE_TABLE(of, ads8344_of_match);
 191
 192static struct spi_driver ads8344_driver = {
 193        .driver = {
 194                .name = "ads8344",
 195                .of_match_table = ads8344_of_match,
 196        },
 197        .probe = ads8344_probe,
 198        .remove = ads8344_remove,
 199};
 200module_spi_driver(ads8344_driver);
 201
 202MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@bootlin.com>");
 203MODULE_DESCRIPTION("ADS8344 driver");
 204MODULE_LICENSE("GPL");
 205