aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2012-11-23 10:13:00 -0500
committerJonathan Cameron <jic23@kernel.org>2012-11-30 07:57:09 -0500
commitbc0a409c5ffd91b5403037ab2798b84dccee4f06 (patch)
tree7a73516c4980b26215c93ae3e1d9836a4bb7ecd8 /drivers/iio
parentfd1a8b9128410c2ea7da69180788e5d144c6ef46 (diff)
iio: adc: Add Texas Instruments ADC081C021/027 support
Add support for reading conversion results from the ADC and provide them through a single IIO channel. A proper scaling factor is also exported based on the reference voltage provided by a regulator. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/adc/Kconfig10
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ti-adc081c.c161
3 files changed, 173 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 408557b02441..961b8d0a4bac 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -115,4 +115,14 @@ config MAX1363
115 max11646, max11647) Provides direct access via sysfs and buffered 115 max11646, max11647) Provides direct access via sysfs and buffered
116 data via the iio dev interface. 116 data via the iio dev interface.
117 117
118config TI_ADC081C
119 tristate "Texas Instruments ADC081C021/027"
120 depends on I2C
121 help
122 If you say yes here you get support for Texas Instruments ADC081C021
123 and ADC081C027 ADC chips.
124
125 This driver can also be built as a module. If so, the module will be
126 called ti-adc081c.
127
118endmenu 128endmenu
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 78202d9eb961..472fd7cd2417 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_AD7887) += ad7887.o
12obj-$(CONFIG_AT91_ADC) += at91_adc.o 12obj-$(CONFIG_AT91_ADC) += at91_adc.o
13obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o 13obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
14obj-$(CONFIG_MAX1363) += max1363.o 14obj-$(CONFIG_MAX1363) += max1363.o
15obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
16
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
new file mode 100644
index 000000000000..f4a46dd8f43b
--- /dev/null
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -0,0 +1,161 @@
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 = IIO_CHAN_INFO_SCALE_SHARED_BIT |
59 IIO_CHAN_INFO_RAW_SEPARATE_BIT,
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");