linux/drivers/iio/adc/ti-adc081c.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Avionic Design GmbH
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/err.h>
  10#include <linux/i2c.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13
  14#include <linux/iio/iio.h>
  15#include <linux/regulator/consumer.h>
  16
  17struct adc081c {
  18        struct i2c_client *i2c;
  19        struct regulator *ref;
  20};
  21
  22#define REG_CONV_RES 0x00
  23
  24static int adc081c_read_raw(struct iio_dev *iio,
  25                            struct iio_chan_spec const *channel, int *value,
  26                            int *shift, long mask)
  27{
  28        struct adc081c *adc = iio_priv(iio);
  29        int err;
  30
  31        switch (mask) {
  32        case IIO_CHAN_INFO_RAW:
  33                err = i2c_smbus_read_word_swapped(adc->i2c, REG_CONV_RES);
  34                if (err < 0)
  35                        return err;
  36
  37                *value = (err >> 4) & 0xff;
  38                return IIO_VAL_INT;
  39
  40        case IIO_CHAN_INFO_SCALE:
  41                err = regulator_get_voltage(adc->ref);
  42                if (err < 0)
  43                        return err;
  44
  45                *value = err / 1000;
  46                *shift = 8;
  47
  48                return IIO_VAL_FRACTIONAL_LOG2;
  49
  50        default:
  51                break;
  52        }
  53
  54        return -EINVAL;
  55}
  56
  57static const struct iio_chan_spec adc081c_channel = {
  58        .type = IIO_VOLTAGE,
  59        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
  60        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  61};
  62
  63static const struct iio_info adc081c_info = {
  64        .read_raw = adc081c_read_raw,
  65        .driver_module = THIS_MODULE,
  66};
  67
  68static int adc081c_probe(struct i2c_client *client,
  69                         const struct i2c_device_id *id)
  70{
  71        struct iio_dev *iio;
  72        struct adc081c *adc;
  73        int err;
  74
  75        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
  76                return -EOPNOTSUPP;
  77
  78        iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
  79        if (!iio)
  80                return -ENOMEM;
  81
  82        adc = iio_priv(iio);
  83        adc->i2c = client;
  84
  85        adc->ref = devm_regulator_get(&client->dev, "vref");
  86        if (IS_ERR(adc->ref))
  87                return PTR_ERR(adc->ref);
  88
  89        err = regulator_enable(adc->ref);
  90        if (err < 0)
  91                return err;
  92
  93        iio->dev.parent = &client->dev;
  94        iio->name = dev_name(&client->dev);
  95        iio->modes = INDIO_DIRECT_MODE;
  96        iio->info = &adc081c_info;
  97
  98        iio->channels = &adc081c_channel;
  99        iio->num_channels = 1;
 100
 101        err = iio_device_register(iio);
 102        if (err < 0)
 103                goto regulator_disable;
 104
 105        i2c_set_clientdata(client, iio);
 106
 107        return 0;
 108
 109regulator_disable:
 110        regulator_disable(adc->ref);
 111
 112        return err;
 113}
 114
 115static int adc081c_remove(struct i2c_client *client)
 116{
 117        struct iio_dev *iio = i2c_get_clientdata(client);
 118        struct adc081c *adc = iio_priv(iio);
 119
 120        iio_device_unregister(iio);
 121        regulator_disable(adc->ref);
 122
 123        return 0;
 124}
 125
 126static const struct i2c_device_id adc081c_id[] = {
 127        { "adc081c", 0 },
 128        { }
 129};
 130MODULE_DEVICE_TABLE(i2c, adc081c_id);
 131
 132#ifdef CONFIG_OF
 133static const struct of_device_id adc081c_of_match[] = {
 134        { .compatible = "ti,adc081c" },
 135        { }
 136};
 137MODULE_DEVICE_TABLE(of, adc081c_of_match);
 138#endif
 139
 140static struct i2c_driver adc081c_driver = {
 141        .driver = {
 142                .name = "adc081c",
 143                .of_match_table = of_match_ptr(adc081c_of_match),
 144        },
 145        .probe = adc081c_probe,
 146        .remove = adc081c_remove,
 147        .id_table = adc081c_id,
 148};
 149module_i2c_driver(adc081c_driver);
 150
 151MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
 152MODULE_DESCRIPTION("Texas Instruments ADC081C021/027 driver");
 153MODULE_LICENSE("GPL v2");
 154