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