diff options
author | Guenter Roeck <linux@roeck-us.net> | 2019-07-01 14:12:38 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2019-09-03 15:47:17 -0400 |
commit | 2c9d5b5e32a2516ae9b1120c7688ea25ffee7805 (patch) | |
tree | 4f357bfad28b8e6dd96d0367fedcfdff5bb0c372 /drivers/hwmon | |
parent | e027a2dea5fdde05740a98f571fc2903060559ce (diff) |
hwmon: Remove ads1015 driver
A driver for ADS1015 with more functionality is available in the iio
subsystem.
Remove the hwmon driver as duplicate. If the chip is used for hardware
monitoring, the iio->hwmon bridge should be used.
Cc: Dirk Eibach <eibach@gdsys.de>
Link: https://lore.kernel.org/r/1562004758-13025-1-git-send-email-linux@roeck-us.net
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/ads1015.c | 324 |
3 files changed, 0 insertions, 335 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 650dd71f9724..76cd0647ee2c 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -1570,16 +1570,6 @@ config SENSORS_ADC128D818 | |||
1570 | This driver can also be built as a module. If so, the module | 1570 | This driver can also be built as a module. If so, the module |
1571 | will be called adc128d818. | 1571 | will be called adc128d818. |
1572 | 1572 | ||
1573 | config SENSORS_ADS1015 | ||
1574 | tristate "Texas Instruments ADS1015" | ||
1575 | depends on I2C | ||
1576 | help | ||
1577 | If you say yes here you get support for Texas Instruments | ||
1578 | ADS1015/ADS1115 12/16-bit 4-input ADC device. | ||
1579 | |||
1580 | This driver can also be built as a module. If so, the module | ||
1581 | will be called ads1015. | ||
1582 | |||
1583 | config SENSORS_ADS7828 | 1573 | config SENSORS_ADS7828 |
1584 | tristate "Texas Instruments ADS7828 and compatibles" | 1574 | tristate "Texas Instruments ADS7828 and compatibles" |
1585 | depends on I2C | 1575 | depends on I2C |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 8db472ea04f0..6a52a964038b 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -35,7 +35,6 @@ obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o | |||
35 | obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o | 35 | obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o |
36 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o | 36 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o |
37 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | 37 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o |
38 | obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o | ||
39 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o | 38 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o |
40 | obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o | 39 | obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o |
41 | obj-$(CONFIG_SENSORS_ADT7X10) += adt7x10.o | 40 | obj-$(CONFIG_SENSORS_ADT7X10) += adt7x10.o |
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c deleted file mode 100644 index 3727a3762eb8..000000000000 --- a/drivers/hwmon/ads1015.c +++ /dev/null | |||
@@ -1,324 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC | ||
4 | * (C) Copyright 2010 | ||
5 | * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de> | ||
6 | * | ||
7 | * Based on the ads7828 driver by Steve Hardy. | ||
8 | * | ||
9 | * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/hwmon.h> | ||
18 | #include <linux/hwmon-sysfs.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include <linux/platform_data/ads1015.h> | ||
25 | |||
26 | /* ADS1015 registers */ | ||
27 | enum { | ||
28 | ADS1015_CONVERSION = 0, | ||
29 | ADS1015_CONFIG = 1, | ||
30 | }; | ||
31 | |||
32 | /* PGA fullscale voltages in mV */ | ||
33 | static const unsigned int fullscale_table[8] = { | ||
34 | 6144, 4096, 2048, 1024, 512, 256, 256, 256 }; | ||
35 | |||
36 | /* Data rates in samples per second */ | ||
37 | static const unsigned int data_rate_table_1015[8] = { | ||
38 | 128, 250, 490, 920, 1600, 2400, 3300, 3300 | ||
39 | }; | ||
40 | |||
41 | static const unsigned int data_rate_table_1115[8] = { | ||
42 | 8, 16, 32, 64, 128, 250, 475, 860 | ||
43 | }; | ||
44 | |||
45 | #define ADS1015_DEFAULT_CHANNELS 0xff | ||
46 | #define ADS1015_DEFAULT_PGA 2 | ||
47 | #define ADS1015_DEFAULT_DATA_RATE 4 | ||
48 | |||
49 | enum ads1015_chips { | ||
50 | ads1015, | ||
51 | ads1115, | ||
52 | }; | ||
53 | |||
54 | struct ads1015_data { | ||
55 | struct device *hwmon_dev; | ||
56 | struct mutex update_lock; /* mutex protect updates */ | ||
57 | struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; | ||
58 | enum ads1015_chips id; | ||
59 | }; | ||
60 | |||
61 | static int ads1015_read_adc(struct i2c_client *client, unsigned int channel) | ||
62 | { | ||
63 | u16 config; | ||
64 | struct ads1015_data *data = i2c_get_clientdata(client); | ||
65 | unsigned int pga = data->channel_data[channel].pga; | ||
66 | unsigned int data_rate = data->channel_data[channel].data_rate; | ||
67 | unsigned int conversion_time_ms; | ||
68 | const unsigned int * const rate_table = data->id == ads1115 ? | ||
69 | data_rate_table_1115 : data_rate_table_1015; | ||
70 | int res; | ||
71 | |||
72 | mutex_lock(&data->update_lock); | ||
73 | |||
74 | /* get channel parameters */ | ||
75 | res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG); | ||
76 | if (res < 0) | ||
77 | goto err_unlock; | ||
78 | config = res; | ||
79 | conversion_time_ms = DIV_ROUND_UP(1000, rate_table[data_rate]); | ||
80 | |||
81 | /* setup and start single conversion */ | ||
82 | config &= 0x001f; | ||
83 | config |= (1 << 15) | (1 << 8); | ||
84 | config |= (channel & 0x0007) << 12; | ||
85 | config |= (pga & 0x0007) << 9; | ||
86 | config |= (data_rate & 0x0007) << 5; | ||
87 | |||
88 | res = i2c_smbus_write_word_swapped(client, ADS1015_CONFIG, config); | ||
89 | if (res < 0) | ||
90 | goto err_unlock; | ||
91 | |||
92 | /* wait until conversion finished */ | ||
93 | msleep(conversion_time_ms); | ||
94 | res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG); | ||
95 | if (res < 0) | ||
96 | goto err_unlock; | ||
97 | config = res; | ||
98 | if (!(config & (1 << 15))) { | ||
99 | /* conversion not finished in time */ | ||
100 | res = -EIO; | ||
101 | goto err_unlock; | ||
102 | } | ||
103 | |||
104 | res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION); | ||
105 | |||
106 | err_unlock: | ||
107 | mutex_unlock(&data->update_lock); | ||
108 | return res; | ||
109 | } | ||
110 | |||
111 | static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel, | ||
112 | s16 reg) | ||
113 | { | ||
114 | struct ads1015_data *data = i2c_get_clientdata(client); | ||
115 | unsigned int pga = data->channel_data[channel].pga; | ||
116 | int fullscale = fullscale_table[pga]; | ||
117 | const int mask = data->id == ads1115 ? 0x7fff : 0x7ff0; | ||
118 | |||
119 | return DIV_ROUND_CLOSEST(reg * fullscale, mask); | ||
120 | } | ||
121 | |||
122 | /* sysfs callback function */ | ||
123 | static ssize_t in_show(struct device *dev, struct device_attribute *da, | ||
124 | char *buf) | ||
125 | { | ||
126 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
127 | struct i2c_client *client = to_i2c_client(dev); | ||
128 | int res; | ||
129 | int index = attr->index; | ||
130 | |||
131 | res = ads1015_read_adc(client, index); | ||
132 | if (res < 0) | ||
133 | return res; | ||
134 | |||
135 | return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res)); | ||
136 | } | ||
137 | |||
138 | static const struct sensor_device_attribute ads1015_in[] = { | ||
139 | SENSOR_ATTR_RO(in0_input, in, 0), | ||
140 | SENSOR_ATTR_RO(in1_input, in, 1), | ||
141 | SENSOR_ATTR_RO(in2_input, in, 2), | ||
142 | SENSOR_ATTR_RO(in3_input, in, 3), | ||
143 | SENSOR_ATTR_RO(in4_input, in, 4), | ||
144 | SENSOR_ATTR_RO(in5_input, in, 5), | ||
145 | SENSOR_ATTR_RO(in6_input, in, 6), | ||
146 | SENSOR_ATTR_RO(in7_input, in, 7), | ||
147 | }; | ||
148 | |||
149 | /* | ||
150 | * Driver interface | ||
151 | */ | ||
152 | |||
153 | static int ads1015_remove(struct i2c_client *client) | ||
154 | { | ||
155 | struct ads1015_data *data = i2c_get_clientdata(client); | ||
156 | int k; | ||
157 | |||
158 | hwmon_device_unregister(data->hwmon_dev); | ||
159 | for (k = 0; k < ADS1015_CHANNELS; ++k) | ||
160 | device_remove_file(&client->dev, &ads1015_in[k].dev_attr); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | #ifdef CONFIG_OF | ||
165 | static 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 | u32 pval; | ||
176 | unsigned int channel; | ||
177 | unsigned int pga = ADS1015_DEFAULT_PGA; | ||
178 | unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; | ||
179 | |||
180 | if (of_property_read_u32(node, "reg", &pval)) { | ||
181 | dev_err(&client->dev, "invalid reg on %pOF\n", node); | ||
182 | continue; | ||
183 | } | ||
184 | |||
185 | channel = pval; | ||
186 | if (channel >= ADS1015_CHANNELS) { | ||
187 | dev_err(&client->dev, | ||
188 | "invalid channel index %d on %pOF\n", | ||
189 | channel, node); | ||
190 | continue; | ||
191 | } | ||
192 | |||
193 | if (!of_property_read_u32(node, "ti,gain", &pval)) { | ||
194 | pga = pval; | ||
195 | if (pga > 6) { | ||
196 | dev_err(&client->dev, "invalid gain on %pOF\n", | ||
197 | node); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | if (!of_property_read_u32(node, "ti,datarate", &pval)) { | ||
203 | data_rate = pval; | ||
204 | if (data_rate > 7) { | ||
205 | dev_err(&client->dev, | ||
206 | "invalid data_rate on %pOF\n", node); | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | data->channel_data[channel].enabled = true; | ||
212 | data->channel_data[channel].pga = pga; | ||
213 | data->channel_data[channel].data_rate = data_rate; | ||
214 | } | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | #endif | ||
219 | |||
220 | static void ads1015_get_channels_config(struct i2c_client *client) | ||
221 | { | ||
222 | unsigned int k; | ||
223 | struct ads1015_data *data = i2c_get_clientdata(client); | ||
224 | struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev); | ||
225 | |||
226 | /* prefer platform data */ | ||
227 | if (pdata) { | ||
228 | memcpy(data->channel_data, pdata->channel_data, | ||
229 | sizeof(data->channel_data)); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | #ifdef CONFIG_OF | ||
234 | if (!ads1015_get_channels_config_of(client)) | ||
235 | return; | ||
236 | #endif | ||
237 | |||
238 | /* fallback on default configuration */ | ||
239 | for (k = 0; k < ADS1015_CHANNELS; ++k) { | ||
240 | data->channel_data[k].enabled = true; | ||
241 | data->channel_data[k].pga = ADS1015_DEFAULT_PGA; | ||
242 | data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | static int ads1015_probe(struct i2c_client *client, | ||
247 | const struct i2c_device_id *id) | ||
248 | { | ||
249 | struct ads1015_data *data; | ||
250 | int err; | ||
251 | unsigned int k; | ||
252 | |||
253 | data = devm_kzalloc(&client->dev, sizeof(struct ads1015_data), | ||
254 | GFP_KERNEL); | ||
255 | if (!data) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | if (client->dev.of_node) | ||
259 | data->id = (enum ads1015_chips) | ||
260 | of_device_get_match_data(&client->dev); | ||
261 | else | ||
262 | data->id = id->driver_data; | ||
263 | i2c_set_clientdata(client, data); | ||
264 | mutex_init(&data->update_lock); | ||
265 | |||
266 | /* build sysfs attribute group */ | ||
267 | ads1015_get_channels_config(client); | ||
268 | for (k = 0; k < ADS1015_CHANNELS; ++k) { | ||
269 | if (!data->channel_data[k].enabled) | ||
270 | continue; | ||
271 | err = device_create_file(&client->dev, &ads1015_in[k].dev_attr); | ||
272 | if (err) | ||
273 | goto exit_remove; | ||
274 | } | ||
275 | |||
276 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
277 | if (IS_ERR(data->hwmon_dev)) { | ||
278 | err = PTR_ERR(data->hwmon_dev); | ||
279 | goto exit_remove; | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | |||
284 | exit_remove: | ||
285 | for (k = 0; k < ADS1015_CHANNELS; ++k) | ||
286 | device_remove_file(&client->dev, &ads1015_in[k].dev_attr); | ||
287 | return err; | ||
288 | } | ||
289 | |||
290 | static const struct i2c_device_id ads1015_id[] = { | ||
291 | { "ads1015", ads1015}, | ||
292 | { "ads1115", ads1115}, | ||
293 | { } | ||
294 | }; | ||
295 | MODULE_DEVICE_TABLE(i2c, ads1015_id); | ||
296 | |||
297 | static const struct of_device_id __maybe_unused ads1015_of_match[] = { | ||
298 | { | ||
299 | .compatible = "ti,ads1015", | ||
300 | .data = (void *)ads1015 | ||
301 | }, | ||
302 | { | ||
303 | .compatible = "ti,ads1115", | ||
304 | .data = (void *)ads1115 | ||
305 | }, | ||
306 | { }, | ||
307 | }; | ||
308 | MODULE_DEVICE_TABLE(of, ads1015_of_match); | ||
309 | |||
310 | static struct i2c_driver ads1015_driver = { | ||
311 | .driver = { | ||
312 | .name = "ads1015", | ||
313 | .of_match_table = of_match_ptr(ads1015_of_match), | ||
314 | }, | ||
315 | .probe = ads1015_probe, | ||
316 | .remove = ads1015_remove, | ||
317 | .id_table = ads1015_id, | ||
318 | }; | ||
319 | |||
320 | module_i2c_driver(ads1015_driver); | ||
321 | |||
322 | MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>"); | ||
323 | MODULE_DESCRIPTION("ADS1015 driver"); | ||
324 | MODULE_LICENSE("GPL"); | ||