source: src/linux/universal/linux-3.2/drivers/hwmon/ads1015.c @ 18171

Last change on this file since 18171 was 18171, checked in by BrainSlayer, 17 months ago

this kernel will be maintained for all targets, so target specific kernel trees will not be neccessary anymore in future

File size: 8.1 KB
Line 
1/*
2 * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC
3 * (C) Copyright 2010
4 * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
5 *
6 * Based on the ads7828 driver by Steve Hardy.
7 *
8 * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/delay.h>
29#include <linux/i2c.h>
30#include <linux/hwmon.h>
31#include <linux/hwmon-sysfs.h>
32#include <linux/err.h>
33#include <linux/mutex.h>
34#include <linux/of.h>
35
36#include <linux/i2c/ads1015.h>
37
38/* ADS1015 registers */
39enum {
40        ADS1015_CONVERSION = 0,
41        ADS1015_CONFIG = 1,
42};
43
44/* PGA fullscale voltages in mV */
45static const unsigned int fullscale_table[8] = {
46        6144, 4096, 2048, 1024, 512, 256, 256, 256 };
47
48/* Data rates in samples per second */
49static const unsigned int data_rate_table[8] = {
50        128, 250, 490, 920, 1600, 2400, 3300, 3300 };
51
52#define ADS1015_DEFAULT_CHANNELS 0xff
53#define ADS1015_DEFAULT_PGA 2
54#define ADS1015_DEFAULT_DATA_RATE 4
55
56struct ads1015_data {
57        struct device *hwmon_dev;
58        struct mutex update_lock; /* mutex protect updates */
59        struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
60};
61
62static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
63                              int *value)
64{
65        u16 config;
66        s16 conversion;
67        struct ads1015_data *data = i2c_get_clientdata(client);
68        unsigned int pga = data->channel_data[channel].pga;
69        int fullscale;
70        unsigned int data_rate = data->channel_data[channel].data_rate;
71        unsigned int conversion_time_ms;
72        int res;
73
74        mutex_lock(&data->update_lock);
75
76        /* get channel parameters */
77        res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
78        if (res < 0)
79                goto err_unlock;
80        config = res;
81        fullscale = fullscale_table[pga];
82        conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
83
84        /* setup and start single conversion */
85        config &= 0x001f;
86        config |= (1 << 15) | (1 << 8);
87        config |= (channel & 0x0007) << 12;
88        config |= (pga & 0x0007) << 9;
89        config |= (data_rate & 0x0007) << 5;
90
91        res = i2c_smbus_write_word_swapped(client, ADS1015_CONFIG, config);
92        if (res < 0)
93                goto err_unlock;
94
95        /* wait until conversion finished */
96        msleep(conversion_time_ms);
97        res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
98        if (res < 0)
99                goto err_unlock;
100        config = res;
101        if (!(config & (1 << 15))) {
102                /* conversion not finished in time */
103                res = -EIO;
104                goto err_unlock;
105        }
106
107        res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
108        if (res < 0)
109                goto err_unlock;
110        conversion = res;
111
112        mutex_unlock(&data->update_lock);
113
114        *value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);
115
116        return 0;
117
118err_unlock:
119        mutex_unlock(&data->update_lock);
120        return res;
121}
122
123/* sysfs callback function */
124static ssize_t show_in(struct device *dev, struct device_attribute *da,
125        char *buf)
126{
127        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
128        struct i2c_client *client = to_i2c_client(dev);
129        int in;
130        int res;
131
132        res = ads1015_read_value(client, attr->index, &in);
133
134        return (res < 0) ? res : sprintf(buf, "%d\n", in);
135}
136
137static const struct sensor_device_attribute ads1015_in[] = {
138        SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
139        SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
140        SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
141        SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
142        SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
143        SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
144        SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
145        SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
146};
147
148/*
149 * Driver interface
150 */
151
152static int ads1015_remove(struct i2c_client *client)
153{
154        struct ads1015_data *data = i2c_get_clientdata(client);
155        int k;
156
157        hwmon_device_unregister(data->hwmon_dev);
158        for (k = 0; k < ADS1015_CHANNELS; ++k)
159                device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
160        kfree(data);
161        return 0;
162}
163
164#ifdef CONFIG_OF
165static int ads1015_get_channels_config_of(struct i2c_client *client)
166{
167        struct ads1015_data *data = i2c_get_clientdata(client);
168        struct device_node *node;
169
170        if (!client->dev.of_node
171            || !of_get_next_child(client->dev.of_node, NULL))
172                return -EINVAL;
173
174        for_each_child_of_node(client->dev.of_node, node) {
175                const __be32 *property;
176                int len;
177                unsigned int channel;
178                unsigned int pga = ADS1015_DEFAULT_PGA;
179                unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
180
181                property = of_get_property(node, "reg", &len);
182                if (!property || len != sizeof(int)) {
183                        dev_err(&client->dev, "invalid reg on %s\n",
184                                node->full_name);
185                        continue;
186                }
187
188                channel = be32_to_cpup(property);
189                if (channel > ADS1015_CHANNELS) {
190                        dev_err(&client->dev,
191                                "invalid channel index %d on %s\n",
192                                channel, node->full_name);
193                        continue;
194                }
195
196                property = of_get_property(node, "ti,gain", &len);
197                if (property && len == sizeof(int)) {
198                        pga = be32_to_cpup(property);
199                        if (pga > 6) {
200                                dev_err(&client->dev,
201                                        "invalid gain on %s\n",
202                                        node->full_name);
203                        }
204                }
205
206                property = of_get_property(node, "ti,datarate", &len);
207                if (property && len == sizeof(int)) {
208                        data_rate = be32_to_cpup(property);
209                        if (data_rate > 7) {
210                                dev_err(&client->dev,
211                                        "invalid data_rate on %s\n",
212                                        node->full_name);
213                        }
214                }
215
216                data->channel_data[channel].enabled = true;
217                data->channel_data[channel].pga = pga;
218                data->channel_data[channel].data_rate = data_rate;
219        }
220
221        return 0;
222}
223#endif
224
225static void ads1015_get_channels_config(struct i2c_client *client)
226{
227        unsigned int k;
228        struct ads1015_data *data = i2c_get_clientdata(client);
229        struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev);
230
231        /* prefer platform data */
232        if (pdata) {
233                memcpy(data->channel_data, pdata->channel_data,
234                       sizeof(data->channel_data));
235                return;
236        }
237
238#ifdef CONFIG_OF
239        if (!ads1015_get_channels_config_of(client))
240                return;
241#endif
242
243        /* fallback on default configuration */
244        for (k = 0; k < ADS1015_CHANNELS; ++k) {
245                data->channel_data[k].enabled = true;
246                data->channel_data[k].pga = ADS1015_DEFAULT_PGA;
247                data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE;
248        }
249}
250
251static int ads1015_probe(struct i2c_client *client,
252                         const struct i2c_device_id *id)
253{
254        struct ads1015_data *data;
255        int err;
256        unsigned int k;
257
258        data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL);
259        if (!data) {
260                err = -ENOMEM;
261                goto exit;
262        }
263
264        i2c_set_clientdata(client, data);
265        mutex_init(&data->update_lock);
266
267        /* build sysfs attribute group */
268        ads1015_get_channels_config(client);
269        for (k = 0; k < ADS1015_CHANNELS; ++k) {
270                if (!data->channel_data[k].enabled)
271                        continue;
272                err = device_create_file(&client->dev, &ads1015_in[k].dev_attr);
273                if (err)
274                        goto exit_free;
275        }
276
277        data->hwmon_dev = hwmon_device_register(&client->dev);
278        if (IS_ERR(data->hwmon_dev)) {
279                err = PTR_ERR(data->hwmon_dev);
280                goto exit_remove;
281        }
282
283        return 0;
284
285exit_remove:
286        for (k = 0; k < ADS1015_CHANNELS; ++k)
287                device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
288exit_free:
289        kfree(data);
290exit:
291        return err;
292}
293
294static const struct i2c_device_id ads1015_id[] = {
295        { "ads1015", 0 },
296        { }
297};
298MODULE_DEVICE_TABLE(i2c, ads1015_id);
299
300static struct i2c_driver ads1015_driver = {
301        .driver = {
302                .name = "ads1015",
303        },
304        .probe = ads1015_probe,
305        .remove = ads1015_remove,
306        .id_table = ads1015_id,
307};
308
309static int __init sensors_ads1015_init(void)
310{
311        return i2c_add_driver(&ads1015_driver);
312}
313
314static void __exit sensors_ads1015_exit(void)
315{
316        i2c_del_driver(&ads1015_driver);
317}
318
319MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>");
320MODULE_DESCRIPTION("ADS1015 driver");
321MODULE_LICENSE("GPL");
322
323module_init(sensors_ads1015_init);
324module_exit(sensors_ads1015_exit);
Note: See TracBrowser for help on using the repository browser.