blob: 356b23a61977a3061a78289152c3f3c6b956e9f4 [file] [log] [blame]
Kyle Swensoncc33c242022-05-16 10:38:04 -06001/*
2 * ./kernel_modules/qcom-adc/ads7924-driver.c
3 *
4 * ads7924-driver.c - driver for TI ADS7924 4-channel A/D converter
5 *
6 * Author: Cradlepoint Technology, Inc. <source@cradlepoint.com>
7 * Kyle Swenson <kswenson@cradlepoint.com>
8 * Derived heavily from similar hwmon-based drivers in the linux source tree.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/hwmon.h>
26#include <linux/hwmon-sysfs.h>
27#include <linux/i2c.h>
28#include <linux/init.h>
29#include <linux/device.h>
30#include <linux/workqueue.h>
31#include <linux/jiffies.h>
32#include <linux/module.h>
33#include <linux/delay.h>
34#include <linux/mutex.h>
35#include <linux/gpio.h>
36#include <linux/timer.h>
37#include <linux/slab.h>
38
39#include "ads7924-regdefs.h"
40#include "adc-averaging.h"
41
42#define ADS7924_NCH 4 /* Number of ADC Channels for the ADS7924 */
43#define ADS7924_SAMPLE_INTERVAL 10 /*In ms -> 100 Hz default */
44#define ADS7924_ENABLE_DEFAULT 0 /*Automatic sampling disabled by default */
45#define ADS7924_DEFAULT_BUFFER_SIZE 16 /*Default length for each channel's buffer */
46#define ADS7924_VMAX 5000 /* Reference voltage, maximum */
47
48/* ADS7924-specific data */
49struct ads7924_data {
50 struct mutex update_lock; /* Mutex protecting updates */
51 struct timer_list sample_timer;
52 struct work_struct workq;
53
54 struct device *hwmon_dev; /* result of register the struct i2c_client->dev with hwmon */
55 struct i2c_client * client;
56 struct gpio_desc * reset;
57 unsigned long last_updated; /* Last updated time (in jiffies) */
58 unsigned enabled; /* */
59 unsigned update_interval; /* in ms */
60 bool valid; /* Validity flag, for first data resquest */
61 unsigned sample_length; /*Number of samples stored for the average */
62 struct adc_channel *channel[ADS7924_NCH];
63};
64
65
66void ads7924_timer_irq(unsigned long arg) {
67 struct ads7924_data *data = (struct ads7924_data *)arg;
68 if (data->enabled) {
69 mod_timer(&data->sample_timer, jiffies + msecs_to_jiffies(data->update_interval));
70 schedule_work(&data->workq);
71 }
72}
73
74void ads7924_start_sampler(struct ads7924_data *data)
75{
76 setup_timer(&data->sample_timer, ads7924_timer_irq, (unsigned long) data);
77 mod_timer(&data->sample_timer, jiffies + msecs_to_jiffies(data->update_interval));
78}
79void ads7924_stop_sampler(struct ads7924_data *data)
80{
81 del_timer(&data->sample_timer);
82}
83
84static uint16_t ads7924_sample_channel(struct i2c_client *client, uint8_t channel)
85{
86 int err;
87 int lb, hb, hb2;
88 uint16_t adc_count = 0;
89 err = i2c_smbus_write_byte_data(client, ADS7924_REG_MODECNTRL, (ADS7924_MODE_MANUAL_SINGLE << 2) | (channel & 0x03));
90 if (err < 0) {
91 dev_warn(&client->dev, "Failed to i2c write");
92 }
93 hb = i2c_smbus_read_byte_data(client, ADS7924_REG_DATA0_U + (channel << 1));
94 lb = i2c_smbus_read_byte_data(client, ADS7924_REG_DATA0_L + (channel << 1));
95 hb2 = i2c_smbus_read_byte_data(client, ADS7924_REG_DATA0_U + (channel << 1));
96 if (hb != hb2)
97 dev_warn(&client->dev, "Warning hb reading inconsistent!\n");
98 if (hb < 0 || lb < 0) {
99 dev_warn(&client->dev, "Failed to i2c read");
100 return (uint16_t) 0xFFFF; /* return a value > 4096, upper layers should check */
101 }
102 adc_count = (uint16_t)((((hb & 0x00FF) << 8) | (lb & 0x00FF)) >> 4);
103
104 return adc_count;
105}
106
107static struct ads7924_data *ads7924_update_device(struct i2c_client *client)
108{
109 struct ads7924_data *data = i2c_get_clientdata(client);
110 uint16_t sample;
111 int i = 0;
112
113 mutex_lock(&data->update_lock);
114
115 for(i=0; i<ADS7924_NCH; i++) {
116 sample = ads7924_sample_channel(client, i);
117 if (!(sample & 0xF000))
118 add_sample(data->channel[i], sample);
119 else
120 dev_info(&client->dev, "Ch%d sample 0x%04x out of range\n", i, sample);
121
122 }
123 data->last_updated = jiffies;
124 data->valid = 1;
125 mutex_unlock(&data->update_lock);
126 return data;
127}
128
129void ads7924_work(struct work_struct *work)
130{
131 struct ads7924_data *data = container_of(work, struct ads7924_data, workq);
132 ads7924_update_device(data->client);
133}
134
135/*
136 Number of samples used to compute the average
137*/
138static ssize_t sample_length_store(struct device *dev, struct device_attribute *da, const char *buf, size_t len)
139{
140 struct i2c_client *client = to_i2c_client(dev);
141 struct ads7924_data *data = i2c_get_clientdata(client);
142 int i;
143 unsigned long length;
144 int err = kstrtoul(buf, 10, &length);
145 if (err)
146 return err;
147
148 if (length >= MAX_SAMPLE_LENGTH) {
149 return -EINVAL;
150 }
151 mutex_lock(&data->update_lock);
152 data->sample_length = length;
153 for (i = 0; i < ADS7924_NCH; i++) {
154 free_adc_channel(data->channel[i]);
155 data->channel[i] = create_adc_channel(data->sample_length);
156 if (!data->channel[i]) {
157 dev_warn(&client->dev, "Failed to resize the channel buffer\n");
158 /*TODO: If this happens, we're pretty screwed. Like, we should unload ourselves. */
159 }
160 }
161 mutex_unlock(&data->update_lock);
162 return len;
163}
164static ssize_t sample_length_show(struct device *dev, struct device_attribute *da, char *buf)
165{
166 struct i2c_client *client = to_i2c_client(dev);
167 struct ads7924_data *data = i2c_get_clientdata(client);
168 return sprintf(buf, "%u", data->sample_length);
169}
170static SENSOR_DEVICE_ATTR(sample_length, S_IRUGO|S_IWUSR|S_IWGRP, sample_length_show, sample_length_store, 0);
171
172
173/*
174 Enable/disable the automatic sample & average functionality. Disabled by default
175*/
176static ssize_t enable_store(struct device *dev, struct device_attribute *da, const char *buf, size_t length)
177{
178 struct i2c_client *client = to_i2c_client(dev);
179 struct ads7924_data *data = i2c_get_clientdata(client);
180 unsigned long enabled;
181 int err = kstrtoul(buf, 10, &enabled);
182 if (err)
183 return err;
184
185 mutex_lock(&data->update_lock);
186 if (enabled)
187 data->enabled = 1;
188 else
189 data->enabled = 0;
190 mutex_unlock(&data->update_lock);
191 ads7924_timer_irq((unsigned long) data);
192 return length;
193}
194static ssize_t enable_show(struct device *dev, struct device_attribute *da, char *buf)
195{
196 struct i2c_client *client = to_i2c_client(dev);
197 struct ads7924_data *data = i2c_get_clientdata(client);
198 return sprintf(buf, "%u", data->enabled);
199}
200static SENSOR_DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP, enable_show, enable_store, 0);
201
202/*
203 update interval : minimium time between sample requests
204*/
205static ssize_t update_interval_store(struct device *dev, struct device_attribute *da, const char *buf, size_t length)
206{
207 struct i2c_client *client = to_i2c_client(dev);
208 struct ads7924_data *data = i2c_get_clientdata(client);
209 unsigned long update_interval;
210 int err = kstrtoul(buf, 10, &update_interval);
211 if (err)
212 return err;
213 mutex_lock(&data->update_lock);
214 data->update_interval = update_interval;
215 mutex_unlock(&data->update_lock);
216 return length;
217}
218static ssize_t update_interval_show(struct device *dev, struct device_attribute *da, char *buf)
219{
220 struct i2c_client *client = to_i2c_client(dev);
221 struct ads7924_data *data = i2c_get_clientdata(client);
222 return sprintf(buf, "%u", data->update_interval);
223}
224static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO|S_IWUSR|S_IWGRP, update_interval_show, update_interval_store, 0);
225
226/*
227 Show the voltage on the specified channel.
228
229 Note that this causes the ADC to sample the specified channel,
230 independently of any averaging that might be going on. Also note that if there
231 is averaging going on, this particular average will not be included in the
232 sample
233
234*/
235static ssize_t ads7924_show_in(struct device *dev, struct device_attribute *da, char *buf)
236{
237 struct i2c_client *client = to_i2c_client(dev);
238 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
239 struct ads7924_data *data = i2c_get_clientdata(client);
240 uint16_t value;
241 mutex_lock(&data->update_lock);
242 /* TODO RATE LIMITE THIS*/
243 value = ads7924_sample_channel(client, attr->index);
244 mutex_unlock(&data->update_lock);
245 return sprintf(buf, "%d", value);
246}
247
248static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ads7924_show_in, NULL, 0);
249static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ads7924_show_in, NULL, 1);
250static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ads7924_show_in, NULL, 2);
251static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ads7924_show_in, NULL, 3);
252
253static ssize_t ads7924_show_average(struct device *dev, struct device_attribute *da, char *buf)
254{
255 struct i2c_client *client = to_i2c_client(dev);
256 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
257 struct ads7924_data *data = ads7924_update_device(client);
258 uint16_t value;
259 if (data) {
260 value = compute_average(data->channel[attr->index]);
261 return sprintf(buf, "%d", value);
262 }
263 return -EAGAIN;
264}
265static SENSOR_DEVICE_ATTR(in0_average, S_IRUGO, ads7924_show_average, NULL, 0);
266static SENSOR_DEVICE_ATTR(in1_average, S_IRUGO, ads7924_show_average, NULL, 1);
267static SENSOR_DEVICE_ATTR(in2_average, S_IRUGO, ads7924_show_average, NULL, 2);
268static SENSOR_DEVICE_ATTR(in3_average, S_IRUGO, ads7924_show_average, NULL, 3);
269
270static struct attribute *ads7924_attrs[] = {
271 &sensor_dev_attr_update_interval.dev_attr.attr, /* Interval between device updates*/
272 &sensor_dev_attr_sample_length.dev_attr.attr, /* Number of samples used to average*/
273 &sensor_dev_attr_enable.dev_attr.attr, /* Enable/disable the timer-based sampleing*/
274 &sensor_dev_attr_in0_average.dev_attr.attr,
275 &sensor_dev_attr_in1_average.dev_attr.attr,
276 &sensor_dev_attr_in2_average.dev_attr.attr,
277 &sensor_dev_attr_in3_average.dev_attr.attr,
278 &sensor_dev_attr_in0_input.dev_attr.attr,
279 &sensor_dev_attr_in1_input.dev_attr.attr,
280 &sensor_dev_attr_in2_input.dev_attr.attr,
281 &sensor_dev_attr_in3_input.dev_attr.attr,
282 NULL
283};
284
285static const struct attribute_group ads7924_group = {
286 .attrs = ads7924_attrs,
287};
288
289static int ads7924_remove(struct i2c_client *client)
290{
291 struct ads7924_data *data = i2c_get_clientdata(client);
292 int i;
293
294 ads7924_stop_sampler(data);
295 mutex_lock(&data->update_lock);
296 for (i = 0; i < ADS7924_NCH; i++)
297 {
298 if (data->channel[i]) {
299 free_adc_channel(data->channel[i]);
300 }
301 data->channel[i] = NULL;
302 }
303
304 hwmon_device_unregister(data->hwmon_dev);
305 sysfs_remove_group(&client->dev.kobj, &ads7924_group);
306 mutex_unlock(&data->update_lock);
307 return 0;
308}
309
310static int ads7924_probe(struct i2c_client *client, const struct i2c_device_id *id)
311{
312 struct ads7924_data *data;
313 int i;
314 uint8_t dev_id;
315 int err;
316 int smbus_err;
317 dev_info(&client->dev, "ads7924 probe begin\n");
318 data = devm_kzalloc(&client->dev, sizeof(struct ads7924_data), GFP_KERNEL);
319 if (!data)
320 return -ENOMEM;
321
322 data->valid = 0;
323 data->update_interval = ADS7924_SAMPLE_INTERVAL;
324 data->sample_length = ADS7924_DEFAULT_BUFFER_SIZE;
325 data->enabled = ADS7924_ENABLE_DEFAULT;
326 data->client = client;
327 data->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
328 if (IS_ERR(data->reset)){
329 dev_warn(&client->dev, "Failed to request the reset gpio, error=%ld\n", PTR_ERR(data->reset));
330 data->reset = NULL;
331 } else {
332 dev_info(&client->dev, "Successfully claimed the reset gpio (gpio %d), value is %d\n",desc_to_gpio(data->reset), gpiod_get_value(data->reset));
333 }
334
335 mdelay(10);
336 smbus_err = i2c_smbus_read_byte_data(client, ADS7924_REG_RESET);
337 if (smbus_err < 0)
338 dev_warn(&client->dev, "failed to read device id register 0x%02X, err=%d\n", ADS7924_REG_RESET, smbus_err);
339
340 dev_id = (uint8_t) (smbus_err & 0xFF);
341 if (dev_id != 0x19) { /* This is my device's ID, at least. */
342 dev_warn(&client->dev, "Device id of 0x%02x doesn't match the expected 0x19\n", dev_id);
343 err = -ENODEV;
344 goto err_free;
345 }
346
347 for (i = 0; i < ADS7924_NCH; i++) {
348 data->channel[i] = create_adc_channel(data->sample_length);
349 if (!data->channel[i]) {
350 dev_warn(&client->dev, "Failed to allocate memeory for adc_channel %d\n", i);
351 return -ENOMEM;
352 }
353 }
354
355 INIT_WORK(&data->workq, ads7924_work);
356 mutex_init(&data->update_lock);
357
358 err = sysfs_create_group(&client->dev.kobj, &ads7924_group);
359 if (err < 0)
360 return err;
361
362 i2c_set_clientdata(client, data);
363
364 data->hwmon_dev = hwmon_device_register(&client->dev);
365
366 if (IS_ERR(data->hwmon_dev)) {
367 err = PTR_ERR(data->hwmon_dev);
368 dev_err(&client->dev, "Failed to register with hwmon, error=%d\n", err);
369 goto err_remove;
370 }
371 ads7924_start_sampler(data);
372 return 0;
373
374
375err_remove:
376 sysfs_remove_group(&client->dev.kobj, &ads7924_group);
377err_free:
378 devm_kfree(&client->dev, data);
379 return err;
380
381}
382
383static const struct i2c_device_id ads7924_device_ids[] = {
384 { "ads7924", 0},
385 { },
386};
387MODULE_DEVICE_TABLE(i2c, ads7924_device_ids);
388
389static struct i2c_driver ads7924_driver = {
390 .class = I2C_CLASS_HWMON,
391 .driver = {
392 .name = "ads7924",
393 },
394 .id_table = ads7924_device_ids,
395 .probe = ads7924_probe,
396 .remove = ads7924_remove,
397};
398
399module_i2c_driver(ads7924_driver);
400
401MODULE_LICENSE("GPL");
402MODULE_AUTHOR("Kyle Swenson <kswenson@cradlepoint.com>");
403MODULE_DESCRIPTION("Driver for TI ADS7924 A/D converter and compatibles");