linux/drivers/iio/adc/ltc2485.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ltc2485.c - Driver for Linear Technology LTC2485 ADC
   4 *
   5 * Copyright (C) 2016 Alison Schofield <amsfield22@gmail.com>
   6 *
   7 * Datasheet: http://cds.linear.com/docs/en/datasheet/2485fd.pdf
   8 */
   9
  10#include <linux/delay.h>
  11#include <linux/i2c.h>
  12#include <linux/module.h>
  13
  14#include <linux/iio/iio.h>
  15#include <linux/iio/sysfs.h>
  16
  17/* Power-on configuration: rejects both 50/60Hz, operates at 1x speed */
  18#define LTC2485_CONFIG_DEFAULT          0
  19
  20struct ltc2485_data {
  21        struct i2c_client       *client;
  22        ktime_t                 time_prev;      /* last conversion */
  23};
  24
  25static void ltc2485_wait_conv(struct ltc2485_data *data)
  26{
  27        const unsigned int conv_time = 147;     /* conversion time ms */
  28        unsigned int time_elapsed;
  29
  30        /* delay if conversion time not passed since last read or write */
  31        time_elapsed = ktime_ms_delta(ktime_get(), data->time_prev);
  32
  33        if (time_elapsed < conv_time)
  34                msleep(conv_time - time_elapsed);
  35}
  36
  37static int ltc2485_read(struct ltc2485_data *data, int *val)
  38{
  39        struct i2c_client *client = data->client;
  40        __be32 buf = 0;
  41        int ret;
  42
  43        ltc2485_wait_conv(data);
  44
  45        ret = i2c_master_recv(client, (char *)&buf, 4);
  46        if (ret < 0)  {
  47                dev_err(&client->dev, "i2c_master_recv failed\n");
  48                return ret;
  49        }
  50        data->time_prev = ktime_get();
  51        *val = sign_extend32(be32_to_cpu(buf) >> 6, 24);
  52
  53        return ret;
  54}
  55
  56static int ltc2485_read_raw(struct iio_dev *indio_dev,
  57                            struct iio_chan_spec const *chan,
  58                            int *val, int *val2, long mask)
  59{
  60        struct ltc2485_data *data = iio_priv(indio_dev);
  61        int ret;
  62
  63        if (mask == IIO_CHAN_INFO_RAW) {
  64                ret = ltc2485_read(data, val);
  65                if (ret < 0)
  66                        return ret;
  67
  68                return IIO_VAL_INT;
  69
  70        } else if (mask == IIO_CHAN_INFO_SCALE) {
  71                *val = 5000;                    /* on board vref millivolts */
  72                *val2 = 25;                     /* 25 (24 + sign) data bits */
  73                return IIO_VAL_FRACTIONAL_LOG2;
  74
  75        } else {
  76                return -EINVAL;
  77        }
  78}
  79
  80static const struct iio_chan_spec ltc2485_channel[] = {
  81        {
  82                .type = IIO_VOLTAGE,
  83                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  84                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)
  85        },
  86};
  87
  88static const struct iio_info ltc2485_info = {
  89        .read_raw = ltc2485_read_raw,
  90};
  91
  92static int ltc2485_probe(struct i2c_client *client,
  93                         const struct i2c_device_id *id)
  94{
  95        struct iio_dev *indio_dev;
  96        struct ltc2485_data *data;
  97        int ret;
  98
  99        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
 100                                     I2C_FUNC_SMBUS_WRITE_BYTE))
 101                return -EOPNOTSUPP;
 102
 103        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 104        if (!indio_dev)
 105                return -ENOMEM;
 106
 107        data = iio_priv(indio_dev);
 108        i2c_set_clientdata(client, indio_dev);
 109        data->client = client;
 110
 111        indio_dev->dev.parent = &client->dev;
 112        indio_dev->name = id->name;
 113        indio_dev->info = &ltc2485_info;
 114        indio_dev->modes = INDIO_DIRECT_MODE;
 115        indio_dev->channels = ltc2485_channel;
 116        indio_dev->num_channels = ARRAY_SIZE(ltc2485_channel);
 117
 118        ret = i2c_smbus_write_byte(data->client, LTC2485_CONFIG_DEFAULT);
 119        if (ret < 0)
 120                return ret;
 121
 122        data->time_prev = ktime_get();
 123
 124        return devm_iio_device_register(&client->dev, indio_dev);
 125}
 126
 127static const struct i2c_device_id ltc2485_id[] = {
 128        { "ltc2485", 0 },
 129        { }
 130};
 131MODULE_DEVICE_TABLE(i2c, ltc2485_id);
 132
 133static struct i2c_driver ltc2485_driver = {
 134        .driver = {
 135                .name = "ltc2485",
 136        },
 137        .probe = ltc2485_probe,
 138        .id_table = ltc2485_id,
 139};
 140module_i2c_driver(ltc2485_driver);
 141
 142MODULE_AUTHOR("Alison Schofield <amsfield22@gmail.com>");
 143MODULE_DESCRIPTION("Linear Technology LTC2485 ADC driver");
 144MODULE_LICENSE("GPL v2");
 145