]>
Commit | Line | Data |
---|---|---|
a20ebd93 BS |
1 | /* |
2 | * AD7152 capacitive sensor driver supporting AD7152/3 | |
3 | * | |
e5664293 | 4 | * Copyright 2010-2011a Analog Devices Inc. |
a20ebd93 BS |
5 | * |
6 | * Licensed under the GPL-2 or later. | |
7 | */ | |
8 | ||
9 | #include <linux/interrupt.h> | |
a20ebd93 BS |
10 | #include <linux/device.h> |
11 | #include <linux/kernel.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/sysfs.h> | |
a20ebd93 | 14 | #include <linux/i2c.h> |
99c97852 | 15 | #include <linux/module.h> |
ea993a51 | 16 | #include <linux/delay.h> |
a20ebd93 | 17 | |
06458e27 JC |
18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> | |
a20ebd93 | 20 | |
3995f917 | 21 | /* |
bb90cf8d | 22 | * TODO: Check compliance of calibbias with abi (units) |
3995f917 | 23 | */ |
a20ebd93 BS |
24 | /* |
25 | * AD7152 registers definition | |
26 | */ | |
27 | ||
e5664293 MH |
28 | #define AD7152_REG_STATUS 0 |
29 | #define AD7152_REG_CH1_DATA_HIGH 1 | |
30 | #define AD7152_REG_CH2_DATA_HIGH 3 | |
31 | #define AD7152_REG_CH1_OFFS_HIGH 5 | |
32 | #define AD7152_REG_CH2_OFFS_HIGH 7 | |
33 | #define AD7152_REG_CH1_GAIN_HIGH 9 | |
34 | #define AD7152_REG_CH1_SETUP 11 | |
35 | #define AD7152_REG_CH2_GAIN_HIGH 12 | |
36 | #define AD7152_REG_CH2_SETUP 14 | |
37 | #define AD7152_REG_CFG 15 | |
38 | #define AD7152_REG_RESEVERD 16 | |
39 | #define AD7152_REG_CAPDAC_POS 17 | |
40 | #define AD7152_REG_CAPDAC_NEG 18 | |
41 | #define AD7152_REG_CFG2 26 | |
42 | ||
43 | /* Status Register Bit Designations (AD7152_REG_STATUS) */ | |
44 | #define AD7152_STATUS_RDY1 (1 << 0) | |
45 | #define AD7152_STATUS_RDY2 (1 << 1) | |
46 | #define AD7152_STATUS_C1C2 (1 << 2) | |
47 | #define AD7152_STATUS_PWDN (1 << 7) | |
48 | ||
49 | /* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */ | |
50 | #define AD7152_SETUP_CAPDIFF (1 << 5) | |
51 | #define AD7152_SETUP_RANGE_2pF (0 << 6) | |
52 | #define AD7152_SETUP_RANGE_0_5pF (1 << 6) | |
53 | #define AD7152_SETUP_RANGE_1pF (2 << 6) | |
54 | #define AD7152_SETUP_RANGE_4pF (3 << 6) | |
2b8cb40c | 55 | #define AD7152_SETUP_RANGE(x) ((x) << 6) |
e5664293 MH |
56 | |
57 | /* Config Register Bit Designations (AD7152_REG_CFG) */ | |
58 | #define AD7152_CONF_CH2EN (1 << 3) | |
59 | #define AD7152_CONF_CH1EN (1 << 4) | |
60 | #define AD7152_CONF_MODE_IDLE (0 << 0) | |
61 | #define AD7152_CONF_MODE_CONT_CONV (1 << 0) | |
62 | #define AD7152_CONF_MODE_SINGLE_CONV (2 << 0) | |
63 | #define AD7152_CONF_MODE_OFFS_CAL (5 << 0) | |
64 | #define AD7152_CONF_MODE_GAIN_CAL (6 << 0) | |
65 | ||
66 | /* Capdac Register Bit Designations (AD7152_REG_CAPDAC_XXX) */ | |
67 | #define AD7152_CAPDAC_DACEN (1 << 7) | |
68 | #define AD7152_CAPDAC_DACP(x) ((x) & 0x1F) | |
69 | ||
c3b7915d MH |
70 | /* CFG2 Register Bit Designations (AD7152_REG_CFG2) */ |
71 | #define AD7152_CFG2_OSR(x) (((x) & 0x3) << 4) | |
72 | ||
e5664293 MH |
73 | enum { |
74 | AD7152_DATA, | |
75 | AD7152_OFFS, | |
76 | AD7152_GAIN, | |
77 | AD7152_SETUP | |
78 | }; | |
a20ebd93 BS |
79 | |
80 | /* | |
81 | * struct ad7152_chip_info - chip specifc information | |
82 | */ | |
83 | ||
84 | struct ad7152_chip_info { | |
a20ebd93 | 85 | struct i2c_client *client; |
3995f917 JC |
86 | /* |
87 | * Capacitive channel digital filter setup; | |
88 | * conversion time/update rate setup per channel | |
89 | */ | |
2b8cb40c MH |
90 | u8 filter_rate_setup; |
91 | u8 setup[2]; | |
a20ebd93 BS |
92 | }; |
93 | ||
ea993a51 JC |
94 | static inline ssize_t ad7152_start_calib(struct device *dev, |
95 | struct device_attribute *attr, | |
96 | const char *buf, | |
97 | size_t len, | |
98 | u8 regval) | |
a20ebd93 | 99 | { |
d30a7f9d | 100 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
bb90cf8d | 101 | struct ad7152_chip_info *chip = iio_priv(indio_dev); |
ea993a51 JC |
102 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
103 | bool doit; | |
2b8cb40c | 104 | int ret, timeout = 10; |
a20ebd93 | 105 | |
ea993a51 | 106 | ret = strtobool(buf, &doit); |
3995f917 JC |
107 | if (ret < 0) |
108 | return ret; | |
a20ebd93 | 109 | |
ea993a51 JC |
110 | if (!doit) |
111 | return 0; | |
a20ebd93 | 112 | |
ea993a51 | 113 | if (this_attr->address == 0) |
e5664293 | 114 | regval |= AD7152_CONF_CH1EN; |
ea993a51 | 115 | else |
e5664293 | 116 | regval |= AD7152_CONF_CH2EN; |
a20ebd93 | 117 | |
bb90cf8d | 118 | mutex_lock(&indio_dev->mlock); |
e5664293 | 119 | ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, regval); |
bb90cf8d MH |
120 | if (ret < 0) { |
121 | mutex_unlock(&indio_dev->mlock); | |
3995f917 | 122 | return ret; |
bb90cf8d | 123 | } |
2b8cb40c MH |
124 | |
125 | do { | |
126 | mdelay(20); | |
127 | ret = i2c_smbus_read_byte_data(chip->client, AD7152_REG_CFG); | |
bb90cf8d MH |
128 | if (ret < 0) { |
129 | mutex_unlock(&indio_dev->mlock); | |
2b8cb40c | 130 | return ret; |
bb90cf8d | 131 | } |
2b8cb40c MH |
132 | } while ((ret == regval) && timeout--); |
133 | ||
bb90cf8d | 134 | mutex_unlock(&indio_dev->mlock); |
3995f917 | 135 | return len; |
a20ebd93 | 136 | } |
ea993a51 JC |
137 | static ssize_t ad7152_start_offset_calib(struct device *dev, |
138 | struct device_attribute *attr, | |
139 | const char *buf, | |
140 | size_t len) | |
a20ebd93 | 141 | { |
e5664293 MH |
142 | return ad7152_start_calib(dev, attr, buf, len, |
143 | AD7152_CONF_MODE_OFFS_CAL); | |
a20ebd93 | 144 | } |
ea993a51 JC |
145 | static ssize_t ad7152_start_gain_calib(struct device *dev, |
146 | struct device_attribute *attr, | |
147 | const char *buf, | |
148 | size_t len) | |
a20ebd93 | 149 | { |
e5664293 MH |
150 | return ad7152_start_calib(dev, attr, buf, len, |
151 | AD7152_CONF_MODE_GAIN_CAL); | |
a20ebd93 BS |
152 | } |
153 | ||
ea993a51 JC |
154 | static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, |
155 | S_IWUSR, NULL, ad7152_start_offset_calib, 0); | |
156 | static IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration, | |
157 | S_IWUSR, NULL, ad7152_start_offset_calib, 1); | |
158 | static IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration, | |
159 | S_IWUSR, NULL, ad7152_start_gain_calib, 0); | |
160 | static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, | |
161 | S_IWUSR, NULL, ad7152_start_gain_calib, 1); | |
162 | ||
fe55a170 | 163 | /* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ |
c3b7915d | 164 | static const unsigned char ad7152_filter_rate_table[][2] = { |
fe55a170 | 165 | {200, 5 + 1}, {50, 20 + 1}, {20, 50 + 1}, {17, 60 + 1}, |
c3b7915d | 166 | }; |
a20ebd93 BS |
167 | |
168 | static ssize_t ad7152_show_filter_rate_setup(struct device *dev, | |
169 | struct device_attribute *attr, | |
170 | char *buf) | |
171 | { | |
d30a7f9d | 172 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
bb90cf8d | 173 | struct ad7152_chip_info *chip = iio_priv(indio_dev); |
a20ebd93 | 174 | |
c3b7915d MH |
175 | return sprintf(buf, "%d\n", |
176 | ad7152_filter_rate_table[chip->filter_rate_setup][0]); | |
a20ebd93 BS |
177 | } |
178 | ||
179 | static ssize_t ad7152_store_filter_rate_setup(struct device *dev, | |
180 | struct device_attribute *attr, | |
181 | const char *buf, | |
182 | size_t len) | |
183 | { | |
d30a7f9d | 184 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
bb90cf8d | 185 | struct ad7152_chip_info *chip = iio_priv(indio_dev); |
3995f917 | 186 | u8 data; |
c3b7915d | 187 | int ret, i; |
a20ebd93 | 188 | |
3995f917 JC |
189 | ret = kstrtou8(buf, 10, &data); |
190 | if (ret < 0) | |
191 | return ret; | |
192 | ||
c3b7915d MH |
193 | for (i = 0; i < ARRAY_SIZE(ad7152_filter_rate_table); i++) |
194 | if (data >= ad7152_filter_rate_table[i][0]) | |
195 | break; | |
196 | ||
197 | if (i >= ARRAY_SIZE(ad7152_filter_rate_table)) | |
198 | i = ARRAY_SIZE(ad7152_filter_rate_table) - 1; | |
199 | ||
bb90cf8d | 200 | mutex_lock(&indio_dev->mlock); |
c3b7915d MH |
201 | ret = i2c_smbus_write_byte_data(chip->client, |
202 | AD7152_REG_CFG2, AD7152_CFG2_OSR(i)); | |
203 | if (ret < 0) { | |
204 | mutex_unlock(&indio_dev->mlock); | |
3995f917 | 205 | return ret; |
c3b7915d | 206 | } |
a20ebd93 | 207 | |
c3b7915d | 208 | chip->filter_rate_setup = i; |
bb90cf8d | 209 | mutex_unlock(&indio_dev->mlock); |
a20ebd93 | 210 | |
3995f917 | 211 | return len; |
a20ebd93 BS |
212 | } |
213 | ||
c3b7915d | 214 | static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, |
a20ebd93 BS |
215 | ad7152_show_filter_rate_setup, |
216 | ad7152_store_filter_rate_setup); | |
217 | ||
c3b7915d MH |
218 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("200 50 20 17"); |
219 | ||
9b724419 MH |
220 | static IIO_CONST_ATTR(in_capacitance_scale_available, |
221 | "0.000061050 0.000030525 0.000015263 0.000007631"); | |
222 | ||
a20ebd93 | 223 | static struct attribute *ad7152_attributes[] = { |
c3b7915d | 224 | &iio_dev_attr_sampling_frequency.dev_attr.attr, |
ea993a51 JC |
225 | &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, |
226 | &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, | |
227 | &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, | |
228 | &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, | |
9b724419 | 229 | &iio_const_attr_in_capacitance_scale_available.dev_attr.attr, |
c3b7915d | 230 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
a20ebd93 BS |
231 | NULL, |
232 | }; | |
233 | ||
234 | static const struct attribute_group ad7152_attribute_group = { | |
235 | .attrs = ad7152_attributes, | |
236 | }; | |
237 | ||
ea993a51 | 238 | static const u8 ad7152_addresses[][4] = { |
e5664293 MH |
239 | { AD7152_REG_CH1_DATA_HIGH, AD7152_REG_CH1_OFFS_HIGH, |
240 | AD7152_REG_CH1_GAIN_HIGH, AD7152_REG_CH1_SETUP }, | |
241 | { AD7152_REG_CH2_DATA_HIGH, AD7152_REG_CH2_OFFS_HIGH, | |
242 | AD7152_REG_CH2_GAIN_HIGH, AD7152_REG_CH2_SETUP }, | |
ea993a51 JC |
243 | }; |
244 | ||
9b724419 | 245 | /* Values are nano relative to pf base. */ |
ea993a51 | 246 | static const int ad7152_scale_table[] = { |
9b724419 | 247 | 30525, 7631, 15263, 61050 |
3995f917 | 248 | }; |
ea993a51 | 249 | |
bb90cf8d | 250 | static int ad7152_write_raw(struct iio_dev *indio_dev, |
3995f917 JC |
251 | struct iio_chan_spec const *chan, |
252 | int val, | |
253 | int val2, | |
254 | long mask) | |
255 | { | |
bb90cf8d | 256 | struct ad7152_chip_info *chip = iio_priv(indio_dev); |
ea993a51 | 257 | int ret, i; |
3995f917 | 258 | |
bb90cf8d MH |
259 | mutex_lock(&indio_dev->mlock); |
260 | ||
3995f917 | 261 | switch (mask) { |
c8a9f805 | 262 | case IIO_CHAN_INFO_CALIBSCALE: |
bb90cf8d MH |
263 | if (val != 1) { |
264 | ret = -EINVAL; | |
265 | goto out; | |
266 | } | |
2b8cb40c MH |
267 | |
268 | val = (val2 * 1024) / 15625; | |
269 | ||
3995f917 | 270 | ret = i2c_smbus_write_word_data(chip->client, |
e5664293 | 271 | ad7152_addresses[chan->channel][AD7152_GAIN], |
2b8cb40c | 272 | swab16(val)); |
3995f917 | 273 | if (ret < 0) |
bb90cf8d | 274 | goto out; |
3995f917 | 275 | |
bb90cf8d MH |
276 | ret = 0; |
277 | break; | |
3995f917 | 278 | |
c8a9f805 | 279 | case IIO_CHAN_INFO_CALIBBIAS: |
bb90cf8d MH |
280 | if ((val < 0) | (val > 0xFFFF)) { |
281 | ret = -EINVAL; | |
282 | goto out; | |
283 | } | |
3995f917 | 284 | ret = i2c_smbus_write_word_data(chip->client, |
e5664293 | 285 | ad7152_addresses[chan->channel][AD7152_OFFS], |
2b8cb40c | 286 | swab16(val)); |
3995f917 | 287 | if (ret < 0) |
bb90cf8d | 288 | goto out; |
3995f917 | 289 | |
bb90cf8d MH |
290 | ret = 0; |
291 | break; | |
c8a9f805 | 292 | case IIO_CHAN_INFO_SCALE: |
bb90cf8d MH |
293 | if (val != 0) { |
294 | ret = -EINVAL; | |
295 | goto out; | |
296 | } | |
ea993a51 | 297 | for (i = 0; i < ARRAY_SIZE(ad7152_scale_table); i++) |
9b724419 | 298 | if (val2 == ad7152_scale_table[i]) |
ea993a51 | 299 | break; |
2b8cb40c MH |
300 | |
301 | chip->setup[chan->channel] &= ~AD7152_SETUP_RANGE_4pF; | |
302 | chip->setup[chan->channel] |= AD7152_SETUP_RANGE(i); | |
303 | ||
304 | ret = i2c_smbus_write_byte_data(chip->client, | |
e5664293 | 305 | ad7152_addresses[chan->channel][AD7152_SETUP], |
2b8cb40c | 306 | chip->setup[chan->channel]); |
ea993a51 | 307 | if (ret < 0) |
bb90cf8d MH |
308 | goto out; |
309 | ||
310 | ret = 0; | |
311 | break; | |
3995f917 | 312 | default: |
bb90cf8d | 313 | ret = -EINVAL; |
3995f917 | 314 | } |
bb90cf8d MH |
315 | |
316 | out: | |
317 | mutex_unlock(&indio_dev->mlock); | |
318 | return ret; | |
3995f917 | 319 | } |
bb90cf8d | 320 | static int ad7152_read_raw(struct iio_dev *indio_dev, |
3995f917 JC |
321 | struct iio_chan_spec const *chan, |
322 | int *val, int *val2, | |
323 | long mask) | |
324 | { | |
bb90cf8d | 325 | struct ad7152_chip_info *chip = iio_priv(indio_dev); |
3995f917 | 326 | int ret; |
ea993a51 | 327 | u8 regval = 0; |
bb90cf8d MH |
328 | |
329 | mutex_lock(&indio_dev->mlock); | |
330 | ||
3995f917 | 331 | switch (mask) { |
e33e0750 | 332 | case IIO_CHAN_INFO_RAW: |
ea993a51 | 333 | /* First set whether in differential mode */ |
2b8cb40c MH |
334 | |
335 | regval = chip->setup[chan->channel]; | |
336 | ||
ea993a51 | 337 | if (chan->differential) |
2b8cb40c MH |
338 | chip->setup[chan->channel] |= AD7152_SETUP_CAPDIFF; |
339 | else | |
340 | chip->setup[chan->channel] &= ~AD7152_SETUP_CAPDIFF; | |
ea993a51 | 341 | |
2b8cb40c MH |
342 | if (regval != chip->setup[chan->channel]) { |
343 | ret = i2c_smbus_write_byte_data(chip->client, | |
344 | ad7152_addresses[chan->channel][AD7152_SETUP], | |
345 | chip->setup[chan->channel]); | |
346 | if (ret < 0) | |
bb90cf8d | 347 | goto out; |
2b8cb40c | 348 | } |
ea993a51 | 349 | /* Make sure the channel is enabled */ |
2b8cb40c MH |
350 | if (chan->channel == 0) |
351 | regval = AD7152_CONF_CH1EN; | |
ea993a51 | 352 | else |
2b8cb40c MH |
353 | regval = AD7152_CONF_CH2EN; |
354 | ||
ea993a51 | 355 | /* Trigger a single read */ |
e5664293 | 356 | regval |= AD7152_CONF_MODE_SINGLE_CONV; |
2b8cb40c | 357 | ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, |
e5664293 | 358 | regval); |
ea993a51 | 359 | if (ret < 0) |
bb90cf8d | 360 | goto out; |
ea993a51 | 361 | |
c3b7915d | 362 | msleep(ad7152_filter_rate_table[chip->filter_rate_setup][1]); |
ea993a51 | 363 | /* Now read the actual register */ |
3995f917 | 364 | ret = i2c_smbus_read_word_data(chip->client, |
e5664293 | 365 | ad7152_addresses[chan->channel][AD7152_DATA]); |
3995f917 | 366 | if (ret < 0) |
bb90cf8d | 367 | goto out; |
2b8cb40c | 368 | *val = swab16(ret); |
ea993a51 | 369 | |
fe55a170 MH |
370 | if (chan->differential) |
371 | *val -= 0x8000; | |
372 | ||
bb90cf8d MH |
373 | ret = IIO_VAL_INT; |
374 | break; | |
c8a9f805 | 375 | case IIO_CHAN_INFO_CALIBSCALE: |
2b8cb40c | 376 | |
3995f917 | 377 | ret = i2c_smbus_read_word_data(chip->client, |
e5664293 | 378 | ad7152_addresses[chan->channel][AD7152_GAIN]); |
3995f917 | 379 | if (ret < 0) |
bb90cf8d | 380 | goto out; |
2b8cb40c MH |
381 | /* 1 + gain_val / 2^16 */ |
382 | *val = 1; | |
383 | *val2 = (15625 * swab16(ret)) / 1024; | |
ea993a51 | 384 | |
bb90cf8d MH |
385 | ret = IIO_VAL_INT_PLUS_MICRO; |
386 | break; | |
c8a9f805 | 387 | case IIO_CHAN_INFO_CALIBBIAS: |
3995f917 | 388 | ret = i2c_smbus_read_word_data(chip->client, |
e5664293 | 389 | ad7152_addresses[chan->channel][AD7152_OFFS]); |
3995f917 | 390 | if (ret < 0) |
bb90cf8d | 391 | goto out; |
2b8cb40c | 392 | *val = swab16(ret); |
ea993a51 | 393 | |
bb90cf8d MH |
394 | ret = IIO_VAL_INT; |
395 | break; | |
c8a9f805 | 396 | case IIO_CHAN_INFO_SCALE: |
ea993a51 | 397 | ret = i2c_smbus_read_byte_data(chip->client, |
e5664293 | 398 | ad7152_addresses[chan->channel][AD7152_SETUP]); |
ea993a51 | 399 | if (ret < 0) |
bb90cf8d | 400 | goto out; |
ea993a51 JC |
401 | *val = 0; |
402 | *val2 = ad7152_scale_table[ret >> 6]; | |
403 | ||
bb90cf8d MH |
404 | ret = IIO_VAL_INT_PLUS_NANO; |
405 | break; | |
3995f917 | 406 | default: |
bb90cf8d | 407 | ret = -EINVAL; |
73327b4c | 408 | } |
bb90cf8d MH |
409 | out: |
410 | mutex_unlock(&indio_dev->mlock); | |
411 | return ret; | |
3995f917 | 412 | } |
9b724419 MH |
413 | |
414 | static int ad7152_write_raw_get_fmt(struct iio_dev *indio_dev, | |
415 | struct iio_chan_spec const *chan, | |
416 | long mask) | |
417 | { | |
418 | switch (mask) { | |
c8a9f805 | 419 | case IIO_CHAN_INFO_SCALE: |
9b724419 MH |
420 | return IIO_VAL_INT_PLUS_NANO; |
421 | default: | |
422 | return IIO_VAL_INT_PLUS_MICRO; | |
423 | } | |
424 | } | |
425 | ||
6fe8135f JC |
426 | static const struct iio_info ad7152_info = { |
427 | .attrs = &ad7152_attribute_group, | |
3995f917 JC |
428 | .read_raw = &ad7152_read_raw, |
429 | .write_raw = &ad7152_write_raw, | |
9b724419 | 430 | .write_raw_get_fmt = &ad7152_write_raw_get_fmt, |
6fe8135f JC |
431 | .driver_module = THIS_MODULE, |
432 | }; | |
3995f917 JC |
433 | |
434 | static const struct iio_chan_spec ad7152_channels[] = { | |
435 | { | |
436 | .type = IIO_CAPACITANCE, | |
437 | .indexed = 1, | |
438 | .channel = 0, | |
c24e97b7 JC |
439 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
440 | BIT(IIO_CHAN_INFO_CALIBSCALE) | | |
441 | BIT(IIO_CHAN_INFO_CALIBBIAS) | | |
442 | BIT(IIO_CHAN_INFO_SCALE), | |
ea993a51 JC |
443 | }, { |
444 | .type = IIO_CAPACITANCE, | |
15e3276f | 445 | .differential = 1, |
ea993a51 | 446 | .indexed = 1, |
15e3276f MH |
447 | .channel = 0, |
448 | .channel2 = 2, | |
c24e97b7 JC |
449 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
450 | BIT(IIO_CHAN_INFO_CALIBSCALE) | | |
451 | BIT(IIO_CHAN_INFO_CALIBBIAS) | | |
452 | BIT(IIO_CHAN_INFO_SCALE), | |
ea993a51 JC |
453 | }, { |
454 | .type = IIO_CAPACITANCE, | |
ea993a51 | 455 | .indexed = 1, |
15e3276f | 456 | .channel = 1, |
c24e97b7 JC |
457 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
458 | BIT(IIO_CHAN_INFO_CALIBSCALE) | | |
459 | BIT(IIO_CHAN_INFO_CALIBBIAS) | | |
460 | BIT(IIO_CHAN_INFO_SCALE), | |
3995f917 JC |
461 | }, { |
462 | .type = IIO_CAPACITANCE, | |
ea993a51 | 463 | .differential = 1, |
3995f917 JC |
464 | .indexed = 1, |
465 | .channel = 1, | |
ea993a51 | 466 | .channel2 = 3, |
c24e97b7 JC |
467 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
468 | BIT(IIO_CHAN_INFO_CALIBSCALE) | | |
469 | BIT(IIO_CHAN_INFO_CALIBBIAS) | | |
470 | BIT(IIO_CHAN_INFO_SCALE), | |
3995f917 JC |
471 | } |
472 | }; | |
a20ebd93 BS |
473 | /* |
474 | * device probe and remove | |
475 | */ | |
476 | ||
4ae1c61f | 477 | static int ad7152_probe(struct i2c_client *client, |
a20ebd93 BS |
478 | const struct i2c_device_id *id) |
479 | { | |
480 | int ret = 0; | |
f4c794a2 JC |
481 | struct ad7152_chip_info *chip; |
482 | struct iio_dev *indio_dev; | |
483 | ||
538ee7cb SK |
484 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); |
485 | if (!indio_dev) | |
486 | return -ENOMEM; | |
f4c794a2 | 487 | chip = iio_priv(indio_dev); |
a20ebd93 | 488 | /* this is only used for device removal purposes */ |
f4c794a2 | 489 | i2c_set_clientdata(client, indio_dev); |
a20ebd93 BS |
490 | |
491 | chip->client = client; | |
a20ebd93 | 492 | |
e5664293 | 493 | /* Establish that the iio_dev is a child of the i2c device */ |
f4c794a2 JC |
494 | indio_dev->name = id->name; |
495 | indio_dev->dev.parent = &client->dev; | |
496 | indio_dev->info = &ad7152_info; | |
3995f917 | 497 | indio_dev->channels = ad7152_channels; |
4050f493 JC |
498 | if (id->driver_data == 0) |
499 | indio_dev->num_channels = ARRAY_SIZE(ad7152_channels); | |
500 | else | |
ea993a51 | 501 | indio_dev->num_channels = 2; |
3995f917 | 502 | indio_dev->num_channels = ARRAY_SIZE(ad7152_channels); |
f4c794a2 | 503 | indio_dev->modes = INDIO_DIRECT_MODE; |
a20ebd93 | 504 | |
f4c794a2 | 505 | ret = iio_device_register(indio_dev); |
a20ebd93 | 506 | if (ret) |
538ee7cb | 507 | return ret; |
a20ebd93 BS |
508 | |
509 | dev_err(&client->dev, "%s capacitive sensor registered\n", id->name); | |
510 | ||
511 | return 0; | |
a20ebd93 BS |
512 | } |
513 | ||
447d4f29 | 514 | static int ad7152_remove(struct i2c_client *client) |
a20ebd93 | 515 | { |
f4c794a2 | 516 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
a20ebd93 | 517 | |
a20ebd93 | 518 | iio_device_unregister(indio_dev); |
a20ebd93 BS |
519 | |
520 | return 0; | |
521 | } | |
522 | ||
523 | static const struct i2c_device_id ad7152_id[] = { | |
524 | { "ad7152", 0 }, | |
4050f493 | 525 | { "ad7153", 1 }, |
a20ebd93 BS |
526 | {} |
527 | }; | |
528 | ||
529 | MODULE_DEVICE_TABLE(i2c, ad7152_id); | |
530 | ||
531 | static struct i2c_driver ad7152_driver = { | |
532 | .driver = { | |
e5664293 | 533 | .name = KBUILD_MODNAME, |
a20ebd93 BS |
534 | }, |
535 | .probe = ad7152_probe, | |
e543acf0 | 536 | .remove = ad7152_remove, |
a20ebd93 BS |
537 | .id_table = ad7152_id, |
538 | }; | |
6e5af184 | 539 | module_i2c_driver(ad7152_driver); |
a20ebd93 BS |
540 | |
541 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | |
e5664293 | 542 | MODULE_DESCRIPTION("Analog Devices AD7152/3 capacitive sensor driver"); |
a20ebd93 | 543 | MODULE_LICENSE("GPL v2"); |